Giter Club home page Giter Club logo

relay-compiler-language-typescript's Introduction

Obsolete

This repository is obsolete as relay@13 now supports TypeScript directly.

relay-compiler-language-typescript

Build Status

A language plugin for Relay that adds TypeScript support, including emitting type definitions.

Installation

Add the package to your dev dependencies:

yarn add graphql relay-compiler --dev
yarn add typescript relay-compiler-language-typescript --dev

Note: Starting with version 15.0.0 relay-compiler-language-typescript requires a minimum TypeScript version of 4.5.0 being installed in your project.

Configuration

relay-compiler

Then configure your relay-compiler script to use it, like so:

{
  "scripts": {
    "relay":
      "relay-compiler --src ./src --schema data/schema.graphql --language typescript --artifactDirectory ./src/__generated__"
  }
}

This is going to store all artifacts in a single directory, which you also need to instruct babel-plugin-relay to use in your .babelrc:

{
  "plugins": [["relay", { "artifactDirectory": "./src/__generated__" }]]
}

TypeScript

Also be sure to configure the TypeScript compiler to transpile to ES2015 modules (or higher) and leave transpilation to CommonJS modules (if required) up to Babel with the following tsconfig.json settings:

{
  "compilerOptions": {
    "module": "ES2015", // ES2015 or higher
    "target": "ES2020"  // best use the highest target setting compatible with your Babel setup
  }
}

The reason for this is that tsc would otherwise generate code where the imported graphql function is being namespaced (react_relay_1 in this example):

react_relay_1.createFragmentContainer(
  MyComponent,
  react_relay_1.graphql`
  ...
`
);

… which makes it impossible for babel-plugin-relay to find the locations where the graphql function is being used.

The generated code uses ES2015 module syntax if module is set to ES2015 or higher in your tsconfig.json. Note that the eagerESModules option from relay-compiler has no effect on the generated code if module is ES2015 or higher.

Custom Headers

If you need to add a custom header to generated files, perhaps for a custom linter or to get boilerplate license code in, that can be passed in also in compilerOptions as banner:

{
  "compilerOptions": {
    "banner": "/* © 2021 Example.org - @generated code */"
  }
}

Problems

React Hot Loader

React Hot Loader is known to not always work well with generated code such as our typing artifacts, which will lead to loading modules with TypeScript types into the browser and break. As a maintainer of RHL pointed out in a similar issue:

The problem - hot reloading is not "complete"

So until RHL will be made “complete” this project can’t gurantee to always work well with it, nor is it our control to do anything about that.

Also see

License

This package is available under the MIT license. See the included LICENSE file for details.

relay-compiler-language-typescript's People

Contributors

alloy avatar anotherhermit avatar artola avatar ashfurrow avatar dependabot-preview[bot] avatar dependabot[bot] avatar ds300 avatar fxone avatar jquense avatar kalekseev avatar kaolin avatar kastermester avatar koddsson avatar ktosiek avatar maraisr avatar martinandert avatar merrywhether avatar n1ru4l avatar nodkz avatar orta avatar renanmav avatar ro-savage avatar saihaj avatar sibelius avatar sorenhoyer avatar tgriesser avatar thicodes avatar timjacobi avatar wadamek65 avatar zephraph avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

relay-compiler-language-typescript's Issues

`getEnumDefinitions` with rare "%future added value"

For example, using github graphql schema.graphql:

"""The possible states of an issue."""
enum IssueState {
  """An issue that is still open"""
  OPEN

  """An issue that has been closed"""
  CLOSED
}

It is generated in the following type, containing an extra and rare "%future added value".

export type IssueState = "CLOSED" | "OPEN" | "%future added value";

Source code:

values.push("%future added value");

Has this extra entry in the alias some especial meaning? It seems error prone.

Figure out how to do scalar type mappings

Right now we transform non-standard scalar types to any.

It should be somewhat straight forward to allow this to be user configurable in such a way that a user can specify that Email should be a string etc.

This is just an issue to keep track of the idea - and to open up the discussion for possible implementation details.

Things to consider:

  • Should we just do a simple type name -> string config (ie {"Email": "string"}) or should we allow for more complex scenarios (ie. importing types from other modules which is then the actual type?)
  • Where do we configure this? Some static file, or?
  • Anything else?

Emitted types break default setup when colocating artefacts.

As reported by @ckknight https://twitter.com/ckknight/status/1026846806930468864, it appears that when one does not enable a single artefact directory –and thus fragment references get typed as any rather than being imported from other artefacts– TS is unable to work with the types:

Type 'any' is not assignable to type 'unique symbol'.

I haven’t yet been able to find any issues on the TS issue tracker about this, so unsure right now how to proceed.

Maybe we should not emit the fragment reference typings when not using the single artefact directory feature, because those typings are moot in that case anyways?

Type errors in example app

ts/__generated__/appQuery.graphql.ts(3,10): error TS2305: Module '"/Users/eloy/Code/React/typescript-relay-modern-compiler/example/node_modules/@types/relay-runtime/index"' has no exported member 'ConcreteRequest'.

3 import { ConcreteRequest } from 'relay-runtime';
           ~~~~~~~~~~~~~~~


ts/components/__generated__/TodoApp_viewer.graphql.ts(4,10): error TS2305: Module '"/Users/eloy/Code/React/typescript-relay-modern-compiler/example/node_modules/@types/relay-runtime/index"' has no exported member 'FragmentReference'.

4 import { FragmentReference } from "relay-runtime";
           ~~~~~~~~~~~~~~~~~


ts/__generated__/appQuery.graphql.ts(8,33): error TS2304: Cannot find name 'TodoApp_viewer_ref'.

