├── .gitattributes ├── .github └── workflows │ ├── bindings.yml │ ├── build-release.yml │ ├── cli.yml │ ├── integration-tests.yml │ ├── ppx.yml │ └── print_esy_cache.js ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── LOCAL_DEVELOPMENT.md ├── README.md ├── build-ci.sh ├── example ├── .gitignore ├── README.md ├── assets │ ├── css │ │ └── style.css │ ├── fonts │ │ └── Ubuntu │ │ │ ├── Ubuntu-Bold.eot │ │ │ ├── Ubuntu-Bold.ttf │ │ │ ├── Ubuntu-Bold.woff │ │ │ ├── Ubuntu-Bold.woff2 │ │ │ ├── Ubuntu-Light.eot │ │ │ ├── Ubuntu-Light.ttf │ │ │ ├── Ubuntu-Light.woff │ │ │ ├── Ubuntu-Light.woff2 │ │ │ ├── Ubuntu-Medium.eot │ │ │ ├── Ubuntu-Medium.ttf │ │ │ ├── Ubuntu-Medium.woff │ │ │ ├── Ubuntu-Medium.woff2 │ │ │ ├── Ubuntu-Regular.eot │ │ │ ├── Ubuntu-Regular.ttf │ │ │ ├── Ubuntu-Regular.woff │ │ │ └── Ubuntu-Regular.woff2 │ ├── images │ │ ├── dashboard │ │ │ ├── circle.png │ │ │ ├── circle.svg │ │ │ ├── img_1.jpg │ │ │ ├── img_2.jpg │ │ │ ├── img_3.jpg │ │ │ └── img_4.jpg │ │ ├── faces-clipart │ │ │ ├── pic-1.png │ │ │ ├── pic-2.png │ │ │ ├── pic-3.png │ │ │ └── pic-4.png │ │ ├── faces │ │ │ ├── face1.jpg │ │ │ ├── face10.jpg │ │ │ ├── face11.jpg │ │ │ ├── face12.jpg │ │ │ ├── face13.jpg │ │ │ ├── face14.jpg │ │ │ ├── face15.jpg │ │ │ ├── face16.jpg │ │ │ ├── face17.jpg │ │ │ ├── face18.jpg │ │ │ ├── face19.jpg │ │ │ ├── face2.jpg │ │ │ ├── face20.jpg │ │ │ ├── face21.jpg │ │ │ ├── face22.jpg │ │ │ ├── face23.jpg │ │ │ ├── face24.jpg │ │ │ ├── face25.jpg │ │ │ ├── face26.jpg │ │ │ ├── face27.jpg │ │ │ ├── face3.jpg │ │ │ ├── face4.jpg │ │ │ ├── face5.jpg │ │ │ ├── face6.jpg │ │ │ ├── face7.jpg │ │ │ ├── face8.jpg │ │ │ └── face9.jpg │ │ ├── favicon.png │ │ ├── logo-mini.svg │ │ ├── logo.svg │ │ └── sprites │ │ │ ├── blue.png │ │ │ ├── dark.png │ │ │ ├── flag.png │ │ │ ├── green.png │ │ │ ├── jsgrid-icons.png │ │ │ ├── red.png │ │ │ └── yellow.png │ └── vendors │ │ ├── css │ │ └── vendor.bundle.base.css │ │ └── mdi │ │ ├── css │ │ ├── materialdesignicons.min.css │ │ └── materialdesignicons.min.css.map │ │ └── fonts │ │ ├── materialdesignicons-webfont.eot │ │ ├── materialdesignicons-webfont.ttf │ │ ├── materialdesignicons-webfont.woff │ │ └── materialdesignicons-webfont.woff2 ├── bsconfig.json ├── index.html ├── package.json ├── relay.config.js ├── schema.graphql ├── src │ ├── App.res │ ├── Avatar.res │ ├── EmphasizedCard.res │ ├── GraphQLWs.res │ ├── Header.res │ ├── Index.res │ ├── Loading.res │ ├── Main.res │ ├── RecentTickets.res │ ├── RelayEnv.res │ ├── SingleTicket.res │ ├── SingleTicketWorkingGroup.res │ ├── SingleTodo.res │ ├── TicketStatusBadge.res │ ├── TodoList.res │ ├── TopCardsDisplayer.res │ └── __generated__ │ │ ├── Avatar_user_graphql.res │ │ ├── MainQuery_graphql.res │ │ ├── RecentTicketsRefetchQuery_graphql.res │ │ ├── RecentTickets_query_graphql.res │ │ ├── RelaySchemaAssets_graphql.res │ │ ├── SingleTicketWorkingGroupRefetchQuery_graphql.res │ │ ├── SingleTicketWorkingGroup_workingGroup_graphql.res │ │ ├── SingleTicket_ticket_graphql.res │ │ ├── SingleTodoDeleteMutation_graphql.res │ │ ├── SingleTodoUpdateMutation_graphql.res │ │ ├── SingleTodo_todoItem_graphql.res │ │ ├── TicketStatusBadge_ticket_graphql.res │ │ ├── TodoListAddTodoMutation_graphql.res │ │ ├── TodoList_query_graphql.res │ │ ├── TopCardsDisplayer_currentVisitorsOnline_Subscription_graphql.res │ │ └── TopCardsDisplayer_siteStatistics_graphql.res ├── webpack.config.js └── yarn.lock ├── packages ├── rescript-relay-cli │ ├── .gitignore │ ├── __tests__ │ │ ├── formatUtils.test.ts │ │ ├── processReanalyzeOutput.test.ts │ │ ├── removeUnusedFields.test.ts │ │ └── testData.txt │ ├── cliUtils.ts │ ├── commands │ │ ├── debugCommand.ts │ │ ├── formatGraphQLCommand.ts │ │ ├── initCommand.ts │ │ └── removeUnusedFieldsCommand.ts │ ├── fileUtils.ts │ ├── formatUtils.ts │ ├── index.ts │ ├── jest.config.js │ ├── package.json │ ├── tsconfig.json │ └── yarn.lock └── rescript-relay │ ├── .gitignore │ ├── .npmignore │ ├── __tests__ │ ├── GroupAvatar.res │ ├── HasNameComponent.res │ ├── ProvidedVariables.res │ ├── RelayEnv.res │ ├── RelayLocalUserModel.res │ ├── RelayRouter.res │ ├── RelayRouter__Types.res │ ├── RelayUserMetaModel.res │ ├── RichContent.res │ ├── TestCompileInterfaces.res │ ├── TestCompileInterfaces.resi │ ├── TestDeferredComponent.res │ ├── TestProviders.res │ ├── TestRelayResolvers.res │ ├── TestRelayUserResolver.res │ ├── TestRelayUserResolver2.res │ ├── Test_aliasedFragments-tests.js │ ├── Test_aliasedFragments.res │ ├── Test_catch-tests.js │ ├── Test_catch.res │ ├── Test_codesplit-tests.js │ ├── Test_codesplit.res │ ├── Test_connections-tests.js │ ├── Test_connections.res │ ├── Test_customScalars-tests.js │ ├── Test_customScalars.res │ ├── Test_deferredComponent.res │ ├── Test_fragment-tests.js │ ├── Test_fragment.res │ ├── Test_fragment_required-tests.js │ ├── Test_fragment_required.res │ ├── Test_inputUnion-tests.js │ ├── Test_inputUnion.res │ ├── Test_localPayload-tests.js │ ├── Test_localPayload.res │ ├── Test_misingFieldHandlers-tests.js │ ├── Test_missingFieldHandlers.res │ ├── Test_mutation-tests.js │ ├── Test_mutation.res │ ├── Test_mutation.resi │ ├── Test_nodeInterface-tests.js │ ├── Test_nodeInterface.res │ ├── Test_nonReact-tests.js │ ├── Test_nonReact.res │ ├── Test_nullableVariables-tests.js │ ├── Test_nullableVariables.res │ ├── Test_observer-tests.js │ ├── Test_observer.res │ ├── Test_paginationInNode-tests.js │ ├── Test_paginationInNode.res │ ├── Test_paginationUnion-tests.js │ ├── Test_paginationUnion.res │ ├── Test_parseCustomScalarArray-tests.js │ ├── Test_parseCustomScalarArray.res │ ├── Test_prefetchablePagination-tests.js │ ├── Test_prefetchablePagination.res │ ├── Test_providedVariables-tests.js │ ├── Test_providedVariables.res │ ├── Test_query-tests.js │ ├── Test_query.res │ ├── Test_queryInputObjects-tests.js │ ├── Test_queryInputObjects.res │ ├── Test_refetching-tests.js │ ├── Test_refetching.res │ ├── Test_refetchingInNode-tests.js │ ├── Test_refetchingInNode.res │ ├── Test_relayResolvers-tests.js │ ├── Test_relayResolvers.res │ ├── Test_relayResolversAll-tests.js │ ├── Test_relayResolversAll.res │ ├── Test_requiredFieldLogger-tests.js │ ├── Test_requiredFieldLogger.res │ ├── Test_serializeCustomScalarArray-tests.js │ ├── Test_serializeCustomScalarArray.res │ ├── Test_subscription-tests.js │ ├── Test_subscription.res │ ├── Test_subscription.resi │ ├── Test_union-tests.js │ ├── Test_unionFragment-tests.js │ ├── Test_unionFragment.res │ ├── Test_unions.res │ ├── Test_updatableFragments-tests.js │ ├── Test_updatableFragments.res │ ├── Test_updatableQuery-tests.js │ ├── Test_updatableQuery.res │ ├── TestsUtils.res │ ├── UserAvatar.res │ ├── UserName.res │ ├── UserService.res │ ├── __generated__ │ │ ├── GroupAvatar_group_graphql.res │ │ ├── HasNameComponent_hasName_graphql.res │ │ ├── LocalUser____relay_model_instance_graphql.res │ │ ├── LocalUser__id_graphql.res │ │ ├── LocalUser_relayResolvers_graphql.res │ │ ├── Query_relayResolvers_graphql.res │ │ ├── RelaySchemaAssets_graphql.res │ │ ├── RichContent_content_graphql.res │ │ ├── TestAliasedFragmentsQuery_graphql.res │ │ ├── TestAliasedFragments_userFirstName_graphql.res │ │ ├── TestAliasedFragments_userLastName_graphql.res │ │ ├── TestCatchLoggedInUserPropQuery_graphql.res │ │ ├── TestCatchMemberPropNestedQuery_graphql.res │ │ ├── TestCatchMemberPropQuery_graphql.res │ │ ├── TestCatchMembersPropQuery_graphql.res │ │ ├── TestCatchUser_user_graphql.res │ │ ├── TestCodesplitQuery_graphql.res │ │ ├── TestCompileInterfacesFragment_user_graphql.res │ │ ├── TestConnections2_user_graphql.res │ │ ├── TestConnections3_user_graphql.res │ │ ├── TestConnectionsQuery_graphql.res │ │ ├── TestConnections_AddFriendMutation_graphql.res │ │ ├── TestConnections_user_graphql.res │ │ ├── TestCustomScalarsQuery_graphql.res │ │ ├── TestFragmentQuery_graphql.res │ │ ├── TestFragmentRequiredPlural_user_graphql.res │ │ ├── TestFragmentRequiredQuery_graphql.res │ │ ├── TestFragmentRequired_user_graphql.res │ │ ├── TestFragment_allowUnsafeEnum_graphql.res │ │ ├── TestFragment_inline_graphql.res │ │ ├── TestFragment_plural_user_graphql.res │ │ ├── TestFragment_sub_user_graphql.res │ │ ├── TestFragment_user_graphql.res │ │ ├── TestInputUnionQuery_graphql.res │ │ ├── TestLocalPayloadQuery_graphql.res │ │ ├── TestLocalPayloadViaNodeInterfaceQuery_graphql.res │ │ ├── TestLocalPayload_user_graphql.res │ │ ├── TestMissingFieldHandlersMeQuery_graphql.res │ │ ├── TestMissingFieldHandlersQuery_graphql.res │ │ ├── TestMutationInline_user_graphql.res │ │ ├── TestMutationQuery_graphql.res │ │ ├── TestMutationSetOnlineStatusComplexMutation_graphql.res │ │ ├── TestMutationSetOnlineStatusMutation_graphql.res │ │ ├── TestMutationWithInlineFragmentSetOnlineStatusMutation_graphql.res │ │ ├── TestMutationWithOnlyFragmentSetOnlineStatusMutation_graphql.res │ │ ├── TestMutation_user_graphql.res │ │ ├── TestNodeInterfaceOnAbstractTypeQuery_graphql.res │ │ ├── TestNodeInterfaceQuery_graphql.res │ │ ├── TestNodeInterface_user_graphql.res │ │ ├── TestNonReactQuery_graphql.res │ │ ├── TestNonReact_user_graphql.res │ │ ├── TestNullableVariablesMutation_graphql.res │ │ ├── TestNullableVariablesQuery_graphql.res │ │ ├── TestObserverQuery_graphql.res │ │ ├── TestPaginationInNodeQuery_graphql.res │ │ ├── TestPaginationInNodeRefetchQuery_graphql.res │ │ ├── TestPaginationInNode_query_graphql.res │ │ ├── TestPaginationInNode_user_graphql.res │ │ ├── TestPaginationUnionQuery_graphql.res │ │ ├── TestPaginationUnionRefetchQuery_graphql.res │ │ ├── TestPaginationUnion_query_graphql.res │ │ ├── TestPaginationUnion_user_graphql.res │ │ ├── TestParseCustomScalarArrayQuery_graphql.res │ │ ├── TestPrefetchablePaginationQuery_graphql.res │ │ ├── TestPrefetchablePaginationRefetchQuery_graphql.res │ │ ├── TestPrefetchablePagination_user__edges_graphql.res │ │ ├── TestPrefetchablePagination_user_graphql.res │ │ ├── TestProvidedVariablesQuery_graphql.res │ │ ├── TestProvidedVariables_user_graphql.res │ │ ├── TestQueryInputObjectsQuery_graphql.res │ │ ├── TestQuery_graphql.res │ │ ├── TestRefetchingInNodeQuery_graphql.res │ │ ├── TestRefetchingInNodeRefetchQuery_graphql.res │ │ ├── TestRefetchingInNode_user_graphql.res │ │ ├── TestRefetchingNoArgsRefetchQuery_graphql.res │ │ ├── TestRefetchingNoArgs_query_graphql.res │ │ ├── TestRefetchingQuery_graphql.res │ │ ├── TestRefetchingRefetchQuery_graphql.res │ │ ├── TestRefetching_user_graphql.res │ │ ├── TestRelayResolversAllQuery_graphql.res │ │ ├── TestRelayResolversQuery_graphql.res │ │ ├── TestRelayResolvers_user_graphql.res │ │ ├── TestRelayUserResolver2_graphql.res │ │ ├── TestRelayUserResolver_graphql.res │ │ ├── TestRequiredFieldLoggerQuery_graphql.res │ │ ├── TestSerializeCustomScalarArrayMutation_graphql.res │ │ ├── TestSubscriptionQuery_graphql.res │ │ ├── TestSubscriptionUserUpdatedSubscription_graphql.res │ │ ├── TestSubscription_user_graphql.res │ │ ├── TestUnionFragmentQuery_graphql.res │ │ ├── TestUnionFragmentUser_user_graphql.res │ │ ├── TestUnionFragment_member_graphql.res │ │ ├── TestUnionFragment_plural_member_graphql.res │ │ ├── TestUnionsQuery_graphql.res │ │ ├── TestUpdatableFragmentsQuery_graphql.res │ │ ├── TestUpdatableFragments_query_graphql.res │ │ ├── TestUpdatableFragments_updatableUser_graphql.res │ │ ├── TestUpdatableQuery_UpdatableQuery_graphql.res │ │ ├── TestUpdatableQuery_graphql.res │ │ ├── UserAvatar_user_graphql.res │ │ ├── UserMeta____relay_model_instance_graphql.res │ │ ├── UserMeta_relayResolvers_graphql.res │ │ ├── UserName_user_graphql.res │ │ └── User_relayResolvers_graphql.res │ ├── jestSetup.js │ ├── queryMock.js │ ├── schema.graphql │ └── utils-tests.js │ ├── __tests_preloaded__ │ ├── Test_preloadedQuery-tests.js │ ├── Test_preloadedQuery.res │ └── __generated__ │ │ ├── TestPreloadedQueryProvidedVariables_user_graphql.res │ │ ├── TestPreloadedQuery_graphql.res │ │ └── TestPreloadedQuery_preloadable_graphql.res │ ├── binaries │ └── .gitkeep │ ├── build-compiler-dev.sh │ ├── compiler.js │ ├── copyPackageJson.js │ ├── jest.config.js │ ├── package.json │ ├── persistedQueries.json │ ├── postinstall.js │ ├── relay.config.js │ ├── rescript-relay-ppx │ ├── .gitignore │ ├── .ocamlformat │ ├── MIT-LICENSE │ ├── README.md │ ├── bin │ │ ├── RescriptRelayPpxApp.ml │ │ └── dune │ ├── dune │ ├── dune-project │ ├── esy.lock │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── index.json │ │ ├── opam │ │ │ ├── base-threads.base │ │ │ │ └── opam │ │ │ ├── base-unix.base │ │ │ │ └── opam │ │ │ ├── dune.3.3.1 │ │ │ │ └── opam │ │ │ ├── fmt.0.8.6 │ │ │ │ └── opam │ │ │ ├── graphql_parser.0.12.2 │ │ │ │ └── opam │ │ │ ├── menhir.20230415 │ │ │ │ └── opam │ │ │ ├── menhirLib.20230415 │ │ │ │ └── opam │ │ │ ├── menhirSdk.20230415 │ │ │ │ └── opam │ │ │ ├── ocaml-compiler-libs.v0.12.4 │ │ │ │ └── opam │ │ │ ├── ocamlbuild.0.14.2 │ │ │ │ └── opam │ │ │ ├── ocamlfind.1.9.6 │ │ │ │ ├── files │ │ │ │ │ └── 0001-Harden-test-for-OCaml-5.patch │ │ │ │ └── opam │ │ │ ├── ppx_derivers.1.2.1 │ │ │ │ └── opam │ │ │ ├── re.1.10.4 │ │ │ │ └── opam │ │ │ ├── seq.base │ │ │ │ ├── files │ │ │ │ │ ├── META.seq │ │ │ │ │ └── seq.install │ │ │ │ └── opam │ │ │ ├── sexplib0.v0.16.0 │ │ │ │ └── opam │ │ │ ├── stdlib-shims.0.3.0 │ │ │ │ └── opam │ │ │ └── topkg.1.0.7 │ │ │ │ └── opam │ │ └── overrides │ │ │ ├── opam__s__ocamlbuild_opam__c__0.14.2_opam_override │ │ │ ├── files │ │ │ │ └── winpatch.patch │ │ │ └── package.json │ │ │ └── opam__s__ocamlfind_opam__c__1.9.6_opam_override │ │ │ ├── files │ │ │ └── findlib.patch │ │ │ └── package.json │ ├── library │ │ ├── DeferredComp.ml │ │ ├── Fragment.ml │ │ ├── Mutation.ml │ │ ├── NonReactUtils.ml │ │ ├── Query.ml │ │ ├── RelayResolverFragment.ml │ │ ├── RelayResolvers.ml │ │ ├── RescriptRelayPpxLibrary.ml │ │ ├── Subscription.ml │ │ ├── UncurriedUtils.ml │ │ ├── UpdatableFragment.ml │ │ ├── UpdatableQuery.ml │ │ ├── Util.ml │ │ └── dune │ ├── package.json │ └── rescript-relay-ppx.opam │ ├── rescript.json │ ├── rescript.release.json │ ├── scripts │ ├── .gitignore │ ├── extract-docs.js │ └── release-postinstall.js │ ├── src │ ├── ReactDOMExperimental.res │ ├── RescriptRelay.res │ ├── RescriptRelay.resi │ ├── RescriptRelayUtils.res │ ├── RescriptRelayUtils.resi │ ├── RescriptRelay_Fragment.res │ ├── RescriptRelay_Fragment.resi │ ├── RescriptRelay_Internal.res │ ├── RescriptRelay_Internal.resi │ ├── RescriptRelay_Mutation.res │ ├── RescriptRelay_Mutation.resi │ ├── RescriptRelay_Query.res │ ├── RescriptRelay_Query.resi │ ├── RescriptRelay_RelayResolvers.res │ ├── RescriptRelay_RelayResolvers.resi │ ├── RescriptRelay_Subscriptions.res │ ├── RescriptRelay_Subscriptions.resi │ └── utils.js │ └── yarn.lock ├── rescript-relay-documentation ├── .gitignore ├── README.md ├── blog │ ├── 2021-01-03-rescript-relay-1.0.0-beta.md │ ├── 2022-10-02-rescript-relay-1.0.0-released.md │ └── 2024-08-06-rescript-relay-3.0.0-released.md ├── docs │ ├── about-rescript-relay.md │ ├── api-reference.md │ ├── client-schema-extensions.md │ ├── codebase-health-considerations.md │ ├── codesplit-directive.md │ ├── custom-scalars.md │ ├── editor-support-and-development-environment.md │ ├── enums.md │ ├── examples.md │ ├── generate.js │ ├── getting-started.md │ ├── input-objects.md │ ├── input-unions.md │ ├── interacting-with-the-store.md │ ├── interfaces.md │ ├── making-queries.md │ ├── migrating-from-javascript-typescript-incrementally.md │ ├── migrating-to-v3.md │ ├── mutations.md │ ├── network-layer.md │ ├── pagination.md │ ├── quirks-of-rescript-relay.md │ ├── refetching-and-loading-more-data.md │ ├── relay-environment.md │ ├── relay-resolvers.md │ ├── relay-video-series.md │ ├── rescript-relay-cli.md │ ├── router.md │ ├── start-here.md │ ├── subscriptions.md │ ├── the-compiler.md │ ├── the-node-interface.md │ ├── tips-and-tricks.md │ ├── tutorial │ │ ├── 1-intro.md │ │ ├── 10-mutations-updates.md │ │ ├── 2-graphql-and-relay.md │ │ ├── 3-query-basics.md │ │ ├── 4-fragments.md │ │ ├── 5-arrays-and-lists.md │ │ ├── 6-queries-for-interaction.md │ │ ├── 7-types-interfaces-polymorphism.md │ │ ├── 8-refetchable-fragments.md │ │ └── 9-connections-pagination.md │ ├── unions.md │ ├── using-fragments.md │ ├── using-with-hasura.md │ ├── using-with-schemas-that-dont-conform-to-the-relay-spec.md │ ├── utilities.md │ ├── variables.md │ └── vscode-extension.md ├── docusaurus.config.js ├── now.json ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── community.md │ │ ├── index.js │ │ ├── showcases.md │ │ └── styles.module.css ├── static │ ├── googlecfd8adbd3329afe2.html │ └── img │ │ ├── docs │ │ └── tutorial │ │ │ ├── arrays-keys-warning-screenshot.png │ │ │ ├── arrays-top-stories-screenshot.png │ │ │ ├── connections-comments-initial-screenshot.png │ │ │ ├── connections-conceptual-graph.png │ │ │ ├── connections-edge-nodes.png │ │ │ ├── connections-full-model-next-page.png │ │ │ ├── connections-full-model.png │ │ │ ├── fragment-image-add-once-compiled.png │ │ │ ├── fragment-newsfeed-story-combined.png │ │ │ ├── fragment-newsfeed-story-image-combined.png │ │ │ ├── fragment-newsfeed-story-image.png │ │ │ ├── fragment-newsfeed-story.png │ │ │ ├── fragment-reuse-combined.png │ │ │ ├── fragment-reuse-seperate.png │ │ │ ├── fragments-image-two-places-compiled.png │ │ │ ├── fragments-newsfeed-story-compilation.png │ │ │ ├── graphql-compiler-combines-fragments.png │ │ │ ├── graphql-graph-detail.png │ │ │ ├── graphql-relay-runtime-fetches-query.png │ │ │ ├── graphql-request.png │ │ │ ├── graphql-response.png │ │ │ ├── interfaces-organization-screenshot.png │ │ │ ├── interfaces-person-screenshot.png │ │ │ ├── intro-screenshot-placeholder.png │ │ │ ├── mutations-comments-composer-screenshot.png │ │ │ ├── mutations-lifecycle.png │ │ │ ├── mutations-like-button.png │ │ │ ├── network-request-with-variables.png │ │ │ ├── preloaded-basic.png │ │ │ ├── preloaded-ideal.png │ │ │ ├── preloaded-lazy.png │ │ │ ├── queries-basic-screenshot.png │ │ │ ├── queries-wrong-hovercard-person.png │ │ │ ├── query-breakdown.png │ │ │ ├── query-upon-graph.png │ │ │ ├── query-variables-hovercard-correct.png │ │ │ ├── refetchable-contacts-initial.png │ │ │ ├── refetchable-suspense-1-data-needed.png │ │ │ ├── refetchable-suspense-3-fallback.png │ │ │ ├── refetchable-transition-search.png │ │ │ └── refetechable-suspense-2-nearest-suspense-point.png │ │ ├── favicon.png │ │ ├── logo.svg │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg └── yarn.lock └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bs.js linguist-generated=true 2 | *.css linguist-generated=true 3 | -------------------------------------------------------------------------------- /.github/workflows/bindings.yml: -------------------------------------------------------------------------------- 1 | name: Bindings 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build: 11 | name: Bindings 12 | runs-on: ubuntu-latest 13 | defaults: 14 | run: 15 | working-directory: packages/rescript-relay 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | env: 22 | CI: true 23 | - name: Install esy 24 | run: npm install -g esy 25 | - name: Build PPX 26 | uses: esy/github-action@6863524ed7748e7882e317e31ac2b8b107011744 27 | with: 28 | cache-key: ${{ hashFiles('esy.lock/index.json') }} 29 | working-directory: packages/rescript-relay/rescript-relay-ppx 30 | - name: Install 31 | run: | 32 | yarn --frozen-lockfile 33 | - name: Build 34 | run: | 35 | yarn build 36 | - name: Test 37 | run: | 38 | yarn test:ci 39 | -------------------------------------------------------------------------------- /.github/workflows/cli.yml: -------------------------------------------------------------------------------- 1 | name: CLI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build: 11 | name: CLI 12 | runs-on: ubuntu-latest 13 | defaults: 14 | run: 15 | working-directory: packages/rescript-relay-cli 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | env: 22 | CI: true 23 | - name: Install 24 | run: | 25 | yarn --frozen-lockfile 26 | - name: Build 27 | run: | 28 | yarn build 29 | - name: Test 30 | run: | 31 | yarn test 32 | -------------------------------------------------------------------------------- /.github/workflows/print_esy_cache.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const os = require("os"); 3 | const path = require("path"); 4 | 5 | const ESY_FOLDER = process.env.ESY__PREFIX 6 | ? process.env.ESY__PREFIX 7 | : path.join(os.homedir(), ".esy"); 8 | const esy3 = fs 9 | .readdirSync(ESY_FOLDER) 10 | .filter((name) => name.length > 0 && name[0] === "3") 11 | .sort() 12 | .pop(); 13 | console.log(`::set-output name=esy_cache::${path.join(ESY_FOLDER, esy3, "i")}`); 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .vscode 4 | .merlin 5 | _build 6 | _esy 7 | _release 8 | *.byte 9 | *.native 10 | *.install 11 | *.bs.js 12 | rescript-relay-compiler 13 | .now 14 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rescript-relay-compiler"] 2 | path = packages/relay 3 | url = git@github.com:zth/relay.git 4 | branch = rescript-relay 5 | -------------------------------------------------------------------------------- /build-ci.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e; 4 | 5 | # make release folder structure 6 | rm -rf _release; 7 | mkdir -p _release/src; 8 | 9 | # build and copy cli 10 | mkdir -p _release/cli; 11 | cd packages/rescript-relay-cli; 12 | echo "Build CLI..."; 13 | yarn; yarn build; 14 | cp dist/index.js ../../_release/cli/cli.js; 15 | cd ../../; 16 | 17 | # build bindings 18 | cd packages/rescript-relay; 19 | echo "Build bindings..."; 20 | yarn; yarn build; 21 | 22 | # copy bindings and readme 23 | echo "Copying bindings and assets..." 24 | cp -rf src ../../_release; 25 | cp .npmignore ../../_release/; 26 | cp ../../README.md ../../_release/; 27 | cp ../../CHANGELOG.md ../../_release/; 28 | 29 | # copy and create mjs version of utils.js 30 | cp src/utils.js ../../_release/src/utils.mjs; 31 | sed -i 's/module\.exports \= /export /g' ../../_release/src/utils.mjs; 32 | 33 | # copy config files 34 | echo "Copying config files..." 35 | cp rescript.release.json ../../_release/rescript.json; 36 | ./copyPackageJson.js ../../_release $INPUT_TAG_NAME 37 | cp yarn.lock ../../_release/; 38 | cp compiler.js ../../_release/; 39 | 40 | # copy real post-install 41 | cp -f scripts/release-postinstall.js ../../_release/postinstall.js 42 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Add any directories, files, or patterns you don't want to be tracked by version control 2 | 3 | /node_modules 4 | /bower_components 5 | package-lock.json 6 | *.bs.js 7 | lib 8 | dist 9 | .bsb.lock 10 | .merlin 11 | index.js -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # RescriptRelay example 2 | 3 | This is an example of how most concepts in RescriptRelay work. You can run it by doing the following: 4 | 5 | ### Run server 6 | 7 | The examples use `graphql-client-example-server`, install and run like this: 8 | 9 | ``` 10 | npm install -g graphql-client-example-server && graphql-client-example-server 11 | ``` 12 | 13 | You will now have a GraphQL server running at https://localhost:4000. 14 | 15 | ### Run client 16 | 17 | `yarn && yarn start` will install all dependencies and start ReScript, Webpack and the Relay compiler. The app will now be available at https://localhost:9000. 18 | -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Bold.eot -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Bold.ttf -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Bold.woff -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Bold.woff2 -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Light.eot -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Light.ttf -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Light.woff -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Light.woff2 -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Medium.eot -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Medium.ttf -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Medium.woff -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Medium.woff2 -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Regular.eot -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Regular.ttf -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Regular.woff -------------------------------------------------------------------------------- /example/assets/fonts/Ubuntu/Ubuntu-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/fonts/Ubuntu/Ubuntu-Regular.woff2 -------------------------------------------------------------------------------- /example/assets/images/dashboard/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/dashboard/circle.png -------------------------------------------------------------------------------- /example/assets/images/dashboard/circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 3 10 | Created with Sketch. 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/assets/images/dashboard/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/dashboard/img_1.jpg -------------------------------------------------------------------------------- /example/assets/images/dashboard/img_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/dashboard/img_2.jpg -------------------------------------------------------------------------------- /example/assets/images/dashboard/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/dashboard/img_3.jpg -------------------------------------------------------------------------------- /example/assets/images/dashboard/img_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/dashboard/img_4.jpg -------------------------------------------------------------------------------- /example/assets/images/faces-clipart/pic-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces-clipart/pic-1.png -------------------------------------------------------------------------------- /example/assets/images/faces-clipart/pic-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces-clipart/pic-2.png -------------------------------------------------------------------------------- /example/assets/images/faces-clipart/pic-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces-clipart/pic-3.png -------------------------------------------------------------------------------- /example/assets/images/faces-clipart/pic-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces-clipart/pic-4.png -------------------------------------------------------------------------------- /example/assets/images/faces/face1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face1.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face10.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face11.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face12.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face13.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face14.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face15.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face16.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face17.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face18.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face19.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face2.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face20.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face21.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face22.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face23.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face24.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face25.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face26.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face27.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face3.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face4.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face5.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face6.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face7.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face8.jpg -------------------------------------------------------------------------------- /example/assets/images/faces/face9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/faces/face9.jpg -------------------------------------------------------------------------------- /example/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/favicon.png -------------------------------------------------------------------------------- /example/assets/images/sprites/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/blue.png -------------------------------------------------------------------------------- /example/assets/images/sprites/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/dark.png -------------------------------------------------------------------------------- /example/assets/images/sprites/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/flag.png -------------------------------------------------------------------------------- /example/assets/images/sprites/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/green.png -------------------------------------------------------------------------------- /example/assets/images/sprites/jsgrid-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/jsgrid-icons.png -------------------------------------------------------------------------------- /example/assets/images/sprites/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/red.png -------------------------------------------------------------------------------- /example/assets/images/sprites/yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/images/sprites/yellow.png -------------------------------------------------------------------------------- /example/assets/vendors/mdi/fonts/materialdesignicons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/vendors/mdi/fonts/materialdesignicons-webfont.eot -------------------------------------------------------------------------------- /example/assets/vendors/mdi/fonts/materialdesignicons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/vendors/mdi/fonts/materialdesignicons-webfont.ttf -------------------------------------------------------------------------------- /example/assets/vendors/mdi/fonts/materialdesignicons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/vendors/mdi/fonts/materialdesignicons-webfont.woff -------------------------------------------------------------------------------- /example/assets/vendors/mdi/fonts/materialdesignicons-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/example/assets/vendors/mdi/fonts/materialdesignicons-webfont.woff2 -------------------------------------------------------------------------------- /example/bsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reason-react-examples", 3 | "uncurried": true, 4 | "jsx": { 5 | "version": 4, 6 | "mode": "automatic" 7 | }, 8 | "sources": { 9 | "dir": "src", 10 | "subdirs": true 11 | }, 12 | "package-specs": [ 13 | { 14 | "module": "commonjs", 15 | "in-source": true 16 | } 17 | ], 18 | "suffix": ".bs.js", 19 | "ppx-flags": [ 20 | [ 21 | "rescript-relay/ppx", 22 | "-uncurried" 23 | ] 24 | ], 25 | "namespace": true, 26 | "bs-dependencies": [ 27 | "@rescript/react", 28 | "rescript-relay", 29 | "@glennsl/rescript-fetch" 30 | ] 31 | } -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | Purple Admin 10 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purple_admin", 3 | "version": "3.0.0", 4 | "description": "", 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "concurrently \"yarn relay:watch\" \"yarn webpack\" \"yarn res:watch\"", 8 | "res": "rescript build -with-deps", 9 | "res:watch": "yarn res -w", 10 | "webpack": "webpack-dev-server", 11 | "relay": "rescript-relay-compiler", 12 | "relay:watch": "rescript-relay-compiler --watch", 13 | "remove-unused-fields": "rescript-relay-cli remove-unused-fields", 14 | "format": "rescript-relay-cli format-all-graphql" 15 | }, 16 | "dependencies": { 17 | "@glennsl/rescript-fetch": "^0.2.0", 18 | "@mdi/font": "3.7.95", 19 | "@rescript/react": "0.11.0", 20 | "bootstrap": "^4.3.1", 21 | "concurrently": "^5.0.0", 22 | "graphql": "15.8.0", 23 | "graphql-ws": "^5.8.2", 24 | "react": "18.2.0", 25 | "react-dom": "18.2.0", 26 | "react-relay": "16.1.0", 27 | "relay-runtime": "16.1.0", 28 | "rescript-relay": "3.0.0-rc.0" 29 | }, 30 | "devDependencies": { 31 | "html-webpack-plugin": "^3.2.0", 32 | "rescript": "11.0.0-rc.8", 33 | "webpack": "^4.41.2", 34 | "webpack-cli": "^3.3.9", 35 | "webpack-dev-server": "^3.9.0" 36 | }, 37 | "author": "bootstrapdash", 38 | "url": "http://www.bootstrapdash.com/", 39 | "copyright": "", 40 | "license": "" 41 | } 42 | -------------------------------------------------------------------------------- /example/relay.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | src: "./src", 3 | schema: "./schema.graphql", 4 | artifactDirectory: "./src/__generated__", 5 | customScalars: { 6 | DateTime: "string" 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /example/src/App.res: -------------------------------------------------------------------------------- 1 | /** 2 | * We wrap
(which contains our main query) in . 3 | * This is because most Relay hooks APIs are suspense-based, so this is 4 | * how we handle our loading state. 5 | */ 6 | @react.component 7 | let make = () => 8 |
9 |
10 | {React.string("Loading...")}
}> 11 |
12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /example/src/Avatar.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment Avatar_user on User { 3 | avatarUrl 4 | fullName 5 | } 6 | `) 7 | 8 | @react.component 9 | let make = (~user as userRef) => { 10 | let user = Fragment.use(userRef) 11 | 12 | <> 13 | {switch user.avatarUrl { 14 | | Some(avatarUrl) => image 15 | | None => React.null 16 | }} 17 | {React.string(user.fullName)} 18 | 19 | } 20 | -------------------------------------------------------------------------------- /example/src/EmphasizedCard.res: -------------------------------------------------------------------------------- 1 | type cardVariant = 2 | | Red 3 | | Blue 4 | | Green 5 | 6 | type icon = 7 | | ChartLine 8 | | Bookmark 9 | | Diamond 10 | 11 | let mapIcon = icon => 12 | switch icon { 13 | | ChartLine => "mdi-chart-line" 14 | | Bookmark => "mdi-bookmark-outline" 15 | | Diamond => "mdi-diamond" 16 | } 17 | 18 | @react.component 19 | let make = (~title, ~subText, ~icon, ~variant) => { 20 | let variantAsBgClass = switch variant { 21 | | Red => "bg-gradient-danger" 22 | | Blue => "bg-gradient-info" 23 | | Green => "bg-gradient-success" 24 | } 25 | 26 |
27 |
28 | circle-image 29 |

30 | {React.string(title)} 31 |

32 |

{React.string(subText)}

33 |
34 |
35 | } 36 | -------------------------------------------------------------------------------- /example/src/GraphQLWs.res: -------------------------------------------------------------------------------- 1 | /** 2 | * Minimal required binding for graphql-wss 3 | * Note that those bindings are RescriptRelay-specific, and 4 | * would need to be adjusted in order to be used for 5 | * other purposes 6 | */ 7 | module Client = { 8 | type t 9 | type errOrCloseEvent 10 | 11 | type clientOptions = {url: string, shouldRetry: errOrCloseEvent => bool} 12 | 13 | @live @obj 14 | external makeClientOptions: ( 15 | ~url: string, 16 | ~shouldRetry: errOrCloseEvent => bool=?, 17 | unit, 18 | ) => clientOptions = "" 19 | 20 | @module("graphql-ws") 21 | external make: clientOptions => t = "createClient" 22 | 23 | type subscribeOptions = { 24 | operationName: string, 25 | query: string, 26 | variables: Js.Json.t, 27 | } 28 | 29 | type unsubscribe = unit => unit 30 | 31 | @send 32 | external subscribe: (t, subscribeOptions, RescriptRelay.Observable.sink<_>) => unsubscribe = 33 | "subscribe" 34 | } 35 | -------------------------------------------------------------------------------- /example/src/Header.res: -------------------------------------------------------------------------------- 1 | @react.component 2 | let make = () => 3 |
4 |

5 | 6 | 7 | 8 | {React.string("Dashboard")} 9 |

10 |
11 | -------------------------------------------------------------------------------- /example/src/Index.res: -------------------------------------------------------------------------------- 1 | /** 2 | * This mounts the app to the DOM. Note that the environment is 3 | * passed to context via here - 4 | * it's a requirement that the environment is available in the 5 | * context. 6 | */ 7 | ReactDOMExperimental.renderConcurrentRootAtElementWithId( 8 | 9 | 10 | , 11 | "app", 12 | ) 13 | -------------------------------------------------------------------------------- /example/src/Loading.res: -------------------------------------------------------------------------------- 1 | @react.component 2 | let make = () =>
{React.string("Loading...")}
3 | -------------------------------------------------------------------------------- /example/src/SingleTicket.res: -------------------------------------------------------------------------------- 1 | module TicketFragment = %relay(` 2 | fragment SingleTicket_ticket on Ticket { 3 | assignee { 4 | __typename 5 | ... on User { 6 | ...Avatar_user 7 | } 8 | ... on WorkingGroup { 9 | ...SingleTicketWorkingGroup_workingGroup 10 | } 11 | } 12 | id 13 | subject 14 | lastUpdated 15 | trackingId 16 | ...TicketStatusBadge_ticket 17 | } 18 | `) 19 | 20 | @react.component 21 | let make = (~ticket as ticketRef) => { 22 | let ticket = TicketFragment.use(ticketRef) 23 | 24 | 25 | 26 | {switch ticket.assignee { 27 | | Some(assignee) => 28 | switch assignee { 29 | | User(user) => 30 | | WorkingGroup(workingGroup) => 31 | }> 32 | 33 | 34 | | UnselectedUnionMember(_) => {React.string("-")} 35 | } 36 | | None => {React.string("Unassigned")} 37 | }} 38 | 39 | {React.string(ticket.subject)} 40 | 41 | {React.string(Belt.Option.getWithDefault(ticket.lastUpdated, "-"))} 42 | {React.string(ticket.trackingId)} 43 | 44 | } 45 | -------------------------------------------------------------------------------- /example/src/SingleTicketWorkingGroup.res: -------------------------------------------------------------------------------- 1 | module WorkingGroupFragment = %relay(` 2 | fragment SingleTicketWorkingGroup_workingGroup on WorkingGroup 3 | @argumentDefinitions(includeMembers: { type: "Boolean", defaultValue: false }) 4 | @refetchable(queryName: "SingleTicketWorkingGroupRefetchQuery") { 5 | name 6 | membersConnection @include(if: $includeMembers) { 7 | edges { 8 | node { 9 | id 10 | fullName 11 | } 12 | } 13 | } 14 | } 15 | `) 16 | 17 | @react.component 18 | let make = (~workingGroup as wgRef) => { 19 | let (workingGroup, refetch) = WorkingGroupFragment.useRefetchable(wgRef) 20 | let (isPending, startTransition) = ReactExperimental.useTransition() 21 | 22 |
23 | {React.string(workingGroup.name)} 24 |
25 | {switch workingGroup.membersConnection { 26 | | Some(membersConnection) => 27 | switch membersConnection { 28 | | {edges: Some(edges)} => 29 | edges 30 | ->Belt.Array.keepMap(edge => 31 | switch edge { 32 | | Some({node: Some(node)}) => Some(node) 33 | | _ => None 34 | } 35 | ) 36 | ->Belt.Array.map(member => 37 |
{React.string(member.fullName)}
38 | ) 39 | ->React.array 40 | | _ => React.null 41 | } 42 | | None => 43 | 53 | }} 54 |
55 |
56 | } 57 | -------------------------------------------------------------------------------- /example/src/TicketStatusBadge.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment TicketStatusBadge_ticket on Ticket { 3 | status 4 | } 5 | `) 6 | 7 | @react.component 8 | let make = (~ticket as ticketRef) => 9 | switch Fragment.use(ticketRef).status { 10 | | Done => 11 | | Progress => 12 | | OnHold => 13 | | Rejected => 14 | | _ => React.null 15 | } 16 | -------------------------------------------------------------------------------- /example/src/__generated__/Avatar_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Avatar.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | avatarUrl: option, 9 | fullName: string, 10 | } 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{}` 19 | ) 20 | @live 21 | let fragmentConverterMap = () 22 | @live 23 | let convertFragment = v => v->RescriptRelay.convertObj( 24 | fragmentConverter, 25 | fragmentConverterMap, 26 | Js.undefined 27 | ) 28 | } 29 | 30 | type t 31 | type fragmentRef 32 | external getFragmentRef: 33 | RescriptRelay.fragmentRefs<[> | #Avatar_user]> => fragmentRef = "%identity" 34 | 35 | module Utils = { 36 | @@warning("-33") 37 | open Types 38 | } 39 | 40 | type relayOperationNode 41 | type operationType = RescriptRelay.fragmentNode 42 | 43 | 44 | let node: operationType = %raw(json` { 45 | "argumentDefinitions": [], 46 | "kind": "Fragment", 47 | "metadata": null, 48 | "name": "Avatar_user", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "avatarUrl", 55 | "storageKey": null 56 | }, 57 | { 58 | "alias": null, 59 | "args": null, 60 | "kind": "ScalarField", 61 | "name": "fullName", 62 | "storageKey": null 63 | } 64 | ], 65 | "type": "User", 66 | "abstractKey": null 67 | } `) 68 | 69 | -------------------------------------------------------------------------------- /example/src/__generated__/RelaySchemaAssets_graphql.res: -------------------------------------------------------------------------------- 1 | /* @generated */ 2 | @@warning("-30") 3 | 4 | @live @unboxed 5 | type enum_TicketStatus = 6 | | Done 7 | | Progress 8 | | OnHold 9 | | Rejected 10 | | FutureAddedValue(string) 11 | 12 | 13 | @live @unboxed 14 | type enum_TicketStatus_input = 15 | | Done 16 | | Progress 17 | | OnHold 18 | | Rejected 19 | 20 | 21 | @live @unboxed 22 | type enum_RequiredFieldAction = 23 | | NONE 24 | | LOG 25 | | THROW 26 | | FutureAddedValue(string) 27 | 28 | 29 | @live @unboxed 30 | type enum_RequiredFieldAction_input = 31 | | NONE 32 | | LOG 33 | | THROW 34 | 35 | 36 | @live 37 | type rec input_AddTodoItemInput = { 38 | text: string, 39 | clientMutationId?: string, 40 | } 41 | 42 | @live 43 | and input_AddTodoItemInput_nullable = { 44 | text: string, 45 | clientMutationId?: Js.Null.t, 46 | } 47 | 48 | @live 49 | and input_DeleteTodoItemInput = { 50 | id: string, 51 | clientMutationId?: string, 52 | } 53 | 54 | @live 55 | and input_DeleteTodoItemInput_nullable = { 56 | id: string, 57 | clientMutationId?: Js.Null.t, 58 | } 59 | 60 | @live 61 | and input_UpdateTodoItemInput = { 62 | id: string, 63 | text: string, 64 | completed: bool, 65 | clientMutationId?: string, 66 | } 67 | 68 | @live 69 | and input_UpdateTodoItemInput_nullable = { 70 | id: string, 71 | text: string, 72 | completed: bool, 73 | clientMutationId?: Js.Null.t, 74 | } 75 | -------------------------------------------------------------------------------- /example/src/__generated__/SingleTodo_todoItem_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc SingleTodo.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | completed: option, 9 | @live id: string, 10 | text: string, 11 | } 12 | } 13 | 14 | module Internal = { 15 | @live 16 | type fragmentRaw 17 | @live 18 | let fragmentConverter: Js.Dict.t>> = %raw( 19 | json`{}` 20 | ) 21 | @live 22 | let fragmentConverterMap = () 23 | @live 24 | let convertFragment = v => v->RescriptRelay.convertObj( 25 | fragmentConverter, 26 | fragmentConverterMap, 27 | Js.undefined 28 | ) 29 | } 30 | 31 | type t 32 | type fragmentRef 33 | external getFragmentRef: 34 | RescriptRelay.fragmentRefs<[> | #SingleTodo_todoItem]> => fragmentRef = "%identity" 35 | 36 | module Utils = { 37 | @@warning("-33") 38 | open Types 39 | } 40 | 41 | type relayOperationNode 42 | type operationType = RescriptRelay.fragmentNode 43 | 44 | 45 | let node: operationType = %raw(json` { 46 | "argumentDefinitions": [], 47 | "kind": "Fragment", 48 | "metadata": null, 49 | "name": "SingleTodo_todoItem", 50 | "selections": [ 51 | { 52 | "alias": null, 53 | "args": null, 54 | "kind": "ScalarField", 55 | "name": "id", 56 | "storageKey": null 57 | }, 58 | { 59 | "alias": null, 60 | "args": null, 61 | "kind": "ScalarField", 62 | "name": "text", 63 | "storageKey": null 64 | }, 65 | { 66 | "alias": null, 67 | "args": null, 68 | "kind": "ScalarField", 69 | "name": "completed", 70 | "storageKey": null 71 | } 72 | ], 73 | "type": "TodoItem", 74 | "abstractKey": null 75 | } `) 76 | 77 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | let path = require("path"); 2 | let HtmlWebpackPlugin = require("html-webpack-plugin"); 3 | let webpack = require("webpack"); 4 | 5 | let outputDir = path.join(__dirname, "assets"); 6 | 7 | module.exports = { 8 | entry: "./src/Index.bs.js", 9 | mode: "development", 10 | output: { 11 | path: outputDir, 12 | publicPath: "/", 13 | filename: "index.js" 14 | }, 15 | plugins: [ 16 | new HtmlWebpackPlugin({ 17 | template: "index.html" 18 | }), 19 | new webpack.DefinePlugin({ 20 | __DEV__: JSON.stringify(process.env.NODE_ENV !== "production") 21 | }) 22 | ], 23 | devServer: { 24 | compress: true, 25 | contentBase: outputDir, 26 | port: process.env.PORT || 9000, 27 | historyApiFallback: true 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /packages/rescript-relay-cli/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules -------------------------------------------------------------------------------- /packages/rescript-relay-cli/commands/debugCommand.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "commander"; 2 | import { 3 | loadRelayConfig, 4 | getRelayArtifactDirectoryLocation, 5 | getAllGeneratedFiles, 6 | findAllSourceFilesFromGeneratedFiles, 7 | findSourceFiles, 8 | getSrcCwd, 9 | } from "../fileUtils"; 10 | 11 | export const addDebugCommand = (program: Command) => { 12 | program 13 | .command("debug") 14 | .description("Prints debug information for the CLI.") 15 | .action(async () => { 16 | const relayConfig = loadRelayConfig(); 17 | const artifactDirectoryLocation = 18 | getRelayArtifactDirectoryLocation(relayConfig); 19 | 20 | console.log( 21 | `Artifact directory location: ${artifactDirectoryLocation}\n` 22 | ); 23 | 24 | console.log("Getting all generated files...\n"); 25 | const allGeneratedFiles = await getAllGeneratedFiles( 26 | artifactDirectoryLocation 27 | ); 28 | console.log( 29 | `Number of generated files found in artifact directory: ${allGeneratedFiles.length}\n` 30 | ); 31 | 32 | console.log("Looking up source files\n"); 33 | 34 | const files = await findAllSourceFilesFromGeneratedFiles( 35 | allGeneratedFiles 36 | ); 37 | 38 | console.log( 39 | `Found ${files.length} source locations with explicit definitions.\n` 40 | ); 41 | 42 | console.log("Looking up source files..\n"); 43 | 44 | const sourceFiles = await findSourceFiles(files, relayConfig.src); 45 | 46 | console.log( 47 | `Found ${ 48 | sourceFiles.length 49 | } actual source files, when looking in ${getSrcCwd(relayConfig.src)}.\n` 50 | ); 51 | 52 | console.log("Done!"); 53 | }); 54 | }; 55 | -------------------------------------------------------------------------------- /packages/rescript-relay-cli/commands/initCommand.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "commander"; 2 | import ora from "ora"; 3 | import path from "path"; 4 | import fs from "fs"; 5 | 6 | // This is WIP 7 | export const addInitCommand = (program: Command) => { 8 | program 9 | .command("init") 10 | .description("Set up RescriptRelay in this directory.") 11 | .action(async () => { 12 | // Being able to run this command means the main package is installed, so we 13 | // don't need to care about that. 14 | const spinner = ora("Setting up RescriptRelay...").start(); 15 | 16 | const packageJsonRaw = fs.readFileSync( 17 | path.resolve(process.cwd(), "package.json"), 18 | "utf8" 19 | ); 20 | 21 | let packageJsonParsed: Record = {}; 22 | 23 | try { 24 | packageJsonParsed = JSON.parse(packageJsonRaw); 25 | } catch (e) { 26 | console.error(e); 27 | spinner.fail( 28 | "Could not load package.json. This command needs to run in the same directory as package.json is located." 29 | ); 30 | return; 31 | } 32 | 33 | /** 34 | * Install correct Relay versions 35 | * Check React version 36 | * Create relay.config.js 37 | * Create artifact directory 38 | */ 39 | 40 | spinner.succeed("Done!"); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/rescript-relay-cli/formatUtils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | extractGraphQLSourceFromReScript, 3 | prettify, 4 | restoreOperationPadding, 5 | } from "./cliUtils"; 6 | 7 | export const formatOperationsInDocument = (doc: string): string => { 8 | const tags = extractGraphQLSourceFromReScript(doc); 9 | 10 | if (tags.length === 0) { 11 | return doc; 12 | } 13 | 14 | let formatted = ""; 15 | 16 | for (let i = 0; i <= tags.length - 1; i += 1) { 17 | const thisTag = tags[i]; 18 | const lastTag = tags[i - 1]; 19 | const lastTagEnd = lastTag == null ? 0 : lastTag.end; 20 | 21 | formatted += doc.slice(lastTagEnd, thisTag.start); 22 | const isCommented = thisTag.content 23 | .split("\n") 24 | .some((line) => line.trim().startsWith("//")); 25 | if (isCommented) { 26 | // Uncomment the `tag`, format it and then comment it back 27 | const uncommentedContent = thisTag.content 28 | .split("\n") 29 | .map((line) => line.replace("//", "")) 30 | .join("\n"); 31 | formatted += restoreOperationPadding( 32 | prettify(uncommentedContent), 33 | uncommentedContent 34 | ) 35 | .split("\n") 36 | // Ignore empty lines 37 | .map((line) => (line !== "" ? `//${line}` : line)) 38 | .join("\n"); 39 | } else { 40 | formatted += restoreOperationPadding( 41 | prettify(thisTag.content), 42 | thisTag.content 43 | ); 44 | } 45 | } 46 | 47 | const lastTag = tags[tags.length - 1]; 48 | formatted += doc.slice(lastTag.end); 49 | 50 | return formatted; 51 | }; 52 | -------------------------------------------------------------------------------- /packages/rescript-relay-cli/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { program } from "commander"; 3 | import { addFormatGraphQLCommands } from "./commands/formatGraphQLCommand"; 4 | import { addDebugCommand } from "./commands/debugCommand"; 5 | import { addRemoveUnusedFieldsCommand } from "./commands/removeUnusedFieldsCommand"; 6 | 7 | program.version("0.1.0"); 8 | 9 | addFormatGraphQLCommands(program); 10 | addDebugCommand(program); 11 | addRemoveUnusedFieldsCommand(program); 12 | // addInitCommand(program); 13 | 14 | program.parse(process.argv); 15 | -------------------------------------------------------------------------------- /packages/rescript-relay-cli/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; -------------------------------------------------------------------------------- /packages/rescript-relay-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-cli", 3 | "version": "0.1.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "commander": "8.0.0", 8 | "cosmiconfig": "^7.0.1", 9 | "graphql": "15.5.1", 10 | "locate-character": "2.0.5", 11 | "ora": "5.4.1", 12 | "prettier": "2.3.2", 13 | "relay-config": "12.0.0", 14 | "@rescript/tools": "^0.1.2" 15 | }, 16 | "devDependencies": { 17 | "@types/jest": "26.0.23", 18 | "@types/node": "15.12.5", 19 | "@types/prettier": "2.3.0", 20 | "@types/relay-config": "6.0.1", 21 | "@vercel/ncc": "0.38.1", 22 | "fast-glob": "3.2.6", 23 | "jest": "27.0.6", 24 | "ts-jest": "27.0.3", 25 | "typescript": "4.3.4" 26 | }, 27 | "scripts": { 28 | "build": "ncc build index.ts -o dist -m", 29 | "build:dev": "ncc build index.ts -o dist", 30 | "test": "jest" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/rescript-relay/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | dist 3 | node_modules 4 | src/Dummy.re* 5 | .bsb.lock 6 | *.log 7 | relay-compiler -------------------------------------------------------------------------------- /packages/rescript-relay/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/packages/rescript-relay/.npmignore -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/GroupAvatar.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment GroupAvatar_group on Group { 3 | name 4 | } 5 | `) 6 | 7 | @react.component 8 | let make = (~group: RescriptRelay.fragmentRefs<[#GroupAvatar_group]>) => { 9 | let group = Fragment.use(group) 10 | React.string("Group name: " ++ group.name) 11 | } 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/HasNameComponent.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment HasNameComponent_hasName on HasName { 3 | name 4 | } 5 | `) 6 | 7 | @react.component 8 | let make = (~hasName: RescriptRelay.fragmentRefs<[#HasNameComponent_hasName]>) => { 9 | let hasName = Fragment.use(hasName) 10 | 11 |
{React.string("Has name: " ++ hasName.name)}
12 | } 13 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/ProvidedVariables.res: -------------------------------------------------------------------------------- 1 | module Bool = { 2 | let get = () => true 3 | } 4 | 5 | module InputC = { 6 | let get = (): RelaySchemaAssets_graphql.input_InputC => { 7 | intStr: 123, 8 | recursiveC: {intStr: 234}, 9 | } 10 | } 11 | 12 | module InputCArr = { 13 | let get = (): option> => Some([{intStr: 123}]) 14 | } 15 | 16 | module IntStr = { 17 | let get = () => 456 18 | } 19 | 20 | module IntStrArr = { 21 | let get = () => [456] 22 | } 23 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RelayEnv.res: -------------------------------------------------------------------------------- 1 | exception Graphql_error(string) 2 | 3 | let fetchQuery: RescriptRelay.Network.fetchFunctionPromise = async ( 4 | operation, 5 | variables, 6 | _cacheConfig, 7 | _uploadables, 8 | ) => { 9 | open Fetch 10 | let resp = await fetch( 11 | "http://graphql/", 12 | { 13 | method: #POST, 14 | body: {"query": operation.text, "id": operation.id, "variables": variables} 15 | ->Js.Json.stringifyAny 16 | ->Belt.Option.getExn 17 | ->Body.string, 18 | headers: Headers.fromObject({ 19 | "content-type": "application/json", 20 | "accept": "application/json", 21 | }), 22 | }, 23 | ) 24 | 25 | if Response.ok(resp) { 26 | let json = await Response.json(resp) 27 | RescriptRelay.Network.preloadResources(~operation, ~variables, ~response=json) 28 | json 29 | } else { 30 | raise(Graphql_error("Request failed: " ++ Response.statusText(resp))) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RelayLocalUserModel.res: -------------------------------------------------------------------------------- 1 | type t = { 2 | id: string, 3 | name: string, 4 | } 5 | 6 | module UserService = { 7 | let getById = id => Some({id, name: "Test User"}) 8 | } 9 | /** 10 | * @RelayResolver LocalUser 11 | */ 12 | let localUser /* : LocalUser_relayResolvers_graphql.localUser_entityResolver */ = id => { 13 | UserService.getById(id->RescriptRelay.dataIdToString) 14 | } 15 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RelayRouter.res: -------------------------------------------------------------------------------- 1 | // Just to enable testing 2 | 3 | let useRegisterPreloadedAsset = (asset: RelayRouter__Types.preloadAsset) => { 4 | ignore(asset) 5 | } 6 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RelayRouter__Types.res: -------------------------------------------------------------------------------- 1 | // Copied from the router, just to enable testing. 2 | type preloadComponentAsset = { 3 | @as("__$rescriptChunkName__") chunk: string, 4 | load: unit => unit, 5 | } 6 | 7 | @live 8 | type preloadAsset = 9 | | Component(preloadComponentAsset) 10 | | Image({url: string}) 11 | | Style({url: string}) 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RelayUserMetaModel.res: -------------------------------------------------------------------------------- 1 | /** 2 | * @RelayResolver UserMeta 3 | * @weak 4 | */ 5 | type t = {online: bool} 6 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/RichContent.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment RichContent_content on RichContent { 3 | content 4 | } 5 | `) 6 | 7 | @react.component 8 | let make = (~content: RescriptRelay.fragmentRefs<[#RichContent_content]>) => { 9 | let content = Fragment.use(content) 10 | 11 |
{React.string("Rich content: " ++ content.content)}
12 | } 13 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestCompileInterfaces.res: -------------------------------------------------------------------------------- 1 | module SubFragment = %relay(` 2 | fragment TestCompileInterfacesFragment_user on User { 3 | lastName 4 | } 5 | `) 6 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestCompileInterfaces.resi: -------------------------------------------------------------------------------- 1 | module SubFragment: { 2 | module Types = TestCompileInterfacesFragment_user_graphql.Types 3 | module Operation = TestCompileInterfacesFragment_user_graphql 4 | let convertFragment: TestCompileInterfacesFragment_user_graphql.Types.fragment => TestCompileInterfacesFragment_user_graphql.Types.fragment 5 | let use: RescriptRelay.fragmentRefs< 6 | [> #TestCompileInterfacesFragment_user], 7 | > => TestCompileInterfacesFragment_user_graphql.Types.fragment 8 | let useOpt: option #TestCompileInterfacesFragment_user]>> => option< 9 | TestCompileInterfacesFragment_user_graphql.Types.fragment, 10 | > 11 | } 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestDeferredComponent.res: -------------------------------------------------------------------------------- 1 | @react.component @relay.deferredComponent 2 | let make = (~name) => { 3 | React.string(name) 4 | } 5 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestProviders.res: -------------------------------------------------------------------------------- 1 | module Wrapper = { 2 | @react.component 3 | let make = (~environment, ~children) => 4 | {React.string("Loading...")} }> 5 | children 6 | 7 | } 8 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestRelayResolvers.res: -------------------------------------------------------------------------------- 1 | /** 2 | * @RelayResolver UserMeta.online: Boolean 3 | */ 4 | let online = userMeta => { 5 | userMeta.online 6 | } 7 | 8 | /** 9 | * @RelayResolver LocalUser.meta: UserMeta 10 | */ 11 | let meta = user => { 12 | { 13 | online: user.name === "Test User", 14 | } 15 | } 16 | 17 | /** 18 | * @RelayResolver LocalUser.name: String 19 | */ 20 | let name = user => { 21 | user.name 22 | } 23 | 24 | /** 25 | * @RelayResolver Query.localUser: LocalUser 26 | */ 27 | let localUser = () => { 28 | { 29 | id: "local-user-1"->RescriptRelay.makeDataId, 30 | } 31 | } 32 | 33 | /** 34 | * @RelayResolver LocalUser.nameRepeated(times: Int!): String 35 | */ 36 | let nameRepeated = (user, args) => { 37 | user.name->Js.String2.repeat(args.times) 38 | } 39 | 40 | /** 41 | * @RelayResolver LocalUser.hasBeenOnlineToday: Boolean 42 | * @live 43 | */ 44 | let hasBeenOnlineToday = user => { 45 | read: suspenseSentinel => { 46 | switch UserService.getUserStatus(user.id) { 47 | | Fetching => suspenseSentinel->RescriptRelay.SuspenseSentinel.suspend 48 | | Value(v) => v 49 | } 50 | }, 51 | subscribe: cb => { 52 | let id = UserService.subscribe(cb) 53 | () => UserService.unsubscribe(id) 54 | }, 55 | } 56 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestRelayUserResolver.res: -------------------------------------------------------------------------------- 1 | type t = string 2 | 3 | /** 4 | * @RelayResolver User.fullName:RelayResolverValue 5 | * @rootFragment TestRelayUserResolver 6 | * 7 | * A users full name. 8 | */ 9 | module Fragment = %relay(` 10 | fragment TestRelayUserResolver on User { 11 | firstName 12 | lastName 13 | } 14 | `) 15 | 16 | let fullName = Fragment.makeRelayResolver(user => { 17 | Some(`${user.firstName} ${user.lastName}`) 18 | }) 19 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestRelayUserResolver2.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment TestRelayUserResolver2 on User { 3 | firstName 4 | lastName 5 | } 6 | `) 7 | 8 | /** 9 | * @RelayResolver User.fullName2(maxLength: Int!): String 10 | * @rootFragment TestRelayUserResolver2 11 | * 12 | * A users full name 2. 13 | */ 14 | let fullName2 = (user, args) => { 15 | let user = Fragment.readResolverFragment(user) 16 | `${user.firstName} ${user.lastName}`->Js.String2.slice(~from=0, ~to_=args.maxLength) 17 | } 18 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_aliasedFragments-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_aliasedFragments } = require("./Test_aliasedFragments.bs"); 7 | 8 | describe("Aliased fragments", () => { 9 | test("basic fragments work", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestAliasedFragmentsQuery", 12 | variables: { 13 | skipThing: false, 14 | }, 15 | data: { 16 | loggedInUser: { 17 | id: "user-1", 18 | firstName: "First", 19 | lastName: "Last", 20 | }, 21 | }, 22 | }); 23 | 24 | t.render(test_aliasedFragments()); 25 | await t.screen.findByText("First Last"); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_aliasedFragments.res: -------------------------------------------------------------------------------- 1 | module FragmentFirstName = %relay(` 2 | fragment TestAliasedFragments_userFirstName on User { 3 | firstName 4 | } 5 | `) 6 | 7 | module FragmentLastName = %relay(` 8 | fragment TestAliasedFragments_userLastName on User { 9 | lastName 10 | } 11 | `) 12 | 13 | module Query = %relay(` 14 | query TestAliasedFragmentsQuery($skipThing: Boolean!) { 15 | loggedInUser { 16 | ...TestAliasedFragments_userFirstName @alias 17 | ...TestAliasedFragments_userLastName @alias @skip(if: $skipThing) 18 | } 19 | } 20 | `) 21 | 22 | module Test = { 23 | @react.component 24 | let make = () => { 25 | let query = Query.use(~variables={skipThing: false}) 26 | let firstNameData = FragmentFirstName.use(query.loggedInUser.testAliasedFragments_userFirstName) 27 | let lastNameData = FragmentLastName.useOpt(query.loggedInUser.testAliasedFragments_userLastName) 28 | 29 |
30 | {React.string( 31 | firstNameData.firstName ++ 32 | " " ++ 33 | switch lastNameData { 34 | | None => "-" 35 | | Some({lastName}) => lastName 36 | }, 37 | )} 38 |
39 | } 40 | } 41 | 42 | @live 43 | let test_aliasedFragments = () => { 44 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 45 | 46 | let environment = RescriptRelay.Environment.make( 47 | ~network, 48 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 49 | ) 50 | 51 | 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_customScalars-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_customScalars } = require("./Test_customScalars.bs"); 7 | 8 | describe("Custom Scalars", () => { 9 | test("custom scalars defined as modules are automatically converted", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestCustomScalarsQuery", 12 | variables: { 13 | beforeDate: "2018-01-01T00:00:00.000Z", 14 | number: 2, 15 | }, 16 | data: { 17 | loggedInUser: { 18 | id: "user-2", 19 | createdAt: new Date(2020, 1, 1, 0, 0, 0, 0).toJSON(), 20 | friends: [], 21 | }, 22 | member: { 23 | id: "user-1", 24 | __typename: "User", 25 | createdAt: new Date(2019, 1, 1, 0, 0, 0, 0).toJSON(), 26 | }, 27 | }, 28 | }); 29 | 30 | t.render(test_customScalars()); 31 | await t.screen.findByText( 32 | "loggedInUser createdAt: " + 33 | new Date(2020, 1, 1, 0, 0, 0, 0).getTime().toString() 34 | ); 35 | 36 | await t.screen.findByText( 37 | "member createdAt: " + 38 | new Date(2019, 1, 1, 0, 0, 0, 0).getTime().toString() 39 | ); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_customScalars.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestCustomScalarsQuery($beforeDate: Datetime, $number: Number!) { 3 | loggedInUser { 4 | createdAt 5 | friends(beforeDate: $beforeDate, number: $number) { 6 | createdAt 7 | } 8 | } 9 | 10 | member(id: "user-1") { 11 | ... on User { 12 | createdAt 13 | } 14 | } 15 | } 16 | `) 17 | 18 | module Test = { 19 | @react.component 20 | let make = () => { 21 | let query = { 22 | Query.use( 23 | ~variables={ 24 | beforeDate: Js.Date.fromFloat(1514764800000.), 25 | number: [2], 26 | }, 27 | ) 28 | } 29 | 30 | <> 31 |
32 | {React.string( 33 | "loggedInUser createdAt: " ++ 34 | query.loggedInUser.createdAt->Js.Date.getTime->Js.Float.toString, 35 | )} 36 |
37 |
38 | {switch query.member { 39 | | Some(User(user)) => 40 | React.string("member createdAt: " ++ user.createdAt->Js.Date.getTime->Js.Float.toString) 41 | | Some(UnselectedUnionMember(_)) | None => React.null 42 | }} 43 |
44 | 45 | } 46 | } 47 | 48 | @live 49 | let test_customScalars = () => { 50 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 51 | 52 | let environment = RescriptRelay.Environment.make( 53 | ~network, 54 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 55 | ) 56 | 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_deferredComponent.res: -------------------------------------------------------------------------------- 1 | module DeferredTest = %relay.deferredComponent(TestDeferredComponent.make) 2 | 3 | let jsx = 4 | Js.log(jsx) 5 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_inputUnion-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_inputUnion } = require("./Test_inputUnion.bs"); 7 | 8 | describe("Query", () => { 9 | test("conversion of input unions work", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestInputUnionQuery", 12 | variables: { 13 | location: { 14 | byAddress: { 15 | city: "City", 16 | }, 17 | }, 18 | }, 19 | data: { 20 | findByLocation: "Got it", 21 | }, 22 | }); 23 | 24 | queryMock.mockQuery({ 25 | name: "TestInputUnionQuery", 26 | variables: { 27 | location: { 28 | byId: "", 29 | }, 30 | }, 31 | data: { 32 | findByLocation: "Got ID", 33 | }, 34 | }); 35 | 36 | t.render(test_inputUnion()); 37 | await t.screen.findByText("Got it"); 38 | await t.screen.findByText("Got ID"); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_inputUnion.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestInputUnionQuery($location: Location!) { 3 | findByLocation(location: $location) 4 | } 5 | `) 6 | 7 | module Test = { 8 | @react.component 9 | let make = () => { 10 | let data = Query.use( 11 | ~variables={ 12 | location: ByAddress({city: "City"}), 13 | }, 14 | ) 15 | 16 | let data2 = Query.use( 17 | ~variables={ 18 | location: ById(""), 19 | }, 20 | ) 21 | 22 | <> 23 |
{React.string(data.findByLocation->Belt.Option.getWithDefault("-"))}
24 |
{React.string(data2.findByLocation->Belt.Option.getWithDefault("-"))}
25 | 26 | } 27 | } 28 | 29 | @live 30 | let test_inputUnion = () => { 31 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 32 | 33 | let environment = RescriptRelay.Environment.make( 34 | ~network, 35 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 36 | ) 37 | 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_misingFieldHandlers-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_missingFieldHandlers } = require("./Test_missingFieldHandlers.bs"); 7 | const { fireEvent } = require("@testing-library/react"); 8 | const ReactTestUtils = require("react-dom/test-utils"); 9 | 10 | describe("Missing field handlers", () => { 11 | test("resolves nodes via top level node field from cache automatically", async () => { 12 | queryMock.mockQuery({ 13 | name: "TestMissingFieldHandlersMeQuery", 14 | data: { 15 | loggedInUser: { 16 | firstName: "First", 17 | id: "123", 18 | }, 19 | }, 20 | }); 21 | 22 | t.render(test_missingFieldHandlers()); 23 | await t.screen.findByText("1: First"); 24 | 25 | ReactTestUtils.act(() => { 26 | fireEvent.click(t.screen.getByText("Show next")); 27 | }); 28 | await t.screen.findByText("2: First"); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_missingFieldHandlers.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestMissingFieldHandlersQuery { 3 | node(id: "123") { 4 | ... on User { 5 | firstName 6 | } 7 | } 8 | } 9 | `) 10 | 11 | module MeQuery = %relay(` 12 | query TestMissingFieldHandlersMeQuery { 13 | loggedInUser { 14 | firstName 15 | } 16 | } 17 | `) 18 | 19 | module RenderMe = { 20 | @react.component 21 | let make = () => { 22 | let query = Query.use(~variables=(), ~fetchPolicy=StoreOnly) 23 | 24 | switch query.node { 25 | | Some(User(user)) => React.string("2: " ++ user.firstName) 26 | | _ => React.string("-") 27 | } 28 | } 29 | } 30 | 31 | module Test = { 32 | @react.component 33 | let make = () => { 34 | let query = MeQuery.use(~variables=()) 35 | let (showNext, setShowNext) = React.useState(() => false) 36 | 37 | <> 38 |
{React.string("1: " ++ query.loggedInUser.firstName)}
39 | {showNext 40 | ? 41 | : } 42 | 43 | } 44 | } 45 | 46 | @live 47 | let test_missingFieldHandlers = () => { 48 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 49 | 50 | let environment = RescriptRelay.Environment.make( 51 | ~network, 52 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 53 | ) 54 | 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_mutation.resi: -------------------------------------------------------------------------------- 1 | @live 2 | let test_mutation: unit => React.element 3 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nodeInterface-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_nodeInterface } = require("./Test_nodeInterface.bs"); 7 | 8 | describe("Node interface", () => { 9 | test("collapsed when only one sub selection exists", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestNodeInterfaceQuery", 12 | data: { 13 | node: { 14 | __typename: "User", 15 | firstName: "First", 16 | id: "123", 17 | }, 18 | }, 19 | }); 20 | 21 | t.render(test_nodeInterface()); 22 | await t.screen.findByText("First"); 23 | }); 24 | 25 | test("validates the typename", async () => { 26 | queryMock.mockQuery({ 27 | name: "TestNodeInterfaceQuery", 28 | data: { 29 | node: { 30 | id: "123", 31 | __typename: "SomethingElse", // This is now invalid/unexpected 32 | }, 33 | }, 34 | }); 35 | 36 | t.render(test_nodeInterface()); 37 | await t.screen.findByText("-"); 38 | }); 39 | 40 | test("nulls node when not of matching type", async () => { 41 | queryMock.mockQuery({ 42 | name: "TestNodeInterfaceQuery", 43 | data: { 44 | node: { 45 | __typename: "Group", 46 | firstName: "First", 47 | id: "123", 48 | }, 49 | }, 50 | }); 51 | 52 | t.render(test_nodeInterface()); 53 | await t.screen.findByText("-"); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nodeInterface.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment TestNodeInterface_user on User { 3 | firstName 4 | } 5 | `) 6 | 7 | module Query = %relay(` 8 | query TestNodeInterfaceQuery { 9 | node(id: "123") { 10 | ... on User { 11 | firstName 12 | ...TestNodeInterface_user 13 | } 14 | } 15 | } 16 | `) 17 | 18 | // This should deoptimize to not collapse the node interface, since the spread 19 | // is on an abstract type. 20 | module QueryAbstract = %relay(` 21 | query TestNodeInterfaceOnAbstractTypeQuery { 22 | node(id: "123") { 23 | ... on Member { 24 | ... on User { 25 | firstName 26 | } 27 | ... on Group { 28 | name 29 | } 30 | } 31 | } 32 | } 33 | `) 34 | 35 | module Test = { 36 | @react.component 37 | let make = () => { 38 | let query = Query.use(~variables=()) 39 | 40 | switch query.node { 41 | | Some(User(user)) => React.string(user.firstName) 42 | | _ => React.string("-") 43 | } 44 | } 45 | } 46 | 47 | @live 48 | let test_nodeInterface = () => { 49 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 50 | 51 | let environment = RescriptRelay.Environment.make( 52 | ~network, 53 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 54 | ) 55 | 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nonReact-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const queryMock = require("./queryMock"); 3 | 4 | const { test_nonReact } = require("./Test_nonReact.bs"); 5 | 6 | describe("Fragment", () => { 7 | test("waitForFragmentData works", async () => { 8 | queryMock.mockQuery({ 9 | name: "TestNonReactQuery", 10 | data: { 11 | loggedInUser: { 12 | id: "user-1", 13 | firstName: "First", 14 | onlineStatus: "Online", 15 | }, 16 | }, 17 | }); 18 | 19 | const res = await test_nonReact(); 20 | expect(res.waitForFragmentData).toEqual({ 21 | firstName: "First", 22 | onlineStatus: "Online", 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nonReact.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestNonReactQuery { 3 | loggedInUser { 4 | firstName 5 | ...TestNonReact_user 6 | } 7 | } 8 | `) 9 | 10 | module Fragment = %relay(` 11 | fragment TestNonReact_user on User { 12 | firstName 13 | onlineStatus 14 | } 15 | `) 16 | 17 | @live 18 | let test_nonReact = async () => { 19 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 20 | 21 | let environment = RescriptRelay.Environment.make( 22 | ~network, 23 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 24 | ) 25 | 26 | let query = await Query.fetchPromised(~environment, ~variables=()) 27 | let fragmentData = await Fragment.waitForFragmentData( 28 | ~environment, 29 | query.loggedInUser.fragmentRefs, 30 | ) 31 | 32 | { 33 | "waitForFragmentData": fragmentData, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nullableVariables-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { test_nullableVariables } = require("./Test_nullableVariables.bs"); 8 | 9 | describe("Mutation", () => { 10 | test("variables can be null", async () => { 11 | queryMock.mockQuery({ 12 | name: "TestNullableVariablesQuery", 13 | data: { 14 | loggedInUser: { 15 | id: "user-1", 16 | avatarUrl: "avatar-url-1", 17 | }, 18 | }, 19 | }); 20 | 21 | t.render(test_nullableVariables()); 22 | await t.screen.findByText("Avatar url is avatar-url-1"); 23 | 24 | queryMock.mockQuery({ 25 | name: "TestNullableVariablesMutation", 26 | variables: { 27 | avatarUrl: null, 28 | someInput: { 29 | int: null, 30 | }, 31 | }, 32 | data: { 33 | updateUserAvatar: { 34 | user: { 35 | id: "user-1", 36 | avatarUrl: null, 37 | someRandomArgField: "test", 38 | }, 39 | }, 40 | }, 41 | }); 42 | 43 | ReactTestUtils.act(() => { 44 | t.fireEvent.click(t.screen.getByText("Change avatar URL")); 45 | }); 46 | 47 | await t.screen.findByText("Avatar url is -"); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_nullableVariables.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestNullableVariablesQuery { 3 | loggedInUser { 4 | avatarUrl 5 | } 6 | } 7 | `) 8 | 9 | module Mutation = %relay(` 10 | mutation TestNullableVariablesMutation($avatarUrl: String, $someInput: SomeInput) @rescriptRelayNullableVariables { 11 | updateUserAvatar(avatarUrl: $avatarUrl) { 12 | user { 13 | avatarUrl 14 | someRandomArgField(someInput: $someInput) 15 | } 16 | } 17 | } 18 | `) 19 | 20 | module Test = { 21 | @react.component 22 | let make = () => { 23 | let environment = RescriptRelay.useEnvironmentFromContext() 24 | let query = Query.use(~variables=()) 25 | let data = query.loggedInUser 26 | 27 |
28 | {React.string("Avatar url is " ++ data.avatarUrl->Belt.Option.getWithDefault("-"))} 29 | 43 |
44 | } 45 | } 46 | 47 | @live 48 | let test_nullableVariables = () => { 49 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 50 | 51 | let environment = RescriptRelay.Environment.make( 52 | ~network, 53 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 54 | ) 55 | 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_observer-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | 5 | const { test_observer } = require("./Test_observer.bs"); 6 | 7 | describe("Observer", () => { 8 | it("errors properly", async () => { 9 | t.render(test_observer()); 10 | await t.screen.findByText("Failed"); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_observer.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestObserverQuery { 3 | loggedInUser { 4 | id 5 | } 6 | } 7 | `) 8 | 9 | module Test = { 10 | @react.component 11 | let make = () => { 12 | let data = Query.use(~variables=()) 13 | 14 |
{React.string(data.loggedInUser.id)}
15 | } 16 | } 17 | 18 | @live 19 | let test_observer = () => { 20 | let network = RescriptRelay.Network.makeObservableBased(~observableFunction=(_, _, _, _) => { 21 | RescriptRelay.Observable.make(sink => { 22 | try { 23 | Js.Exn.raiseError("Some error") 24 | } catch { 25 | | Js.Exn.Error(obj) => 26 | sink.error(obj) 27 | sink.complete() 28 | } 29 | 30 | None 31 | }) 32 | }) 33 | 34 | let environment = RescriptRelay.Environment.make( 35 | ~network, 36 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 37 | ) 38 | 39 | React.string("Failed")}> 40 | 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_parseCustomScalarArray-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { 7 | test_parseCustomScalarArray, 8 | } = require("./Test_parseCustomScalarArray.bs"); 9 | 10 | describe("Parse Custom Scalar Array", () => { 11 | test("array of a custom scalars defined as modules are automatically converted", async () => { 12 | queryMock.mockQuery({ 13 | name: "TestParseCustomScalarArrayQuery", 14 | data: { 15 | loggedInUser: { 16 | id: "user-2", 17 | intStrings: ["1", "2", "3"], 18 | intString: "9", 19 | justStrings: ["10", "20", "30"], 20 | justString: "99", 21 | }, 22 | }, 23 | }); 24 | 25 | t.render(test_parseCustomScalarArray()); 26 | 27 | await t.screen.findByText("10, 20, 30"); 28 | await t.screen.findByText("9"); 29 | await t.screen.findByText("99"); 30 | await t.screen.findByText("1, 2, 3"); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_parseCustomScalarArray.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestParseCustomScalarArrayQuery { 3 | loggedInUser { 4 | intStrings 5 | intString 6 | justStrings 7 | justString 8 | } 9 | } 10 | `) 11 | 12 | module Test = { 13 | @react.component 14 | let make = () => { 15 | let query = { 16 | Query.use(~variables=()) 17 | } 18 | 19 | let intStrings = query.loggedInUser.intStrings->Belt.Option.getWithDefault([]) 20 | let intString = query.loggedInUser.intString 21 | let justStrings = query.loggedInUser.justStrings->Belt.Option.getWithDefault([]) 22 | let justString = query.loggedInUser.justString 23 | 24 | <> 25 |
26 | {intStrings 27 | ->Belt.Array.map(Belt.Int.toString(_)) 28 | ->Js.Array2.joinWith(", ") 29 | ->React.string} 30 |
31 |
32 | {intString 33 | ->Belt.Option.map(React.int(_)) 34 | ->Belt.Option.getWithDefault(React.null)} 35 |
36 |
37 | {justStrings 38 | ->Js.Array2.joinWith(", ") 39 | ->React.string} 40 |
41 |
42 | {justString 43 | ->Belt.Option.map(React.string(_)) 44 | ->Belt.Option.getWithDefault(React.null)} 45 |
46 | 47 | } 48 | } 49 | 50 | @live 51 | let test_parseCustomScalarArray = () => { 52 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 53 | 54 | let environment = RescriptRelay.Environment.make( 55 | ~network, 56 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 57 | ) 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_providedVariables-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { test_providedVariables } = require("./Test_providedVariables.bs"); 8 | 9 | describe("Provided variables", () => { 10 | test("provided variables work", async () => { 11 | queryMock.mockQuery({ 12 | name: "TestProvidedVariablesQuery", 13 | variables: { 14 | __relay_internal__pv__ProvidedVariablesBool: true, 15 | __relay_internal__pv__ProvidedVariablesInputC: { 16 | intStr: "123", 17 | recursiveC: { 18 | intStr: "234", 19 | }, 20 | }, 21 | __relay_internal__pv__ProvidedVariablesInputCArr: [ 22 | { 23 | intStr: "123", 24 | }, 25 | ], 26 | __relay_internal__pv__ProvidedVariablesIntStr: "456", 27 | __relay_internal__pv__ProvidedVariablesIntStrArr: ["456"], 28 | }, 29 | data: { 30 | loggedInUser: { 31 | __typename: "User", 32 | id: "user-1", 33 | someRandomArgField: "hello", 34 | }, 35 | }, 36 | }); 37 | 38 | t.render(test_providedVariables()); 39 | await t.screen.findByText("hello"); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_providedVariables.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment TestProvidedVariables_user on User 3 | @argumentDefinitions( 4 | # Regular unconverted value 5 | bool: { type: "Boolean!", provider: "ProvidedVariables.Bool" } 6 | 7 | # Recursive input with custom scalar 8 | inputC: { type: "InputC!", provider: "ProvidedVariables.InputC" } 9 | 10 | # Array of recursive input with custom scalar 11 | inputCArr: { type: "[InputC!]", provider: "ProvidedVariables.InputCArr" } 12 | 13 | # Custom scalar 14 | intStr: { type: "IntString!", provider: "ProvidedVariables.IntStr" } 15 | 16 | # Custom scalar array 17 | intStrArr: { type: "[IntString!]!", provider: "ProvidedVariables.IntStrArr" } 18 | ) { 19 | someRandomArgField(bool: $bool, inputC: $inputC, inputCArr: $inputCArr, intStr: $intStr, intStrArr: $intStrArr) 20 | } 21 | `) 22 | 23 | module Query = %relay(` 24 | query TestProvidedVariablesQuery { 25 | loggedInUser { 26 | ...TestProvidedVariables_user 27 | } 28 | } 29 | `) 30 | 31 | module Test = { 32 | @react.component 33 | let make = () => { 34 | let query = Query.use(~variables=()) 35 | let user = Fragment.use(query.loggedInUser.fragmentRefs) 36 | 37 |
{React.string(user.someRandomArgField->Belt.Option.getWithDefault("-"))}
38 | } 39 | } 40 | 41 | @live 42 | let test_providedVariables = () => { 43 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 44 | 45 | let environment = RescriptRelay.Environment.make( 46 | ~network, 47 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 48 | ) 49 | 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_queryInputObjects-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_queryInputObjects } = require("./Test_queryInputObjects.bs"); 7 | 8 | describe("Query with input objects", () => { 9 | test("basic input object conversion works", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestQueryInputObjectsQuery", 12 | variables: { 13 | input: { 14 | id: 123, 15 | someOtherId: 1.5, 16 | }, 17 | }, 18 | data: { 19 | search: "yup", 20 | }, 21 | }); 22 | 23 | t.render(test_queryInputObjects()); 24 | await t.screen.findByText("yup"); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_queryInputObjects.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestQueryInputObjectsQuery($input: SearchInput!) { 3 | search(input: $input) 4 | } 5 | `) 6 | 7 | module Test = { 8 | @react.component 9 | let make = () => { 10 | let data = Query.use(~variables={input: {id: 123, someOtherId: 1.5}}) 11 | 12 |
13 | {switch data.search { 14 | | None => React.string("-") 15 | | Some(search) => React.string(search) 16 | }} 17 |
18 | } 19 | } 20 | 21 | @live 22 | let test_queryInputObjects = () => { 23 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 24 | 25 | let environment = RescriptRelay.Environment.make( 26 | ~network, 27 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 28 | ) 29 | 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_refetching-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { test_refetching } = require("./Test_refetching.bs"); 8 | 9 | describe("Fragment", () => { 10 | test("refetching works", async () => { 11 | queryMock.mockQuery({ 12 | name: "TestRefetchingQuery", 13 | data: { 14 | loggedInUser: { 15 | id: "user-1", 16 | firstName: "First", 17 | onlineStatus: null, 18 | friendsConnection: { 19 | totalCount: 20, 20 | }, 21 | }, 22 | }, 23 | }); 24 | 25 | t.render(test_refetching()); 26 | 27 | await t.screen.findByText("First is -"); 28 | await t.screen.findByText("Friends: 20"); 29 | 30 | queryMock.mockQuery({ 31 | name: "TestRefetchingRefetchQuery", 32 | variables: { 33 | id: "user-1", 34 | showOnlineStatus: true, 35 | friendsOnlineStatuses: ["Online", "offline"], 36 | }, 37 | data: { 38 | node: { 39 | __typename: "User", 40 | id: "user-1", 41 | firstName: "First", 42 | onlineStatus: "Online", 43 | friendsConnection: { 44 | totalCount: 10, 45 | }, 46 | }, 47 | }, 48 | }); 49 | 50 | ReactTestUtils.act(() => { 51 | t.fireEvent.click(t.screen.getByText("Fetch online status")); 52 | }); 53 | 54 | await t.screen.findByText("First is online"); 55 | await t.screen.findByText("Friends: 10"); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_refetchingInNode-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const queryMock = require("./queryMock"); 4 | const ReactTestUtils = require("react-dom/test-utils"); 5 | 6 | const { test_refetching } = require("./Test_refetchingInNode.bs"); 7 | 8 | describe("Fragment", () => { 9 | test("refetching in node works", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestRefetchingInNodeQuery", 12 | variables: { 13 | userId: "user-1", 14 | friendsOnlineStatuses: ["Online"], 15 | }, 16 | data: { 17 | node: { 18 | __typename: "User", 19 | id: "user-1", 20 | firstName: "First", 21 | onlineStatus: null, 22 | friendsConnection: { 23 | totalCount: 10, 24 | }, 25 | }, 26 | }, 27 | }); 28 | 29 | t.render(test_refetching()); 30 | 31 | await t.screen.findByText("First is -"); 32 | await t.screen.findByText("Friends: 10"); 33 | 34 | queryMock.mockQuery({ 35 | name: "TestRefetchingInNodeRefetchQuery", 36 | variables: { 37 | id: "user-1", 38 | showOnlineStatus: true, 39 | friendsOnlineStatuses: null, 40 | }, 41 | data: { 42 | node: { 43 | __typename: "User", 44 | id: "user-1", 45 | firstName: "First", 46 | onlineStatus: "Online", 47 | friendsConnection: { 48 | totalCount: 20, 49 | }, 50 | }, 51 | }, 52 | }); 53 | 54 | ReactTestUtils.act(() => { 55 | t.fireEvent.click(t.screen.getByText("Fetch online status")); 56 | }); 57 | 58 | await t.screen.findByText("First is online"); 59 | await t.screen.findByText("Friends: 20"); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_relayResolvers-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_relayResolvers } = require("./Test_relayResolvers.bs"); 7 | 8 | describe("Relay Resolvers", () => { 9 | test("basic Relay Resolvers work", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestRelayResolversQuery", 12 | data: { 13 | loggedInUser: { 14 | id: "user-1", 15 | firstName: "First", 16 | lastName: "Last", 17 | isOnline: true, 18 | }, 19 | }, 20 | }); 21 | 22 | t.render(test_relayResolvers()); 23 | await t.screen.findByText("First Last Fi is online"); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_relayResolvers.res: -------------------------------------------------------------------------------- 1 | RescriptRelay.relayFeatureFlags.enableRelayResolvers = true 2 | 3 | module Query = %relay(` 4 | query TestRelayResolversQuery { 5 | loggedInUser { 6 | ...TestRelayResolvers_user 7 | } 8 | } 9 | `) 10 | 11 | module Fragment = %relay(` 12 | fragment TestRelayResolvers_user on User { 13 | isOnline 14 | fullName 15 | fullName2(maxLength: 2) 16 | } 17 | `) 18 | 19 | module Test = { 20 | @react.component 21 | let make = () => { 22 | let query = Query.use(~variables=()) 23 | let data = Fragment.use(query.loggedInUser.fragmentRefs) 24 | 25 |
26 | {switch data { 27 | | {isOnline: Some(isOnline), fullName: Some(fullName), fullName2: Some(fullName2)} => 28 | React.string(`${fullName} ${fullName2} is ${isOnline ? "online" : "offline"}`) 29 | | _ => React.string("-") 30 | }} 31 |
32 | } 33 | } 34 | 35 | @live 36 | let test_relayResolvers = () => { 37 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 38 | 39 | let environment = RescriptRelay.Environment.make( 40 | ~network, 41 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 42 | ) 43 | 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_relayResolversAll-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | 6 | const { test_relayResolversAll } = require("./Test_relayResolversAll.bs"); 7 | 8 | describe("Relay Resolvers all", () => { 9 | test("basic Relay Resolvers work", async () => { 10 | queryMock.mockQuery({ 11 | name: "TestRelayResolversAllQuery", 12 | data: {}, 13 | }); 14 | 15 | t.render(test_relayResolversAll()); 16 | await t.screen.findByText( 17 | "Test User is online, Test UserTest User and has been online today: true" 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_relayResolversAll.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestRelayResolversAllQuery { 3 | localUser { 4 | name 5 | nameRepeated(times: 2) 6 | meta @required(action: NONE) { 7 | online 8 | } 9 | hasBeenOnlineToday 10 | } 11 | } 12 | `) 13 | 14 | module Test = { 15 | @react.component 16 | let make = () => { 17 | let data = Query.use(~variables=(), ~fetchPolicy=StoreOnly) 18 | 19 |
20 | {switch data.localUser { 21 | | Some({ 22 | meta: {online: Some(online)}, 23 | name: Some(name), 24 | nameRepeated: Some(nameRepeated), 25 | hasBeenOnlineToday: Some(hasBeenOnlineToday), 26 | }) => 27 | React.string( 28 | name ++ 29 | " is " ++ 30 | (online ? "online" : "offline") ++ 31 | ", " ++ 32 | nameRepeated ++ 33 | " and has been online today: " ++ 34 | switch hasBeenOnlineToday { 35 | | false => "false" 36 | | true => "true" 37 | }, 38 | ) 39 | | _ => React.string("No user...") 40 | }} 41 |
42 | } 43 | } 44 | 45 | @live 46 | let test_relayResolversAll = () => { 47 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 48 | 49 | let environment = RescriptRelay.Environment.make( 50 | ~network, 51 | ~store=RescriptRelay.Store._makeLiveStoreCjs(~source=RescriptRelay.RecordSource.make()), 52 | ) 53 | 54 | RescriptRelay.relayFeatureFlags.enableRelayResolvers = true 55 | 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_requiredFieldLogger-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const queryMock = require("./queryMock"); 3 | 4 | const { 5 | test_requiredFieldLogger, 6 | getLoggedArg, 7 | expectedArg, 8 | } = require("./Test_requiredFieldLogger.bs"); 9 | 10 | describe("RequiredFieldLogger", () => { 11 | test("logs missing field", async () => { 12 | queryMock.mockQuery({ 13 | name: "TestRequiredFieldLoggerQuery", 14 | data: { 15 | loggedInUser: { 16 | id: "user-123", 17 | firstName: null, 18 | }, 19 | users: null, 20 | }, 21 | }); 22 | 23 | await test_requiredFieldLogger(); 24 | 25 | expect(getLoggedArg()).toStrictEqual(expectedArg); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_requiredFieldLogger.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query TestRequiredFieldLoggerQuery { 3 | loggedInUser { 4 | firstName @required(action: LOG) 5 | } 6 | } 7 | `) 8 | 9 | module Logger = { 10 | let loggedArg = ref((None: option)) 11 | 12 | let mock: RescriptRelay.RelayFieldLogger.t = arg => loggedArg := Some(arg) 13 | 14 | let getLoggedArg = () => loggedArg.contents 15 | 16 | let expectedArg: RescriptRelay.RelayFieldLogger.arg = MissingRequiredFieldLog({ 17 | owner: "TestRequiredFieldLoggerQuery", 18 | fieldPath: "loggedInUser.firstName", 19 | }) 20 | } 21 | 22 | @live 23 | let test_requiredFieldLogger = () => { 24 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 25 | 26 | let environment = RescriptRelay.Environment.make( 27 | ~network, 28 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 29 | ~relayFieldLogger=Logger.mock, 30 | ) 31 | 32 | Js.Promise.make((~resolve, ~reject as _) => { 33 | Query.fetch(~environment, ~variables=(), ~onResult=res => resolve(res)) 34 | }) 35 | } 36 | 37 | let getLoggedArg = Logger.getLoggedArg 38 | 39 | let expectedArg = Logger.expectedArg 40 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_serializeCustomScalarArray-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { 8 | test_serializeCustomScalarArray, 9 | } = require("./Test_serializeCustomScalarArray.bs"); 10 | 11 | describe("Serialize Custom Scalar Array", () => { 12 | test("serializes custom scalar array", async () => { 13 | const logSpy = jest.spyOn(console, "log"); 14 | t.render(test_serializeCustomScalarArray()); 15 | 16 | const resolveQuery = queryMock.mockQueryWithControlledResolution({ 17 | name: "TestSerializeCustomScalarArrayMutation", 18 | variables: { 19 | input: [97, 98, 99], 20 | }, 21 | data: { 22 | serializeCustomScalarArray: { 23 | works: true, 24 | }, 25 | }, 26 | }); 27 | 28 | ReactTestUtils.act(() => { 29 | t.fireEvent.click(t.screen.getByText("Fire mutation")); 30 | }); 31 | 32 | await t.screen.findByText("Mutating..."); 33 | 34 | ReactTestUtils.act(() => { 35 | resolveQuery(); 36 | }); 37 | 38 | expect(logSpy).toHaveBeenCalledTimes(3); 39 | expect(logSpy).toHaveBeenNthCalledWith(1, "serialize", 97); 40 | expect(logSpy).toHaveBeenNthCalledWith(2, "serialize", 98); 41 | expect(logSpy).toHaveBeenNthCalledWith(3, "serialize", 99); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_serializeCustomScalarArray.res: -------------------------------------------------------------------------------- 1 | module Mutation = %relay(` 2 | mutation TestSerializeCustomScalarArrayMutation($input: [IntString!]!) { 3 | serializeCustomScalarArray(input: $input) { 4 | works 5 | } 6 | } 7 | `) 8 | 9 | module Test = { 10 | @react.component 11 | let make = () => { 12 | let (mutate, isMutating) = Mutation.use() 13 | 14 |
15 | 21 | {if isMutating { 22 | React.string("Mutating...") 23 | } else { 24 | React.null 25 | }} 26 |
27 | } 28 | } 29 | 30 | @live 31 | let test_serializeCustomScalarArray = () => { 32 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery) 33 | 34 | let environment = RescriptRelay.Environment.make( 35 | ~network, 36 | ~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()), 37 | ) 38 | 39 | 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_subscription.resi: -------------------------------------------------------------------------------- 1 | @live 2 | let test_subscription: unit => { 3 | "pushNext": Js.Json.t => unit, 4 | "render": unit => React.element, 5 | "subscriptionFunction": ('b, 'c, 'd) => RescriptRelay.Observable.t, 6 | } 7 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_updatableFragments-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { test_updatableFragments } = require("./Test_updatableFragments.bs"); 8 | 9 | describe("Updatable fragments", () => { 10 | test("updatable fragments work", async () => { 11 | queryMock.mockQuery({ 12 | name: "TestUpdatableFragmentsQuery", 13 | data: { 14 | loggedInUser: { 15 | __typename: "User", 16 | id: "user-1", 17 | firstName: "First", 18 | isOnline: false, 19 | bestFriend: { 20 | __typename: "User", 21 | id: "user-2", 22 | firstName: "Isaac", 23 | }, 24 | }, 25 | }, 26 | }); 27 | 28 | t.render(test_updatableFragments()); 29 | await t.screen.findByText("First is offline and best friends with Isaac"); 30 | ReactTestUtils.act(() => { 31 | t.fireEvent.click(t.screen.getByText("Change status")); 32 | }); 33 | await t.screen.findByText("Mrmr is online and best friends with Newton"); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/Test_updatableQuery-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const t = require("@testing-library/react"); 3 | const React = require("react"); 4 | const queryMock = require("./queryMock"); 5 | const ReactTestUtils = require("react-dom/test-utils"); 6 | 7 | const { test_updatableQuery } = require("./Test_updatableQuery.bs"); 8 | 9 | describe("Updatable query", () => { 10 | test("updatable queries work", async () => { 11 | queryMock.mockQuery({ 12 | name: "TestUpdatableQuery", 13 | variables: { 14 | id: "user-1", 15 | }, 16 | data: { 17 | user: { 18 | __typename: "User", 19 | id: "user-1", 20 | firstName: "First", 21 | isOnline: false, 22 | bestFriend: { 23 | __typename: "User", 24 | id: "user-2", 25 | firstName: "Isaac", 26 | }, 27 | }, 28 | }, 29 | }); 30 | 31 | t.render(test_updatableQuery()); 32 | await t.screen.findByText("First is offline and best friends with Isaac"); 33 | ReactTestUtils.act(() => { 34 | t.fireEvent.click(t.screen.getByText("Change status")); 35 | }); 36 | await t.screen.findByText("Mrmr is online and best friends with Newton"); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/TestsUtils.res: -------------------------------------------------------------------------------- 1 | exception Malformed_date 2 | exception Malformed_number 3 | 4 | module Datetime = { 5 | @editor.completeFrom(Js.Date) 6 | type t = Js.Date.t 7 | 8 | let parse = t => 9 | switch t->Js.Json.decodeString { 10 | | None => raise(Malformed_date) 11 | | Some(dateStr) => dateStr->Js.Date.fromString 12 | } 13 | let serialize = t => t->Js.Date.toJSONUnsafe->Js.Json.string 14 | } 15 | 16 | module IntString = { 17 | type t = int 18 | @live let parse = Belt.Int.fromString 19 | let serialize = int => { 20 | // This log is used for testing purposes - do not remove 21 | Js.log2("serialize", int) 22 | Belt.Int.toString(int) 23 | } 24 | } 25 | 26 | type number = array 27 | 28 | module Number = { 29 | type t = number 30 | let serialize = t => Js.Json.number(Belt.Float.fromInt(t->Belt.Array.reduce(0, (x, y) => y + x))) 31 | 32 | let parse = t => 33 | switch t->Js.Json.decodeNumber { 34 | | None => raise(Malformed_number) 35 | | Some(_) => [] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/UserAvatar.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment UserAvatar_user on User { 3 | avatarUrl 4 | ...UserName_user @codesplit @alias 5 | } 6 | `) 7 | 8 | @react.component 9 | let make = (~user: RescriptRelay.fragmentRefs<[#UserAvatar_user]>) => { 10 | let user = Fragment.use(user) 11 | 12 | open Fragment.Operation.CodesplitComponents 13 | 14 | <> 15 |
16 | {React.string("User avatarUrl: " ++ user.avatarUrl->Belt.Option.getWithDefault("-"))} 17 |
18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/UserName.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment UserName_user on User { 3 | firstName 4 | lastName 5 | } 6 | `) 7 | 8 | @react.component 9 | let make = (~user: RescriptRelay.fragmentRefs<[#UserName_user]>) => { 10 | let user = Fragment.use(user) 11 |
{React.string("User name: " ++ user.firstName ++ " " ++ user.lastName)}
12 | } 13 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/UserService.res: -------------------------------------------------------------------------------- 1 | let subCounter = ref(0) 2 | let subscribers = [] 3 | 4 | let subscribe = cb => { 5 | let count = subCounter.contents 6 | subCounter := count + 1 7 | subscribers->Js.Array2.push((count, cb))->ignore 8 | count 9 | } 10 | 11 | let unsubscribe = id => { 12 | switch subscribers->Js.Array2.findIndex(((itemId, _)) => itemId === id) { 13 | | -1 => () 14 | | idx => subscribers->Js.Array2.spliceInPlace(~add=[], ~pos=idx, ~remove=1)->ignore 15 | } 16 | } 17 | 18 | let wait = duration => 19 | Js.Promise2.make((~resolve, ~reject as _) => { 20 | let _ = Js.Global.setTimeout(() => { 21 | resolve() 22 | }, duration) 23 | }) 24 | 25 | @unboxed 26 | type userStatusValue = Fetching | Value(bool) 27 | 28 | let userStatuses = Js.Dict.empty() 29 | 30 | let readUserStatus = userId => userStatuses->Js.Dict.get(userId) 31 | 32 | let getUserStatus = async userId => { 33 | userStatuses->Js.Dict.set(userId, Fetching) 34 | 35 | await wait(200) 36 | subscribers->Js.Array2.forEach(((_, cb)) => { 37 | cb() 38 | }) 39 | userStatuses->Js.Dict.set(userId, Value(true)) 40 | true 41 | } 42 | 43 | let getUserStatus = userId => { 44 | switch userStatuses->Js.Dict.get(userId) { 45 | | None => 46 | getUserStatus(userId)->ignore 47 | Fetching 48 | 49 | | Some(v) => v 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/GroupAvatar_group_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc GroupAvatar.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | name: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #GroupAvatar_group]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "GroupAvatar_group", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "name", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "Group", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/HasNameComponent_hasName_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc HasNameComponent.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | @live __typename: string, 9 | name: string, 10 | } 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{}` 19 | ) 20 | @live 21 | let fragmentConverterMap = () 22 | @live 23 | let convertFragment = v => v->RescriptRelay.convertObj( 24 | fragmentConverter, 25 | fragmentConverterMap, 26 | Js.undefined 27 | ) 28 | } 29 | 30 | type t 31 | type fragmentRef 32 | external getFragmentRef: 33 | RescriptRelay.fragmentRefs<[> | #HasNameComponent_hasName]> => fragmentRef = "%identity" 34 | 35 | module Utils = { 36 | @@warning("-33") 37 | open Types 38 | } 39 | 40 | type relayOperationNode 41 | type operationType = RescriptRelay.fragmentNode 42 | 43 | 44 | let node: operationType = %raw(json` { 45 | "argumentDefinitions": [], 46 | "kind": "Fragment", 47 | "metadata": null, 48 | "name": "HasNameComponent_hasName", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "__typename", 55 | "storageKey": null 56 | }, 57 | { 58 | "alias": null, 59 | "args": null, 60 | "kind": "ScalarField", 61 | "name": "name", 62 | "storageKey": null 63 | } 64 | ], 65 | "type": "HasName", 66 | "abstractKey": "__isHasName" 67 | } `) 68 | 69 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/LocalUser__id_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc RelayLocalUserModel.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | @live id: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #LocalUser__id]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "LocalUser__id", 48 | "selections": [ 49 | { 50 | "kind": "ClientExtension", 51 | "selections": [ 52 | { 53 | "alias": null, 54 | "args": null, 55 | "kind": "ScalarField", 56 | "name": "id", 57 | "storageKey": null 58 | } 59 | ] 60 | } 61 | ], 62 | "type": "LocalUser", 63 | "abstractKey": null 64 | } `) 65 | 66 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/LocalUser_relayResolvers_graphql.res: -------------------------------------------------------------------------------- 1 | /* @generated */ 2 | @@warning("-30") 3 | 4 | type metaResolver = (RelayLocalUserModel.t, ) => RelayUserMetaModel.t 5 | 6 | type nameResolver = (RelayLocalUserModel.t, ) => string 7 | 8 | type nameRepeatedResolverArgs = { 9 | times: int, 10 | } 11 | type nameRepeatedResolver = (RelayLocalUserModel.t, nameRepeatedResolverArgs) => string 12 | 13 | type hasBeenOnlineTodayResolver = (RelayLocalUserModel.t, ) => RescriptRelay.liveState 14 | 15 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/Query_relayResolvers_graphql.res: -------------------------------------------------------------------------------- 1 | /* @generated */ 2 | @@warning("-30") 3 | 4 | type localUserResolver = () => RescriptRelay.dataIdObject 5 | 6 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/RichContent_content_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc RichContent.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | content: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #RichContent_content]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "RichContent_content", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "content", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "RichContent", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestAliasedFragments_userFirstName_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Test_aliasedFragments.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | firstName: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #TestAliasedFragments_userFirstName]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "TestAliasedFragments_userFirstName", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "firstName", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "User", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestAliasedFragments_userLastName_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Test_aliasedFragments.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | lastName: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #TestAliasedFragments_userLastName]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "TestAliasedFragments_userLastName", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "lastName", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "User", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestCatchUser_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Test_catch.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment_t = { 8 | createdAt: TestsUtils.Datetime.t, 9 | } 10 | type fragment = RescriptRelay.CatchResult.t 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{"__root":{"value_createdAt":{"c":"TestsUtils.Datetime"}}}` 19 | ) 20 | @live 21 | let fragmentConverterMap = { 22 | "TestsUtils.Datetime": TestsUtils.Datetime.parse, 23 | } 24 | @live 25 | let convertFragment = v => v->RescriptRelay.convertObj( 26 | fragmentConverter, 27 | fragmentConverterMap, 28 | Js.undefined 29 | ) 30 | } 31 | 32 | type t 33 | type fragmentRef 34 | external getFragmentRef: 35 | RescriptRelay.fragmentRefs<[> | #TestCatchUser_user]> => fragmentRef = "%identity" 36 | 37 | module Utils = { 38 | @@warning("-33") 39 | open Types 40 | } 41 | 42 | type relayOperationNode 43 | type operationType = RescriptRelay.fragmentNode 44 | 45 | 46 | let node: operationType = %raw(json` { 47 | "argumentDefinitions": [], 48 | "kind": "Fragment", 49 | "metadata": { 50 | "catchTo": "RESULT" 51 | }, 52 | "name": "TestCatchUser_user", 53 | "selections": [ 54 | { 55 | "alias": null, 56 | "args": null, 57 | "kind": "ScalarField", 58 | "name": "createdAt", 59 | "storageKey": null 60 | } 61 | ], 62 | "type": "User", 63 | "abstractKey": null 64 | } `) 65 | 66 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestCompileInterfacesFragment_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc TestCompileInterfaces.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | lastName: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #TestCompileInterfacesFragment_user]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "TestCompileInterfacesFragment_user", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "lastName", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "User", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestFragment_sub_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Test_fragment.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | @live lastName: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #TestFragment_sub_user]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "TestFragment_sub_user", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "lastName", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "User", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestNodeInterface_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc Test_nodeInterface.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | firstName: string, 9 | } 10 | } 11 | 12 | module Internal = { 13 | @live 14 | type fragmentRaw 15 | @live 16 | let fragmentConverter: Js.Dict.t>> = %raw( 17 | json`{}` 18 | ) 19 | @live 20 | let fragmentConverterMap = () 21 | @live 22 | let convertFragment = v => v->RescriptRelay.convertObj( 23 | fragmentConverter, 24 | fragmentConverterMap, 25 | Js.undefined 26 | ) 27 | } 28 | 29 | type t 30 | type fragmentRef 31 | external getFragmentRef: 32 | RescriptRelay.fragmentRefs<[> | #TestNodeInterface_user]> => fragmentRef = "%identity" 33 | 34 | module Utils = { 35 | @@warning("-33") 36 | open Types 37 | } 38 | 39 | type relayOperationNode 40 | type operationType = RescriptRelay.fragmentNode 41 | 42 | 43 | let node: operationType = %raw(json` { 44 | "argumentDefinitions": [], 45 | "kind": "Fragment", 46 | "metadata": null, 47 | "name": "TestNodeInterface_user", 48 | "selections": [ 49 | { 50 | "alias": null, 51 | "args": null, 52 | "kind": "ScalarField", 53 | "name": "firstName", 54 | "storageKey": null 55 | } 56 | ], 57 | "type": "User", 58 | "abstractKey": null 59 | } `) 60 | 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestRelayUserResolver2_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc TestRelayUserResolver2.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | firstName: string, 9 | lastName: string, 10 | } 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{}` 19 | ) 20 | @live 21 | let fragmentConverterMap = () 22 | @live 23 | let convertFragment = v => v->RescriptRelay.convertObj( 24 | fragmentConverter, 25 | fragmentConverterMap, 26 | Js.undefined 27 | ) 28 | } 29 | 30 | type t 31 | type fragmentRef 32 | external getFragmentRef: 33 | RescriptRelay.fragmentRefs<[> | #TestRelayUserResolver2]> => fragmentRef = "%identity" 34 | 35 | module Utils = { 36 | @@warning("-33") 37 | open Types 38 | } 39 | 40 | type relayOperationNode 41 | type operationType = RescriptRelay.fragmentNode 42 | 43 | 44 | let node: operationType = %raw(json` { 45 | "argumentDefinitions": [], 46 | "kind": "Fragment", 47 | "metadata": null, 48 | "name": "TestRelayUserResolver2", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "firstName", 55 | "storageKey": null 56 | }, 57 | { 58 | "alias": null, 59 | "args": null, 60 | "kind": "ScalarField", 61 | "name": "lastName", 62 | "storageKey": null 63 | } 64 | ], 65 | "type": "User", 66 | "abstractKey": null 67 | } `) 68 | 69 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/TestRelayUserResolver_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc TestRelayUserResolver.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | firstName: string, 9 | lastName: string, 10 | } 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{}` 19 | ) 20 | @live 21 | let fragmentConverterMap = () 22 | @live 23 | let convertFragment = v => v->RescriptRelay.convertObj( 24 | fragmentConverter, 25 | fragmentConverterMap, 26 | Js.undefined 27 | ) 28 | } 29 | 30 | type t 31 | type fragmentRef 32 | external getFragmentRef: 33 | RescriptRelay.fragmentRefs<[> | #TestRelayUserResolver]> => fragmentRef = "%identity" 34 | 35 | module Utils = { 36 | @@warning("-33") 37 | open Types 38 | } 39 | 40 | type relayOperationNode 41 | type operationType = RescriptRelay.fragmentNode 42 | 43 | 44 | let node: operationType = %raw(json` { 45 | "argumentDefinitions": [], 46 | "kind": "Fragment", 47 | "metadata": null, 48 | "name": "TestRelayUserResolver", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "firstName", 55 | "storageKey": null 56 | }, 57 | { 58 | "alias": null, 59 | "args": null, 60 | "kind": "ScalarField", 61 | "name": "lastName", 62 | "storageKey": null 63 | } 64 | ], 65 | "type": "User", 66 | "abstractKey": null 67 | } `) 68 | 69 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/UserMeta____relay_model_instance_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc RelayUserMetaModel.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = unit 8 | } 9 | 10 | module Internal = { 11 | @live 12 | type fragmentRaw 13 | @live 14 | let fragmentConverter: Js.Dict.t>> = %raw( 15 | json`{}` 16 | ) 17 | @live 18 | let fragmentConverterMap = () 19 | @live 20 | let convertFragment = v => v->RescriptRelay.convertObj( 21 | fragmentConverter, 22 | fragmentConverterMap, 23 | Js.undefined 24 | ) 25 | } 26 | 27 | type t 28 | type fragmentRef 29 | external getFragmentRef: 30 | RescriptRelay.fragmentRefs<[> | #UserMeta____relay_model_instance]> => fragmentRef = "%identity" 31 | 32 | module Utils = { 33 | @@warning("-33") 34 | open Types 35 | } 36 | 37 | type relayOperationNode 38 | type operationType = RescriptRelay.fragmentNode 39 | 40 | 41 | let node: operationType = %raw(json` { 42 | "argumentDefinitions": [], 43 | "kind": "Fragment", 44 | "metadata": null, 45 | "name": "UserMeta____relay_model_instance", 46 | "selections": [ 47 | { 48 | "kind": "ClientExtension", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "__relay_model_instance", 55 | "storageKey": null 56 | } 57 | ] 58 | } 59 | ], 60 | "type": "UserMeta", 61 | "abstractKey": null 62 | } `) 63 | 64 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/UserMeta_relayResolvers_graphql.res: -------------------------------------------------------------------------------- 1 | /* @generated */ 2 | @@warning("-30") 3 | 4 | type onlineResolver = (RelayUserMetaModel.t, ) => bool 5 | 6 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/UserName_user_graphql.res: -------------------------------------------------------------------------------- 1 | /* @sourceLoc UserName.res */ 2 | /* @generated */ 3 | %%raw("/* @generated */") 4 | module Types = { 5 | @@warning("-30") 6 | 7 | type fragment = { 8 | firstName: string, 9 | lastName: string, 10 | } 11 | } 12 | 13 | module Internal = { 14 | @live 15 | type fragmentRaw 16 | @live 17 | let fragmentConverter: Js.Dict.t>> = %raw( 18 | json`{}` 19 | ) 20 | @live 21 | let fragmentConverterMap = () 22 | @live 23 | let convertFragment = v => v->RescriptRelay.convertObj( 24 | fragmentConverter, 25 | fragmentConverterMap, 26 | Js.undefined 27 | ) 28 | } 29 | 30 | type t 31 | type fragmentRef 32 | external getFragmentRef: 33 | RescriptRelay.fragmentRefs<[> | #UserName_user]> => fragmentRef = "%identity" 34 | 35 | module Utils = { 36 | @@warning("-33") 37 | open Types 38 | } 39 | 40 | type relayOperationNode 41 | type operationType = RescriptRelay.fragmentNode 42 | 43 | 44 | let node: operationType = %raw(json` { 45 | "argumentDefinitions": [], 46 | "kind": "Fragment", 47 | "metadata": null, 48 | "name": "UserName_user", 49 | "selections": [ 50 | { 51 | "alias": null, 52 | "args": null, 53 | "kind": "ScalarField", 54 | "name": "firstName", 55 | "storageKey": null 56 | }, 57 | { 58 | "alias": null, 59 | "args": null, 60 | "kind": "ScalarField", 61 | "name": "lastName", 62 | "storageKey": null 63 | } 64 | ], 65 | "type": "User", 66 | "abstractKey": null 67 | } `) 68 | 69 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/__generated__/User_relayResolvers_graphql.res: -------------------------------------------------------------------------------- 1 | /* @generated */ 2 | @@warning("-30") 3 | 4 | type fullNameResolver = (RescriptRelay.resolverFragmentRefs<[#TestRelayUserResolver]>, ) => RescriptRelay.any 5 | 6 | type fullName2ResolverArgs = { 7 | maxLength: int, 8 | } 9 | type fullName2Resolver = (RescriptRelay.resolverFragmentRefs<[#TestRelayUserResolver2]>, fullName2ResolverArgs) => string 10 | 11 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/jestSetup.js: -------------------------------------------------------------------------------- 1 | global.fetch = require("node-fetch"); 2 | const queryMock = require("./queryMock"); 3 | 4 | beforeEach(() => { 5 | queryMock.setup("http://graphql/"); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests__/queryMock.js: -------------------------------------------------------------------------------- 1 | const { QueryMock } = require("graphql-query-test-mock"); 2 | 3 | module.exports = new QueryMock(); 4 | -------------------------------------------------------------------------------- /packages/rescript-relay/__tests_preloaded__/Test_preloadedQuery-tests.js: -------------------------------------------------------------------------------- 1 | require("@testing-library/jest-dom/extend-expect"); 2 | const nock = require("nock"); 3 | const t = require("@testing-library/react"); 4 | const React = require("react"); 5 | 6 | const { test_preloadedQuery } = require("./Test_preloadedQuery.bs"); 7 | 8 | nock(`http://graphql`) 9 | .persist() 10 | .post("/") 11 | .reply((_uri, data, cb) => { 12 | const { id, variables } = data; 13 | if (id == null) { 14 | throw new Error("Got no ID."); 15 | } 16 | 17 | expect(variables).toEqual({ 18 | status: "Online", 19 | __relay_internal__pv__ProvidedVariablesBool: true, 20 | __relay_internal__pv__ProvidedVariablesInputC: { 21 | intStr: "123", 22 | recursiveC: { 23 | intStr: "234", 24 | }, 25 | }, 26 | __relay_internal__pv__ProvidedVariablesInputCArr: [ 27 | { 28 | intStr: "123", 29 | }, 30 | ], 31 | __relay_internal__pv__ProvidedVariablesIntStr: "456", 32 | }); 33 | 34 | cb(null, [ 35 | 200, 36 | { 37 | data: { 38 | loggedInUser: { 39 | id: "", 40 | someRandomArgField: "Random", 41 | }, 42 | users: { 43 | edges: [ 44 | { 45 | node: { id: "", firstName: "First", onlineStatus: "Idle" }, 46 | }, 47 | ], 48 | }, 49 | }, 50 | }, 51 | ]); 52 | }); 53 | 54 | describe("Preloaded Query", () => { 55 | test("basic preloaded queries work", async () => { 56 | expect.assertions(1); 57 | t.render(test_preloadedQuery()); 58 | await t.screen.findByText("Preloaded First is idle"); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /packages/rescript-relay/binaries/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/packages/rescript-relay/binaries/.gitkeep -------------------------------------------------------------------------------- /packages/rescript-relay/build-compiler-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ../relay/compiler; 3 | cargo build && cp -f target/debug/relay ../../rescript-relay/rescript-relay-compiler; 4 | cd ../../rescript-relay; -------------------------------------------------------------------------------- /packages/rescript-relay/compiler.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | var spawn = require("child_process").spawn; 5 | var path = require("path"); 6 | 7 | var input = process.argv.slice(2); 8 | 9 | spawn(path.join(__dirname, "rescript-relay-compiler.exe"), input, { 10 | stdio: "inherit", 11 | }).on("exit", process.exit); 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/copyPackageJson.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const tagName = process.argv[3]; 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | 6 | const pkgJsonRaw = fs.readFileSync( 7 | path.resolve(path.join(__dirname, "./package.json")), 8 | "utf-8" 9 | ); 10 | 11 | const pkgJson = JSON.parse(pkgJsonRaw); 12 | 13 | // Bypass forcing package name and version for the beta track. 14 | if (tagName && tagName !== "beta") { 15 | const commit = require("child_process") 16 | .execSync("git rev-parse HEAD") 17 | .toString() 18 | .trim() 19 | .slice(0, 8); 20 | 21 | pkgJson.version = `0.0.0-${tagName}-${commit}`; 22 | } 23 | 24 | fs.writeFileSync( 25 | path.resolve(path.join(process.argv[2], "package.json")), 26 | JSON.stringify(pkgJson, null, 2) 27 | ); 28 | -------------------------------------------------------------------------------- /packages/rescript-relay/jest.config.js: -------------------------------------------------------------------------------- 1 | const PERSISTING = Boolean(process.env.ENABLE_PERSISTING); 2 | 3 | module.exports = { 4 | testEnvironment: "jsdom", 5 | bail: true, 6 | testRegex: PERSISTING 7 | ? "/__tests_preloaded__/.*-tests.js$" 8 | : "/__tests__/.*-tests.js$", 9 | roots: PERSISTING 10 | ? ["/__tests_preloaded__"] 11 | : ["/__tests__"], 12 | setupFilesAfterEnv: ["/__tests__/jestSetup.js"], 13 | }; 14 | -------------------------------------------------------------------------------- /packages/rescript-relay/persistedQueries.json: -------------------------------------------------------------------------------- 1 | { 2 | "64e1bd5c44a860103e5980b544f5e454": "query TestPreloadedQuery(\n $status: OnlineStatus\n) {\n users(status: $status) {\n edges {\n node {\n id\n firstName\n onlineStatus\n }\n }\n }\n}\n" 3 | } 4 | -------------------------------------------------------------------------------- /packages/rescript-relay/postinstall.js: -------------------------------------------------------------------------------- 1 | // PLACEHOLDER 2 | -------------------------------------------------------------------------------- /packages/rescript-relay/relay.config.js: -------------------------------------------------------------------------------- 1 | const PERSISTING = Boolean(process.env.ENABLE_PERSISTING); 2 | 3 | module.exports = { 4 | schema: "./__tests__/schema.graphql", 5 | artifactDirectory: PERSISTING 6 | ? "./__tests_preloaded__/__generated__" 7 | : "./__tests__/__generated__", 8 | src: PERSISTING ? "./__tests_preloaded__" : "./__tests__", 9 | language: "rescript", 10 | customScalarTypes: { 11 | Datetime: "TestsUtils.Datetime", 12 | IntString: "TestsUtils.IntString", 13 | JSON: "Js.Json.t", 14 | Number: "TestsUtils.Number", 15 | }, 16 | persistConfig: PERSISTING 17 | ? { 18 | file: "./persistedQueries.json", 19 | algorithm: "MD5", 20 | } 21 | : undefined, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/.gitignore: -------------------------------------------------------------------------------- 1 | .merlin 2 | node_modules/ 3 | _build 4 | _esy 5 | _release 6 | *.byte 7 | *.native 8 | *.install 9 | **/.merlin 10 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/.ocamlformat: -------------------------------------------------------------------------------- 1 | profile = default 2 | version = 0.26.1 3 | 4 | field-space = tight-decl 5 | break-cases = toplevel 6 | module-item-spacing = preserve 7 | cases-exp-indent = 2 8 | space-around-arrays = false 9 | space-around-lists = false 10 | space-around-records = false 11 | space-around-variants = false -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016-2018 Various Authors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/README.md: -------------------------------------------------------------------------------- 1 | # rescript-relay-ppx 2 | 3 | A project which demonstrates a Reason workflow with [Esy][]. 4 | 5 | [esy]: https://github.com/esy/esy 6 | 7 | ## Usage 8 | 9 | You need Esy, you can install the beta using [npm](https://npmjs.com): 10 | 11 | % npm install -g esy@latest 12 | 13 | > NOTE: Make sure `esy --version` returns at least `0.5.8` for this project to build. 14 | 15 | Then run the `esy` command from this project root to install and build depenencies. 16 | 17 | % esy 18 | 19 | Now you can run your editor within the environment (which also includes merlin): 20 | 21 | % esy $EDITOR 22 | % esy vim 23 | 24 | Alternatively you can try [vim-reasonml](https://github.com/jordwalke/vim-reasonml) 25 | which loads esy project environments automatically. 26 | 27 | After you make some changes to source code, you can re-run project's build 28 | again with the same simple `esy` command. 29 | 30 | % esy 31 | 32 | And test compiled executable (runs `scripts.tests` specified in 33 | `package.json`): 34 | 35 | % esy test 36 | 37 | Documentation for the libraries in the project can be generated with: 38 | 39 | % esy doc 40 | % open-cli `esy echo '#{self.target_dir}/default/_doc/_html/index.html'` 41 | 42 | This assumes you have a command like [open-cli](https://github.com/sindresorhus/open-cli) installed on your system. 43 | 44 | Shell into environment: 45 | 46 | % esy shell 47 | 48 | ## Create Prebuilt Release: 49 | 50 | `esy` allows creating prebuilt binary packages for your current platform, with 51 | no dependencies. 52 | 53 | % esy npm-release 54 | % cd _release 55 | % npm publish 56 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/bin/RescriptRelayPpxApp.ml: -------------------------------------------------------------------------------- 1 | open Ppxlib 2 | 3 | let () = 4 | Driver.add_arg "-uncurried" 5 | (Arg.Unit (fun () -> RescriptRelayPpxLibrary.UncurriedUtils.enabled := true)) 6 | ~doc:"Run in uncurried mode" 7 | 8 | let () = 9 | Driver.add_arg "-non-react" 10 | (Arg.Unit (fun () -> RescriptRelayPpxLibrary.NonReactUtils.enabled := true)) 11 | ~doc:"Run non-React mode" 12 | 13 | let _ = Driver.run_as_ppx_rewriter () 14 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/bin/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name RescriptRelayPpxApp) 3 | (public_name RescriptRelayPpxApp.exe) 4 | (libraries rescript-relay-ppx ppxlib)) 5 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/dune: -------------------------------------------------------------------------------- 1 | (env (release-static (ocamlopt_flags (:standard -ccopt -static)))) 2 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 1.2) 2 | (name rescript-relay-ppx) 3 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/.gitattributes: -------------------------------------------------------------------------------- 1 | 2 | # Set eol to LF so files aren't converted to CRLF-eol on Windows. 3 | * text eol=lf linguist-generated 4 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Reset any possible .gitignore, we want all esy.lock to be un-ignored. 3 | !* 4 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/base-threads.base/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "https://github.com/ocaml/opam-repository/issues" 3 | description: """ 4 | Threads library distributed with the OCaml compiler 5 | """ 6 | 7 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/base-unix.base/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "https://github.com/ocaml/opam-repository/issues" 3 | description: """ 4 | Unix library distributed with the OCaml compiler 5 | """ 6 | 7 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/fmt.0.8.6/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "Daniel Bünzli " 3 | authors: [ "The fmt programmers" ] 4 | homepage: "https://erratique.ch/software/fmt" 5 | doc: "https://erratique.ch/software/fmt" 6 | dev-repo: "git+https://erratique.ch/repos/fmt.git" 7 | bug-reports: "https://github.com/dbuenzli/fmt/issues" 8 | tags: [ "string" "format" "pretty-print" "org:erratique" ] 9 | license: "ISC" 10 | depends: [ 11 | "ocaml" {>= "4.03.0" & < "5.0"} 12 | "ocamlfind" {build} 13 | "ocamlbuild" {build} 14 | "topkg" {build & >= "0.9.0"} 15 | # Can be removed once ocaml >= 4.07 16 | "seq" 17 | "stdlib-shims" 18 | ] 19 | depopts: [ "base-unix" "cmdliner" ] 20 | conflicts: [ "cmdliner" {< "0.9.8"} ] 21 | build: [[ 22 | "ocaml" "pkg/pkg.ml" "build" 23 | "--dev-pkg" "%{pinned}%" 24 | "--with-base-unix" "%{base-unix:installed}%" 25 | "--with-cmdliner" "%{cmdliner:installed}%" ]] 26 | 27 | synopsis: """OCaml Format pretty-printer combinators""" 28 | description: """\ 29 | 30 | Fmt exposes combinators to devise `Format` pretty-printing functions. 31 | 32 | Fmt depends only on the OCaml standard library. The optional `Fmt_tty` 33 | library that allows to setup formatters for terminal color output 34 | depends on the Unix library. The optional `Fmt_cli` library that 35 | provides command line support for Fmt depends on [`Cmdliner`][cmdliner]. 36 | 37 | Fmt is distributed under the ISC license. 38 | 39 | [cmdliner]: http://erratique.ch/software/cmdliner 40 | """ 41 | url { 42 | archive: "https://erratique.ch/software/fmt/releases/fmt-0.8.6.tbz" 43 | checksum: "5407789e5f0ea42272ca19353b1abfd3" 44 | } 45 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/graphql_parser.0.12.2/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "Andreas Garnaes " 3 | authors: "Andreas Garnaes " 4 | homepage: "https://github.com/andreas/ocaml-graphql-server" 5 | doc: "https://andreas.github.io/ocaml-graphql-server/" 6 | bug-reports: "https://github.com/andreas/ocaml-graphql-server/issues" 7 | dev-repo: "git+https://github.com/andreas/ocaml-graphql-server.git" 8 | 9 | build: [ 10 | ["dune" "build" "-p" name "-j" jobs] 11 | ["dune" "runtest" "-p" name "-j" jobs] {with-test} 12 | ] 13 | 14 | depends: [ 15 | "ocaml" {>= "4.03.0"} 16 | "dune" {>= "1.4"} 17 | "menhir" {build & >= "20180523"} 18 | "alcotest" {with-test & >= "0.8.1"} 19 | "fmt" {>= "0.8.0" & < "0.8.7"} 20 | "re" {>= "1.5.0"} 21 | ] 22 | 23 | synopsis: "Library for parsing GraphQL queries" 24 | 25 | url { 26 | archive: "https://github.com/andreas/ocaml-graphql-server/releases/download/0.12.2/graphql-0.12.2.tbz" 27 | checksum: "d7c79e9527a57051b40c005c36cf236f" 28 | } 29 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/menhir.20230415/opam: -------------------------------------------------------------------------------- 1 | 2 | opam-version: "2.0" 3 | maintainer: "francois.pottier@inria.fr" 4 | authors: [ 5 | "François Pottier " 6 | "Yann Régis-Gianas " 7 | ] 8 | homepage: "http://gitlab.inria.fr/fpottier/menhir" 9 | dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git" 10 | bug-reports: "https://gitlab.inria.fr/fpottier/menhir/-/issues" 11 | license: "GPL-2.0-only" 12 | build: [ 13 | ["dune" "build" "-p" name "-j" jobs] 14 | ] 15 | depends: [ 16 | "ocaml" {>= "4.03.0"} 17 | "dune" {>= "2.8.0"} 18 | "menhirLib" {= version} 19 | "menhirSdk" {= version} 20 | ] 21 | synopsis: "An LR(1) parser generator" 22 | url { 23 | src: 24 | "https://gitlab.inria.fr/fpottier/menhir/-/archive/20230415/archive.tar.gz" 25 | checksum: [ 26 | "md5=7c4b51e1b666711af04f7832ebc90618" 27 | "sha512=aa8a34c173d9a82d3503919de8377f1b8c9ff721882486f0b5ae2bdb9b22ee7f5ba8f6ef25e00fbb35704fac9fc3bda71908512ed4cbd345d9dc29d6ede149b2" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/menhirLib.20230415/opam: -------------------------------------------------------------------------------- 1 | 2 | opam-version: "2.0" 3 | maintainer: "francois.pottier@inria.fr" 4 | authors: [ 5 | "François Pottier " 6 | "Yann Régis-Gianas " 7 | ] 8 | homepage: "http://gitlab.inria.fr/fpottier/menhir" 9 | dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git" 10 | bug-reports: "https://gitlab.inria.fr/fpottier/menhir/-/issues" 11 | license: "LGPL-2.0-only with OCaml-LGPL-linking-exception" 12 | build: [ 13 | ["dune" "build" "-p" name "-j" jobs] 14 | ] 15 | depends: [ 16 | "ocaml" { >= "4.03.0" } 17 | "dune" { >= "2.8.0" } 18 | ] 19 | conflicts: [ 20 | "menhir" { != version } 21 | ] 22 | synopsis: "Runtime support library for parsers generated by Menhir" 23 | url { 24 | src: 25 | "https://gitlab.inria.fr/fpottier/menhir/-/archive/20230415/archive.tar.gz" 26 | checksum: [ 27 | "md5=7c4b51e1b666711af04f7832ebc90618" 28 | "sha512=aa8a34c173d9a82d3503919de8377f1b8c9ff721882486f0b5ae2bdb9b22ee7f5ba8f6ef25e00fbb35704fac9fc3bda71908512ed4cbd345d9dc29d6ede149b2" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/menhirSdk.20230415/opam: -------------------------------------------------------------------------------- 1 | 2 | opam-version: "2.0" 3 | maintainer: "francois.pottier@inria.fr" 4 | authors: [ 5 | "François Pottier " 6 | "Yann Régis-Gianas " 7 | ] 8 | homepage: "http://gitlab.inria.fr/fpottier/menhir" 9 | dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git" 10 | bug-reports: "https://gitlab.inria.fr/fpottier/menhir/-/issues" 11 | license: "LGPL-2.0-only with OCaml-LGPL-linking-exception" 12 | build: [ 13 | ["dune" "build" "-p" name "-j" jobs] 14 | ] 15 | depends: [ 16 | "ocaml" { >= "4.03.0" } 17 | "dune" { >= "2.8.0" } 18 | ] 19 | conflicts: [ 20 | "menhir" { != version } 21 | ] 22 | synopsis: "Compile-time library for auxiliary tools related to Menhir" 23 | url { 24 | src: 25 | "https://gitlab.inria.fr/fpottier/menhir/-/archive/20230415/archive.tar.gz" 26 | checksum: [ 27 | "md5=7c4b51e1b666711af04f7832ebc90618" 28 | "sha512=aa8a34c173d9a82d3503919de8377f1b8c9ff721882486f0b5ae2bdb9b22ee7f5ba8f6ef25e00fbb35704fac9fc3bda71908512ed4cbd345d9dc29d6ede149b2" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/ocaml-compiler-libs.v0.12.4/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "OCaml compiler libraries repackaged" 3 | description: """ 4 | This packages exposes the OCaml compiler libraries repackages under 5 | the toplevel names Ocaml_common, Ocaml_bytecomp, Ocaml_optcomp, ...""" 6 | maintainer: ["Jane Street developers"] 7 | authors: ["Jane Street Group, LLC"] 8 | license: "MIT" 9 | homepage: "https://github.com/janestreet/ocaml-compiler-libs" 10 | bug-reports: "https://github.com/janestreet/ocaml-compiler-libs/issues" 11 | depends: [ 12 | "dune" {>= "2.8"} 13 | "ocaml" {>= "4.04.1"} 14 | "odoc" {with-doc} 15 | ] 16 | build: [ 17 | ["dune" "subst"] {dev} 18 | [ 19 | "dune" 20 | "build" 21 | "-p" 22 | name 23 | "-j" 24 | jobs 25 | "@install" 26 | "@runtest" {with-test} 27 | "@doc" {with-doc} 28 | ] 29 | ] 30 | dev-repo: "git+https://github.com/janestreet/ocaml-compiler-libs.git" 31 | url { 32 | src: 33 | "https://github.com/janestreet/ocaml-compiler-libs/releases/download/v0.12.4/ocaml-compiler-libs-v0.12.4.tbz" 34 | checksum: [ 35 | "sha256=4ec9c9ec35cc45c18c7a143761154ef1d7663036a29297f80381f47981a07760" 36 | "sha512=978dba8dfa61f98fa24fda7a9c26c2e837081f37d1685fe636dc19cfc3278a940cf01a10293504b185c406706bc1008bc54313d50f023bcdea6d5ac6c0788b35" 37 | ] 38 | } 39 | x-commit-hash: "8cd12f18bb7171c2b67d661868c4271fae528d93" 40 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/ocamlbuild.0.14.2/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: 3 | "OCamlbuild is a build system with builtin rules to easily build most OCaml projects" 4 | maintainer: "Gabriel Scherer " 5 | authors: ["Nicolas Pouillard" "Berke Durak"] 6 | license: "LGPL-2.0-or-later WITH OCaml-LGPL-linking-exception" 7 | homepage: "https://github.com/ocaml/ocamlbuild/" 8 | doc: "https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc" 9 | bug-reports: "https://github.com/ocaml/ocamlbuild/issues" 10 | depends: [ 11 | "ocaml" {>= "4.03"} 12 | ] 13 | conflicts: [ 14 | "base-ocamlbuild" 15 | "ocamlfind" {< "1.6.2"} 16 | ] 17 | build: [ 18 | [ 19 | make 20 | "-f" 21 | "configure.make" 22 | "all" 23 | "OCAMLBUILD_PREFIX=%{prefix}%" 24 | "OCAMLBUILD_BINDIR=%{bin}%" 25 | "OCAMLBUILD_LIBDIR=%{lib}%" 26 | "OCAMLBUILD_MANDIR=%{man}%" 27 | "OCAML_NATIVE=%{ocaml:native}%" 28 | "OCAML_NATIVE_TOOLS=%{ocaml:native}%" 29 | ] 30 | [make "check-if-preinstalled" "all" "opam-install"] 31 | ] 32 | dev-repo: "git+https://github.com/ocaml/ocamlbuild.git" 33 | url { 34 | src: "https://github.com/ocaml/ocamlbuild/archive/refs/tags/0.14.2.tar.gz" 35 | checksum: [ 36 | "md5=2f407fadd57b073155a6aead887d9676" 37 | "sha512=f568bf10431a1f701e8bd7554dc662400a0d978411038bbad93d44dceab02874490a8a5886a9b44e017347e7949997f13f5c3752f74e1eb5e273d2beb19a75fd" 38 | ] 39 | } -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/ocamlfind.1.9.6/files/0001-Harden-test-for-OCaml-5.patch: -------------------------------------------------------------------------------- 1 | diff a/configure b/configure 2 | --- a/configure 3 | +++ b/configure 4 | @@ -294,7 +294,7 @@ 5 | # If findlib has been configured -sitelib $(ocamlc -where) then there's 6 | # nothing to do, but otherwise we need to put OCaml's Standard Library 7 | # into the path setting. 8 | - if [ ! -e "${ocaml_sitelib}/stdlib/META" ]; then 9 | + if [ ! -e "${ocaml_sitelib}/stdlib.cmi" ]; then 10 | ocamlpath="${ocaml_core_stdlib}${path_sep}${ocamlpath}" 11 | fi 12 | fi 13 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/ocamlfind.1.9.6/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "A library manager for OCaml" 3 | description: """ 4 | Findlib is a library manager for OCaml. It provides a convention how 5 | to store libraries, and a file format ("META") to describe the 6 | properties of libraries. There is also a tool (ocamlfind) for 7 | interpreting the META files, so that it is very easy to use libraries 8 | in programs and scripts. 9 | """ 10 | license: "MIT" 11 | maintainer: "Thomas Gazagnaire " 12 | authors: "Gerd Stolpmann " 13 | homepage: "http://projects.camlcity.org/projects/findlib.html" 14 | bug-reports: "https://github.com/ocaml/ocamlfind/issues" 15 | depends: [ 16 | "ocaml" {>= "3.08.0"} 17 | ] 18 | depopts: ["graphics"] 19 | build: [ 20 | [ 21 | "./configure" 22 | "-bindir" bin 23 | "-sitelib" lib 24 | "-mandir" man 25 | "-config" "%{lib}%/findlib.conf" 26 | "-no-custom" 27 | "-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"} 28 | "-no-topfind" {ocaml:preinstalled} 29 | ] 30 | [make "all"] 31 | [make "opt"] {ocaml:native} 32 | ] 33 | install: [ 34 | [make "install"] 35 | ["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled} 36 | ] 37 | extra-files: ["0001-Harden-test-for-OCaml-5.patch" "md5=3cddbf72164c29d4e50e077a92a37c6c"] 38 | # See https://github.com/ocaml/ocamlfind/pull/61 39 | patches: ["0001-Harden-test-for-OCaml-5.patch"] 40 | dev-repo: "git+https://github.com/ocaml/ocamlfind.git" 41 | url { 42 | src: "http://download.camlcity.org/download/findlib-1.9.6.tar.gz" 43 | checksum: [ 44 | "md5=96c6ee50a32cca9ca277321262dbec57" 45 | "sha512=cfaf1872d6ccda548f07d32cc6b90c3aafe136d2aa6539e03143702171ee0199add55269bba894c77115535dc46a5835901a5d7c75768999e72db503bfd83027" 46 | ] 47 | } 48 | available: os != "win32" 49 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/ppx_derivers.1.2.1/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "jeremie@dimino.org" 3 | authors: ["Jérémie Dimino"] 4 | license: "BSD-3-Clause" 5 | homepage: "https://github.com/ocaml-ppx/ppx_derivers" 6 | bug-reports: "https://github.com/ocaml-ppx/ppx_derivers/issues" 7 | dev-repo: "git+https://github.com/ocaml-ppx/ppx_derivers.git" 8 | build: [ 9 | ["dune" "build" "-p" name "-j" jobs] 10 | ] 11 | depends: [ 12 | "ocaml" 13 | "dune" 14 | ] 15 | synopsis: "Shared [@@deriving] plugin registry" 16 | description: """ 17 | Ppx_derivers is a tiny package whose sole purpose is to allow 18 | ppx_deriving and ppx_type_conv to inter-operate gracefully when linked 19 | as part of the same ocaml-migrate-parsetree driver.""" 20 | url { 21 | src: "https://github.com/ocaml-ppx/ppx_derivers/archive/1.2.1.tar.gz" 22 | checksum: "md5=5dc2bf130c1db3c731fe0fffc5648b41" 23 | } 24 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/re.1.10.4/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | 3 | maintainer: "rudi.grinberg@gmail.com" 4 | authors: [ 5 | "Jerome Vouillon" 6 | "Thomas Gazagnaire" 7 | "Anil Madhavapeddy" 8 | "Rudi Grinberg" 9 | "Gabriel Radanne" 10 | ] 11 | license: "LGPL-2.0-or-later WITH OCaml-LGPL-linking-exception" 12 | homepage: "https://github.com/ocaml/ocaml-re" 13 | bug-reports: "https://github.com/ocaml/ocaml-re/issues" 14 | dev-repo: "git+https://github.com/ocaml/ocaml-re.git" 15 | 16 | build: [ 17 | ["dune" "subst"] {dev} 18 | ["dune" "build" "-p" name "-j" jobs] 19 | ["dune" "runtest" "-p" name "-j" jobs] {with-test} 20 | ] 21 | 22 | depends: [ 23 | "ocaml" {>= "4.03"} 24 | "dune" {>= "2.0"} 25 | "ounit" {with-test} 26 | "seq" 27 | ] 28 | 29 | synopsis: "RE is a regular expression library for OCaml" 30 | description: """ 31 | Pure OCaml regular expressions with: 32 | * Perl-style regular expressions (module Re.Perl) 33 | * Posix extended regular expressions (module Re.Posix) 34 | * Emacs-style regular expressions (module Re.Emacs) 35 | * Shell-style file globbing (module Re.Glob) 36 | * Compatibility layer for OCaml's built-in Str module (module Re.Str) 37 | """ 38 | url { 39 | src: 40 | "https://github.com/ocaml/ocaml-re/releases/download/1.10.4/re-1.10.4.tbz" 41 | checksum: [ 42 | "sha256=83eb3e4300aa9b1dc7820749010f4362ea83524742130524d78c20ce99ca747c" 43 | "sha512=92b05cf92c389fa8c753f2acca837b15dd05a4a2e8e2bec7a269d2e14c35b1a786d394258376648f80b4b99250ba1900cfe68230b8385aeac153149d9ce56099" 44 | ] 45 | } 46 | x-commit-hash: "e9a4cecb8294c1839db18b1d0c30e755ec85ed5e" 47 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/seq.base/files/META.seq: -------------------------------------------------------------------------------- 1 | name="seq" 2 | version="[distributed with OCaml 4.07 or above]" 3 | description="dummy backward-compatibility package for iterators" 4 | requires="" 5 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/seq.base/files/seq.install: -------------------------------------------------------------------------------- 1 | lib:[ 2 | "META.seq" {"META"} 3 | ] 4 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/seq.base/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: " " 3 | authors: " " 4 | homepage: " " 5 | depends: [ 6 | "ocaml" {>= "4.07.0"} 7 | ] 8 | dev-repo: "git+https://github.com/ocaml/ocaml.git" 9 | bug-reports: "https://caml.inria.fr/mantis/main_page.php" 10 | synopsis: 11 | "Compatibility package for OCaml's standard iterator type starting from 4.07." 12 | extra-files: [ 13 | ["seq.install" "md5=026b31e1df290373198373d5aaa26e42"] 14 | ["META.seq" "md5=b33c8a1a6c7ed797816ce27df4855107"] 15 | ] 16 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/sexplib0.v0.16.0/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "Jane Street developers" 3 | authors: ["Jane Street Group, LLC"] 4 | homepage: "https://github.com/janestreet/sexplib0" 5 | bug-reports: "https://github.com/janestreet/sexplib0/issues" 6 | dev-repo: "git+https://github.com/janestreet/sexplib0.git" 7 | doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/sexplib0/index.html" 8 | license: "MIT" 9 | build: [ 10 | ["dune" "build" "-p" name "-j" jobs] 11 | ] 12 | depends: [ 13 | "ocaml" {>= "4.08.0"} 14 | "dune" {>= "2.0.0"} 15 | ] 16 | available: arch != "arm32" & arch != "x86_32" 17 | synopsis: "Library containing the definition of S-expressions and some base converters" 18 | description: " 19 | Part of Jane Street's Core library 20 | The Core suite of libraries is an industrial strength alternative to 21 | OCaml's standard library that was developed by Jane Street, the 22 | largest industrial user of OCaml. 23 | " 24 | url { 25 | src: "https://ocaml.janestreet.com/ocaml-core/v0.16/files/sexplib0-v0.16.0.tar.gz" 26 | checksum: "sha256=86dba26468194512f789f2fb709063515a9cb4e5c4461c021c239a369590701d" 27 | } 28 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/opam/stdlib-shims.0.3.0/opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "The stdlib-shims programmers" 3 | authors: "The stdlib-shims programmers" 4 | homepage: "https://github.com/ocaml/stdlib-shims" 5 | doc: "https://ocaml.github.io/stdlib-shims/" 6 | dev-repo: "git+https://github.com/ocaml/stdlib-shims.git" 7 | bug-reports: "https://github.com/ocaml/stdlib-shims/issues" 8 | tags: ["stdlib" "compatibility" "org:ocaml"] 9 | license: ["LGPL-2.1-only WITH OCaml-LGPL-linking-exception"] 10 | depends: [ 11 | "dune" 12 | "ocaml" {>= "4.02.3"} 13 | ] 14 | build: [ "dune" "build" "-p" name "-j" jobs ] 15 | synopsis: "Backport some of the new stdlib features to older compiler" 16 | description: """ 17 | Backport some of the new stdlib features to older compiler, 18 | such as the Stdlib module. 19 | 20 | This allows projects that require compatibility with older compiler to 21 | use these new features in their code. 22 | """ 23 | x-commit-hash: "fb6815e5d745f07fd567c11671149de6ef2e74c8" 24 | url { 25 | src: 26 | "https://github.com/ocaml/stdlib-shims/releases/download/0.3.0/stdlib-shims-0.3.0.tbz" 27 | checksum: [ 28 | "sha256=babf72d3917b86f707885f0c5528e36c63fccb698f4b46cf2bab5c7ccdd6d84a" 29 | "sha512=1151d7edc8923516e9a36995a3f8938d323aaade759ad349ed15d6d8501db61ffbe63277e97c4d86149cf371306ac23df0f581ec7e02611f58335126e1870980" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/overrides/opam__s__ocamlbuild_opam__c__0.14.2_opam_override/files/winpatch.patch: -------------------------------------------------------------------------------- 1 | --- ./Makefile 2 | +++ ./Makefile 3 | @@ -271,7 +271,7 @@ 4 | echo ' "ocamlbuild.byte" {"ocamlbuild.byte"}' >> ocamlbuild.install 5 | ifeq ($(OCAML_NATIVE), true) 6 | echo ' "ocamlbuild.native" {"ocamlbuild.native"}' >> ocamlbuild.install 7 | - echo ' "ocamlbuild.native" {"ocamlbuild"}' >> ocamlbuild.install 8 | + echo " \"ocamlbuild.native\" {\"ocamlbuild${EXE}\"}" >> ocamlbuild.install 9 | else 10 | echo ' "ocamlbuild.byte" {"ocamlbuild"}' >> ocamlbuild.install 11 | endif 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/overrides/opam__s__ocamlbuild_opam__c__0.14.2_opam_override/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": [ 3 | [ 4 | "bash", 5 | "-c", 6 | "#{os == 'windows' ? 'patch -p1 < winpatch.patch' : 'true'}" 7 | ], 8 | [ 9 | "make", 10 | "-f", 11 | "configure.make", 12 | "all", 13 | "OCAMLBUILD_PREFIX=#{self.install}", 14 | "OCAMLBUILD_BINDIR=#{self.bin}", 15 | "OCAMLBUILD_LIBDIR=#{self.lib}", 16 | "OCAMLBUILD_MANDIR=#{self.man}", 17 | "OCAMLBUILD_NATIVE=true", 18 | "OCAMLBUILD_NATIVE_TOOLS=true", 19 | "EXE=#{os == 'windows' ? '.exe': ''}" 20 | ], 21 | [ 22 | "make", 23 | "check-if-preinstalled", 24 | "all", 25 | "EXE=#{os == 'windows' ? '.exe': ''}", 26 | "opam-install" 27 | ] 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/overrides/opam__s__ocamlfind_opam__c__1.9.6_opam_override/files/findlib.patch: -------------------------------------------------------------------------------- 1 | --- ./Makefile 2 | +++ ./Makefile 3 | @@ -55,7 +55,7 @@ 4 | export USE_CYGPATH; \ 5 | cat findlib.conf.in | \ 6 | $(SH) tools/patch '@SITELIB@' '$(OCAML_SITELIB)' | \ 7 | - $(SH) tools/patch '@FINDLIB_PATH@' '$(FINDLIB_PATH)' -p >findlib.conf 8 | + $(SH) tools/patch '@FINDLIB_PATH@' '$(FINDLIB_PATH)' >findlib.conf 9 | if ./tools/cmd_from_same_dir ocamlc; then \ 10 | echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \ 11 | fi 12 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/esy.lock/overrides/opam__s__ocamlfind_opam__c__1.9.6_opam_override/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": [ 3 | [ 4 | "bash", 5 | "-c", 6 | "#{os == 'windows' ? 'patch -p1 < findlib.patch' : 'true'}" 7 | ], 8 | [ 9 | "./configure", 10 | "-bindir", 11 | "#{self.bin}", 12 | "-sitelib", 13 | "#{self.lib}", 14 | "-mandir", 15 | "#{self.man}", 16 | "-config", 17 | "#{self.lib}/findlib.conf", 18 | "-no-custom", 19 | "-no-topfind" 20 | ], 21 | [ 22 | "make", 23 | "all" 24 | ], 25 | [ 26 | "make", 27 | "opt" 28 | ] 29 | ], 30 | "install": [ 31 | [ 32 | "make", 33 | "install" 34 | ], 35 | [ 36 | "install", 37 | "-m", 38 | "0755", 39 | "ocaml-stub", 40 | "#{self.bin}/ocaml" 41 | ], 42 | [ 43 | "mkdir", 44 | "-p", 45 | "#{self.toplevel}" 46 | ], 47 | [ 48 | "install", 49 | "-m", 50 | "0644", 51 | "src/findlib/topfind", 52 | "#{self.toplevel}/topfind" 53 | ] 54 | ], 55 | "exportedEnv": { 56 | "OCAML_TOPLEVEL_PATH": { 57 | "val": "#{self.toplevel}", 58 | "scope": "global" 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/NonReactUtils.ml: -------------------------------------------------------------------------------- 1 | let enabled = ref false 2 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/RelayResolverFragment.ml: -------------------------------------------------------------------------------- 1 | open Ppxlib 2 | open Util 3 | let make ~loc ~moduleName = 4 | let typeFromGeneratedModule = makeTypeAccessor ~loc ~moduleName in 5 | let valFromGeneratedModule = makeExprAccessor ~loc ~moduleName in 6 | let moduleIdentFromGeneratedModule = makeModuleIdent ~loc ~moduleName in 7 | Ast_helper.Mod.mk 8 | (Pmod_structure 9 | (List.concat 10 | [ 11 | [ 12 | [%stri [@@@warning "-32-34-60"]]; 13 | [%stri include [%m moduleIdentFromGeneratedModule ["Utils"]]]; 14 | [%stri 15 | module Types = [%m moduleIdentFromGeneratedModule ["Types"]]]; 16 | [%stri 17 | let convertFragment : 18 | [%t typeFromGeneratedModule ["Types"; "fragment"]] -> 19 | [%t typeFromGeneratedModule ["Types"; "fragment"]] = 20 | [%e valFromGeneratedModule ["Internal"; "convertFragment"]]]; 21 | [%stri 22 | let makeRelayResolver 23 | (resolver : 24 | [%t 25 | makeTypeAccessorWithParams 26 | ["RescriptRelay_RelayResolvers"; "resolver"] 27 | ~loc 28 | ~params: 29 | [ 30 | typeFromGeneratedModule ["Types"; "fragment"]; 31 | makeTypeAccessorRaw ~loc ["t"]; 32 | ]]) = 33 | RescriptRelay_RelayResolvers.makeRelayResolver 34 | ~convertFragment 35 | ~node:[%e valFromGeneratedModule ["node"]] 36 | resolver]; 37 | ]; 38 | ] 39 | |> List.map UncurriedUtils.mapStructureItem)) 40 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/Subscription.ml: -------------------------------------------------------------------------------- 1 | open Ppxlib 2 | open Util 3 | 4 | let make ~loc ~moduleName = 5 | let typeFromGeneratedModule = makeTypeAccessor ~loc ~moduleName in 6 | let valFromGeneratedModule = makeExprAccessor ~loc ~moduleName in 7 | let moduleIdentFromGeneratedModule = makeModuleIdent ~loc ~moduleName in 8 | Ast_helper.Mod.mk 9 | (Pmod_structure 10 | (List.concat 11 | [ 12 | [ 13 | [%stri [@@@ocaml.warning "-32-34-60"]]; 14 | [%stri include [%m moduleIdentFromGeneratedModule ["Utils"]]]; 15 | [%stri module Operation = [%m moduleIdentFromGeneratedModule []]]; 16 | [%stri 17 | module Types = [%m moduleIdentFromGeneratedModule ["Types"]]]; 18 | [%stri 19 | let convertVariables : 20 | [%t typeFromGeneratedModule ["Types"; "variables"]] -> 21 | [%t typeFromGeneratedModule ["Types"; "variables"]] = 22 | [%e valFromGeneratedModule ["Internal"; "convertVariables"]]]; 23 | [%stri 24 | let convertResponse : 25 | [%t typeFromGeneratedModule ["Types"; "response"]] -> 26 | [%t typeFromGeneratedModule ["Types"; "response"]] = 27 | [%e valFromGeneratedModule ["Internal"; "convertResponse"]]]; 28 | [%stri 29 | let subscribe = 30 | RescriptRelay_Subscriptions.subscribe ~convertVariables 31 | ~convertResponse 32 | ~node:[%e valFromGeneratedModule ["node"]]]; 33 | ]; 34 | ] 35 | |> List.map UncurriedUtils.mapStructureItem)) 36 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/UpdatableFragment.ml: -------------------------------------------------------------------------------- 1 | open Ppxlib 2 | open Util 3 | let make ~loc ~moduleName = 4 | let valFromGeneratedModule = makeExprAccessor ~loc ~moduleName in 5 | let moduleIdentFromGeneratedModule = makeModuleIdent ~loc ~moduleName in 6 | Ast_helper.Mod.mk 7 | (Pmod_structure 8 | (List.concat 9 | [ 10 | [ 11 | [%stri [@@@warning "-32-34-60"]]; 12 | [%stri 13 | module Types = [%m moduleIdentFromGeneratedModule ["Types"]]]; 14 | [%stri 15 | let readUpdatableFragment = [%e valFromGeneratedModule ["readUpdatableFragment"]]]; 16 | ]; 17 | ] 18 | |> List.map UncurriedUtils.mapStructureItem)) 19 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/UpdatableQuery.ml: -------------------------------------------------------------------------------- 1 | open Ppxlib 2 | open Util 3 | let make ~loc ~moduleName = 4 | let valFromGeneratedModule = makeExprAccessor ~loc ~moduleName in 5 | let moduleIdentFromGeneratedModule = makeModuleIdent ~loc ~moduleName in 6 | Ast_helper.Mod.mk 7 | (Pmod_structure 8 | (List.concat 9 | [ 10 | [ 11 | [%stri [@@@warning "-32-34-60"]]; 12 | [%stri 13 | module Types = [%m moduleIdentFromGeneratedModule ["Types"]]]; 14 | [%stri 15 | let readUpdatableQuery = 16 | [%e valFromGeneratedModule ["readUpdatableQuery"]]]; 17 | ]; 18 | ] 19 | |> List.map UncurriedUtils.mapStructureItem)) 20 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/library/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name RescriptRelayPpxLibrary) 3 | (public_name rescript-relay-ppx) 4 | (libraries ppxlib graphql_parser str) 5 | (kind ppx_rewriter) 6 | (preprocess 7 | (pps ppxlib.metaquot)) 8 | (flags :standard -w -9-27)) 9 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-ppx", 3 | "version": "0.1.0", 4 | "description": "Starter Reason Esy Pesy Project", 5 | "esy": { 6 | "build": "dune build -p #{self.name}", 7 | "buildsInSource": "_build" 8 | }, 9 | "scripts": { 10 | "start": "esy x RescriptRelayPpxApp.exe", 11 | "linux-release-static": "dune build --root . ./bin/RescriptRelayPpxApp.exe --ignore-promoted-rules --no-config --profile release-static" 12 | }, 13 | "dependencies": { 14 | "ocaml": "4.14.0", 15 | "@opam/dune": "3.3.1", 16 | "@opam/graphql_parser": "0.12.2", 17 | "@opam/ppxlib": "*" 18 | }, 19 | "resolutions": { 20 | "@opam/ppxlib": "zth/ppxlib:ppxlib.opam#32f83395fb89693a873541298b6367449f23bc4a" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript-relay-ppx/rescript-relay-ppx.opam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/packages/rescript-relay/rescript-relay-ppx/rescript-relay-ppx.opam -------------------------------------------------------------------------------- /packages/rescript-relay/rescript.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay", 3 | "version": "0.1.0", 4 | "uncurried": true, 5 | "namespace": false, 6 | "jsx": { 7 | "mode": "automatic", 8 | "version": 4 9 | }, 10 | "sources": [ 11 | { 12 | "dir": "src", 13 | "subdirs": true 14 | }, 15 | { 16 | "dir": "__tests__", 17 | "type": "dev", 18 | "subdirs": true 19 | }, 20 | { 21 | "dir": "__tests_preloaded__", 22 | "type": "dev", 23 | "subdirs": true 24 | } 25 | ], 26 | "package-specs": { 27 | "module": "commonjs", 28 | "in-source": true 29 | }, 30 | "ppx-flags": [ 31 | "./rescript-relay-ppx/_build/default/bin/RescriptRelayPpxApp.exe -uncurried" 32 | ], 33 | "bs-dependencies": ["@rescript/react"], 34 | "bs-dev-dependencies": ["@glennsl/rescript-fetch"], 35 | "suffix": ".bs.js" 36 | } 37 | -------------------------------------------------------------------------------- /packages/rescript-relay/rescript.release.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay", 3 | "version": "0.1.0", 4 | "namespace": false, 5 | "sources": [ 6 | { 7 | "dir": "src" 8 | } 9 | ], 10 | "package-specs": { 11 | "module": "commonjs", 12 | "in-source": true 13 | }, 14 | "bs-dependencies": ["@rescript/react"], 15 | "suffix": ".bs.js", 16 | "warnings": { 17 | "error": "+101" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/rescript-relay/scripts/.gitignore: -------------------------------------------------------------------------------- 1 | output.json 2 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/ReactDOMExperimental.res: -------------------------------------------------------------------------------- 1 | include ReactDOM.Client 2 | 3 | @val @return(nullable) 4 | external getElementById: string => option = "document.getElementById" 5 | 6 | let renderConcurrentRootAtElementWithId: (React.element, string) => unit = (content, id) => 7 | switch getElementById(id) { 8 | | None => 9 | raise( 10 | Invalid_argument( 11 | "ReactExperimental.renderConcurrentRootAtElementWithId : no element of id " ++ 12 | id ++ " found in the HTML.", 13 | ), 14 | ) 15 | | Some(element) => createRoot(element)->Root.render(content) 16 | } 17 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelayUtils.resi: -------------------------------------------------------------------------------- 1 | /**Tries to return a record from a nested path of linked records.*/ 2 | let resolveNestedRecord: ( 3 | ~rootRecord: option, 4 | ~path: list, 5 | ) => option 6 | 7 | /**Tries to return a record from a nested path of linked records, starting from the root.*/ 8 | let resolveNestedRecordFromRoot: ( 9 | ~store: RescriptRelay.RecordSourceSelectorProxy.t, 10 | ~path: list, 11 | ) => option 12 | 13 | /**Helpers for handling connections.*/ 14 | type insertAt = 15 | | Start 16 | | End 17 | 18 | type connectionConfig = { 19 | parentID: RescriptRelay.dataId, 20 | key: string, 21 | filters: option, 22 | } 23 | 24 | let removeNodeFromConnections: ( 25 | ~store: RescriptRelay.RecordSourceSelectorProxy.t, 26 | ~node: RescriptRelay.RecordProxy.t, 27 | ~connections: list, 28 | ) => unit 29 | 30 | let createAndAddEdgeToConnections: ( 31 | ~store: RescriptRelay.RecordSourceSelectorProxy.t, 32 | ~node: RescriptRelay.RecordProxy.t, 33 | ~connections: list, 34 | ~edgeName: string, 35 | ~insertAt: insertAt, 36 | ) => unit 37 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelay_Internal.resi: -------------------------------------------------------------------------------- 1 | let internal_useConvertedValue: ('a => 'a, 'a) => 'a 2 | let internal_cleanObjectFromUndefinedRaw: 't => 't 3 | let internal_removeUndefinedAndConvertNullsRaw: 't => 't 4 | let internal_nullableToOptionalExnHandler: option => 'a> => option< 5 | Js.Nullable.t<'b> => 'a, 6 | > 7 | @live @unboxed type rec arg = Arg(_): arg 8 | 9 | let unwrapUnion: ('a, array) => 'a 10 | let wrapUnion: 'a => 'a 11 | 12 | external internal_resolverFragmentRefsToFragmentRefs: RescriptRelay.resolverFragmentRefs< 13 | 'a, 14 | > => RescriptRelay.fragmentRefs<'a> = "%identity" 15 | 16 | external internal_resolverFragmentRefsToFragmentRefsPlural: RescriptRelay.resolverFragmentRefs< 17 | 'a, 18 | > => array> = "%identity" 19 | 20 | let applyCodesplitMetadata: ('node, array<(string, dict => unit)>) => 'node 21 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelay_RelayResolvers.res: -------------------------------------------------------------------------------- 1 | open RescriptRelay 2 | 3 | @module("relay-runtime/lib/store/ResolverFragments") 4 | external readFragment_: (fragmentNode<'node>, 'fragmentRef) => 'fragment = "readFragment" 5 | 6 | type resolver<'fragment, 't> = 'fragment => option<'t> 7 | 8 | // This is abstract just to hide the implementation details that don't need to be known anyway. 9 | type relayResolver 10 | external mkRelayResolver: 'a => relayResolver = "%identity" 11 | 12 | let makeRelayResolver = ( 13 | ~node, 14 | ~convertFragment: 'fragment => 'fragment, 15 | resolver: resolver<'fragment, 't>, 16 | ) => { 17 | let relayResolver = fRef => { 18 | resolver(readFragment_(node, fRef)->convertFragment) 19 | } 20 | relayResolver->mkRelayResolver 21 | } 22 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelay_RelayResolvers.resi: -------------------------------------------------------------------------------- 1 | open RescriptRelay 2 | 3 | type resolver<'fragment, 't> = 'fragment => option<'t> 4 | type relayResolver 5 | 6 | let makeRelayResolver: ( 7 | ~node: fragmentNode<'a>, 8 | ~convertFragment: 'fragment => 'fragment, 9 | resolver<'fragment, 't>, 10 | ) => relayResolver 11 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelay_Subscriptions.res: -------------------------------------------------------------------------------- 1 | open RescriptRelay 2 | 3 | type updaterFn<'response> = (RecordSourceSelectorProxy.t, 'response) => unit 4 | type subscriptionConfig<'node, 'variables, 'response> = { 5 | subscription: subscriptionNode<'node>, 6 | variables: 'variables, 7 | onCompleted?: unit => unit, 8 | onError?: Js.Exn.t => unit, 9 | onNext?: 'response => unit, 10 | updater?: updaterFn<'response>, 11 | } 12 | 13 | @module("relay-runtime") 14 | external requestSubscription_: ( 15 | Environment.t, 16 | subscriptionConfig<'node, 'variables, 'response>, 17 | ) => Disposable.t = "requestSubscription" 18 | 19 | let subscribe = ( 20 | ~node, 21 | ~convertVariables: 'variables => 'variables, 22 | ~convertResponse: 'response => 'response, 23 | ) => { 24 | ( 25 | ~environment: Environment.t, 26 | ~variables: 'variables, 27 | ~onCompleted=?, 28 | ~onError=?, 29 | ~onNext=?, 30 | ~updater=?, 31 | ) => { 32 | requestSubscription_( 33 | environment, 34 | { 35 | ?onCompleted, 36 | subscription: node, 37 | variables: variables->convertVariables, 38 | ?onError, 39 | onNext: ?switch onNext { 40 | | Some(onNext) => Some(response => onNext(response->convertResponse)) 41 | | None => None 42 | }, 43 | updater: ?switch updater { 44 | | Some(updater) => Some((store, response) => updater(store, response->convertResponse)) 45 | | None => None 46 | }, 47 | }, 48 | ) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/rescript-relay/src/RescriptRelay_Subscriptions.resi: -------------------------------------------------------------------------------- 1 | open RescriptRelay 2 | 3 | let subscribe: ( 4 | ~node: subscriptionNode<'a>, 5 | ~convertVariables: 'variables => 'variables, 6 | ~convertResponse: 'response => 'response, 7 | ) => ( 8 | ~environment: Environment.t, 9 | ~variables: 'variables, 10 | ~onCompleted: unit => unit=?, 11 | ~onError: Js.Exn.t => unit=?, 12 | ~onNext: 'response => unit=?, 13 | ~updater: (RecordSourceSelectorProxy.t, 'response) => unit=?, 14 | ) => Disposable.t 15 | -------------------------------------------------------------------------------- /rescript-relay-documentation/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # production 5 | /build 6 | 7 | # generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | .vercel 22 | -------------------------------------------------------------------------------- /rescript-relay-documentation/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using Docusaurus 2, a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=1 yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/about-rescript-relay.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: about-rescript-relay 3 | title: About RescriptRelay 4 | sidebar_label: About RescriptRelay 5 | --- 6 | 7 | 8 | ## An opinionated binding to Relay 9 | 10 | RescriptRelay does _not_ aim to be a 1-to-1 binding of all of Relay. Rather, we take the following approach: 11 | 12 | - Focus on binding the parts that lend themselves well to ReScripts type system. In our case, this means _we only bind Relay's hooks, not their higher-order components_. 13 | - Include tools and utilities that help make life with Relay easier. This includes simplifying common patterns like updating the store, dealing with connections and so on. 14 | 15 | This means there's quite a large part of the API surface we won't cover. Rest assured though, what we won't cover will only be _additional ways of doing the same thing_. -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/client-schema-extensions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: client-schema-extensions 3 | title: Client Schema Extensions 4 | sidebar_label: Client Schema Extensions 5 | --- 6 | 7 | You're encouraged to read the [official Relay documentation on client schema extensions](https://relay.dev/docs/guides/client-schema-extensions/). Client schema extensions work the same in RescriptRelay as in Relay itself. 8 | 9 | For updating client-only data, you're encouraged to refer to the [page in modifying the store locally](interacting-with-the-store.md). 10 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/editor-support-and-development-environment.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: editor-support-and-development-environment 3 | title: Editor Support & Development Environment 4 | sidebar_label: Editor Support & Development Environment 5 | --- 6 | 7 | This page details how to set up the best possible development environment for RescriptRelay. 8 | 9 | ## Editor extensions 10 | 11 | First of all, make sure you have [rescript-vscode](https://github.com/rescript-lang/rescript-vscode) set up for proper language support. 12 | 13 | If you're using VSCode, you are **highly encouraged** to use our [dedicated VSCode extension](vscode-extension). 14 | 15 | _WIP, more info about other editors than VSCode coming soon_. 16 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: examples 3 | title: Examples 4 | sidebar_label: Examples 5 | --- 6 | 7 | Here's a collection of examples made using RescriptRelay. 8 | 9 | - [A simple dashboard showcasing most of RescriptRelay's featues](https://github.com/zth/rescript-relay/tree/master/example) 10 | - [A port of Relay official issue tracker example](https://github.com/cometkim/rescript-relay-issue-tracker) 11 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/generate.js: -------------------------------------------------------------------------------- 1 | let fs = require("fs"); 2 | let path = require("path"); 3 | 4 | let makeSnakeCase = str => 5 | str 6 | .split(" ") 7 | .map(s => s.toLowerCase()) 8 | .join("-"); 9 | 10 | let makeTitle = str => 11 | str 12 | .split(" ") 13 | .map(s => `${s[0].toUpperCase()}${s.slice(1).toLowerCase()}`) 14 | .join(" "); 15 | 16 | let name = process.argv[2]; 17 | let snakeCase = makeSnakeCase(name); 18 | let title = makeTitle(name); 19 | 20 | fs.writeFileSync( 21 | path.join(__dirname, `${snakeCase}.md`), 22 | `--- 23 | id: ${snakeCase} 24 | title: ${title} 25 | sidebar_label: ${title} 26 | --- 27 | 28 | _WIP_. 29 | ` 30 | ); 31 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/input-objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: input-objects 3 | title: Input Objects 4 | sidebar_label: Input Objects 5 | --- 6 | 7 | ## Input objects in RescriptRelay 8 | 9 | All input objects in your schema will have their types (and maker functions) emitted into the generated file `RelaySchemaAssets_graphql.res`. This means you'll have access to the type definition of all of your input objects regardless of what you're doing. Handy if you're for example making general functions to produce various input objects. 10 | 11 | ### `null` in input objects 12 | 13 | You can refer to the page on [variables](variables#rescriptrelaynullablevariables) if you need to send an explicit `null` as the value of a prop in an input object. 14 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/network-layer.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: network-layer 3 | title: Network Layer 4 | sidebar_label: Network Layer 5 | --- 6 | 7 | _WIP_. 8 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/quirks-of-rescript-relay.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: quirks-of-rescript-relay 3 | title: Quirks of RescriptRelay 4 | sidebar_label: Quirks of RescriptRelay 5 | --- 6 | 7 | Ahh, what would a framework be without quirks and weird stuff? RescriptRelay comes with a few _gotchas_ that are good to keep in mind. 8 | 9 | ## Field names 10 | 11 | Since ReScript has reserved words (like `type` and `val`), none of the fields you query for can end up being called a reserved word in your views. This is simply because you won't be able to access the field since you cannot use the reserved word as an accessor. 12 | 13 | This is more a quirk of ReScript than anything, but it does mean that you'll need to _alias_ any field whose name is a reserved word into something that's not a reserved word. For example: 14 | 15 | ```graphql 16 | fragment UserProfile_user on User { 17 | firstName 18 | userType: type 19 | } 20 | ``` 21 | 22 | `type` is a reserved word, so we alias it to `userType`. This means that in our view we access it like this: 23 | 24 | ```rescript 25 | user.userType 26 | ``` 27 | 28 | ...and this will work fine. 29 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/router.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: router 3 | title: Router 4 | sidebar_label: Router 5 | --- 6 | 7 | The [rescript-relay-router](https://www.npmjs.com/package/rescript-relay-router) is designed for scale, performance and ergonomics. Tailored for usage with `rescript-relay`. A _modern_ router, targeting modern browsers and developer workflows using `vite`. 8 | 9 | Read all about the [rescript-relay-router](https://github.com/zth/rescript-relay-router/blob/main/packages/rescript-relay-router/README.md) at the official repository. 10 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/start-here.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: start-here 3 | title: Start Here 4 | sidebar_label: Start Here 5 | --- 6 | 7 | RescriptRelay is a way to use [Relay](https://relay.dev), a JavaScript client-side framework for building data-driven applications using GraphQL, together with [ReScript](https://rescript-lang.org/). This page will briefly introduce the documentation, how it's structured and what to expect. 8 | 9 | ## Structure 10 | 11 | The documentation is roughly divided into 3 parts: 12 | 13 | ##### 1. A walkthrough setting up RescriptRelay and introducing the main features 14 | 15 | Each page in the walkthrough will introduce a concept from Relay and explain how to achieve the same thing in RescriptRelay. Each page will also have a section of _recommended background reading_ that you're encouraged to look into if you're not familiar with the concepts explained. 16 | 17 | ##### 2. An API reference covering the full RescriptRelay API surface 18 | 19 | This will detail all modules, functions and concepts of RescriptRelay in good, old plain table form. 20 | 21 | ##### 3. Guides, tips and tricks 22 | 23 | Here you'll find resources for making life with RescriptRelay easier. 24 | 25 | ## The next step 26 | 27 | Ok, enough introduction! Let's move on to [getting started](getting-started) and start setting up RescriptRelay in your project. 28 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/the-compiler.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: the-compiler 3 | title: The Compiler 4 | sidebar_label: The Compiler 5 | --- 6 | 7 | ## A short introduction of the Relay Compiler 8 | 9 | Relay's compiler is responsible for taking all GraphQL operations defined in your code, analyze their relationships and check their validity. It then compiles them to generated files containing optimized artifacts that Relay uses at runtime to make queries and understand the response. This means that Relay moves work like parsing and understanding how responses to queries are structured to compile time. A good example of how Relay treats performance as a core feature. 10 | 11 | In addition to emitting runtime artifacts, the compiler also _emits ReScript types through RescriptRelay's language plugin for the compiler_, describing your operations and their relationships. RescriptRelay takes these types and uses them to enforce type safety. This means that Relay and RescriptRelay can _guarantee type-safety_ when interacting with all data, and that you'll get a great developer experience through the tooling that types enable. 12 | 13 | As said before, you really don't have to think about the generated artifacts as RescriptRelay does the heavy lifting of using them for you, but if you're interested, have a look at the files in your `artifactDirectory`. 14 | 15 | You can [read more about the Relay compiler here](https://relay.dev/docs/en/graphql-in-relay.html#relay-compiler). 16 | 17 | ## How RescriptRelay uses the Relay compiler 18 | 19 | When you run the compiler, you run `rescript-relay-compiler` and not `relay-compiler` - why is that? Well, it's because RescriptRelay ships a thin layer on top of `relay-compiler`, that sets up the configuration the Relay compiler needs to produce ReScript automatically. It also enforces a more strict configuration of Relay that RescriptRelay needs to do its thing. 20 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/tips-and-tricks.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: tips-and-tricks 3 | title: Tips and Tricks 4 | sidebar_label: Tips and Tricks 5 | --- 6 | 7 | Here's a collection of continously updated tips and tricks that'll simplify your life using RescriptRelay. 8 | 9 | ## Use the dedicated VSCode extension 10 | 11 | Beta state, but usable 12 | Will help you tremendously 13 | 14 | ## Avoid having to specify types 15 | 16 | Use fastpipe 17 | 18 | ## Deep pattern matching 19 | 20 | Reducing the number of switches 21 | 22 | ## Finding the types if needed 23 | 24 | ## Make use of generated helpers 25 | 26 | - Connections 27 | - Make variables and input objects 28 | 29 | ## Preload queries 30 | 31 | ## Stringify and parse enums manually 32 | 33 | ## Always rerun the compiler when upgrading 34 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/using-with-schemas-that-dont-conform-to-the-relay-spec.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: using-with-schemas-that-dont-conform-to-the-relay-spec 3 | title: Using with schemas that don't conform to the Relay spec 4 | sidebar_label: Using with schemas that don't conform to the Relay spec 5 | --- 6 | 7 | _This section is a WIP_. 8 | 9 | Relay, and by extension RescriptRelay, expects your schema to conform to certain practices for it to work optimally. The practices are outlined in [the Relay server specification](using-with-schemas-that-dont-conform-to-the-relay-spec). This page will discuss what to do when your schema does not conform to the specification, but you still want to use RescriptRelay. 10 | 11 | ## Global Object Identification and the `Node` interface 12 | 13 | The Relay specification expects all your GraphQL objects to have _globally unique IDs_. _Work in progress..._. 14 | -------------------------------------------------------------------------------- /rescript-relay-documentation/docs/utilities.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: utilities 3 | title: Utilities 4 | sidebar_label: Utilities 5 | --- 6 | 7 | WIP. 8 | -------------------------------------------------------------------------------- /rescript-relay-documentation/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-documentation", 3 | "version": 2 4 | } 5 | -------------------------------------------------------------------------------- /rescript-relay-documentation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-documentation", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy" 11 | }, 12 | "dependencies": { 13 | "@docusaurus/core": "2.1.0", 14 | "@docusaurus/preset-classic": "2.1.0", 15 | "@mdx-js/react": "^1.6.21", 16 | "@svgr/webpack": "^5.5.0", 17 | "clsx": "^1.1.1", 18 | "file-loader": "^6.2.0", 19 | "prism-react-renderer": "1.3.1", 20 | "react": "^17.0.1", 21 | "react-dom": "^17.0.1", 22 | "url-loader": "^4.1.1" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /rescript-relay-documentation/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Any CSS included here will be global. The classic template 10 | * bundles Infima by default. Infima is a CSS framework designed to 11 | * work well for content-centric websites. 12 | */ 13 | 14 | /* You can override the default Infima variables here. */ 15 | :root { 16 | --ifm-color-primary: #db4d3f; 17 | --ifm-color-primary-dark: #bc2d1e; 18 | --ifm-color-primary-darker: #961608; 19 | --ifm-color-primary-darkest: #961608; 20 | --ifm-color-primary-light: #f77567; 21 | --ifm-color-primary-lighter: #ff9e94; 22 | --ifm-color-primary-lightest: #ff9e94; 23 | } 24 | 25 | .color1 { 26 | background-color: rgba(96, 165, 250, 0.5); 27 | } 28 | 29 | .color2 { 30 | background-color: rgb(216, 180, 254, 0.5); 31 | } 32 | 33 | .color3 { 34 | background-color: rgb(254, 240, 138, 0.5); 35 | } 36 | 37 | .color4 { 38 | background-color: rgb(153, 246, 228, 0.5); 39 | } 40 | 41 | .color5 { 42 | background-color: rgba(246, 186, 153, 0.5); 43 | } 44 | 45 | .code-change { 46 | background-color: rgba(20, 178, 76, 0.5); 47 | } -------------------------------------------------------------------------------- /rescript-relay-documentation/src/pages/community.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Community 3 | description: RescriptRelay's community 4 | hide_table_of_contents: true 5 | --- 6 | 7 | # Community 8 | 9 | The RescriptRelay community packs a bunch of enthusiastic companies and individual building products spanning a vast amount of industries. You're very much welcome to join us! We're primarily located at: 10 | 11 | 1. At [**Discord**](https://discord.gg/wzj4EN8XDc) 12 | 2. And, recently started [GitHub discussions](https://github.com/zth/rescript-relay/discussions) 13 | 14 | Come join us, no question is too simple, whether it's about RescriptRelay, ReScript or Relay itself. We're a small but active community interested in learning from each other. 15 | -------------------------------------------------------------------------------- /rescript-relay-documentation/src/pages/showcases.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Showcases 3 | description: Showcases 4 | hide_table_of_contents: true 5 | --- 6 | 7 | # Showcases 8 | 9 | Coming soon. 10 | -------------------------------------------------------------------------------- /rescript-relay-documentation/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * CSS files with the .module.css suffix will be treated as CSS modules 10 | * and scoped locally. 11 | */ 12 | 13 | .heroBanner { 14 | padding: 4rem 0; 15 | text-align: center; 16 | position: relative; 17 | overflow: hidden; 18 | } 19 | 20 | @media screen and (max-width: 966px) { 21 | .heroBanner { 22 | padding: 2rem; 23 | } 24 | } 25 | 26 | .buttons { 27 | display: flex; 28 | align-items: center; 29 | justify-content: center; 30 | } 31 | 32 | .features { 33 | display: flex; 34 | align-items: center; 35 | padding: 2rem 0; 36 | width: 100%; 37 | } 38 | 39 | .featureImage { 40 | height: 200px; 41 | width: 200px; 42 | } 43 | -------------------------------------------------------------------------------- /rescript-relay-documentation/static/googlecfd8adbd3329afe2.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlecfd8adbd3329afe2.html -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/arrays-keys-warning-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/arrays-keys-warning-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/arrays-top-stories-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/arrays-top-stories-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/connections-comments-initial-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/connections-comments-initial-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/connections-conceptual-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/connections-conceptual-graph.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/connections-edge-nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/connections-edge-nodes.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/connections-full-model-next-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/connections-full-model-next-page.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/connections-full-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/connections-full-model.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-image-add-once-compiled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-image-add-once-compiled.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-combined.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-combined.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-image-combined.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-image-combined.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story-image.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-newsfeed-story.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-reuse-combined.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-reuse-combined.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragment-reuse-seperate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragment-reuse-seperate.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragments-image-two-places-compiled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragments-image-two-places-compiled.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/fragments-newsfeed-story-compilation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/fragments-newsfeed-story-compilation.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/graphql-compiler-combines-fragments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/graphql-compiler-combines-fragments.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/graphql-graph-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/graphql-graph-detail.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/graphql-relay-runtime-fetches-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/graphql-relay-runtime-fetches-query.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/graphql-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/graphql-request.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/graphql-response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/graphql-response.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/interfaces-organization-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/interfaces-organization-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/interfaces-person-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/interfaces-person-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/intro-screenshot-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/intro-screenshot-placeholder.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/mutations-comments-composer-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/mutations-comments-composer-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/mutations-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/mutations-lifecycle.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/mutations-like-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/mutations-like-button.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/network-request-with-variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/network-request-with-variables.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/preloaded-basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/preloaded-basic.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/preloaded-ideal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/preloaded-ideal.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/preloaded-lazy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/preloaded-lazy.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/queries-basic-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/queries-basic-screenshot.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/queries-wrong-hovercard-person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/queries-wrong-hovercard-person.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/query-breakdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/query-breakdown.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/query-upon-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/query-upon-graph.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/query-variables-hovercard-correct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/query-variables-hovercard-correct.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/refetchable-contacts-initial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/refetchable-contacts-initial.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/refetchable-suspense-1-data-needed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/refetchable-suspense-1-data-needed.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/refetchable-suspense-3-fallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/refetchable-suspense-3-fallback.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/refetchable-transition-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/refetchable-transition-search.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/docs/tutorial/refetechable-suspense-2-nearest-suspense-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/docs/tutorial/refetechable-suspense-2-nearest-suspense-point.png -------------------------------------------------------------------------------- /rescript-relay-documentation/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zth/rescript-relay/39b586f006b173ad4ad3f7c3cf329e1422d93e58/rescript-relay-documentation/static/img/favicon.png -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | --------------------------------------------------------------------------------