nitro-graphql 2.0.0-beta.38 → 2.0.0-beta.39

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
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="./.docs/public/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
3
+ <img src="./.github/assets/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
4
4
 
5
5
  # Nitro GraphQL
6
6
 
@@ -633,7 +633,7 @@ import { defineResolver, defineQuery, defineMutation, defineField, defineDirecti
633
633
  | `defineGraphQLConfig` | GraphQL server config | `defineGraphQLConfig({ maskedErrors: {...} })` |
634
634
  | `defineSchema` | Schema with Zod integration | `defineSchema({ Book: selectBookSchema })` |
635
635
 
636
- **Additional Utilities** from `nitro-graphql/utils`:
636
+ **Additional Utilities** from `nitro-graphql/core`:
637
637
  - `createDefaultMaskError()` - Error handler for ZodError and HTTPError (use in `defineGraphQLConfig`)
638
638
 
639
639
  ### Type Generation
@@ -1,5 +1,5 @@
1
- import { generateAll, generateClient, generateServer } from "./generate.mjs";
2
1
  import { init } from "./init.mjs";
2
+ import { generateAll, generateClient, generateServer } from "./generate.mjs";
3
3
  import { validate } from "./validate.mjs";
4
4
 
5
5
  export { generateAll, generateClient, generateServer, init, validate };
@@ -3,10 +3,41 @@ import { CLIContext } from "../index.mjs";
3
3
  //#region src/cli/commands/init.d.ts
4
4
 
5
5
  /**
6
- * Initialize project structure
6
+ * Available templates from the examples directory
7
+ */
8
+ declare const AVAILABLE_TEMPLATES: readonly [{
9
+ readonly name: "drizzle-orm";
10
+ readonly description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL";
11
+ }, {
12
+ readonly name: "vite";
13
+ readonly description: "Vite + Nitro GraphQL integration";
14
+ }, {
15
+ readonly name: "vite-react";
16
+ readonly description: "Vite + React + Nitro GraphQL";
17
+ }, {
18
+ readonly name: "vite-vue";
19
+ readonly description: "Vite + Vue + Nitro GraphQL";
20
+ }, {
21
+ readonly name: "better-auth";
22
+ readonly description: "Nitro + GraphQL + Better Auth integration";
23
+ }];
24
+ type TemplateName = typeof AVAILABLE_TEMPLATES[number]['name'];
25
+ /**
26
+ * List available templates
27
+ */
28
+ declare function listTemplates(): void;
29
+ /**
30
+ * Initialize project from template
31
+ */
32
+ declare function initFromTemplate(projectName: string, templateName: string, options?: {
33
+ force?: boolean;
34
+ cwd?: string;
35
+ }): Promise<void>;
36
+ /**
37
+ * Initialize project structure (basic scaffolding)
7
38
  */
8
39
  declare function init(ctx: CLIContext, options?: {
9
40
  force?: boolean;
10
41
  }): Promise<void>;
11
42
  //#endregion
12
- export { init };
43
+ export { AVAILABLE_TEMPLATES, TemplateName, init, initFromTemplate, listTemplates };
@@ -1,12 +1,103 @@
1
1
  import { LOG_TAG } from "../../core/constants.mjs";
2
2
  import consola from "consola";
3
- import { join, relative } from "pathe";
4
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
3
+ import { basename, join, relative, resolve } from "pathe";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { downloadTemplate } from "giget";
5
6
 
6
7
  //#region src/cli/commands/init.ts
7
8
  const logger = consola.withTag(LOG_TAG);
8
9
  /**
9
- * Initialize project structure
10
+ * Available templates from the examples directory
11
+ */
12
+ const AVAILABLE_TEMPLATES = [
13
+ {
14
+ name: "drizzle-orm",
15
+ description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL"
16
+ },
17
+ {
18
+ name: "vite",
19
+ description: "Vite + Nitro GraphQL integration"
20
+ },
21
+ {
22
+ name: "vite-react",
23
+ description: "Vite + React + Nitro GraphQL"
24
+ },
25
+ {
26
+ name: "vite-vue",
27
+ description: "Vite + Vue + Nitro GraphQL"
28
+ },
29
+ {
30
+ name: "better-auth",
31
+ description: "Nitro + GraphQL + Better Auth integration"
32
+ }
33
+ ];
34
+ /**
35
+ * Default GitHub template source
36
+ */
37
+ const DEFAULT_TEMPLATE_REGISTRY = "github:productdevbook/nitro-graphql/examples";
38
+ /**
39
+ * List available templates
40
+ */
41
+ function listTemplates() {
42
+ logger.info("Available templates:\n");
43
+ for (const template of AVAILABLE_TEMPLATES) console.log(` ${template.name.padEnd(15)} - ${template.description}`);
44
+ console.log("\nUsage:");
45
+ console.log(" nitro-graphql init <project-name> --template <template-name>");
46
+ console.log(" nitro-graphql init my-app -t drizzle-orm");
47
+ console.log("\nCustom templates:");
48
+ console.log(" nitro-graphql init my-app -t gh:user/repo");
49
+ console.log(" nitro-graphql init my-app -t github:user/repo/subdir");
50
+ }
51
+ /**
52
+ * Initialize project from template
53
+ */
54
+ async function initFromTemplate(projectName, templateName, options = {}) {
55
+ const { force, cwd = process.cwd() } = options;
56
+ const targetDir = resolve(cwd, projectName);
57
+ if (existsSync(targetDir) && !force) {
58
+ logger.error(`Directory "${projectName}" already exists. Use --force to overwrite.`);
59
+ process.exit(1);
60
+ }
61
+ let templateSource;
62
+ if (templateName.includes(":") || templateName.includes("/")) templateSource = templateName;
63
+ else {
64
+ if (!AVAILABLE_TEMPLATES.find((t) => t.name === templateName)) {
65
+ logger.error(`Unknown template: "${templateName}"`);
66
+ logger.info("Use --list to see available templates");
67
+ process.exit(1);
68
+ }
69
+ templateSource = `${DEFAULT_TEMPLATE_REGISTRY}/${templateName}`;
70
+ }
71
+ logger.info(`Downloading template: ${templateName}`);
72
+ logger.debug(`Source: ${templateSource}`);
73
+ try {
74
+ const result = await downloadTemplate(templateSource, {
75
+ dir: targetDir,
76
+ force
77
+ });
78
+ logger.success(`Template downloaded to: ${result.dir}`);
79
+ const packageJsonPath = join(targetDir, "package.json");
80
+ if (existsSync(packageJsonPath)) try {
81
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
82
+ packageJson.name = basename(projectName).replace(/[^a-z0-9-]/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "my-graphql-app";
83
+ writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf-8");
84
+ logger.debug(`Updated package.json name to: ${packageJson.name}`);
85
+ } catch {
86
+ logger.warn("Could not update package.json name");
87
+ }
88
+ console.log("");
89
+ logger.info("Next steps:");
90
+ console.log(` cd ${projectName}`);
91
+ console.log(" pnpm install");
92
+ console.log(" pnpm dev");
93
+ console.log("");
94
+ } catch (error) {
95
+ logger.error("Failed to download template:", error);
96
+ process.exit(1);
97
+ }
98
+ }
99
+ /**
100
+ * Initialize project structure (basic scaffolding)
10
101
  */
11
102
  async function init(ctx, options = {}) {
12
103
  const { force } = options;
@@ -97,4 +188,4 @@ export const helloQueries = defineQuery({
97
188
  }
98
189
 
99
190
  //#endregion
100
- export { init };
191
+ export { AVAILABLE_TEMPLATES, init, initFromTemplate, listTemplates };
@@ -0,0 +1,7 @@
1
+ import { ArgsDef, CommandDef } from "citty";
2
+
3
+ //#region src/cli/completions.d.ts
4
+
5
+ declare function initCompletions<T extends ArgsDef = ArgsDef>(command: CommandDef<T>): Promise<void>;
6
+ //#endregion
7
+ export { initCompletions };
@@ -0,0 +1,34 @@
1
+ import { AVAILABLE_TEMPLATES } from "./commands/init.mjs";
2
+
3
+ //#region src/cli/completions.ts
4
+ async function initCompletions(command) {
5
+ const { default: tab } = await import("@bomb.sh/tab/citty");
6
+ await tab(command, { subCommands: {
7
+ "init": { options: {
8
+ template: (complete) => {
9
+ for (const template of AVAILABLE_TEMPLATES) complete(template.name, template.description);
10
+ complete("gh:", "GitHub shorthand (gh:user/repo)");
11
+ complete("github:", "GitHub template (github:user/repo/path)");
12
+ complete("gitlab:", "GitLab template (gitlab:user/repo)");
13
+ },
14
+ cwd: (complete) => {
15
+ complete(".", "Current directory");
16
+ }
17
+ } },
18
+ "generate": { options: { cwd: (complete) => {
19
+ complete(".", "Current directory");
20
+ } } },
21
+ "generate:server": { options: { cwd: (complete) => {
22
+ complete(".", "Current directory");
23
+ } } },
24
+ "generate:client": { options: { cwd: (complete) => {
25
+ complete(".", "Current directory");
26
+ } } },
27
+ "validate": { options: { cwd: (complete) => {
28
+ complete(".", "Current directory");
29
+ } } }
30
+ } });
31
+ }
32
+
33
+ //#endregion
34
+ export { initCompletions };
@@ -173,9 +173,14 @@ const validateCommand = defineCommand({
173
173
  const initCommand = defineCommand({
174
174
  meta: {
175
175
  name: "init",
176
- description: "Initialize project structure"
176
+ description: "Initialize project structure or download a template"
177
177
  },
178
178
  args: {
179
+ projectName: {
180
+ type: "positional",
181
+ description: "Project name (directory to create)",
182
+ required: false
183
+ },
179
184
  cwd: {
180
185
  type: "string",
181
186
  description: "Set working directory"
@@ -184,12 +189,36 @@ const initCommand = defineCommand({
184
189
  type: "boolean",
185
190
  alias: "f",
186
191
  description: "Force overwrite existing files"
192
+ },
193
+ template: {
194
+ type: "string",
195
+ alias: "t",
196
+ description: "Template to use (e.g., drizzle-orm, vite-react)"
197
+ },
198
+ list: {
199
+ type: "boolean",
200
+ alias: "l",
201
+ description: "List available templates"
187
202
  }
188
203
  },
189
204
  async run({ args }) {
205
+ const { listTemplates, initFromTemplate, init } = await import("./commands/init.mjs");
206
+ if (args.list) {
207
+ listTemplates();
208
+ return;
209
+ }
210
+ if (args.template) {
211
+ const projectName = args.projectName || args.template;
212
+ logger.info(`Creating project "${projectName}" from template "${args.template}"...`);
213
+ await initFromTemplate(projectName, args.template, {
214
+ force: Boolean(args.force),
215
+ cwd: args.cwd || process.cwd()
216
+ });
217
+ logger.success("Project created successfully!");
218
+ return;
219
+ }
190
220
  const ctx = await createCLIContext({ cwd: args.cwd });
191
221
  logger.info("Initializing nitro-graphql project...");
192
- const { init } = await import("./commands/init.mjs");
193
222
  await init(ctx, { force: Boolean(args.force) });
194
223
  logger.success("Project initialized!");
195
224
  }
@@ -213,7 +242,12 @@ const main = defineCommand({
213
242
  "init": initCommand
214
243
  }
215
244
  });
216
- runMain(main);
245
+ async function run() {
246
+ const { initCompletions } = await import("./completions.mjs");
247
+ await initCompletions(main);
248
+ return runMain(main);
249
+ }
250
+ run();
217
251
 
218
252
  //#endregion
219
253
  export { createCLIContext, defineConfig, loadConfig };
@@ -24,7 +24,7 @@ interface MaskErrorOptions {
24
24
  * @example Basic usage
25
25
  * ```ts
26
26
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
27
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
27
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
28
28
  *
29
29
  * export default defineGraphQLConfig({
30
30
  * maskedErrors: {
@@ -36,7 +36,7 @@ interface MaskErrorOptions {
36
36
  * @example Custom status codes
37
37
  * ```ts
38
38
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
39
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
39
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
40
40
  *
41
41
  * export default defineGraphQLConfig({
42
42
  * maskedErrors: {
@@ -51,7 +51,7 @@ interface MaskErrorOptions {
51
51
  * @example Custom error handling with fallback to default
52
52
  * ```ts
53
53
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
54
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
54
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
55
55
  *
56
56
  * const defaultMaskError = createDefaultMaskError()
57
57
  *
@@ -14,7 +14,7 @@ import { GraphQLError } from "graphql";
14
14
  * @example Basic usage
15
15
  * ```ts
16
16
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
17
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
17
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
18
18
  *
19
19
  * export default defineGraphQLConfig({
20
20
  * maskedErrors: {
@@ -26,7 +26,7 @@ import { GraphQLError } from "graphql";
26
26
  * @example Custom status codes
27
27
  * ```ts
28
28
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
29
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
29
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
30
30
  *
31
31
  * export default defineGraphQLConfig({
32
32
  * maskedErrors: {
@@ -41,7 +41,7 @@ import { GraphQLError } from "graphql";
41
41
  * @example Custom error handling with fallback to default
42
42
  * ```ts
43
43
  * import { defineGraphQLConfig } from 'nitro-graphql/define'
44
- * import { createDefaultMaskError } from 'nitro-graphql/core/utils'
44
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
45
45
  *
46
46
  * const defaultMaskError = createDefaultMaskError()
47
47
  *
package/dist/define.d.mts CHANGED
@@ -195,7 +195,7 @@ declare function defineField(resolvers: Resolvers): Resolvers;
195
195
  *
196
196
  * @example
197
197
  * ```typescript
198
- * import { createDefaultMaskError } from 'nitro-graphql/utils'
198
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
199
199
  *
200
200
  * // GraphQL Yoga configuration
201
201
  * export default defineGraphQLConfig({
package/dist/define.mjs CHANGED
@@ -203,7 +203,7 @@ function defineField(resolvers) {
203
203
  *
204
204
  * @example
205
205
  * ```typescript
206
- * import { createDefaultMaskError } from 'nitro-graphql/utils'
206
+ * import { createDefaultMaskError } from 'nitro-graphql/core'
207
207
  *
208
208
  * // GraphQL Yoga configuration
209
209
  * export default defineGraphQLConfig({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.38",
4
+ "version": "2.0.0-beta.39",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -85,6 +85,7 @@
85
85
  },
86
86
  "dependencies": {
87
87
  "@apollo/subgraph": "^2.12.2",
88
+ "@bomb.sh/tab": "^0.0.11",
88
89
  "@graphql-codegen/core": "^5.0.0",
89
90
  "@graphql-codegen/import-types-preset": "^3.0.1",
90
91
  "@graphql-codegen/typed-document-node": "^6.1.5",
@@ -103,6 +104,7 @@
103
104
  "citty": "^0.1.6",
104
105
  "consola": "^3.4.2",
105
106
  "defu": "^6.1.4",
107
+ "giget": "^2.0.0",
106
108
  "graphql-config": "^5.1.5",
107
109
  "graphql-scalars": "^1.25.0",
108
110
  "knitwork": "^1.3.0",