@ttoss/graphql-api 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,26 +9,14 @@ This package offers an opinionated approach to building a GraphQL API using the
9
9
  As **Relay** is the primary GraphQL client in the ttoss ecosystem, this package implements the [Relay Server Specification](https://relay.dev/docs/guides/graphql-server-specification/) for seamless client-server interaction.
10
10
 
11
11
  1. **Schema Building**:
12
- Generate the GraphQL schema required for Relay's introspection queries by running:
13
-
14
- ```bash
15
- ttoss-graphql-api build-schema
16
- ```
12
+ Generate the GraphQL schema required for Relay's introspection queries with [@ttoss/graphql-api-cli](https://ttoss.dev/docs/modules/packages/graphql-api-cli/).
17
13
 
18
14
  1. **TypeScript Types Generation**:
19
- Automatically generate TypeScript types for your GraphQL schema with the same command:
20
-
21
- ```bash
22
- ttoss-graphql-api build-schema
23
- ```
15
+ Automatically generate TypeScript types for your GraphQL schema with [@ttoss/graphql-api-cli](https://ttoss.dev/docs/modules/packages/graphql-api-cli/).
24
16
 
25
17
  1. **AWS AppSync Support**:
26
18
  Create GraphQL APIs compatible with AWS AppSync. Additionally, this package includes support for running a local GraphQL API server for development and testing purposes.
27
19
 
28
- ## ESM Only
29
-
30
- This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
31
-
32
20
  ## Installation
33
21
 
34
22
  ```bash
@@ -450,39 +438,7 @@ import { allow, deny, shield } from '@ttoss/graphql-api/shield';
450
438
 
451
439
  ## Building Schema and Types
452
440
 
453
- As Relay needs an introspection query to work, this package provides a way to build the GraphQL schema by running `ttoss-graphl-api build-schema`. It build the schema using the `schemaComposer` from `src/schemaComposer.ts` file and save the schema in `schema/schema.graphql` file and TypeScript types in `schema/types.ts` file.
454
-
455
- ```bash
456
- ttoss-graphl-api build-schema
457
- ```
458
-
459
- You can add the `build-schema` script to your `package.json`:
460
-
461
- ```json
462
- {
463
- "scripts": {
464
- "build-schema": "ttoss-graphl-api build-schema"
465
- }
466
- }
467
- ```
468
-
469
- ### Options
470
-
471
- #### `--directory`/`-d`
472
-
473
- If your `schemaComposer` is in a different directory, you can pass the `--directory`/`-d` option to `ttoss-graphl-api build-schema` command:
474
-
475
- ```bash
476
- ttoss-graphl-api build-schema -d tests
477
- ```
478
-
479
- #### `--external`
480
-
481
- External dependencies to ignore during build. If you don't set this option, the `build-schema` command will use the `dependencies` and `devDependencies` from your `package.json` file.
482
-
483
- ```bash
484
- ttoss-graphl-api build-schema --external graphql-compose,graphql
485
- ```
441
+ Check [@ttoss/graphql-api-cli](https://ttoss.dev/docs/modules/packages/graphql-api-cli/) for more information about how to build the schema and types.
486
442
 
487
443
  ## How to Create Tests
488
444
 
@@ -0,0 +1,16 @@
1
+ import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose';
2
+ export * from 'graphql-compose';
3
+ export { composeWithConnection } from 'graphql-compose-connection';
4
+ import { GraphQLSchema } from 'graphql';
5
+ import { IMiddleware, IMiddlewareGenerator } from 'graphql-middleware';
6
+ export { IMiddleware as Middleware } from 'graphql-middleware';
7
+
8
+ declare const composeWithRelay: <TContext>(tc: ObjectTypeComposer<any, TContext>) => ObjectTypeComposer<any, TContext>;
9
+
10
+ type BuildSchemaInput<TContext = unknown> = {
11
+ schemaComposer: SchemaComposer<TContext>;
12
+ middlewares?: (IMiddleware | IMiddlewareGenerator<unknown, TContext, unknown>)[];
13
+ };
14
+ declare const buildSchema: ({ schemaComposer, middlewares, }: BuildSchemaInput) => GraphQLSchema;
15
+
16
+ export { type BuildSchemaInput, buildSchema, composeWithRelay };
package/dist/index.js ADDED
@@ -0,0 +1,200 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ "use strict";
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all) __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true
12
+ });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
17
+ get: () => from[key],
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
21
+ return to;
22
+ };
23
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
24
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
25
+ value: true
26
+ }), mod);
27
+
28
+ // src/index.ts
29
+ var src_exports = {};
30
+ __export(src_exports, {
31
+ buildSchema: () => buildSchema,
32
+ composeWithConnection: () => import_graphql_compose_connection.composeWithConnection,
33
+ composeWithRelay: () => composeWithRelay
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+
37
+ // src/composeWithRelay/composeWithRelay.ts
38
+ var import_graphql_compose3 = require("graphql-compose");
39
+
40
+ // src/composeWithRelay/nodeFieldConfig.ts
41
+ var import_graphql_compose = require("graphql-compose");
42
+ var import_ids = require("@ttoss/ids");
43
+ var getNodeFieldConfig = (typeMapForRelayNode, nodeInterface) => {
44
+ return {
45
+ description: "Fetches an object that has globally unique ID among all types",
46
+ type: nodeInterface,
47
+ args: {
48
+ id: {
49
+ type: "ID!",
50
+ description: "The globally unique ID among all types"
51
+ }
52
+ },
53
+ // eslint-disable-next-line max-params
54
+ resolve: (source, args, context, info) => {
55
+ if (!args.id || !(typeof args.id === "string")) {
56
+ return null;
57
+ }
58
+ const {
59
+ type
60
+ } = (0, import_ids.fromGlobalId)(args.id);
61
+ if (!typeMapForRelayNode[type]) {
62
+ return null;
63
+ }
64
+ const {
65
+ tc,
66
+ resolver: findById
67
+ } = typeMapForRelayNode[type];
68
+ if (findById && findById.resolve && tc) {
69
+ const graphqlType = tc.getType();
70
+ let projection;
71
+ if (info) {
72
+ projection = (0, import_graphql_compose.getProjectionFromAST)({
73
+ ...info,
74
+ returnType: graphqlType
75
+ });
76
+ } else {
77
+ projection = {};
78
+ }
79
+ const idArgName = Object.keys(findById.args)[0];
80
+ return findById.resolve({
81
+ source,
82
+ args: {
83
+ [idArgName]: args.id
84
+ },
85
+ // eg. mongoose has _id fieldname, so should map
86
+ context,
87
+ info,
88
+ projection
89
+ }).then(res => {
90
+ if (!res) {
91
+ return res;
92
+ }
93
+ res.__nodeType = graphqlType;
94
+ return res;
95
+ });
96
+ }
97
+ return null;
98
+ }
99
+ };
100
+ };
101
+
102
+ // src/composeWithRelay/nodeInterface.ts
103
+ var import_graphql_compose2 = require("graphql-compose");
104
+ var NodeTC = import_graphql_compose2.InterfaceTypeComposer.createTemp({
105
+ name: "Node",
106
+ description: "An object, that can be fetched by the globally unique ID among all types.",
107
+ fields: {
108
+ id: {
109
+ type: "ID!",
110
+ description: "The globally unique ID among all types."
111
+ }
112
+ },
113
+ resolveType: payload => {
114
+ return payload.__nodeType.name ? payload.__nodeType.name : null;
115
+ }
116
+ });
117
+ var NodeInterface = NodeTC.getType();
118
+ var getNodeInterface = sc => {
119
+ if (sc.hasInstance("Node", import_graphql_compose2.InterfaceTypeComposer)) {
120
+ return sc.get("Node");
121
+ }
122
+ sc.set("Node", NodeTC);
123
+ return NodeTC;
124
+ };
125
+
126
+ // src/composeWithRelay/composeWithRelay.ts
127
+ var import_ids2 = require("@ttoss/ids");
128
+ var TypeMapForRelayNode = {};
129
+ var composeWithRelay = tc => {
130
+ if (!(tc instanceof import_graphql_compose3.ObjectTypeComposer)) {
131
+ throw new Error("You should provide ObjectTypeComposer instance to composeWithRelay method");
132
+ }
133
+ const nodeInterface = getNodeInterface(tc.schemaComposer);
134
+ const nodeFieldConfig = getNodeFieldConfig(TypeMapForRelayNode, nodeInterface);
135
+ if (tc.getTypeName() === "Query" || tc.getTypeName() === "RootQuery") {
136
+ tc.setField("node", nodeFieldConfig);
137
+ return tc;
138
+ }
139
+ if (tc.getTypeName() === "Mutation" || tc.getTypeName() === "RootMutation") {
140
+ return tc;
141
+ }
142
+ if (!tc.hasRecordIdFn()) {
143
+ throw new Error(`ObjectTypeComposer(${tc.getTypeName()}) should have recordIdFn. This function returns ID from provided object.`);
144
+ }
145
+ const findById = tc.getResolver("findById");
146
+ if (!findById) {
147
+ throw new Error(`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithRelay should have findById resolver.`);
148
+ }
149
+ TypeMapForRelayNode[tc.getTypeName()] = {
150
+ resolver: findById,
151
+ tc
152
+ };
153
+ tc.addFields({
154
+ id: {
155
+ type: "ID!",
156
+ description: "The globally unique ID among all types",
157
+ resolve: source => {
158
+ return (0, import_ids2.toGlobalId)(tc.getTypeName(), tc.getRecordId(source).toString());
159
+ }
160
+ }
161
+ });
162
+ tc.addInterface(nodeInterface);
163
+ return tc;
164
+ };
165
+
166
+ // src/composeWithRelay/index.ts
167
+ var import_graphql_compose4 = require("graphql-compose");
168
+ composeWithRelay(import_graphql_compose4.schemaComposer.Query);
169
+
170
+ // src/index.ts
171
+ var import_graphql_compose_connection = require("graphql-compose-connection");
172
+ __reExport(src_exports, require("graphql-compose"), module.exports);
173
+
174
+ // src/buildSchema.ts
175
+ var import_graphql_middleware = require("graphql-middleware");
176
+ var buildSchema = ({
177
+ schemaComposer: schemaComposer2,
178
+ middlewares
179
+ }) => {
180
+ if (!schemaComposer2) {
181
+ throw new Error("No schemaComposer provided");
182
+ }
183
+ const schema = schemaComposer2.buildSchema();
184
+ if (middlewares) {
185
+ return (0, import_graphql_middleware.applyMiddleware)(schema, ...middlewares.map(middleware => {
186
+ if (middleware.generate) {
187
+ return middleware.generate(schema);
188
+ }
189
+ return middleware;
190
+ }));
191
+ }
192
+ return schema;
193
+ };
194
+ // Annotate the CommonJS export names for ESM import in node:
195
+ 0 && (module.exports = {
196
+ buildSchema,
197
+ composeWithConnection,
198
+ composeWithRelay,
199
+ ...require("graphql-compose")
200
+ });
@@ -0,0 +1,2 @@
1
+ export * from 'graphql-shield';
2
+ export { IMiddleware, IMiddlewareFieldMap, IMiddlewareFunction, IMiddlewareGenerator, IMiddlewareGeneratorConstructor, IMiddlewareTypeMap } from 'graphql-middleware';
package/dist/shield.js ADDED
@@ -0,0 +1,29 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ "use strict";
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
11
+ get: () => from[key],
12
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
13
+ });
14
+ }
15
+ return to;
16
+ };
17
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
18
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
19
+ value: true
20
+ }), mod);
21
+
22
+ // src/shield.ts
23
+ var shield_exports = {};
24
+ module.exports = __toCommonJS(shield_exports);
25
+ __reExport(shield_exports, require("graphql-shield"), module.exports);
26
+ // Annotate the CommonJS export names for ESM import in node:
27
+ 0 && (module.exports = {
28
+ ...require("graphql-shield")
29
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/graphql-api",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "A library for building GraphQL APIs using ttoss ecosystem.",
5
5
  "license": "MIT",
6
6
  "author": "ttoss",
@@ -25,17 +25,11 @@
25
25
  "types": "./dist/shield.d.ts"
26
26
  }
27
27
  },
28
- "bin": {
29
- "ttoss-graphql-api": "./bin/cli.js"
30
- },
31
28
  "files": [
32
29
  "dist"
33
30
  ],
34
31
  "sideEffects": false,
35
32
  "dependencies": {
36
- "@graphql-codegen/core": "^4.0.2",
37
- "@graphql-codegen/typescript": "^4.1.2",
38
- "esbuild": "^0.24.0",
39
33
  "graphql-compose": "^9.0.11",
40
34
  "graphql-compose-connection": "^8.2.1",
41
35
  "graphql-middleware": "^6.1.35",
@@ -47,7 +41,6 @@
47
41
  "graphql": "^16.6.0"
48
42
  },
49
43
  "devDependencies": {
50
- "commander": "^12.1.0",
51
44
  "graphql": "^16.9.0",
52
45
  "jest": "^29.7.0",
53
46
  "tsup": "^8.3.5",
@@ -62,7 +55,7 @@
62
55
  "provenance": true
63
56
  },
64
57
  "scripts": {
65
- "build-config": "tsup-node",
58
+ "build": "tsup",
66
59
  "test": "jest --projects tests/unit"
67
60
  }
68
61
  }
package/bin/cli.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import '../dist/esm/cli.js';
package/dist/cli.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import 'graphql-shield';
2
- import 'graphql-middleware';
package/dist/esm/cli.js DELETED
@@ -1,173 +0,0 @@
1
- /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
-
3
- // src/cli.ts
4
- import * as esbuild from "esbuild";
5
- import * as fs from "node:fs";
6
- import * as path from "node:path";
7
- import * as typescriptPlugin from "@graphql-codegen/typescript";
8
- import { Command } from "commander";
9
- import { codegen } from "@graphql-codegen/core";
10
- import { parse } from "graphql";
11
- import log from "npmlog";
12
-
13
- // package.json
14
- var package_default = {
15
- name: "@ttoss/graphql-api",
16
- version: "0.8.0",
17
- description: "A library for building GraphQL APIs using ttoss ecosystem.",
18
- license: "MIT",
19
- author: "ttoss",
20
- contributors: ["Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"],
21
- repository: {
22
- type: "git",
23
- url: "https://github.com/ttoss/ttoss.git",
24
- directory: "packages/graphql-api"
25
- },
26
- type: "module",
27
- exports: {
28
- ".": "./src/index.ts",
29
- "./shield": "./src/shield.ts"
30
- },
31
- bin: {
32
- "ttoss-graphql-api": "./bin/cli.js"
33
- },
34
- files: ["dist"],
35
- scripts: {
36
- "build-config": "tsup-node",
37
- test: "jest --projects tests/unit"
38
- },
39
- sideEffects: false,
40
- dependencies: {
41
- "@graphql-codegen/core": "^4.0.2",
42
- "@graphql-codegen/typescript": "^4.1.2",
43
- "@ttoss/ids": "workspace:^",
44
- esbuild: "^0.24.0",
45
- "graphql-compose": "^9.0.11",
46
- "graphql-compose-connection": "^8.2.1",
47
- "graphql-middleware": "^6.1.35",
48
- "graphql-shield": "^7.6.5",
49
- npmlog: "^7.0.1"
50
- },
51
- peerDependencies: {
52
- graphql: "^16.6.0"
53
- },
54
- devDependencies: {
55
- "@ttoss/config": "workspace:^",
56
- commander: "^12.1.0",
57
- graphql: "^16.9.0",
58
- jest: "^29.7.0",
59
- tsup: "^8.3.5"
60
- },
61
- keywords: ["api", "graphql"],
62
- publishConfig: {
63
- access: "public",
64
- exports: {
65
- ".": {
66
- import: "./dist/esm/index.js",
67
- require: "./dist/index.js",
68
- types: "./dist/index.d.ts"
69
- },
70
- "./shield": {
71
- import: "./dist/esm/shield.js",
72
- require: "./dist/shield.js",
73
- types: "./dist/shield.d.ts"
74
- }
75
- },
76
- provenance: true
77
- }
78
- };
79
-
80
- // src/cli.ts
81
- var logPrefix = "graphql-api";
82
- var importSchemaComposer = async ({
83
- external,
84
- schemaComposerPath
85
- }) => {
86
- const lastEntryPointName = schemaComposerPath.split("/").pop();
87
- const filename = lastEntryPointName?.split(".")[0];
88
- const outfile = path.resolve(process.cwd(), "out", filename + ".js");
89
- const packageJsonPath = path.resolve(process.cwd(), "package.json");
90
- const packageJson = await fs.promises.readFile(packageJsonPath, "utf-8");
91
- const dependencies = Object.keys(JSON.parse(packageJson).dependencies).filter(dependency => {
92
- if (dependency.startsWith("@ttoss/")) {
93
- return false;
94
- }
95
- if (dependency === "graphql") {
96
- return false;
97
- }
98
- return true;
99
- });
100
- const result = await esbuild.build({
101
- bundle: true,
102
- entryPoints: [schemaComposerPath],
103
- external: external || dependencies,
104
- format: "esm",
105
- outfile,
106
- platform: "node",
107
- target: "ES2023",
108
- treeShaking: true
109
- });
110
- if (result.errors.length > 0) {
111
- console.error("Error building config file: ", filename);
112
- throw result.errors;
113
- }
114
- try {
115
- return await import(outfile);
116
- } catch (error) {
117
- console.error("Failed importing build config file: ", filename);
118
- throw error;
119
- }
120
- };
121
- var buildSchema = async ({
122
- directory,
123
- external
124
- }) => {
125
- log.info(logPrefix, "Building schema...");
126
- await fs.promises.mkdir("schema", {
127
- recursive: true
128
- });
129
- try {
130
- await fs.promises.access("schema/types.ts");
131
- } catch {
132
- await fs.promises.writeFile("schema/types.ts", "");
133
- }
134
- const schemaComposerPath = path.resolve(process.cwd(), directory, "schemaComposer.ts");
135
- const {
136
- schemaComposer
137
- } = await importSchemaComposer({
138
- external,
139
- schemaComposerPath
140
- });
141
- const sdl = schemaComposer.toSDL();
142
- const codegenConfig = {
143
- documents: [],
144
- config: {
145
- declarationKind: {
146
- type: "interface",
147
- interface: "interface"
148
- },
149
- namingConvention: "keep"
150
- },
151
- filename: "schema/types.ts",
152
- schema: parse(sdl),
153
- plugins: [{
154
- typescript: {}
155
- }],
156
- pluginMap: {
157
- typescript: typescriptPlugin
158
- }
159
- };
160
- await fs.promises.writeFile("schema/schema.graphql", sdl);
161
- log.info(logPrefix, "Generating types...");
162
- const typesOutput = await codegen(codegenConfig);
163
- const typesOutputIgnore = ["/* eslint-disable */"].join("\n");
164
- await fs.promises.writeFile("schema/types.ts", `${typesOutputIgnore}
165
- ${typesOutput}`);
166
- log.info(logPrefix, "Schema and types generated!");
167
- };
168
- var program = new Command();
169
- program.name("ttoss-graphql-api").version(package_default.version, "-v, --version", "Output the current version of the GraphQL API");
170
- program.command("build-schema").option("-d, --directory <directory>", "Schema composer directory", "src").option("--external <external...>", "External dependencies to ignore during build").action(options => {
171
- return buildSchema(options);
172
- });
173
- program.parse(process.argv);