Git Product home page Git Product logo

tools's Introduction

Player Tools

Warning Player is still in early development, some features may still be in progress.

CircleCI codecov License: MIT

Tools to aid in the development, and debugging of experiences built with Player.

Place for:

  • Player Language
  • XLR
  • Devtools Common

Contributing

We actively welcome pull requests. Learn how to contribute. Be sure to read our code of conduct.

tools's People

Contributors

adierkens avatar brocollie08 avatar hborawski avatar intuit-svc avatar ketanreddy avatar lexfm avatar mercillo avatar mrigankmg avatar neveena avatar rafbcampos avatar sugarmanz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tools's Issues

XLR Converters and utils should work by default in the browser

Importing and using the TSWriter from xlr-converters results in an exception for the path module:

import { TSWriter } from "@player-tools/xlr-converters";

const tsWriter = new TSWriter();
✘ [ERROR] Could not resolve "path"

    ../../../../../../node_modules/.aspect_rules_js/@[email protected]/node_modules/@typescript/vfs/dist/vfs.esm.js:575:17:
      575 │   return require(String.fromCharCode(112, 97, 116, 104));
          ╵                  ^

  The package "path" wasn't found on the file system but is built into node. Are you trying to
  bundle for node? You can use "platform: 'node'" to do that, which will remove this error.

When Returning Effective Type from the SDK Fill in Generics and Compute Effective Objects

All of the logic that we do in validation to fill in generics, compute the effective object results from intersections/unions and solve the extends notation for ObjectType nodes we should all compute when we return an object from the SDK. Currently we only expand the extends notation but by doing all the other operations we can return a more useful type for some operations (like generating JSON that fills in some of those objects in drag and drop). If we compute these objects when retrieving them from the SDK, they should also be added to the cache used for validation in #24.

Add `Extends` parameter to Object Type for Custom Primitives

Right now even if an interface extends a class that is specified as a custom primitive, it is serialized and merged into the object. Since we defer serializing those classes to execution time, we should also be doing that in the inheritance case.

The proposed solution is some sort of extends parameter that should be added to the ObjectNode type that takes a RefNode where the type to merge into the ObjectNode at runtime is stored. Then, in the validator when we get an ObjectNode we should opaquely pull that type and merge its properties into the object before examining it.

[devtools] Add Player instance highlight

We can have multiple Player instances on the same page. Although the basic dev tools plugin has a dropdown to select different Player instances, they are shown as IDs.

So this is an issue for adding support to highlight the currently inspected Player when we select the instance in the dropdown and add an icon button to highlight the Player instance being inspected when the user clicks on it.

Possible solutions on how to highlight the Player instance:

  • Add an ID to the WrapperComponent and add a script into the extension to add a border to an element for a given ID; or
  • Use a ContentScript to wrap the component based on an ID; or
  • Add an Event to highlight based on the Player ID, and hook that into the WrappedComponent, so we add/remove a class to add a border.

[devtools] Flipper client connection

Description

The connection between a ReactPlayer instance and a Flipper client was tested during the POC. However, the final version is still pending implementation.

TODO:

  1. Uncomment the code at devtools/plugins/desktop/common/src/communication-layer/index.ts (lines 29-64);
  2. Add the devtools/plugins/mobile/flipper-desktop-client to a Flipper desktop (docs), and verify if the connection between the inspected Player-UI instance and Flipper;
  3. Fix connection errors and verify if the client works as intended (we use the same client as the dev tools panel, so the plugin content should be the same as the browser extension).

Explore Additional Ways to Expose Capabilities via the `ExtendedPlayerPlugin`

Right now the ExtendedPlayerPlugin uses generic arguments to hold the interfaces for each Capability which is then parsed by the CLI to convert the interfaces to XLR. While it works, there might be a cleaner way to do this. The keys to a good design here are:

  1. It should be easy for capability authors to write/maintain
  2. It should be explicit
  3. It should be verifiable
  4. It should be easy to parse

Better Tests

Test coverage overall is lacking at best. Most of the big entry points have functional tests to ensure that TS -> XLR and XLR -> TS are stable but a lot of the helper functionality and LSP things could use a lot more test coverage.

Update Oclif Versions

The versions of the oclif libraries we're using are pretty old. We should look at upgrading them to more recent versions.

More Efficient Validation

Right now for validation we fill in references, solve generics, generate effective types etc. as we walk through the XLR tree. A more efficient way to do things might be to resolve everything in the SDK before passing it to the validation logic. That would probably simplify some steps in validation related to those more expensive operations and if we cache those computed nodes, speed up subsequent validation calls to the same object. Obviously if new types are loaded in we'll need to invalidate that cache but that probably won't happen too often.

