nitro-graphql 2.0.0-beta.72 → 2.0.0-beta.73
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 +1 -1
- package/dist/cli/adapter.d.mts +0 -3
- package/dist/cli/adapter.mjs +6 -29
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/config.d.mts +4 -5
- package/dist/cli/config.mjs +3 -1
- package/dist/cli/index.d.mts +3 -6
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/server/graphql-handler.mjs +2 -1
- package/dist/cli/server/watcher.mjs +1 -1
- package/dist/core/codegen/client.d.mts +4 -27
- package/dist/core/codegen/client.mjs +26 -445
- package/dist/core/codegen/file-header.d.mts +7 -0
- package/dist/core/codegen/file-header.mjs +12 -0
- package/dist/core/codegen/index.d.mts +7 -5
- package/dist/core/codegen/index.mjs +7 -5
- package/dist/core/codegen/{runtime.d.mts → runtime-generator.d.mts} +1 -1
- package/dist/core/codegen/{runtime.mjs → runtime-generator.mjs} +1 -1
- package/dist/core/codegen/schema-loader.d.mts +2 -7
- package/dist/core/codegen/schema-loader.mjs +65 -70
- package/dist/core/codegen/server-type-helpers.d.mts +14 -0
- package/dist/core/codegen/server-type-helpers.mjs +76 -0
- package/dist/core/codegen/server.d.mts +1 -15
- package/dist/core/codegen/server.mjs +15 -105
- package/dist/core/codegen/subscription-extractor.d.mts +20 -0
- package/dist/core/codegen/subscription-extractor.mjs +30 -0
- package/dist/core/codegen/vue-subscription-builder.d.mts +10 -0
- package/dist/core/codegen/vue-subscription-builder.mjs +351 -0
- package/dist/core/constants.d.mts +5 -53
- package/dist/core/constants.mjs +13 -54
- package/dist/core/create-config.d.mts +31 -0
- package/dist/core/create-config.mjs +42 -0
- package/dist/core/debug/index.d.mts +2 -2
- package/dist/core/debug/index.mjs +2 -2
- package/dist/core/debug/template.d.mts +1 -5
- package/dist/core/debug/template.mjs +1 -1
- package/dist/core/extend/loader.d.mts +0 -1
- package/dist/core/extend/loader.mjs +59 -89
- package/dist/core/index.d.mts +22 -17
- package/dist/core/index.mjs +19 -15
- package/dist/core/manifest.mjs +3 -1
- package/dist/core/pubsub/index.d.mts +2 -109
- package/dist/core/pubsub/index.mjs +1 -145
- package/dist/core/pubsub/memory-pubsub.d.mts +109 -0
- package/dist/core/pubsub/memory-pubsub.mjs +146 -0
- package/dist/core/scanning/ast-scanner.mjs +4 -2
- package/dist/core/scanning/directives.mjs +2 -3
- package/dist/core/scanning/documents.d.mts +4 -3
- package/dist/core/scanning/documents.mjs +1 -1
- package/dist/core/scanning/{common.d.mts → file-scanner.d.mts} +1 -1
- package/dist/core/scanning/{common.mjs → file-scanner.mjs} +2 -10
- package/dist/core/scanning/index.d.mts +3 -3
- package/dist/core/scanning/index.mjs +3 -3
- package/dist/core/scanning/resolvers.mjs +8 -9
- package/dist/core/scanning/schemas.d.mts +1 -5
- package/dist/core/scanning/schemas.mjs +2 -24
- package/dist/core/schema/builder.d.mts +4 -2
- package/dist/core/schema/builder.mjs +4 -2
- package/dist/core/schema/index.d.mts +2 -2
- package/dist/core/schema/index.mjs +2 -2
- package/dist/core/server/apollo.d.mts +20 -0
- package/dist/core/server/apollo.mjs +54 -0
- package/dist/core/server/index.d.mts +4 -2
- package/dist/core/server/index.mjs +3 -2
- package/dist/core/server/types.d.mts +7 -14
- package/dist/core/server/types.mjs +15 -1
- package/dist/core/server/yoga.d.mts +1 -7
- package/dist/core/server/yoga.mjs +4 -13
- package/dist/core/types/adapter.d.mts +4 -39
- package/dist/core/types/codegen.d.mts +22 -45
- package/dist/core/types/config.d.mts +33 -121
- package/dist/core/types/define.d.mts +8 -5
- package/dist/core/types/index.d.mts +5 -4
- package/dist/core/types/scanning.d.mts +4 -1
- package/dist/core/types/standard-schema.d.mts +64 -0
- package/dist/core/utils/directive-parser.d.mts +8 -63
- package/dist/core/utils/directive-parser.mjs +114 -166
- package/dist/core/utils/file-io.d.mts +1 -5
- package/dist/core/utils/file-io.mjs +1 -11
- package/dist/core/utils/index.d.mts +5 -4
- package/dist/core/utils/index.mjs +6 -5
- package/dist/core/utils/logger.d.mts +1 -10
- package/dist/core/utils/logger.mjs +1 -19
- package/dist/core/utils/ofetch-templates.mjs +3 -4
- package/dist/core/utils/runtime.d.mts +1 -30
- package/dist/core/utils/runtime.mjs +2 -44
- package/dist/core/utils/string.d.mts +10 -0
- package/dist/core/utils/string.mjs +12 -0
- package/dist/core/watcher/create-watcher.d.mts +103 -0
- package/dist/core/watcher/create-watcher.mjs +143 -0
- package/dist/core/watcher/index.d.mts +2 -107
- package/dist/core/watcher/index.mjs +1 -139
- package/dist/define.d.mts +4 -2
- package/dist/define.mjs +7 -6
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +1 -1
- package/dist/nitro/adapter.d.mts +6 -10
- package/dist/nitro/adapter.mjs +12 -42
- package/dist/nitro/codegen/client-types.d.mts +12 -0
- package/dist/nitro/codegen/client-types.mjs +73 -0
- package/dist/nitro/codegen/external-types.d.mts +8 -0
- package/dist/nitro/codegen/external-types.mjs +47 -0
- package/dist/nitro/codegen/index.d.mts +4 -0
- package/dist/nitro/codegen/index.mjs +4 -0
- package/dist/nitro/codegen/server-types.d.mts +12 -0
- package/dist/nitro/codegen/server-types.mjs +81 -0
- package/dist/nitro/defaults.d.mts +28 -0
- package/dist/nitro/defaults.mjs +34 -0
- package/dist/nitro/index.d.mts +11 -3
- package/dist/nitro/index.mjs +1 -1
- package/dist/nitro/paths.d.mts +3 -2
- package/dist/nitro/paths.mjs +13 -9
- package/dist/nitro/rollup.mjs +4 -3
- package/dist/nitro/routes/_ws-handler.d.mts +6 -0
- package/dist/nitro/routes/_ws-handler.mjs +49 -0
- package/dist/nitro/routes/apollo-server-ws.d.mts +1 -1
- package/dist/nitro/routes/apollo-server-ws.mjs +9 -44
- package/dist/nitro/routes/apollo-server.d.mts +1 -1
- package/dist/nitro/routes/apollo-server.mjs +16 -55
- package/dist/nitro/routes/debug.d.mts +1 -1
- package/dist/nitro/routes/debug.mjs +1 -0
- package/dist/nitro/routes/graphql-yoga-ws.d.mts +1 -1
- package/dist/nitro/routes/graphql-yoga-ws.mjs +6 -44
- package/dist/nitro/routes/graphql-yoga.mjs +7 -5
- package/dist/nitro/routes/health.mjs +22 -24
- package/dist/nitro/setup/extend-loader.d.mts +6 -5
- package/dist/nitro/setup/extend-loader.mjs +30 -58
- package/dist/nitro/setup/file-watcher.mjs +6 -4
- package/dist/nitro/setup/logging.d.mts +1 -8
- package/dist/nitro/setup/logging.mjs +7 -22
- package/dist/nitro/setup/rollup-integration.mjs +32 -1
- package/dist/nitro/setup/scanner.d.mts +8 -43
- package/dist/nitro/setup/scanner.mjs +56 -58
- package/dist/nitro/setup/security.d.mts +10 -0
- package/dist/nitro/setup/security.mjs +17 -0
- package/dist/nitro/setup/type-generation.d.mts +13 -0
- package/dist/nitro/setup/type-generation.mjs +16 -0
- package/dist/nitro/setup.d.mts +4 -3
- package/dist/nitro/setup.mjs +87 -74
- package/dist/nitro/state.d.mts +32 -0
- package/dist/nitro/state.mjs +58 -0
- package/dist/nitro/types/augmentation.d.mts +59 -0
- package/dist/nitro/types/augmentation.mjs +1 -0
- package/dist/nitro/types/config.d.mts +327 -0
- package/dist/nitro/types/config.mjs +1 -0
- package/dist/nitro/types/define.d.mts +13 -0
- package/dist/nitro/types/define.mjs +1 -0
- package/dist/nitro/types/index.d.mts +10 -0
- package/dist/nitro/types/index.mjs +1 -0
- package/dist/nitro/virtual/debug-info.d.mts +9 -0
- package/dist/nitro/virtual/debug-info.mjs +35 -0
- package/dist/nitro/virtual/graphql-config.d.mts +9 -0
- package/dist/nitro/virtual/graphql-config.mjs +33 -0
- package/dist/nitro/virtual/index.d.mts +25 -0
- package/dist/nitro/virtual/index.mjs +45 -0
- package/dist/nitro/virtual/module-config.d.mts +9 -0
- package/dist/nitro/virtual/module-config.mjs +10 -0
- package/dist/nitro/virtual/pubsub.d.mts +9 -0
- package/dist/nitro/virtual/pubsub.mjs +17 -0
- package/dist/nitro/virtual/server-directives.d.mts +9 -0
- package/dist/nitro/virtual/server-directives.mjs +12 -0
- package/dist/nitro/virtual/server-resolvers.d.mts +9 -0
- package/dist/nitro/virtual/server-resolvers.mjs +17 -0
- package/dist/nitro/virtual/server-schemas.d.mts +9 -0
- package/dist/nitro/virtual/server-schemas.mjs +31 -0
- package/dist/nitro/virtual/stubs.d.mts +42 -10
- package/dist/nitro/virtual/stubs.mjs +0 -5
- package/dist/nitro/virtual/utils.d.mts +15 -0
- package/dist/nitro/virtual/utils.mjs +26 -0
- package/dist/nitro/virtual/validation-schemas.d.mts +9 -0
- package/dist/nitro/virtual/validation-schemas.mjs +33 -0
- package/native/index.js +52 -52
- package/package.json +15 -15
- package/dist/cli/commands/index.d.mts +0 -5
- package/dist/cli/commands/index.mjs +0 -5
- package/dist/core/codegen/plugin.d.mts +0 -19
- package/dist/core/codegen/plugin.mjs +0 -29
- package/dist/core/config.d.mts +0 -45
- package/dist/core/config.mjs +0 -76
- package/dist/nitro/codegen.d.mts +0 -18
- package/dist/nitro/codegen.mjs +0 -171
- package/dist/nitro/config.d.mts +0 -50
- package/dist/nitro/config.mjs +0 -55
- package/dist/nitro/types.d.mts +0 -549
- package/dist/nitro/virtual/generators.d.mts +0 -38
- package/dist/nitro/virtual/generators.mjs +0 -190
- /package/dist/{nitro/types.mjs → core/types/standard-schema.mjs} +0 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_GRAPHQL_SCALARS } from "../constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { loadGraphQLDocuments } from "./document-loader.mjs";
|
|
4
|
-
import { downloadAndSaveSchema, graphQLLoadSchemaSync, loadExternalSchema } from "./schema-loader.mjs";
|
|
2
|
+
import { GENERATED_FILE_HEADER } from "./file-header.mjs";
|
|
5
3
|
import { defu as defu$1 } from "defu";
|
|
6
4
|
import consola from "consola";
|
|
7
5
|
import { codegen } from "@graphql-codegen/core";
|
|
@@ -11,7 +9,7 @@ import { plugin as plugin$1 } from "@graphql-codegen/typescript";
|
|
|
11
9
|
import { plugin as plugin$2 } from "@graphql-codegen/typescript-generic-sdk";
|
|
12
10
|
import { plugin as plugin$3 } from "@graphql-codegen/typescript-operations";
|
|
13
11
|
import { printSchemaWithDirectives } from "@graphql-tools/utils";
|
|
14
|
-
import {
|
|
12
|
+
import { parse } from "graphql";
|
|
15
13
|
//#region src/core/codegen/client.ts
|
|
16
14
|
/**
|
|
17
15
|
* Default client codegen configuration
|
|
@@ -23,22 +21,16 @@ const DEFAULT_CLIENT_CODEGEN_CONFIG = {
|
|
|
23
21
|
strictScalars: true,
|
|
24
22
|
maybeValue: "T | null | undefined",
|
|
25
23
|
inputMaybeValue: "T | undefined",
|
|
26
|
-
documentMode: "string",
|
|
27
24
|
pureMagicComment: true,
|
|
28
25
|
dedupeOperationSuffix: true,
|
|
29
26
|
rawRequest: true,
|
|
30
27
|
scalars: DEFAULT_GRAPHQL_SCALARS
|
|
31
28
|
};
|
|
32
29
|
/**
|
|
33
|
-
* Generate generic SDK
|
|
30
|
+
* Generate generic SDK stub for schema-only generation (no documents)
|
|
34
31
|
*/
|
|
35
32
|
function generateGenericSdkContent() {
|
|
36
|
-
return
|
|
37
|
-
/* eslint-disable eslint-comments/no-unlimited-disable */
|
|
38
|
-
/* tslint:disable */
|
|
39
|
-
/* eslint-disable */
|
|
40
|
-
/* prettier-ignore */
|
|
41
|
-
|
|
33
|
+
return `${GENERATED_FILE_HEADER}
|
|
42
34
|
import type { GraphQLResolveInfo } from 'graphql'
|
|
43
35
|
export type RequireFields<T, K extends keyof T> = Omit<T, K> & { [P in K]-?: NonNullable<T[P]> }
|
|
44
36
|
|
|
@@ -61,38 +53,30 @@ export function getSdk(requester: Requester): Sdk {
|
|
|
61
53
|
}
|
|
62
54
|
/**
|
|
63
55
|
* Generate client-side GraphQL types
|
|
64
|
-
* Pure function that generates TypeScript types from a GraphQL schema and documents
|
|
65
56
|
*/
|
|
66
57
|
async function generateClientTypesCore(input) {
|
|
67
58
|
const { schema, schemaString, documents, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath } = input;
|
|
68
59
|
if (documents.length === 0 && !serviceName) return false;
|
|
69
60
|
const schemaSDL = schemaString || (schema ? printSchemaWithDirectives(schema) : null);
|
|
70
61
|
if (!schemaSDL) return false;
|
|
71
|
-
const mergedConfig = defu$1(
|
|
72
|
-
const
|
|
62
|
+
const mergedConfig = defu$1(config, DEFAULT_CLIENT_CODEGEN_CONFIG);
|
|
63
|
+
const resolvedSdkConfig = defu$1(sdkConfig, mergedConfig);
|
|
64
|
+
const parsedSchema = parse(schemaSDL);
|
|
73
65
|
try {
|
|
74
66
|
if (documents.length === 0) return {
|
|
75
|
-
types: await codegen({
|
|
67
|
+
types: GENERATED_FILE_HEADER + await codegen({
|
|
76
68
|
filename: outputPath || "client-types.generated.ts",
|
|
77
|
-
schema:
|
|
69
|
+
schema: parsedSchema,
|
|
78
70
|
documents: [],
|
|
79
71
|
config: mergedConfig,
|
|
80
|
-
plugins: [{
|
|
81
|
-
pluginMap: {
|
|
82
|
-
pluginContent: { plugin: pluginContent },
|
|
83
|
-
typescript: { plugin: plugin$1 }
|
|
84
|
-
}
|
|
72
|
+
plugins: [{ typescript: {} }],
|
|
73
|
+
pluginMap: { typescript: { plugin: plugin$1 } }
|
|
85
74
|
}),
|
|
86
75
|
sdk: generateGenericSdkContent()
|
|
87
76
|
};
|
|
88
77
|
const enableTypedDocumentNode = config.typedDocumentNode === true;
|
|
89
|
-
const plugins = [
|
|
90
|
-
{ pluginContent: {} },
|
|
91
|
-
{ typescript: {} },
|
|
92
|
-
{ typescriptOperations: {} }
|
|
93
|
-
];
|
|
78
|
+
const plugins = [{ typescript: {} }, { typescriptOperations: {} }];
|
|
94
79
|
const pluginMap = {
|
|
95
|
-
pluginContent: { plugin: pluginContent },
|
|
96
80
|
typescript: { plugin: plugin$1 },
|
|
97
81
|
typescriptOperations: { plugin: plugin$3 }
|
|
98
82
|
};
|
|
@@ -100,9 +84,9 @@ async function generateClientTypesCore(input) {
|
|
|
100
84
|
plugins.push({ typedDocumentNode: {} });
|
|
101
85
|
pluginMap.typedDocumentNode = { plugin };
|
|
102
86
|
}
|
|
103
|
-
const
|
|
87
|
+
const generated = await codegen({
|
|
104
88
|
filename: outputPath || "client-types.generated.ts",
|
|
105
|
-
schema:
|
|
89
|
+
schema: parsedSchema,
|
|
106
90
|
documents: [...documents],
|
|
107
91
|
config: mergedConfig,
|
|
108
92
|
plugins,
|
|
@@ -111,24 +95,20 @@ async function generateClientTypesCore(input) {
|
|
|
111
95
|
const typesPath = virtualTypesPath || (serviceName ? `#graphql/client/${serviceName}` : "#graphql/client");
|
|
112
96
|
const sdkOutput = await preset.buildGeneratesSection({
|
|
113
97
|
baseOutputDir: outputPath || "client-types.generated.ts",
|
|
114
|
-
schema:
|
|
98
|
+
schema: parsedSchema,
|
|
115
99
|
documents: [...documents],
|
|
116
|
-
config:
|
|
100
|
+
config: resolvedSdkConfig,
|
|
117
101
|
presetConfig: { typesPath },
|
|
118
|
-
plugins: [{
|
|
119
|
-
pluginMap: {
|
|
120
|
-
pluginContent: { plugin: pluginContent },
|
|
121
|
-
typescriptGenericSdk: { plugin: plugin$2 }
|
|
122
|
-
}
|
|
102
|
+
plugins: [{ typescriptGenericSdk: {} }],
|
|
103
|
+
pluginMap: { typescriptGenericSdk: { plugin: plugin$2 } }
|
|
123
104
|
});
|
|
105
|
+
const results = await Promise.all(sdkOutput.map(async (config) => ({
|
|
106
|
+
file: config.filename,
|
|
107
|
+
content: await codegen(config)
|
|
108
|
+
})));
|
|
124
109
|
return {
|
|
125
|
-
types:
|
|
126
|
-
sdk:
|
|
127
|
-
return {
|
|
128
|
-
file: config.filename,
|
|
129
|
-
content: await codegen(config)
|
|
130
|
-
};
|
|
131
|
-
})))[0]?.content || ""
|
|
110
|
+
types: GENERATED_FILE_HEADER + generated,
|
|
111
|
+
sdk: GENERATED_FILE_HEADER + (results[0]?.content || "")
|
|
132
112
|
};
|
|
133
113
|
} catch (error) {
|
|
134
114
|
consola.error("[nitro-graphql] Client type generation failed:", error.message);
|
|
@@ -136,7 +116,7 @@ async function generateClientTypesCore(input) {
|
|
|
136
116
|
}
|
|
137
117
|
}
|
|
138
118
|
/**
|
|
139
|
-
* Generate client types for external GraphQL service
|
|
119
|
+
* Generate client types for an external GraphQL service
|
|
140
120
|
*/
|
|
141
121
|
async function generateExternalClientTypesCore(service, schema, documents, virtualTypesPath) {
|
|
142
122
|
return generateClientTypesCore({
|
|
@@ -148,404 +128,5 @@ async function generateExternalClientTypesCore(service, schema, documents, virtu
|
|
|
148
128
|
virtualTypesPath
|
|
149
129
|
});
|
|
150
130
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Convert first character to uppercase (PascalCase)
|
|
153
|
-
*/
|
|
154
|
-
function toPascalCase(str) {
|
|
155
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Extract subscription operations from GraphQL documents
|
|
159
|
-
*/
|
|
160
|
-
function extractSubscriptions(docs) {
|
|
161
|
-
const subscriptions = [];
|
|
162
|
-
for (const doc of docs) {
|
|
163
|
-
if (!doc.document) continue;
|
|
164
|
-
for (const def of doc.document.definitions) if (def.kind === Kind.OPERATION_DEFINITION && def.operation === "subscription") {
|
|
165
|
-
const operationDef = def;
|
|
166
|
-
const name = operationDef.name?.value;
|
|
167
|
-
if (!name) continue;
|
|
168
|
-
const firstSelection = operationDef.selectionSet.selections[0];
|
|
169
|
-
if (firstSelection.kind !== Kind.FIELD) continue;
|
|
170
|
-
const fieldName = firstSelection.name.value;
|
|
171
|
-
const hasVariables = (operationDef.variableDefinitions?.length || 0) > 0;
|
|
172
|
-
subscriptions.push({
|
|
173
|
-
name,
|
|
174
|
-
typeName: toPascalCase(name),
|
|
175
|
-
fieldName,
|
|
176
|
-
hasVariables
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return subscriptions;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Generate subscription builder code (Drizzle-style API) + Vue Composables
|
|
184
|
-
* Returns empty string if subscriptions are not enabled or no subscription operations found
|
|
185
|
-
*/
|
|
186
|
-
function generateSubscriptionBuilder(docs, subscriptionsEnabled) {
|
|
187
|
-
if (!subscriptionsEnabled) return "";
|
|
188
|
-
const subscriptions = extractSubscriptions(docs);
|
|
189
|
-
if (subscriptions.length === 0) return "";
|
|
190
|
-
let output = `
|
|
191
|
-
// === Subscription Imports ===
|
|
192
|
-
import { ref, onUnmounted, computed } from 'vue'
|
|
193
|
-
import type { Ref } from 'vue'
|
|
194
|
-
import type {
|
|
195
|
-
ConnectionState,
|
|
196
|
-
SubscriptionHandle,
|
|
197
|
-
SubscriptionSession,
|
|
198
|
-
SubscriptionTransport,
|
|
199
|
-
TransportOptions,
|
|
200
|
-
} from 'nitro-graphql/subscribe'
|
|
201
|
-
import { subscriptionClient } from './subscribe'
|
|
202
|
-
|
|
203
|
-
// === Subscription Types ===
|
|
204
|
-
export type { ConnectionState, SubscriptionHandle, SubscriptionSession, SubscriptionTransport, TransportOptions }
|
|
205
|
-
|
|
206
|
-
// Forward declaration for UseSubscriptionSessionReturn (defined below)
|
|
207
|
-
export interface UseSubscriptionSessionReturn {
|
|
208
|
-
/** The underlying session object */
|
|
209
|
-
session: SubscriptionSession
|
|
210
|
-
/** Subscribe using the shared session (updates reactive refs) */
|
|
211
|
-
subscribe: <TData = unknown>(
|
|
212
|
-
query: string,
|
|
213
|
-
variables: unknown,
|
|
214
|
-
onData?: (data: TData) => void,
|
|
215
|
-
onError?: (error: Error) => void,
|
|
216
|
-
) => SubscriptionHandle
|
|
217
|
-
/** Close all subscriptions and the connection */
|
|
218
|
-
close: () => void
|
|
219
|
-
/** Is the session connected (reactive) */
|
|
220
|
-
isConnected: Ref<boolean>
|
|
221
|
-
/** Current connection state (reactive) */
|
|
222
|
-
state: Ref<ConnectionState>
|
|
223
|
-
/** Number of active subscriptions (reactive) */
|
|
224
|
-
subscriptionCount: Ref<number>
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface UseSubscriptionOptions<T> {
|
|
228
|
-
/** Auto-start subscription on mount (default: false) */
|
|
229
|
-
immediate?: boolean
|
|
230
|
-
/** Callback when subscription starts */
|
|
231
|
-
onStart?: () => void
|
|
232
|
-
/** Callback when subscription stops */
|
|
233
|
-
onStop?: () => void
|
|
234
|
-
/** Callback when data is received */
|
|
235
|
-
onData?: (data: T) => void
|
|
236
|
-
/** Callback when error occurs */
|
|
237
|
-
onError?: (error: Error) => void
|
|
238
|
-
/** Callback when WebSocket connects */
|
|
239
|
-
onConnected?: () => void
|
|
240
|
-
/** Callback when WebSocket reconnects */
|
|
241
|
-
onReconnected?: () => void
|
|
242
|
-
/** Callback when WebSocket disconnects */
|
|
243
|
-
onDisconnected?: () => void
|
|
244
|
-
/** Callback when connection state changes */
|
|
245
|
-
onStateChange?: (state: ConnectionState) => void
|
|
246
|
-
/** Use existing session for multiplexing (pass result from useSubscriptionSession) */
|
|
247
|
-
session?: UseSubscriptionSessionReturn
|
|
248
|
-
/** Transport type: 'websocket' (default), 'sse', or 'auto' (WS first, SSE fallback) */
|
|
249
|
-
transport?: SubscriptionTransport
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
export interface UseSubscriptionReturn<T> {
|
|
253
|
-
/** Reactive subscription data */
|
|
254
|
-
data: Ref<T | null>
|
|
255
|
-
/** Reactive error state */
|
|
256
|
-
error: Ref<Error | null>
|
|
257
|
-
/** Is subscription active */
|
|
258
|
-
isActive: Ref<boolean>
|
|
259
|
-
/** Connection state */
|
|
260
|
-
state: Ref<ConnectionState>
|
|
261
|
-
/** Active transport type ('websocket' | 'sse') */
|
|
262
|
-
transport: Ref<'websocket' | 'sse'>
|
|
263
|
-
/** Start subscription */
|
|
264
|
-
start: () => void
|
|
265
|
-
/** Stop subscription */
|
|
266
|
-
stop: () => void
|
|
267
|
-
/** Restart subscription */
|
|
268
|
-
restart: () => void
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// === Subscription Builder (Drizzle-style API) ===
|
|
272
|
-
interface SubscriptionBuilder<TData> {
|
|
273
|
-
onData(fn: (data: TData) => void): SubscriptionBuilder<TData>
|
|
274
|
-
onError(fn: (error: Error) => void): SubscriptionBuilder<TData>
|
|
275
|
-
start(): SubscriptionHandle
|
|
276
|
-
subscribe(fn: (data: TData) => void): SubscriptionHandle
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function createSubscriptionBuilder<TData>(query: string, variables: unknown): SubscriptionBuilder<TData> {
|
|
280
|
-
let onDataFn: ((data: TData) => void) | undefined
|
|
281
|
-
let onErrorFn: ((error: Error) => void) | undefined
|
|
282
|
-
|
|
283
|
-
const builder: SubscriptionBuilder<TData> = {
|
|
284
|
-
onData(fn: (data: TData) => void) {
|
|
285
|
-
onDataFn = fn
|
|
286
|
-
return builder
|
|
287
|
-
},
|
|
288
|
-
onError(fn: (error: Error) => void) {
|
|
289
|
-
onErrorFn = fn
|
|
290
|
-
return builder
|
|
291
|
-
},
|
|
292
|
-
start(): SubscriptionHandle {
|
|
293
|
-
return subscriptionClient.subscribe(query, variables, onDataFn, onErrorFn)
|
|
294
|
-
},
|
|
295
|
-
subscribe(fn: (data: TData) => void): SubscriptionHandle {
|
|
296
|
-
return subscriptionClient.subscribe(query, variables, fn, undefined)
|
|
297
|
-
},
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return builder
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export const subscription = {
|
|
304
|
-
`;
|
|
305
|
-
for (const sub of subscriptions) if (sub.hasVariables) output += ` ${sub.typeName}(variables: Types.${sub.typeName}SubscriptionVariables): SubscriptionBuilder<Types.${sub.typeName}Subscription['${sub.fieldName}']> {
|
|
306
|
-
return createSubscriptionBuilder<Types.${sub.typeName}Subscription['${sub.fieldName}']>(${sub.typeName}Document, variables)
|
|
307
|
-
},
|
|
308
|
-
`;
|
|
309
|
-
else output += ` ${sub.typeName}(): SubscriptionBuilder<Types.${sub.typeName}Subscription['${sub.fieldName}']> {
|
|
310
|
-
return createSubscriptionBuilder<Types.${sub.typeName}Subscription['${sub.fieldName}']>(${sub.typeName}Document, undefined)
|
|
311
|
-
},
|
|
312
|
-
`;
|
|
313
|
-
output += `}
|
|
314
|
-
|
|
315
|
-
// === Framework-Agnostic Session (for non-Vue usage) ===
|
|
316
|
-
/**
|
|
317
|
-
* Create a multiplexed subscription session (framework-agnostic)
|
|
318
|
-
* All subscriptions share a single WebSocket connection.
|
|
319
|
-
*
|
|
320
|
-
* @example
|
|
321
|
-
* // Vanilla JS / Node.js / React / etc.
|
|
322
|
-
* const session = createSubscriptionSession()
|
|
323
|
-
* const sub1 = session.subscribe(query1, vars1, onData1)
|
|
324
|
-
* const sub2 = session.subscribe(query2, vars2, onData2)
|
|
325
|
-
* // Both use the same WebSocket connection
|
|
326
|
-
* sub1.unsubscribe()
|
|
327
|
-
* session.close() // Close all
|
|
328
|
-
*
|
|
329
|
-
* @returns SubscriptionSession - Framework-agnostic session object
|
|
330
|
-
*/
|
|
331
|
-
export function createSubscriptionSession(): SubscriptionSession {
|
|
332
|
-
return subscriptionClient.createSession()
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// === Vue Composable: useSubscriptionSession (Multiplexing) ===
|
|
336
|
-
export interface UseSubscriptionSessionReturn {
|
|
337
|
-
/** The underlying session object */
|
|
338
|
-
session: SubscriptionSession
|
|
339
|
-
/** Subscribe using the shared session */
|
|
340
|
-
subscribe: <TData = unknown>(
|
|
341
|
-
query: string,
|
|
342
|
-
variables: unknown,
|
|
343
|
-
onData?: (data: TData) => void,
|
|
344
|
-
onError?: (error: Error) => void,
|
|
345
|
-
) => SubscriptionHandle
|
|
346
|
-
/** Close all subscriptions and the connection */
|
|
347
|
-
close: () => void
|
|
348
|
-
/** Is the session connected (reactive) */
|
|
349
|
-
isConnected: Ref<boolean>
|
|
350
|
-
/** Current connection state (reactive) */
|
|
351
|
-
state: Ref<ConnectionState>
|
|
352
|
-
/** Number of active subscriptions (reactive) */
|
|
353
|
-
subscriptionCount: Ref<number>
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Vue composable for multiplexed subscription session
|
|
358
|
-
* Provides reactive state and automatic cleanup on unmount.
|
|
359
|
-
*
|
|
360
|
-
* @example
|
|
361
|
-
* // Vue 3 component
|
|
362
|
-
* const session = useSubscriptionSession()
|
|
363
|
-
* const { data } = useCountdown({ from: 10 }, { session })
|
|
364
|
-
* // Session auto-closes on component unmount
|
|
365
|
-
*
|
|
366
|
-
* @returns UseSubscriptionSessionReturn - Vue-reactive session wrapper
|
|
367
|
-
*/
|
|
368
|
-
export function useSubscriptionSession(): UseSubscriptionSessionReturn {
|
|
369
|
-
const session = subscriptionClient.createSession()
|
|
370
|
-
|
|
371
|
-
// Use refs for reactivity (session getters are not reactive)
|
|
372
|
-
const isConnected = ref(session.isConnected)
|
|
373
|
-
const state = ref<ConnectionState>(session.state)
|
|
374
|
-
const subscriptionCount = ref(session.subscriptionCount)
|
|
375
|
-
|
|
376
|
-
// Update refs when session state changes
|
|
377
|
-
function updateRefs() {
|
|
378
|
-
isConnected.value = session.isConnected
|
|
379
|
-
state.value = session.state
|
|
380
|
-
subscriptionCount.value = session.subscriptionCount
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Subscribe to session state changes for automatic reactivity
|
|
384
|
-
const unsubscribeStateChange = session.onStateChange(() => {
|
|
385
|
-
updateRefs()
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
function subscribe<TData = unknown>(
|
|
389
|
-
query: string,
|
|
390
|
-
variables: unknown,
|
|
391
|
-
onData?: (data: TData) => void,
|
|
392
|
-
onError?: (error: Error) => void,
|
|
393
|
-
): SubscriptionHandle {
|
|
394
|
-
return session.subscribe(query, variables, onData as (data: unknown) => void, onError)
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function close() {
|
|
398
|
-
session.close()
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
onUnmounted(() => {
|
|
402
|
-
unsubscribeStateChange()
|
|
403
|
-
close()
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
return {
|
|
407
|
-
session,
|
|
408
|
-
subscribe,
|
|
409
|
-
close,
|
|
410
|
-
isConnected,
|
|
411
|
-
state,
|
|
412
|
-
subscriptionCount,
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// === Vue Composables ===
|
|
417
|
-
function createUseSubscription<TData, TVariables = undefined>(
|
|
418
|
-
query: string,
|
|
419
|
-
getVariables: () => TVariables,
|
|
420
|
-
): (options?: UseSubscriptionOptions<TData>) => UseSubscriptionReturn<TData> {
|
|
421
|
-
return (options: UseSubscriptionOptions<TData> = {}): UseSubscriptionReturn<TData> => {
|
|
422
|
-
const data = ref<TData | null>(null) as Ref<TData | null>
|
|
423
|
-
const error = ref<Error | null>(null)
|
|
424
|
-
const isActive = ref(false)
|
|
425
|
-
const state = ref<ConnectionState>('idle')
|
|
426
|
-
const transport = ref<'websocket' | 'sse'>('websocket')
|
|
427
|
-
let handle: SubscriptionHandle | null = null
|
|
428
|
-
|
|
429
|
-
// Resolve transport options
|
|
430
|
-
const transportOptions: TransportOptions = {
|
|
431
|
-
transport: options.transport,
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function start() {
|
|
435
|
-
stop()
|
|
436
|
-
isActive.value = true
|
|
437
|
-
error.value = null
|
|
438
|
-
options.onStart?.()
|
|
439
|
-
|
|
440
|
-
const variables = getVariables()
|
|
441
|
-
|
|
442
|
-
if (options.session) {
|
|
443
|
-
// Use existing session for multiplexing (WebSocket only)
|
|
444
|
-
handle = options.session.subscribe<TData>(
|
|
445
|
-
query,
|
|
446
|
-
variables,
|
|
447
|
-
(d: TData) => {
|
|
448
|
-
data.value = d
|
|
449
|
-
options.onData?.(d)
|
|
450
|
-
},
|
|
451
|
-
(e: Error) => {
|
|
452
|
-
error.value = e
|
|
453
|
-
options.onError?.(e)
|
|
454
|
-
},
|
|
455
|
-
)
|
|
456
|
-
transport.value = 'websocket'
|
|
457
|
-
} else {
|
|
458
|
-
// Create dedicated connection with transport selection
|
|
459
|
-
handle = subscriptionClient.subscribe<TData>(
|
|
460
|
-
query,
|
|
461
|
-
variables,
|
|
462
|
-
(d: TData) => {
|
|
463
|
-
data.value = d
|
|
464
|
-
options.onData?.(d)
|
|
465
|
-
},
|
|
466
|
-
(e: Error) => {
|
|
467
|
-
error.value = e
|
|
468
|
-
options.onError?.(e)
|
|
469
|
-
},
|
|
470
|
-
transportOptions,
|
|
471
|
-
)
|
|
472
|
-
// Update transport ref from handle
|
|
473
|
-
transport.value = handle.transport
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function stop() {
|
|
478
|
-
if (handle) {
|
|
479
|
-
handle.unsubscribe()
|
|
480
|
-
handle = null
|
|
481
|
-
isActive.value = false
|
|
482
|
-
options.onStop?.()
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function restart() {
|
|
487
|
-
stop()
|
|
488
|
-
start()
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
if (options.immediate) {
|
|
492
|
-
start()
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
onUnmounted(stop)
|
|
496
|
-
|
|
497
|
-
return { data, error, isActive, state, transport, start, stop, restart }
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// === Subscription Return Types ===
|
|
502
|
-
`;
|
|
503
|
-
for (const sub of subscriptions) {
|
|
504
|
-
const typeName = `Types.${sub.typeName}Subscription['${sub.fieldName}']`;
|
|
505
|
-
output += `/** Return type for use${sub.typeName} composable */
|
|
506
|
-
export type Use${sub.typeName}Return = UseSubscriptionReturn<${typeName}>
|
|
507
|
-
`;
|
|
508
|
-
}
|
|
509
|
-
output += `
|
|
510
|
-
// === Vue Composables ===
|
|
511
|
-
`;
|
|
512
|
-
for (const sub of subscriptions) {
|
|
513
|
-
const typeName = `Types.${sub.typeName}Subscription['${sub.fieldName}']`;
|
|
514
|
-
const varsType = `Types.${sub.typeName}SubscriptionVariables`;
|
|
515
|
-
if (sub.hasVariables) output += `/**
|
|
516
|
-
* Vue composable for ${sub.typeName} subscription
|
|
517
|
-
* @param variables - Subscription variables
|
|
518
|
-
* @param options - Subscription options (immediate, onData, onError, session, etc.)
|
|
519
|
-
* @returns Reactive subscription state: { data, error, isActive, state, start, stop, restart }
|
|
520
|
-
*/
|
|
521
|
-
export function use${sub.typeName}(
|
|
522
|
-
variables: ${varsType},
|
|
523
|
-
options?: UseSubscriptionOptions<${typeName}>,
|
|
524
|
-
): Use${sub.typeName}Return {
|
|
525
|
-
return createUseSubscription<${typeName}, ${varsType}>(
|
|
526
|
-
${sub.typeName}Document,
|
|
527
|
-
() => variables,
|
|
528
|
-
)(options)
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
`;
|
|
532
|
-
else output += `/**
|
|
533
|
-
* Vue composable for ${sub.typeName} subscription
|
|
534
|
-
* @param options - Subscription options (immediate, onData, onError, session, etc.)
|
|
535
|
-
* @returns Reactive subscription state: { data, error, isActive, state, start, stop, restart }
|
|
536
|
-
*/
|
|
537
|
-
export function use${sub.typeName}(
|
|
538
|
-
options?: UseSubscriptionOptions<${typeName}>,
|
|
539
|
-
): Use${sub.typeName}Return {
|
|
540
|
-
return createUseSubscription<${typeName}, undefined>(
|
|
541
|
-
${sub.typeName}Document,
|
|
542
|
-
() => undefined,
|
|
543
|
-
)(options)
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
`;
|
|
547
|
-
}
|
|
548
|
-
return output;
|
|
549
|
-
}
|
|
550
131
|
//#endregion
|
|
551
|
-
export { DEFAULT_CLIENT_CODEGEN_CONFIG,
|
|
132
|
+
export { DEFAULT_CLIENT_CODEGEN_CONFIG, generateClientTypesCore, generateExternalClientTypesCore };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/core/codegen/file-header.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Standard header prepended to all generated files
|
|
4
|
+
*/
|
|
5
|
+
declare const GENERATED_FILE_HEADER = "// THIS FILE IS GENERATED, DO NOT EDIT!\n/* eslint-disable eslint-comments/no-unlimited-disable */\n/* tslint:disable */\n/* eslint-disable */\n/* prettier-ignore */\n";
|
|
6
|
+
//#endregion
|
|
7
|
+
export { GENERATED_FILE_HEADER };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/core/codegen/file-header.ts
|
|
2
|
+
/**
|
|
3
|
+
* Standard header prepended to all generated files
|
|
4
|
+
*/
|
|
5
|
+
const GENERATED_FILE_HEADER = `// THIS FILE IS GENERATED, DO NOT EDIT!
|
|
6
|
+
/* eslint-disable eslint-comments/no-unlimited-disable */
|
|
7
|
+
/* tslint:disable */
|
|
8
|
+
/* eslint-disable */
|
|
9
|
+
/* prettier-ignore */
|
|
10
|
+
`;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { GENERATED_FILE_HEADER };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { DEFAULT_CLIENT_CODEGEN_CONFIG, generateClientTypesCore, generateExternalClientTypesCore } from "./client.mjs";
|
|
1
2
|
import { loadGraphQLDocuments } from "./document-loader.mjs";
|
|
3
|
+
import { GENERATED_FILE_HEADER } from "./file-header.mjs";
|
|
4
|
+
import { generateResolverModule, generateRuntimeIndex, generateSchemaModule } from "./runtime-generator.mjs";
|
|
2
5
|
import { GraphQLLoadSchemaOptions, GraphQLTypeDefPointer, downloadAndSaveSchema, graphQLLoadSchemaSync, loadExternalSchema } from "./schema-loader.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { generateResolverModule, generateRuntimeIndex, generateSchemaModule } from "./runtime.mjs";
|
|
6
|
-
import { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore, generateTypes } from "./server.mjs";
|
|
6
|
+
import { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore } from "./server.mjs";
|
|
7
|
+
import { SubscriptionInfo, extractSubscriptions } from "./subscription-extractor.mjs";
|
|
7
8
|
import { validateNoDuplicateTypes, validateSchemaFiles } from "./validation.mjs";
|
|
8
|
-
|
|
9
|
+
import { generateSubscriptionBuilder } from "./vue-subscription-builder.mjs";
|
|
10
|
+
export { DEFAULT_CLIENT_CODEGEN_CONFIG, DEFAULT_SERVER_CODEGEN_CONFIG, GENERATED_FILE_HEADER, type GraphQLLoadSchemaOptions, type GraphQLTypeDefPointer, type SubscriptionInfo, downloadAndSaveSchema, extractSubscriptions, generateClientTypesCore, generateExternalClientTypesCore, generateResolverModule, generateRuntimeIndex, generateSchemaModule, generateServerTypesCore, generateSubscriptionBuilder, graphQLLoadSchemaSync, loadExternalSchema, loadGraphQLDocuments, validateNoDuplicateTypes, validateSchemaFiles };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { GENERATED_FILE_HEADER
|
|
1
|
+
import { GENERATED_FILE_HEADER } from "./file-header.mjs";
|
|
2
|
+
import { DEFAULT_CLIENT_CODEGEN_CONFIG, generateClientTypesCore, generateExternalClientTypesCore } from "./client.mjs";
|
|
2
3
|
import { loadGraphQLDocuments } from "./document-loader.mjs";
|
|
4
|
+
import { generateResolverModule, generateRuntimeIndex, generateSchemaModule } from "./runtime-generator.mjs";
|
|
3
5
|
import { downloadAndSaveSchema, graphQLLoadSchemaSync, loadExternalSchema } from "./schema-loader.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore, generateTypes } from "./server.mjs";
|
|
6
|
+
import { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore } from "./server.mjs";
|
|
7
|
+
import { extractSubscriptions } from "./subscription-extractor.mjs";
|
|
7
8
|
import { validateNoDuplicateTypes, validateSchemaFiles } from "./validation.mjs";
|
|
8
|
-
|
|
9
|
+
import { generateSubscriptionBuilder } from "./vue-subscription-builder.mjs";
|
|
10
|
+
export { DEFAULT_CLIENT_CODEGEN_CONFIG, DEFAULT_SERVER_CODEGEN_CONFIG, GENERATED_FILE_HEADER, downloadAndSaveSchema, extractSubscriptions, generateClientTypesCore, generateExternalClientTypesCore, generateResolverModule, generateRuntimeIndex, generateSchemaModule, generateServerTypesCore, generateSubscriptionBuilder, graphQLLoadSchemaSync, loadExternalSchema, loadGraphQLDocuments, validateNoDuplicateTypes, validateSchemaFiles };
|
|
@@ -3,16 +3,10 @@ import { GraphQLSchema } from "graphql";
|
|
|
3
3
|
import { LoadSchemaOptions, UnnormalizedTypeDefPointer } from "@graphql-tools/load";
|
|
4
4
|
|
|
5
5
|
//#region src/core/codegen/schema-loader.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Type definition pointer for GraphQL schemas
|
|
8
|
-
*/
|
|
9
6
|
type GraphQLTypeDefPointer = UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[];
|
|
10
|
-
/**
|
|
11
|
-
* Options for loading GraphQL schemas
|
|
12
|
-
*/
|
|
13
7
|
type GraphQLLoadSchemaOptions = Partial<LoadSchemaOptions>;
|
|
14
8
|
/**
|
|
15
|
-
* Load GraphQL schema synchronously
|
|
9
|
+
* Load GraphQL schema synchronously from pointers
|
|
16
10
|
*/
|
|
17
11
|
declare function graphQLLoadSchemaSync(schemaPointers: GraphQLTypeDefPointer, data?: GraphQLLoadSchemaOptions): GraphQLSchema | undefined;
|
|
18
12
|
/**
|
|
@@ -21,6 +15,7 @@ declare function graphQLLoadSchemaSync(schemaPointers: GraphQLTypeDefPointer, da
|
|
|
21
15
|
declare function loadExternalSchema(service: ExternalServiceCodegenConfig, buildDir?: string): Promise<GraphQLSchema | undefined>;
|
|
22
16
|
/**
|
|
23
17
|
* Download and save schema from external service
|
|
18
|
+
* Supports modes: true/'once' (download if missing), 'always' (check for updates), 'manual' (skip)
|
|
24
19
|
*/
|
|
25
20
|
declare function downloadAndSaveSchema(service: ExternalServiceCodegenConfig, buildDir: string): Promise<string | undefined>;
|
|
26
21
|
//#endregion
|