8         readonly " $fragments": TodoApp_viewer_ref;
                                  ~~~~~~~~~~~~~~~~~~


ts/app.tsx(74,25): error TS2322: Type '{ viewer: any; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Type '{ viewer: any; }' is not assignable to type 'Props'.
    Property 'relay' is missing in type '{ viewer: any; }'.

74         return <TodoApp viewer={props.viewer} />;
                           ~~~~~~~~~~~~~~~~~~~~~


ts/components/TodoApp.tsx(56,21): error TS2322: Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'Props'.
    Property 'relay' is missing in type '{ viewer: TodoApp_viewer; }'.

56           <TodoList viewer={this.props.viewer} />
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~


ts/components/TodoApp.tsx(57,40): error TS2322: Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'Props'.
    Property 'relay' is missing in type '{ viewer: TodoApp_viewer; }'.

57           {hasTodos && <TodoListFooter viewer={this.props.viewer} />}
                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~


ts/components/TodoList.tsx(49,9): error TS2322: Type '{ key: string; todo: { readonly id: string; readonly complete: boolean | null; readonly " $fragme...' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Type '{ key: string; todo: { readonly id: string; readonly complete: boolean | null; readonly " $fragme...' is not assignable to type 'Props'.
    Property 'relay' is missing in type '{ key: string; todo: { readonly id: string; readonly complete: boolean | null; readonly " $fragme...'.

49         key={node.id}
           ~~~~~~~~~~~~~50         todo={node}
   ~~~~~~~~~~~~~~~~~~~51         viewer={this.props.viewer}
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


ts/components/__generated__/TodoApp_viewer.graphql.ts(10,29): error TS2304: Cannot find name 'TodoListFooter_viewer_ref'.

10     readonly " $fragments": TodoListFooter_viewer_ref & TodoList_viewer_ref;
                               ~~~~~~~~~~~~~~~~~~~~~~~~~


ts/components/__generated__/TodoApp_viewer.graphql.ts(10,57): error TS2304: Cannot find name 'TodoList_viewer_ref'.

10     readonly " $fragments": TodoListFooter_viewer_ref & TodoList_viewer_ref;
                                                           ~~~~~~~~~~~~~~~~~~~


ts/components/__generated__/TodoList_viewer.graphql.ts(13,45): error TS2304: Cannot find name 'Todo_todo_ref'.

13                     readonly " $fragments": Todo_todo_ref;
                                               ~~~~~~~~~~~~~


ts/components/__generated__/TodoList_viewer.graphql.ts(20,29): error TS2304: Cannot find name 'Todo_viewer_ref'.

20     readonly " $fragments": Todo_viewer_ref;
                               ~~~~~~~~~~~~~~~

Relay 2: Cannot find module 'graphql-compiler'

relay-compiler --src . --include 'components/**' 'pages/**' --schema 'api/schema.graphql' --language typescript --artifactDirectory 'generated'

Error: Cannot find module 'graphql-compiler'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/Users/steida/dev/este/node_modules/relay-compiler-language-typescript/lib/TypeScriptGenerator.js:21:23)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)

Not compatible with @types/relay-runtime 1.3.9

I don't know whether it's broken because of @types/relay-runtime 1.3.9 (1.3.8 works) or generated types are obsolete.

generated/AppQuery.graphql.ts:96:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string; "defaultValue": null; }[]; "selections": ({ "kind": string; ... 4 more ...; "selections"?: undefined; } | { ...; } | { ...; })[]; }; "operation": ...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

96 const node: ConcreteRequest = (function(){
         ~~~~

generated/CreateWebMutation.graphql.ts:43:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string; "defaultValue": null; }[]; "selections": { "kind": string; "alias": null; ... 5 more ...; "selections": { ...; }[]; }[]; }; "operation": { ...; };...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

43 const node: ConcreteRequest = (function(){
         ~~~~

generated/DeleteWebMutation.graphql.ts:36:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string; "defaultValue": null; }[]; "selections": { "kind": string; "alias": null; ... 5 more ...; "selections": { ...; }[]; }[]; }; "operation": { ...; };...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

36 const node: ConcreteRequest = (function(){
         ~~~~

generated/SetUserThemeMutation.graphql.ts:37:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string;"defaultValue": null; }[]; "selections": { "kind": string; "alias": null; ... 5 more ...; "selections": { ...; }[]; }[]; }; "operation": { ...; };...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

37 const node: ConcreteRequest = (function(){
         ~~~~

generated/signinMutation.graphql.ts:44:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string; "defaultValue": null; }[]; "selections": { "kind": string; "alias": null; ... 5 more ...; "selections": ({ ...; } | { ...; })[]; }[]; }; "operatio...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