Error Thrown when Indexing Long Lists

When using typeof to enumerate a long list of consts to get a set of values, if the list is long enough, typescript will truncate the the values we use to convert to XLR and we get an error thrown. It seems like our current approach of pulling that info from the Type object might need to be more robust. This branch has a failing test that can be used to validate the new approach works.

image

Generate Swift Structs/Protocols from XLRs

Using XLRs, it should be possible to generate basic Protocols/Structs from their originating Typescript types to remove manually having to create them. There are a few potential use cases for this:

  • Generating stubs for Swift Player Assets from their Typescript counterparts
  • Generating Swift structs/protocols for the types used in Core Player that need to be used in iOS Player.
  • Potentially stubbing out iOS Plugins from their Typescript counterparts (This may require enhancements in the XLR processor to handle Typescript classes)

[devtools] Android messenger

The dev tools plugins rely on Messenger to communicate.

Although it's agnostic about which API to send and listen to messages, this does not relate to the platform. The current implementation, written in TypeScript, aims for the browser.

We must generate a Messenger for Android that complies with the web counterpart.

Example of how we leverage Messenger on a web plugin here.

Decouple Expression LSP

  • Break up the Expression LSP into a core and language server implementation to decouple the two pieces.
  • Integrate the core into the JSON language service to allow validation on expressions at validation time.

Update LSP To Parse and Validate AsyncNodes

Background

Currently, any AsyncNode objects encountered in content won't be parsed as player specific node types as there is no definition for it in the LSP parser here nor logic in the parse function here that will create it as a specific node type. That means that it will just be treated as an ObjectASTNode. While this won't cause any content validation issues, it does mean that validation rules can't be written against AST Nodes. One such validation would be ensuring that all Async Nodes have unique IDs as that will cause issues at runtime. This would function similarly to the existing DuplicateIDPlugin here.

TO DO

  • Define an AsyncASTNode type
  • Update parsing logic to identify and create AsyncASTNodes
  • Create new 1st party validator to validate unique AST node id properties

Ephemeral Union/Intersection Types have `unknown` in the Description

When computing the intersection/union type, the resulting intermediate object is expected to look like:

{A.name} & {B.name} or {A.name} | {B.name}

However when an object literal is one of the types getting combined the resulting object will look like:

{A.name} & undefined or {A.name} | undefined

We should probably use something like "Object Literal" instead of undefined. The string is mostly just used to aid in validation messages to give an idea of where a validation issue is thrown and really isn't meant to be user facing so its mostly just a quality of life thing.

[devtools] iOS Messenger

The dev tools plugins rely on Messenger to communicate.

Although it's agnostic about which API to send and listen to messages, this does not relate to the platform. The current implementation, written in TypeScript, aims for the browser.

We must generate a Messenger for iOS that complies with the web counterpart.

Example of how we leverage Messenger on a web plugin here.

Helper Function for Transforms

A majority of transform functions are just visiting every node, checking if its a certain type, and doing some modification. Walking the tree from a starting node is something that we should make a function for so that a transform just has to supply a function to check if the transform is applicable and a function to do the actual replacement. This would cut down on code duplication and prevent some traversal mistakes.

TSConfig not loading in DSL validation

Describe the bug

The TSConfig loading mechanism in the DSL validate cli plugin doesn't use the built-in ts version and config isn't loaded properly.

To Reproduce

Run the validator using a local tsconfig.json using:

{
    "target": "esnext",
    "moduleResolution": "nodenext",
}

You'll get an error saying: Unexpected moduleResolution: nodenext

Expected behavior

The built-in ts.parseJsonConfigFileContent() method or similar is used to get a valid config

Cache Nodes During TS -> XLR Conversion

We should do some sort of caching during TS Node to XLR Node conversion process since, especially with the core Player types, there is a good chance that we reprocess some of the low level nodes / high level types. Performance is already ok so I would also want to make sure that there is a measurable impact to make the complexity worth it.

Provide More Information When an XLR Compilation Error is Thrown

When an issue is encountered when compiling an XLR, we generally provide information around what caused the error but we should also attach info around:

  • The identifier of the top level type where the error originated from to make it easy to track down the problematic type in the code base.
  • The TS source of the node where the error occurred to make it easy to diagnose the error at a glance.

Allow LSPAssetsPlugin to Load Assets from Module

Problem