44 const node: ConcreteRequest = (function(){
         ~~~~

generated/webMutation.graphql.ts:46:7 - error TS2739: Type '{ "kind": string; "fragment": { "kind": string; "name": string; "type": string; "metadata": null; "argumentDefinitions": { "kind": string; "name": string; "type": string; "defaultValue": null; }[]; "selections": { "kind": string; "alias": null; ... 5 more ...; "selections": { ...; }[]; }[]; }; "operation": { ...; };...' is missing the following properties from type 'ConcreteRequest': operationKind, name, id, text, metadata

46 const node: ConcreteRequest = (function(){
         ~~~~

pages/_app.tsx:67:49 - error TS2339: Property 'text' does not exist on type 'RequestNode'.
  Property 'text' does not exist on type 'ConcreteBatchRequest'.

67         body: JSON.stringify({ query: operation.text, variables }),

Related este/este#1642

Regarding runtime support

I forgot to reply to your comments regarding runtime transformation.

My idea regarding transforming the typescript code (converting graphql tagged template literals into require's) was simply that if we could create a single typescript transformer to handle both relay modern and relay classic (in pure classic or in compat mode) it would be much easier to set up a Relay project using TypeScript. I would like to get the experience regarding this into a state where one simply installs a plugin for the relay-compiler and a typescript transformer and then configures the way the typescript code is compiled and then moves along.

However, this is obviously something that needs to happen after we've gotten the relay-compiler stuff working.

React Hot Loader can't load generated artifacts

Hi @alloy, thanks for the project.
I've tried it with my project and I get the following error when I use webpack-dev-server with react hot loader:
screenshot from 2018-09-06 00-16-38
This error happen on page refresh, on HMR the page renders without such problems.
I would appreciate any ideas how that can be mitigated.

Can we make fragment reference related properties optional?

For those that test their Relay containers by manually stubbing data, it would be nice to have the fragment reference related properties be optional so that those don’t need to be specified.

I don’t recall the exact mechanics of the future fragment reference support when TS 2.8 comes out, but would an alternative option be to somehow use a union, so that either the exact data or a correct fragment reference can be passed in?

const enum foo$ref { }

interface Props {
	bar: string
}

function foo(x: Props | { " $refType": foo$ref }) { }

foo({ bar: "bar" })
foo({ " $refType": ({} as any) as foo$ref })

Helper types for the component props

This is just me shoving ideas out of my head, we don’t need this for initial release.

I’d like to improve on the experience on this when writing components, ie. having to import the fragment types and making sure you use the right ones, even when adding new properties seem... like not a great experience to me.

I’ve been thinking about this, and so far I’ve come to the conclusion that creating a d.ts file as part of the plugin run which could declare a bunch of types usable throughout ones entire codebase might be helpful. Ie. if we can create a type MyComponentFragmentContainerProps<TProps> (better name needed) which more or less does the opposite of the types we need for the definitelytyped repo, ie takes a type object of non relay props and returns a new type containing all that + the fragment types and then the relay prop. We’d probably need different types for the 3 different kind of containers due to differences in the relay prop.

I’m not entirely sure if this is doable without adding more support in the relay compiler itself or not, but if any is needed it shouldn’t be that much, and I’m sure we could make something flow users can use as well.

Let me know if I need to elaborate (I’m typing this from my iPad atm) the ideas, or if you have different ideas for making this nicer.

symbol breaks on pass-through colocation

First & foremost, THANK YOU. The amount of work that you've put into making this a reality is no short of monumental & it's amazing! My app is a hot mess of JS, Flow, and TS and this plugin handles it all with ease.

I've been using it for about a week and there's just one thing I can't seem to do:

I've got a fragment like this:

fragment Foo_item on Item {
  ...Bar_item
  id
}

I tried writing something like this: <Bar item={item}/>

i got this:

TS2322: Type 'Foo_item' is not assignable to type 'Bar_item'.
  Types of property '" $refType"' are incompatible.
  Type 'typeof _Foo_item$ref' is not assignable to type 'typeof _Bar_item$ref'.

I tried running the example (used npm pack and updated the example version to 1.0.1) to make sure i wasn't crazy & i got this:

Error:(56, 21) TS2322: Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'IntrinsicAttributes & Pick<Props & { relay: never; }, "viewer"> & ComponentRef & { children?: Rea...'.
  Type '{ viewer: TodoApp_viewer; }' is not assignable to type 'Pick<Props & { relay: never; }, "viewer">'.
    Types of property 'viewer' are incompatible.
      Type 'TodoApp_viewer' is not assignable to type 'TodoList_viewer'.
        Property 'todos' is missing in type 'TodoApp_viewer'.

Seems related to #58, although just like the example I've got all my artifacts in a single folder.
FWIW I wouldn't mind if the symbol was removed from the types. I use relay with storybook & if the symbol were removed then I wouldn't have to cast my mock input data to the appropriate type.

Potential language server changes

Reading through the changelog of VS Code 1.20 i found this:

Spaces got you down? When you type ., VS Code now shows all known properties for JavaScript and TypeScript, even if a property name contain whitespaces or other non-identifier characters.

It seems we need a new way to deal with hiding members other than simply prefixing a whitespace. I'm not sure if it is possible to use symbols or something similiar to accomplish this?

Support --noImplicitAny

I'm using --noImplicitAny, and I can't compile when I include the generated mutation files.
Is there a way to add the required : any and as any annotations to the generated files?

E.g.

const node: ConcreteRequest = (function(){
var v0: any = [],
v1: any = [...];
return {
  "kind": "Request",
   ...
} as any)();

Thanks for the efforts

Cannot Parse `.js` Files

Hi there!

Bug: I get the following error when running

relay-compiler --src ./client --schema server/graphql/schema.graphql --language typescript --artifactDirectory ./client/__generated__

ERROR:
GraphQLCompilerContext: Unknown document `ProductListItem_product`.

When I console log this._documents in GraphQLCompilerContext._get when using the npm command with the language plugin I get a list of documents that do not include the missing fragment.

documents OrderedMap { "SignUpSignInForm_user": [object Object], "AddressBookItemStreet_address": [object Object], "Step4Payment_user": [object Object], "CorporatePageDiscountsAvailable_Query": [object Object], "RecentPostTile_blogPost": [object Object], "Step3GiftingOptions_cart": [object Object], "TestingQueryRendererTestQuery_Query": [object Object], "TestComponent_user": [object Object], "GuestSignUpStep_user": [object Object], "PaymentForm_user": [object Object], "BlogPostTile_blogPost": [object Object], "BlogPageRefetchQuery": [object Object], "BlogPage_viewer": [object Object], "CorporatePage_viewer": [object Object], "BlogPostPageRefetchQuery": [object Object], "BlogPostPage_viewer": [object Object], "CheckoutStepper_viewer": [object Object], "CorporatePageBestSellers_Query": [object Object], "RecentPosts_viewer": [object Object], "BecomeACeoPage_viewer": [object Object], "WeddingsPage_viewer": [object Object], "AddressBookItemName_address": [object Object], "HostATastingPage_viewer": [object Object] }

If I run the regular npm command

relay-compiler --src ./client --schema server/graphql/schema.graphql --extensions js ts tsx

then I get a much larger list of documents

{ "NextAndPrevButtonsMainQuery": [object Object], "App_Query": [object Object], "AddressBookEditMutation": [object Object], "ProductTIAT_Query": [object Object], "BlogPostPage_Query": [object Object], "BlogPage_Query": [object Object], "UserLogoutMutation": [object Object], "ProductReviewUpdateMutation": [object Object], "ThisIsATreePage_Query": [object Object], "CartDeleteMutation": [object Object], "WishListDeleteMutation": [object Object], "CartUpdateShippingAddressMutation": [object Object], "ProductReviewDeleteMutation": [object Object], "AuthDialogRefetchQuery": [object Object], "AddressValidationMutation": [object Object], "CorporatePageDiscountsAvailable_Query": [object Object], "UserRecoverPasswordMutation": [object Object], "CartUpdateGiftReceiptMutation": [object Object], "OrderAddMutation": [object Object], "CartUpdateBillingInfoMutation": [object Object], "ReferralCodeLookupRefetchQuery": [object Object], "ProductReviewAddMutation": [object Object], "DisconnectSSOaccountMutation": [object Object], "WishListAddMutation": [object Object], "CartAddMutation": [object Object], "CartUpdateTaxRateMutation": [object Object], "AppComponentRefetchQuery": [object Object], "ProductDetailsPageRefetchQuery": [object Object], "CartUpdateShippingCostsAndTaxRateMutation": [object Object], "TestingQueryRendererTestQuery_Query": [object Object], "AddressBookAddMutation": [object Object], "CartDeleteTaxRatesMutation": [object Object], "CreateConciergeRequestMutation": [object Object], "CartPromoCodeDeleteMutation": [object Object], "UserSetDefaultPaymentMutation": [object Object], "UserSetDefaultShippingAddressMutation": [object Object], "ShopLandingPage_Query": [object Object], "ReferralCodeGenerate_Query": [object Object], "CorporateGiftingSendFormMutation": [object Object], "CartPromoCodeAutoAddMutation": [object Object], "UserLoginMutation": [object Object], "UserUpdateInfoMutation": [object Object], "queries_WeddingsPage_Query": [object Object], "queries_ReturnPage_Query": [object Object], "queries_FaqPage_Query": [object Object], "queries_PrivacyPolicyPage_Query": [object Object], "queries_PaymentsPage_Query": [object Object], "queries_AddressesPage_Query": [object Object], "queries_FavoritesPage_Query": [object Object], "queries_OrdersPage_Query": [object Object], "queries_MyAccountPage_Query": [object Object], "queries_ResetPasswordPage_Query": [object Object], "queries_ReceiptPage_Query": [object Object], "RegisterMutation": [object Object], "UserResetPasswordMutation": [object Object], "BlogPageRefetchQuery": [object Object], "CartUpdateShippingInfoAndTaxRateMutation": [object Object], "ProductsCatalogRefetchQuery": [object Object], "BlogPostPageRefetchQuery": [object Object], "CorporatePage_Query": [object Object], "BecomeACeoPage_Query": [object Object], "CeoSignUpFormMutation": [object Object], "OrdersPageRefetchQuery": [object Object], "OrderCancelMutation": [object Object], "CartDeleteShippingCostsMutation": [object Object], "StripePaymentAddMutation": [object Object], "ReferralCodeLookup_Query": [object Object], "CartUpdateGiftMessageMutation": [object Object], "HostATastingFormMutation": [object Object], "CartUpdateShippingCostsMutation": [object Object], "Checkout_Query": [object Object], "CartUpdateRecipientBirthDateMutation": [object Object], "HomePageRefetchQuery": [object Object], "CartDeleteEverythingMutation": [object Object], "CartUpdatePromoCodesMutation": [object Object], "CorporatePageBestSellers_Query": [object Object], "ProductCatalog_Query": [object Object], "HostATastingPage_Query": [object Object], "BuyAgainButtonContainerQuery": [object Object], "CartAddBulkMutation": [object Object], "ProductDetails_Query": [object Object], "CartUpdateShippingInfoMutation": [object Object], "HomePage_Query": [object Object], "AuthDialog_user": [object Object], "ProductListItem_product": [object Object], "HomePage_viewer": [object Object], "SignUpSignInForm_user": [object Object], "GuestSignUpStep_user": [object Object], "SelectShippingMethod_user": [object Object], "AddressBookItemStreet_address": [object Object], "AddressBookItemName_address": [object Object], "AddressBookItemText_address": [object Object], "AddressBookItemTextMobile_address": [object Object], "AddressBookItem_address": [object Object], "AccountAddressBook_user": [object Object], "AccountAddAddressDialog_user": [object Object], "SelectShippingMethod_cart": [object Object], "AccountShippingForm_user": [object Object], "AddressForm_user": [object Object], "AddressForm_cart": [object Object], "ShippingForm_user": [object Object], "ShippingCompletedView_cart": [object Object], "Step2Shipping_user": [object Object], "SummaryPromoCode_cart": [object Object], "GuestPaymentView_user": [object Object], "AccountAddAddressForm_user": [object Object], "EditPaymentDialogContent_user": [object Object], "AccountEditPaymentDialog_user": [object Object], "AccountAddPaymentDialog_user": [object Object], "EditPaymentInformation_stripePayment": [object Object], "EditPaymentDialogContent_stripePayment": [object Object], "AccountEditPaymentDialog_stripePayment": [object Object], "StripePaymentV2_stripePayment": [object Object], "StripePaymentCollectionV2_stripePaymentCollection": [object Object], "SelectedStripePayment_stripePaymentCollection": [object Object], "AccountPaymentView_user": [object Object], "PaymentForm_user": [object Object], "Step4Payment_user": [object Object], "CartEntry_cartEntry": [object Object], "ReviewProductList_user": [object Object], "GiftMessageDialog_cart": [object Object], "GiftMessageReview_cart": [object Object], "ReviewForm_user": [object Object], "Step5Review_user": [object Object], "AlcoholForm_cart": [object Object], "StepAlcoholDOB_cart": [object Object], "GiftingOptionsForm_cart": [object Object], "GiftingCompletedView_cart": [object Object], "Step3GiftingOptions_cart": [object Object], "CheckoutStepper_viewer": [object Object], "SummaryPanel_viewer": [object Object], "Checkout_viewer": [object Object], "NavbarComponent_viewer": [object Object], "ShopLeftNavComponent_viewer": [object Object], "OrderItem_order": [object Object], "Cart_viewer": [object Object], "CartRightNavComponent_viewer": [object Object], "ProductDetailPurchaseInfo_product": [object Object], "ProductDetailsInfo_product": [object Object], "ProductReviewComment_productReview": [object Object], "ProductDetailsPage_viewer": [object Object], "AppComponent_viewer": [object Object], "RecentPostTile_blogPost": [object Object], "RecentPosts_viewer": [object Object], "BlogPostPage_viewer_20J5Pl": [object Object], "BlogPostTile_blogPost": [object Object], "BlogPage_viewer_1G22uz": [object Object], "ThisIsATreePage_viewer": [object Object], "AuthDialog_user_20e7Da": [object Object], "ReferralCodeLookup_viewer_1KiJL6": [object Object], "ProductDetailsPage_viewer_1iVCTk": [object Object], "TestComponent_user": [object Object], "ShopLandingPage_viewer": [object Object], "ReferralCodeGenerate_viewer": [object Object], "WeddingsPage_viewer": [object Object], "ReturnPage_viewer": [object Object], "FaqPage_viewer": [object Object], "PrivacyPolicyPage_viewer": [object Object], "PaymentsPage_viewer": [object Object], "AddressesPage_viewer": [object Object], "FavoritesPage_viewer": [object Object], "OrderItem_cart": [object Object], "OrdersPage_viewer": [object Object], "MyAccountPage_viewer": [object Object], "ResetPasswordPage_viewer": [object Object], "ReceiptPage_viewer_xeX6W": [object Object], "ProductsCatalog_viewer_4muyEu": [object Object], "CorporatePage_viewer": [object Object], "BecomeACeoPage_viewer": [object Object], "OrdersPage_viewer_3Qq0NA": [object Object], "HostATastingPage_viewer": [object Object], "BuyAgainButton_product": [object Object], "ProductDetailsPage_viewer_3VRWUf": [object Object] }

The strange part is that if I wipe node_modules, and then run the regular command, it will not emit the artifacts because it cannot read .tsx. But if I run the language plugin command (which will fail and give the Unknown Document error), and then run the regular command, then the artifacts are created.

I've attempted to make a project to reproduce this error, but I haven't had luck reproducing it.

Any thoughts on what it could be?

Thanks!

Include `devOnlyAssignments` in the generated module

It would be nice to be able to use devOnlyAssignments (https://github.com/facebook/relay/blob/f8585ab4f90f2e707d5555c9f7b423de3ea553bd/packages/relay-compiler/language/RelayLanguagePluginInterface.js#L176) to provide the text in dev when using persisted queries.

With my current setup it would make working non-local backends easier since there is no need to upload persisted queries every time queries change when developing.

I was able to hack my local version to produce this:

if (__DEV__) {
  (node as any).params.text = "query ...";
}

I guess we could add a flag to enable this and configure the if dev check or maybe just use process.env.NODE_ENV.

graphql: Unexpected invocation at runtime

Hi,

I cannot seem to get the Babel transform running on my generated typescript code. Perhaps you can shed some light on what I am doing wrong. Both relay-compiler and webpack-dev-server start up fine without any errors, generated .graphql.ts files show up in my artifact directory, but in browser console I get

Uncaught Error: graphql: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site`

Using v1.5.0-plugin.5 from alloy/relay. I run webpack with webpack-dev-server, this is how I run my compiler:

relay-compiler --src ./src --artifactDirectory ./__generated__ --schema ../schema.graphql --language=typescript

This is my .babelrc

{
  "plugins": [
    ["relay", { "artifactDirectory": "./__generated__" }]
  ]
}

I have this in my webpack config:

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                exclude: /node_modules/,
                use: [
                    { loader: 'babel-loader' },
                    { loader: 'ts-loader', options: { transpileOnly: true } },
                ],
            },
        ],
    },

Relevant packages:

    "react-relay": "https://github.com/alloy/relay/releases/download/v1.5.0-plugin.5/react-relay-1.5.0-plugin.5.tgz",
    "relay-compiler": "https://github.com/alloy/relay/releases/download/v1.5.0-plugin.5/relay-compiler-1.5.0-plugin.5.tgz",
    "relay-runtime": "https://github.com/alloy/relay/releases/download/v1.5.0-plugin.5/relay-runtime-1.5.0-plugin.5.tgz",
    "babel-plugin-relay": "https://github.com/alloy/relay/releases/download/v1.5.0-plugin.5/babel-plugin-relay-1.5.0-plugin.5.tgz",
    "relay-compiler-language-typescript": "0.9.0",
    "webpack": "4.2.0",
    "webpack-cli": "2.0.13",
    "webpack-dev-server": "3.1.1"
    "ts-loader": "4.1.0",
    "ts-node": "4.1.0",

Any help would be greatly appreciated. Thanks!

Make repo public?

Is there a reason to keep this private? I’ve already ran into a few situations where I may, for instance, want to CC one of the Relay team members.

Emit separate interfaces for each type and its selections

Often we need to have a reference to a type that’s being used somewhere deeper into a fragment’s query. For instance, consider this fragment’s typings:

export type ArtworkSidebarArtists_artwork = {
    readonly artists: ReadonlyArray<({
        readonly name: string | null;
        readonly href: string | null;
    }) | null> | null;
};

To some functions we end up passing a single element of the artists array, so currently in our code we do the following:

type Artist = ArtworkSidebarArtists_artwork["artists"][0]

It would be easy to emit the following artefact instead:

export type Artist = {
    readonly name: string | null;
    readonly href: string | null;
};

export type ArtworkSidebarArtists_artwork = {
    readonly artists: ReadonlyArray<Artist | null> | null;
};

The only situation I imagine where it gets more complex is around naming the types when you have multiple selections on the same type in a single fragment. For instance, let’s say we had the following fragment typing:

export type ArtworkSidebarArtists_artwork = {
    readonly artists: ReadonlyArray<({
        readonly name: string | null;
        readonly related_artists: ReadonlyArray<({
            href: string | null;
        }) | null> | null;
    }) | null> | null;
};

In this case we can’t just call the type Artist, because we have to differentiate between the artwork’s artist and the artists related to the artwork’s artist.

Encoding the path into the name of the type (e.g. ArtworkSidebarArtists_artwork_artists_related_artists_Artist) would be counter-productive, as in that case you could just as well use plain TS code to get the type reference (e.g. ArtworkSidebarArtists_artwork["artists"][0]["related_artists"][0]).

Maybe this is enough of an edge-case that we simply don’t emit named typings for such situations at all, which could instead encourage people to refactor that nested part of the query into a container/fragment of its own?

artifactDirectory command not working

My project compiles the typescript files in the src folder and writes it to a outputs folder.

It always generates the __generated__ folder inside my src folder, I may be wrong but I thought the artifactDirectory should be used to specify on where everything should be written to.

Here is my yarn relay:
"relay": "relay-compiler --src ./src --schema schema.graphql --extensions=tsx --extensions=ts --language typescript --artifactDirectory ./outputs/__generated__",

My .babelrc:

...
"plugins": [
    "@babel/plugin-transform-modules-commonjs",
    ["relay", { "artifactDirectory": "./outputs/__generated__" }]
  ]

I am using:

"react-relay": "^1.6.2",
 "relay-runtime": "1.7.0-rc.1"
"babel-plugin-relay": "^1.6.2",
"relay-compiler": "^1.6.2",
 "relay-compiler-language-typescript": "^1.1.1",

The __generated__ is always compiled at src/__generated__ and so the app doesn't start.

Am I missing something?

types nested under interface always marked as optional

OK bear with me on this one: All Animals make noise. A Dog is an Animal. A Bark is the kind of Noise a Dog makes.

IDL:

interface Animal {
  id: ID
  noise: Noise!
}
interface Noise {
  name: String!
}
type Dog implements Animal {
  id: ID
  noise: Bark!
}
type Bark implements Noise {
  name: String!
}

fragment:

animal {
  ... on Dog {
    noise {
    ... on Bark {
        name
      }
    }
  }
}

artifact:

readonly animal: ({
  readonly noise?: {
    readonly name: string;
  };
})

I believe it's a bug that noise is marked as optional here. Noise is guaranteed for all Animals, and therefore all Dogs (graphql forces all sub-type to be sub-classed & to have matching nullability).

This seems very close to #64, but it's a little nuanced since it only crops up when 2 interfaces are used.
Reproduction branch is here: https://github.com/mattkrick/relay-compiler-language-typescript/tree/double-int-null/example

Simple test script

To save you the hassle of running what is currently in this repo, here's a simple test script:

#!/bin/bash
git clone [email protected]:kastermester/relay
cd relay
git checkout configurable-artifact-extensions
npm install && npm run build
cd dist/relay-runtime && npm pack && mv relay-runtime-1.4.1.tgz ..
cd ../relay-compiler && npm pack && mv relay-compiler-1.4.1.tgz ..
cd ../../..
git clone [email protected]:kastermester/typescript-relay-modern-compiler
cd typescript-relay-modern-compiler
npm install && npm install ../relay/dist/relay-compiler-1.4.1.tgz
npm run build && npm test

I suggest that I simply create a new repo with the new code (including tests) once we've fully determined the exact approach we're gonna take with implementing the plugin, and then we can simply leave this as a place for discussion the more general decisions. I'm really looking forward to getting this working :)

handling null from store.delete

  • Say I have a Menu: [Dessert!]!
  • I get back [{id: 'cakes'}, {id: 'pies'}] from the server
  • then in my updater, i call store.delete('cakes')
  • Now I have [null, {id: 'pies'}] even though my typing says Dessert is guaranteed

how do you guys handle this?
is there some secret way to clean up all arrays & connections outside of the view layer?
should the type always list a possible null?

Not working with CreateReactApp

So, I'm trying to get this working with CreateReactApp and running into some issues.

Typescript is complaining about the graphql.ts artifacts, lots of errors like this:

image

Given that this is a CreateReactApp which hasn't been ejected, I had to make these exceptions to these instructions:

I'm still compiling the artifacts into the subfolders rather than the root directory because CreateReactApp doesn't allow .babelrc.

package.json:

"relay": "relay-compiler --src ./src --schema ./../components/api/app/assets/javascripts/api/relay/schema.json --language typescript",

tsconfig.json:

{
  "compilerOptions": {
    "target": "es2015",
    "module": "esnext", // CreateReactApp won't let me change this
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve"
  },
  "include": [
    "src"
  ]
}

Hoping to find a workaround without ejecting my app; any insight into what causes these errors?

Use in TS-package with module: commonjs

@alloy I have been fiddling around for several hours as I need to incorporate Relay in a module that is currently compiled with TS to a commonjs-module.

The result is that then the babel-relay-transform does not work. Changing to es2015 module fixes that part but breaks the interaction with other modules. I changed my babelrc to apply "transform-es2015-modules-commonjs" after the relay-transform, but that does not fix the issue.

Do you have any experience with this issue? I know this is not an issue directly related to this library, but I was thinking it was worth asking as I would assume it could also be an issue other people with experience. Feel free to just close this issue if it does not belong here.

Support Relay v2.0.0

Hi there,

At the time of writing this issue, Relay is on 1.7.0-rc.1, so it is a little early to fix.

First Problem

So I'm testing out the latest master branch of FB with persisted queries, and I'm running into the following error

> relay-compiler --src ./client --schema server/graphql/schema.graphql --extensions=js --extensions=tsx --extensions=ts --language typescript --persist --persist-output ./server/queryMap.json

HINT: pass --watch to keep watching for changes.

Writing ts
ERROR:
Error writing modules:
TypeError: Cannot read property 'indexOf' of undefined
    at /node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:93:73
    at Array.filter (<anonymous>)
    at transformNonNullableInputType (/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:93:14)
    at Object.transformInputType (/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:62:16)
    at /node_modules/relay-compiler-language-typescript/lib/TypeScriptGenerator.js:296:82
    at Array.map (<anonymous>)
    at generateInputVariablesType (/node_modules/relay-compiler-language-typescript/lib/TypeScriptGenerator.js:295:99)
    at Object.Root (/node_modules/relay-compiler-language-typescript/lib/TypeScriptGenerator.js:174:42)
    at Object.visit (/node_modules/graphql/language/visitor.js:254:26)
    at Object.visitIR [as visit] (/node_modules/graphql-compiler/lib/GraphQLIRVisitor.js:32:29)

Seems to be related to this line:
https://github.com/relay-tools/relay-compiler-language-typescript/blob/master/src/TypeScriptTypeTransformers.ts#L137

When I console.log state, the shape is now

{
  customScalars: {},
  existingFragmentNames: {},
  generatedInputObjectTypes: { DonationUpdateInput: 'pending' },
  generatedFragments: {},
  usedEnums: {},
  usedFragments: {},
  useHaste: false,
  useSingleArtifactDirectory: false,
};

Where DonationUpdateInput is a GraphQL Mutation Input.

It seems like inputFieldWhiteList is no longer a part of TypeGeneratorOptions

https://github.com/facebook/relay/blob/4343e80b48ad21d7bc40b57abdcb9acb751c45b3/packages/relay-compiler/language/RelayLanguagePluginInterface.js#L173

Because it was renamed to optionalInputFields

facebook/relay@1755b04

Renaming all instances of inputFieldWhiteList to optionalInputFields fixed it for me.

You can check out the changes here: ONEHOPEWINE@120f447

Second Problem

After applying the above fix, only Queries (that are used for the third parameter for createRefetchContainer) and Mutations are able to be parsed. All other fragments are not parsed, which includes the second parameter of RefetchContainer & createFragmentContainer, where a GQL query is a value to a key that is a React prop name. Not sure how to go forward from here.

Build files for persisted queries if you are curious. It requires React 16.5.2 because RelayContainer hooks into React.context.unstable_read. Its currently breaking for my use case because we use found-relay, which mutates the Relay context, and it seems like the Relay team are migrating to the new React.context API: https://github.com/ONEHOPEWINE/relay/releases/tag/1.7.1-rc.1

Test coverage

From https://github.com/alloy/relay/pull/5#issuecomment-358279558

I think as soon as we have something running in the repo that sort of works - we should look into porting as many tests as possible from the relay-compiler repo - I'm just not sure where to start with that.

I don’t think we really need to do too much. Having a bunch of input/output tests like the ones merged in #4 and maybe some extra unit tests around the GraphQL tag finding aspect would probably be enough imo.

Are there specifics you were thinking of that need extra testing?

CI setup

Once we can npm install without all this manual npm pack stuff I think we should look into setting up some CI stuff :)

TSLint and Prettier

Just adding this issue to remind ourselves to get this added.

I attempted to do this earlier, but given that I still cannot install stuff with our lock-file, yarn shouted in my face.

Release new package compatible with Relay v2

If I try to update to Relay v2, still using v1.1.1 of this package, I get and error in TypeScriptTypeTransformers regarding the breaking change inputFieldWhiteList => optionalInputFields.
This code was fixed in master #78, but not released as a new npm package.
Is it possible?

Check-in generated artifacts of example app?

It might be nice for people to be able to quickly see real world artefacts and also for us to update those along with plugin changes so that we can review this besides any other tests. What do you think?

Example missing dependency

When cloning the repo and attempting to run example for the first time this error appears:

example [master●] % yarn install
yarn install v1.3.2
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
error "../relay-compiler-language-typescript-1.0.0-alpha.6.tgz": Tarball is not in network and can not be located in cache (["/Users/damassi/Sites/github/relay-compiler-language-typescript/relay-compiler-language-typescript-1.0.0-alpha.6.tgz","/Users/damassi/Library/Caches/Yarn/v1/npm-relay-compiler-language-typescript-1.0.0-alpha.6-471eb1864600c1c97656e50bff8e6bd66de607ef/.yarn-tarball.tgz"])
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

It seems like yarn pack needs to be run in the root so that it's picked up by package.json, but when attempting to run that command it outputs the wrong version:

relay-compiler-language-typescript [master●] % yarn pack
yarn pack v1.3.2
success Wrote tarball to "/Users/damassi/Sites/github/relay-compiler-language-typescript/relay-compiler-language-typescript-v0.9.0.tgz".
✨  Done in 0.13s.

(v0.9.0.tgz)

Implementation language

As we discussed there's some options here:

1 Write in flow
2 Write in TS
3 A mix of the two. I'm thinking here that maintaining d.ts files for the GraphQLIR types is actually quite simple, it's almost a direct copy/paste from the official repo's flow types. This way we can implement in TS (and the remaining bits in flow)

  • Code that will be passed the raw TS source and return DocumentNode[] from the graphql package.
  • Code that will be passed GraphQLIR (and possibly a few other options) and return the TypeScript type definitions as text.

If we can get the flow definitions for the relay-compiler package into flow - I'm actually thinking the 3rd approach might be the best way forward? It would allow us to not rely on too many handwritten typings and let each language do what they do best (in this regard).

Import fragment references

Facebook internally uses the Haste module system, which makes imports work without having to specify the directory where the module resides. This makes it naturally resistant against issues such as moving files around.

Here’s the maintained OSS version of Haste that’s used by Jest https://github.com/facebook/jest/tree/master/packages/jest-haste-map. I have never used it before, so not sure if we can easily use it for our needs, but I assume it would require a custom Babel plugin that would take a persisted map and rewrites imports at compile time.

Issue with Nested Fragment Containers

First - Thanks for all your work on this ❤️

I'm running into an issue with nested Fragment Containers and types after updating to 1.1.0.

My components are like this:

QueryRenderer
  FragmentContainerOne
    ...
    FragmentContainerTwo

My query contains both fragments:

query ContainerQuery() {
  foo {
    ...FragmentContainerOne_foo        
  }
  bar {
    ...FragmentContainerTwo_bar
  }
}

FragmentContainerOne works fine and has the following Props:

interface Props {
  foo: FragmentContainerOne_foo;
  bar: FragmentContainerTwo_bar;
}

When I go to pass bar into FragmentContainerTwo I get a type error:

Type 'ReadonlyArray<{ readonly id: string; readonly name: string; readonly " $refType": any; }>' is not assignable to type 'ReadonlyArray<_FragmentRefs<any>>'.
  Type '{ readonly id: string; readonly name: string; readonly " $refType": any; }' is not assignable to type '_FragmentRefs<any>'.
    Property '" $fragmentRefs"' is missing in type '{ readonly id: string; readonly name: string; readonly " $refType": any; }'.

Sorry this one is not edited to be a generic example since I think its more useful to have the exact error and my actual type is pretty simple.

If you've got any ideas let me know and I am happy to help figure this out. I can also create an example to reproduce if nothing jumps out at you from my description.

Maximum call stack size exceeded, possibly due to self-referencing type

When I run relay-compiler while using this plugin to generate TypeScript output, I get the following output and error:

> relay-compiler --src ./frontend/src --schema mydb_schema.graphql --language typescript --artifactDirectory relay-generated

Watchman:  Watchman was not found in PATH.  See https://facebook.github.io/watchman/docs/install.html for installation instructions
HINT: pass --watch to keep watching for changes.

Writing ts
ERROR:
Error writing modules:
RangeError: Maximum call stack size exceeded
    at Object.createIdentifier (/src/node_modules/typescript/lib/typescript.js:48807:30)
    at transformGraphQLEnumType (/src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:55:42)
    at transformNonNullableInputType (/src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:79:16)
    at transformInputType (/src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:63:13)
    at /src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:89:30
    at Array.map (<anonymous>)
    at transformNonNullableInputType (/src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:86:14)
    at transformInputType (/src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:63:13)
    at /src/node_modules/relay-compiler-language-typescript/lib/TypeScriptTypeTransformers.js:89:30
    at Array.map (<anonymous>)

Although I haven't yet created a minimal repro of the issue, the crash is caused when I use a particular type as input parameter to a query. The query is:

const query = graphql`
    query DashboardRepoQuery($filter: DbRepoFilter) {
        allDbRepos(filter: $filter) {
            nodes {
                slug
            }
        }
    }
`;

And the DbRepoFilter type (which is auto-generated by Postgraphile) is:

input DbRepoFilter {
  """Filter by the object’s `slug` field."""
  slug: StringFilter

  """Filter by the object’s `content` field."""
  content: JSONFilter

  """Checks for all expressions in this list."""
  and: [DbRepoFilter!]

  """Checks for any expressions in this list."""
  or: [DbRepoFilter!]

  """Negates the expression."""
  not: DbRepoFilter
}

If this info isn't sufficient, let me know and I can try to create a simpler and more self-contained repro.

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.