Currently, the CLI's LSPAssetsPlugin plugin only allows users to specify a file path to load XLRs into the LSP. This requires some unfriendly initialization of the plugin when passing XLR enabled packages as you would need to do something like the below to initialize it:

new LSPAssetsPlugin({
        path: path.join(require.resolve('@player-ui/types'), '..')
      })

Given that the entrypoint for each module can be different, the added effort of finding how many levels to go up from the entrypoint to get to the xlr folder in the module may require some trial and error.

Proposed Solution

If we embrace subpath exports (which are supported back through node 14) to allow the manifest.js file in the generated XLR folder to be accessed via a subpath, the package author can easily expose the XLR location and the integration author can access it in a standard way without having to know how the original package is setup. Example:

In the XLR enabled library's package.json

...
"exports": {
    "./xlr": "./dist/xlr/manifest.js"
  },
...

In the CLI Preset of the integrating application

new LSPAssetsPlugin({
        path: require.resolve('@player-ui/types/xlr')
      })

Work to Do

  • Update Player's Bazel rules to generate a subpath export for XLR enabled packages
  • Update LSPAssetsPlugin to allow loading XLRs via Module or Make a new plugin for specifically loading XLRs via module

[@player-tools/json-language-service] DuplicateIdPlugin: Template Support

Is your feature request related to a problem? Please describe.

The existing DuplicateIdPlugin only errors for IDs that are hardcoded the same, content templates, or nested templates, may produce duplicate IDs in assets if the _indexN_ replacement is not used in the identifier.

Describe the solution you'd like

The DuplicateIdPlugin should throw errors if an ID in a template does not use the _indexN_ replacement in identifiers for template content.

Additional context

For nested templates, may need to ensure the ID contains the _indexN_ replacement for all the template levels above it

ObjectNode `extends` Property Not Cascaded Through

Scenario

Interface A extends a custom primitive
Interface B extends interface A

When exported, A will have the correct extends field but B (and any other interface C that extends B) will not have the correct extends information. That field needs to be cascaded up in the same way that generic tokens are.

Some Expressions Do Not Have Their Argument Names Exported

For functions that use withoutContext the compiler is used to infer the return type of the function since it can’t be statically analyzed. There are two ways the expression functions are written

export const size = withoutContext((val: unknown): number => {...}  

and

export const ceil = withoutContext<[number | string], number>((num) => {...} 

We get the argument names with the first syntax but not the second. I believe the error comes from the typescript compiler not properly tracking things when the return type is inferred. This is supported by hovering over those function in your editor and seeing the LSP suggestion. An easy workaround would be to just rewrite the functions in the first, more declarative manner but it should be something we should also try and fix in XLR if possible. We may be able to do something with the generics and mapping the types manually to the parameters of the function instead of the assumed TS type but I am not 100% sure how flexible that will be for other use cases.

[Async] Load Player async asset type in LSP to accept async assets for validation

Consume types done in player-ui/player#467 to power validation on Player content that contains an async asset:

{
  "id": "view",
  "type": "info",
  "title": {
    "id": "some-async-asset",
    "async": true
  }
}

Note that this is only targeting support for async assets. The base capability (AsyncNodePlugin) can support async nodes anywhere in the view AST, but the use cases have only been for asset-level async nodes. If use cases arise, we can look into fully featured validation support for any async node in the view AST.

[@player-tools/cli] Add more info on compilation failures

Feature request

It'd be beneficial to have the error stack logged on compilation errors here, so we can pinpoint where the syntax error occurred (given that it could be within an imported file).

Context

It could be challenging to determine where the error originated if you leverage barrels or flow import the .tsx files from elsewhere.

Example:

// index.ts
import { PLUGIN_ID } from "../constants";
import { navigation } from "./navigation";
import { schema } from "./schema";
import { views } from "./views";

const flow = {
  id: PLUGIN_ID,
  views,
  navigation,
  schema,
};

export default flow;

If there is an error on any of the views leveraged by the flow above, the error will point to the file being compiled:

Error compiling index.ts: Expected comma at character 26

Hopefully, the error stack trace can provide more info on which imported file is the culprit.

[devtools] add documentation for the generators

We just merged the generator for dev tools React plugins, but we still need the documentation on how to use it.
We could add a session to the README here and a recipe to the player-ui/player docs.

Export Custom Primitives in Manifest

It would be useful to know what custom primitives were used to generate XLRs to know a minimal set of the types that would be needed to fully fill in the tree. The manifest would be the appropriate place to put this information. Functionally This should be done in the CLI when writing the manifests out. My suggestion would be to make a top level metaData object with a primitives key that maps to an array of strings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.