@luckystack/devkit 0.6.7 → 0.7.0
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/CHANGELOG.md +90 -0
- package/CLAUDE.md +129 -125
- package/LICENSE +21 -21
- package/README.md +44 -44
- package/dist/{chunk-EU2RFSLO.js → chunk-BZTCJ7JY.js} +1 -1
- package/dist/chunk-BZTCJ7JY.js.map +1 -0
- package/dist/cli/validateDeploy.js +1 -1
- package/dist/cli/validateDeploy.js.map +1 -1
- package/dist/index.js +257 -35
- package/dist/index.js.map +1 -1
- package/dist/supervisor.js +96 -45
- package/dist/supervisor.js.map +1 -1
- package/dist/templates/api.template.ts +54 -54
- package/dist/templates/page_dashboard.template.tsx +35 -35
- package/dist/templates/page_plain.template.tsx +32 -32
- package/dist/templates/sync_client.template.ts +40 -40
- package/dist/templates/sync_client_paired.template.ts +38 -38
- package/dist/templates/sync_client_standalone.template.ts +36 -36
- package/dist/templates/sync_server.template.ts +64 -64
- package/docs/cli.md +245 -245
- package/docs/hot-reload.md +365 -365
- package/docs/loader-pipeline.md +324 -324
- package/docs/runtime-type-resolver.md +258 -258
- package/docs/supervisor.md +292 -292
- package/docs/ts-program-cache.md +200 -199
- package/docs/type-map-generation.md +410 -392
- package/package.json +10 -4
- package/dist/chunk-EU2RFSLO.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/validateDeploy.ts"],"sourcesContent":["#!/usr/bin/env node\r\n//? `luckystack-validate-deploy` CLI. Loads the consumer's compiled\r\n//? services.config.js and deploy.config.js as side-effects (they call\r\n//? `registerServicesConfig` / `registerDeployConfig` on import), then runs\r\n//? `validateDeploy()` and prints findings.\r\n//?\r\n//? Designed to be a pre-deploy gate: exit 1 on any error finding, 0\r\n//? otherwise. Warnings print to stderr but never fail the run.\r\n\r\nimport { pathToFileURL } from 'node:url';\r\nimport path from 'node:path';\r\nimport {\r\n getDeployConfig,\r\n getServicesConfig,\r\n isDeployConfigRegistered,\r\n isServicesConfigRegistered,\r\n} from '@luckystack/core';\r\n\r\nimport { validateDeploy, type ValidationFinding } from '../validateDeploy';\r\n\r\ninterface CliArgs {\r\n deploy: string | null;\r\n services: string | null;\r\n failOnWarning: boolean;\r\n}\r\n\r\nconst parseArgs = (argv: readonly string[]): CliArgs => {\r\n const args: CliArgs = {\r\n deploy: null,\r\n services: null,\r\n failOnWarning: false,\r\n };\r\n\r\n for (let i = 0; i < argv.length; i++) {\r\n const flag = argv[i];\r\n const next: string | undefined = i + 1 < argv.length ? argv[i + 1] : undefined;\r\n switch (flag) {\r\n case '--deploy':\r\n case '-d': {\r\n args.deploy = next ?? null;\r\n i++;\r\n break;\r\n }\r\n case '--services':\r\n case '-s': {\r\n args.services = next ?? null;\r\n i++;\r\n break;\r\n }\r\n case '--strict': {\r\n args.failOnWarning = true;\r\n break;\r\n }\r\n case '--help':\r\n case '-h': {\r\n printHelp();\r\n process.exit(0);\r\n break;\r\n }\r\n default: {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return args;\r\n};\r\n\r\nconst printHelp = (): void => {\r\n process.stdout.write(`\r\nluckystack-validate-deploy — pre-deploy validator for services + deploy configs\r\n\r\nUSAGE\r\n luckystack-validate-deploy --deploy <file> --services <file> [options]\r\n\r\nREQUIRED\r\n --deploy, -d <file> Path to compiled deploy.config.js (registers DeployConfig).\r\n --services, -s <file> Path to compiled services.config.js (registers ServicesConfig).\r\n\r\nOPTIONS\r\n --strict Exit 1 on warnings as well as errors.\r\n --help, -h Show this help.\r\n\r\nWHAT IT CHECKS\r\n - Every service is assigned to exactly one preset.\r\n - Every preset references services that exist.\r\n - Every environment binding's service matches an actual service.\r\n - Every environment's redis/mongo resource keys exist.\r\n - Fallback envs must share the same redis/mongo resource keys.\r\n - synchronizedEnvKeys and urlEnvKey values resolve at config time (warning only).\r\n - Services bound in no environment (warning only — valid mid-rollout).\r\n\r\nEXAMPLES\r\n luckystack-validate-deploy --deploy dist/deploy.config.js --services dist/services.config.js\r\n npx tsx packages/devkit/dist/cli/validateDeploy.js --deploy ./deploy.config.ts --services ./services.config.ts\r\n`);\r\n};\r\n\r\nconst ALLOWED_CONFIG_EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts']);\r\n\r\nconst importConfig = async (file: string, label: string): Promise<void> => {\r\n const abs = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\r\n\r\n //? Guard: resolved path must stay inside cwd (or the resolved project root)\r\n //? to prevent `--deploy ../../../../etc/shadow` style path injection.\r\n const root = path.resolve(process.cwd());\r\n const resolved = path.resolve(abs);\r\n if (!resolved.startsWith(root + path.sep) && resolved !== root) {\r\n throw new Error(\r\n `[luckystack-validate-deploy] ${label} path \"${file}\" resolves outside the project root — aborting`,\r\n );\r\n }\r\n\r\n //? Guard: only load known JS/TS module extensions.\r\n const ext = path.extname(resolved).toLowerCase();\r\n if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {\r\n throw new Error(\r\n `[luckystack-validate-deploy] ${label} path \"${file}\" has disallowed extension \"${ext}\" — expected one of ${[...ALLOWED_CONFIG_EXTENSIONS].join(', ')}`,\r\n );\r\n }\r\n\r\n try {\r\n await import(pathToFileURL(resolved).href);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n throw new Error(`[luckystack-validate-deploy] failed to import ${label} at ${abs}: ${message}`);\r\n }\r\n};\r\n\r\nconst COLORS = process.stdout.isTTY\r\n ? {\r\n reset: '\u001b[0m',\r\n bold: '\u001b[1m',\r\n dim: '\u001b[2m',\r\n red: '\u001b[31m',\r\n green: '\u001b[32m',\r\n yellow: '\u001b[33m',\r\n cyan: '\u001b[36m',\r\n }\r\n : { reset: '', bold: '', dim: '', red: '', green: '', yellow: '', cyan: '' };\r\n\r\nconst printFinding = (finding: ValidationFinding): void => {\r\n const tag = finding.severity === 'error'\r\n ? `${COLORS.red}${COLORS.bold}ERROR${COLORS.reset}`\r\n : `${COLORS.yellow}${COLORS.bold}WARN ${COLORS.reset}`;\r\n const code = `${COLORS.dim}[${finding.code}]${COLORS.reset}`;\r\n const location = finding.location ? `\\n ${COLORS.dim}at ${finding.location}${COLORS.reset}` : '';\r\n const sink = finding.severity === 'error' ? process.stderr : process.stdout;\r\n sink.write(`${tag} ${code} ${finding.message}${location}\\n`);\r\n};\r\n\r\nconst main = async (): Promise<void> => {\r\n const args = parseArgs(process.argv.slice(2));\r\n\r\n if (!args.deploy || !args.services) {\r\n process.stderr.write('[luckystack-validate-deploy] --deploy and --services are required. Run with --help for usage.\\n');\r\n process.exit(2);\r\n }\r\n\r\n await importConfig(args.deploy, 'deploy config');\r\n await importConfig(args.services, 'services config');\r\n\r\n if (!isDeployConfigRegistered()) {\r\n process.stderr.write('[luckystack-validate-deploy] deploy config file did not call registerDeployConfig — nothing to validate.\\n');\r\n process.exit(2);\r\n }\r\n if (!isServicesConfigRegistered()) {\r\n process.stderr.write('[luckystack-validate-deploy] services config file did not call registerServicesConfig — nothing to validate.\\n');\r\n process.exit(2);\r\n }\r\n\r\n const result = validateDeploy({\r\n services: getServicesConfig(),\r\n deploy: getDeployConfig(),\r\n });\r\n\r\n for (const finding of result.findings) {\r\n printFinding(finding);\r\n }\r\n\r\n const summary = result.ok\r\n ? `${COLORS.green}${COLORS.bold}OK${COLORS.reset}`\r\n : `${COLORS.red}${COLORS.bold}FAILED${COLORS.reset}`;\r\n process.stdout.write(\r\n `\\n${summary} — ${String(result.errorCount)} error(s), ${String(result.warningCount)} warning(s)\\n`,\r\n );\r\n\r\n if (result.errorCount > 0) {\r\n process.exit(1);\r\n }\r\n if (args.failOnWarning && result.warningCount > 0) {\r\n process.exit(1);\r\n }\r\n process.exit(0);\r\n};\r\n\r\nmain().catch((error: unknown) => {\r\n const message = error instanceof Error ? error.stack ?? error.message : String(error);\r\n process.stderr.write(`[luckystack-validate-deploy] fatal: ${message}\\n`);\r\n process.exit(1);\r\n});\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/validateDeploy.ts"],"sourcesContent":["#!/usr/bin/env node\n//? `luckystack-validate-deploy` CLI. Loads the consumer's compiled\n//? services.config.js and deploy.config.js as side-effects (they call\n//? `registerServicesConfig` / `registerDeployConfig` on import), then runs\n//? `validateDeploy()` and prints findings.\n//?\n//? Designed to be a pre-deploy gate: exit 1 on any error finding, 0\n//? otherwise. Warnings print to stderr but never fail the run.\n\nimport { pathToFileURL } from 'node:url';\nimport path from 'node:path';\nimport {\n getDeployConfig,\n getServicesConfig,\n isDeployConfigRegistered,\n isServicesConfigRegistered,\n} from '@luckystack/core';\n\nimport { validateDeploy, type ValidationFinding } from '../validateDeploy';\n\ninterface CliArgs {\n deploy: string | null;\n services: string | null;\n failOnWarning: boolean;\n}\n\nconst parseArgs = (argv: readonly string[]): CliArgs => {\n const args: CliArgs = {\n deploy: null,\n services: null,\n failOnWarning: false,\n };\n\n for (let i = 0; i < argv.length; i++) {\n const flag = argv[i];\n const next: string | undefined = i + 1 < argv.length ? argv[i + 1] : undefined;\n switch (flag) {\n case '--deploy':\n case '-d': {\n args.deploy = next ?? null;\n i++;\n break;\n }\n case '--services':\n case '-s': {\n args.services = next ?? null;\n i++;\n break;\n }\n case '--strict': {\n args.failOnWarning = true;\n break;\n }\n case '--help':\n case '-h': {\n printHelp();\n process.exit(0);\n break;\n }\n default: {\n break;\n }\n }\n }\n\n return args;\n};\n\nconst printHelp = (): void => {\n process.stdout.write(`\nluckystack-validate-deploy — pre-deploy validator for services + deploy configs\n\nUSAGE\n luckystack-validate-deploy --deploy <file> --services <file> [options]\n\nREQUIRED\n --deploy, -d <file> Path to compiled deploy.config.js (registers DeployConfig).\n --services, -s <file> Path to compiled services.config.js (registers ServicesConfig).\n\nOPTIONS\n --strict Exit 1 on warnings as well as errors.\n --help, -h Show this help.\n\nWHAT IT CHECKS\n - Every service is assigned to exactly one preset.\n - Every preset references services that exist.\n - Every environment binding's service matches an actual service.\n - Every environment's redis/mongo resource keys exist.\n - Fallback envs must share the same redis/mongo resource keys.\n - synchronizedEnvKeys and urlEnvKey values resolve at config time (warning only).\n - Services bound in no environment (warning only — valid mid-rollout).\n\nEXAMPLES\n luckystack-validate-deploy --deploy dist/deploy.config.js --services dist/services.config.js\n npx tsx packages/devkit/dist/cli/validateDeploy.js --deploy ./deploy.config.ts --services ./services.config.ts\n`);\n};\n\nconst ALLOWED_CONFIG_EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts']);\n\nconst importConfig = async (file: string, label: string): Promise<void> => {\n const abs = path.isAbsolute(file) ? file : path.join(process.cwd(), file);\n\n //? Guard: resolved path must stay inside cwd (or the resolved project root)\n //? to prevent `--deploy ../../../../etc/shadow` style path injection.\n const root = path.resolve(process.cwd());\n const resolved = path.resolve(abs);\n if (!resolved.startsWith(root + path.sep) && resolved !== root) {\n throw new Error(\n `[luckystack-validate-deploy] ${label} path \"${file}\" resolves outside the project root — aborting`,\n );\n }\n\n //? Guard: only load known JS/TS module extensions.\n const ext = path.extname(resolved).toLowerCase();\n if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {\n throw new Error(\n `[luckystack-validate-deploy] ${label} path \"${file}\" has disallowed extension \"${ext}\" — expected one of ${[...ALLOWED_CONFIG_EXTENSIONS].join(', ')}`,\n );\n }\n\n try {\n await import(pathToFileURL(resolved).href);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`[luckystack-validate-deploy] failed to import ${label} at ${abs}: ${message}`);\n }\n};\n\nconst COLORS = process.stdout.isTTY\n ? {\n reset: '\u001b[0m',\n bold: '\u001b[1m',\n dim: '\u001b[2m',\n red: '\u001b[31m',\n green: '\u001b[32m',\n yellow: '\u001b[33m',\n cyan: '\u001b[36m',\n }\n : { reset: '', bold: '', dim: '', red: '', green: '', yellow: '', cyan: '' };\n\nconst printFinding = (finding: ValidationFinding): void => {\n const tag = finding.severity === 'error'\n ? `${COLORS.red}${COLORS.bold}ERROR${COLORS.reset}`\n : `${COLORS.yellow}${COLORS.bold}WARN ${COLORS.reset}`;\n const code = `${COLORS.dim}[${finding.code}]${COLORS.reset}`;\n const location = finding.location ? `\\n ${COLORS.dim}at ${finding.location}${COLORS.reset}` : '';\n const sink = finding.severity === 'error' ? process.stderr : process.stdout;\n sink.write(`${tag} ${code} ${finding.message}${location}\\n`);\n};\n\nconst main = async (): Promise<void> => {\n const args = parseArgs(process.argv.slice(2));\n\n if (!args.deploy || !args.services) {\n process.stderr.write('[luckystack-validate-deploy] --deploy and --services are required. Run with --help for usage.\\n');\n process.exit(2);\n }\n\n await importConfig(args.deploy, 'deploy config');\n await importConfig(args.services, 'services config');\n\n if (!isDeployConfigRegistered()) {\n process.stderr.write('[luckystack-validate-deploy] deploy config file did not call registerDeployConfig — nothing to validate.\\n');\n process.exit(2);\n }\n if (!isServicesConfigRegistered()) {\n process.stderr.write('[luckystack-validate-deploy] services config file did not call registerServicesConfig — nothing to validate.\\n');\n process.exit(2);\n }\n\n const result = validateDeploy({\n services: getServicesConfig(),\n deploy: getDeployConfig(),\n });\n\n for (const finding of result.findings) {\n printFinding(finding);\n }\n\n const summary = result.ok\n ? `${COLORS.green}${COLORS.bold}OK${COLORS.reset}`\n : `${COLORS.red}${COLORS.bold}FAILED${COLORS.reset}`;\n process.stdout.write(\n `\\n${summary} — ${String(result.errorCount)} error(s), ${String(result.warningCount)} warning(s)\\n`,\n );\n\n if (result.errorCount > 0) {\n process.exit(1);\n }\n if (args.failOnWarning && result.warningCount > 0) {\n process.exit(1);\n }\n process.exit(0);\n};\n\nmain().catch((error: unknown) => {\n const message = error instanceof Error ? error.stack ?? error.message : String(error);\n process.stderr.write(`[luckystack-validate-deploy] fatal: ${message}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validateDeploy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BZTCJ7JY.js";
|
|
4
4
|
|
|
5
5
|
// src/typeMap/discovery.ts
|
|
6
6
|
import fs from "fs";
|
|
@@ -468,7 +468,7 @@ var convertTypeNode = (node) => {
|
|
|
468
468
|
return args.length === 1 && arg0 ? `z.array(${convertTypeNode(arg0)})` : anyFallback("Array without element type");
|
|
469
469
|
}
|
|
470
470
|
case "Date": {
|
|
471
|
-
return "z.
|
|
471
|
+
return "z.iso.datetime()";
|
|
472
472
|
}
|
|
473
473
|
default: {
|
|
474
474
|
return anyFallback(`unresolved TypeReference '${name}'`);
|
|
@@ -519,6 +519,41 @@ var typeTextToZodSource = (typeText) => {
|
|
|
519
519
|
return convertTypeNode(statement.type);
|
|
520
520
|
};
|
|
521
521
|
|
|
522
|
+
// src/typeMap/extractionDiagnostics.ts
|
|
523
|
+
import { tryCatchSync as tryCatchSync2 } from "@luckystack/core";
|
|
524
|
+
var failures = /* @__PURE__ */ new Map();
|
|
525
|
+
var keyOf = (filePath, kind, field) => `${filePath}|${kind}|${field}`;
|
|
526
|
+
var messageOf = (error) => {
|
|
527
|
+
if (error instanceof Error) return error.message;
|
|
528
|
+
if (typeof error === "string") return error;
|
|
529
|
+
const [, encoded] = tryCatchSync2(() => JSON.stringify(error));
|
|
530
|
+
return encoded ?? Object.prototype.toString.call(error);
|
|
531
|
+
};
|
|
532
|
+
var recordExtractionOutcome = ({
|
|
533
|
+
filePath,
|
|
534
|
+
kind,
|
|
535
|
+
field,
|
|
536
|
+
error
|
|
537
|
+
}) => {
|
|
538
|
+
const key = keyOf(filePath, kind, field);
|
|
539
|
+
if (error === null) {
|
|
540
|
+
failures.delete(key);
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
failures.set(key, { filePath, kind, field, message: messageOf(error) });
|
|
544
|
+
};
|
|
545
|
+
var routeKeyOf = ({ filePath, kind }) => {
|
|
546
|
+
const [, route] = tryCatchSync2(() => kind === "api" ? `${extractPagePath(filePath)}/${extractApiName(filePath)}@${extractApiVersion(filePath)}` : `${extractSyncPagePath(filePath)}/${extractSyncName(filePath)}@${extractSyncVersion(filePath)}`);
|
|
547
|
+
return route;
|
|
548
|
+
};
|
|
549
|
+
var findExtractionFailure = (route, kind, field) => {
|
|
550
|
+
for (const failure of failures.values()) {
|
|
551
|
+
if (failure.kind !== kind || failure.field !== field) continue;
|
|
552
|
+
if (routeKeyOf(failure) === route) return failure.message;
|
|
553
|
+
}
|
|
554
|
+
return void 0;
|
|
555
|
+
};
|
|
556
|
+
|
|
522
557
|
// src/typeMap/emitterArtifacts.ts
|
|
523
558
|
var buildImportStatements = ({
|
|
524
559
|
namedImports,
|
|
@@ -683,12 +718,17 @@ var validateGeneratedTypeIdentifiers = (content) => {
|
|
|
683
718
|
};
|
|
684
719
|
var collectFallbacks = (typesByPage, syncTypesByPage) => {
|
|
685
720
|
const entries = [];
|
|
686
|
-
const flagField = (route, kind, field, value) => {
|
|
721
|
+
const flagField = (route, kind, field, value, checkZod = false) => {
|
|
722
|
+
const extractionError = findExtractionFailure(route, kind, field);
|
|
723
|
+
if (extractionError !== void 0) {
|
|
724
|
+
entries.push({ route, kind, field, fallback: value, reason: "extraction-error", detail: extractionError });
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
687
727
|
if (value === "{ }" || value === "{ status: string }") {
|
|
688
728
|
entries.push({ route, kind, field, fallback: value, reason: "default-fallback" });
|
|
689
729
|
return;
|
|
690
730
|
}
|
|
691
|
-
const zodSrc = typeTextToZodSource(value);
|
|
731
|
+
const zodSrc = checkZod ? typeTextToZodSource(value) : null;
|
|
692
732
|
if (zodSrc?.includes("z.any()")) {
|
|
693
733
|
entries.push({ route, kind, field, fallback: value.slice(0, 80), reason: "zod-any-fallback" });
|
|
694
734
|
}
|
|
@@ -697,8 +737,9 @@ var collectFallbacks = (typesByPage, syncTypesByPage) => {
|
|
|
697
737
|
for (const [apiKey, entry] of apis) {
|
|
698
738
|
const { name, version } = splitVersionedKey(apiKey);
|
|
699
739
|
const route = `${pagePath}/${name}@${version}`;
|
|
700
|
-
flagField(route, "api", "input", entry.input);
|
|
740
|
+
flagField(route, "api", "input", entry.input, true);
|
|
701
741
|
flagField(route, "api", "output", entry.output);
|
|
742
|
+
flagField(route, "api", "stream", entry.stream);
|
|
702
743
|
}
|
|
703
744
|
}
|
|
704
745
|
for (const [pagePath, syncs] of syncTypesByPage) {
|
|
@@ -708,6 +749,8 @@ var collectFallbacks = (typesByPage, syncTypesByPage) => {
|
|
|
708
749
|
flagField(route, "sync", "clientInput", entry.clientInput);
|
|
709
750
|
flagField(route, "sync", "serverOutput", entry.serverOutput);
|
|
710
751
|
flagField(route, "sync", "clientOutput", entry.clientOutput);
|
|
752
|
+
flagField(route, "sync", "serverStream", entry.serverStream);
|
|
753
|
+
flagField(route, "sync", "clientStream", entry.clientStream);
|
|
711
754
|
}
|
|
712
755
|
}
|
|
713
756
|
return entries;
|
|
@@ -1146,7 +1189,7 @@ var getServerProgram = () => {
|
|
|
1146
1189
|
var invalidateProgramCache = () => {
|
|
1147
1190
|
cachedProgram = null;
|
|
1148
1191
|
};
|
|
1149
|
-
var DEPTH_LIMIT =
|
|
1192
|
+
var DEPTH_LIMIT = 14;
|
|
1150
1193
|
var JSON_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
1151
1194
|
"Json",
|
|
1152
1195
|
"JsonValue",
|
|
@@ -1169,12 +1212,37 @@ var SKIP_EXPANSION = /* @__PURE__ */ new Set([
|
|
|
1169
1212
|
"ArrayBuffer",
|
|
1170
1213
|
"ReadonlyArray"
|
|
1171
1214
|
]);
|
|
1215
|
+
var TRANSPORT_DEPENDENT_BINARY_TYPES = /* @__PURE__ */ new Set([
|
|
1216
|
+
"Buffer",
|
|
1217
|
+
"ArrayBuffer",
|
|
1218
|
+
"SharedArrayBuffer",
|
|
1219
|
+
"DataView",
|
|
1220
|
+
"Blob",
|
|
1221
|
+
"File",
|
|
1222
|
+
"Int8Array",
|
|
1223
|
+
"Uint8Array",
|
|
1224
|
+
"Uint8ClampedArray",
|
|
1225
|
+
"Int16Array",
|
|
1226
|
+
"Uint16Array",
|
|
1227
|
+
"Int32Array",
|
|
1228
|
+
"Uint32Array",
|
|
1229
|
+
"Float32Array",
|
|
1230
|
+
"Float64Array",
|
|
1231
|
+
"BigInt64Array",
|
|
1232
|
+
"BigUint64Array"
|
|
1233
|
+
]);
|
|
1234
|
+
var UnsupportedWireTypeError = class extends Error {
|
|
1235
|
+
constructor(typeName) {
|
|
1236
|
+
super(`[TypeMapGenerator] ${typeName} has transport-dependent or non-JSON output semantics. Return an explicit JSON DTO/base64 string, or use a transport-specific custom route.`);
|
|
1237
|
+
this.name = "UnsupportedWireTypeError";
|
|
1238
|
+
}
|
|
1239
|
+
};
|
|
1172
1240
|
var isJsonLikeType = (type, checker) => {
|
|
1173
1241
|
const symbolName = type.symbol?.name ?? "";
|
|
1174
1242
|
const aliasName = type.aliasSymbol?.name ?? "";
|
|
1175
1243
|
if (JSON_TYPE_NAMES.has(symbolName) || JSON_TYPE_NAMES.has(aliasName)) return true;
|
|
1176
|
-
const rendered = checker.typeToString(type);
|
|
1177
|
-
return
|
|
1244
|
+
const rendered = checker.typeToString(type).trim();
|
|
1245
|
+
return /^(?:Prisma\.)?(?:Input)?Json(?:Value|Object|Array)$/.test(rendered);
|
|
1178
1246
|
};
|
|
1179
1247
|
var getLiteralTypeFromExpression = (expression, checker, depth) => {
|
|
1180
1248
|
if (ts4.isParenthesizedExpression(expression)) {
|
|
@@ -1258,8 +1326,64 @@ var collectTypeSymbolFallback = (type) => {
|
|
|
1258
1326
|
importPath: normalizeImportPath(sourceFile)
|
|
1259
1327
|
}];
|
|
1260
1328
|
};
|
|
1261
|
-
var
|
|
1262
|
-
|
|
1329
|
+
var WIRE_PROJECTED_TYPES = /* @__PURE__ */ new Map([["Date", "string"]]);
|
|
1330
|
+
var resolveToJsonReturnType = (type, checker) => {
|
|
1331
|
+
const toJson = type.getProperty("toJSON");
|
|
1332
|
+
if (!toJson) return null;
|
|
1333
|
+
const declaration = toJson.valueDeclaration ?? toJson.declarations?.[0];
|
|
1334
|
+
if (!declaration) return null;
|
|
1335
|
+
const signature = checker.getTypeOfSymbolAtLocation(toJson, declaration).getCallSignatures()[0];
|
|
1336
|
+
return signature ? signature.getReturnType() : null;
|
|
1337
|
+
};
|
|
1338
|
+
var isFunctionValueType = (type) => type.getCallSignatures().length > 0;
|
|
1339
|
+
var typeNameOf = (type, checker) => {
|
|
1340
|
+
const objectType = type;
|
|
1341
|
+
if (type.flags & ts4.TypeFlags.Object && objectType.objectFlags & ts4.ObjectFlags.Reference) {
|
|
1342
|
+
const targetName = objectType.target.getSymbol()?.name;
|
|
1343
|
+
if (targetName) return targetName;
|
|
1344
|
+
}
|
|
1345
|
+
return type.getSymbol()?.name ?? checker.typeToString(type);
|
|
1346
|
+
};
|
|
1347
|
+
var assertSupportedWireType = (type, checker) => {
|
|
1348
|
+
const typeName = typeNameOf(type, checker);
|
|
1349
|
+
if (TRANSPORT_DEPENDENT_BINARY_TYPES.has(typeName)) {
|
|
1350
|
+
throw new UnsupportedWireTypeError(typeName);
|
|
1351
|
+
}
|
|
1352
|
+
if ((type.flags & (ts4.TypeFlags.BigInt | ts4.TypeFlags.BigIntLiteral)) !== 0) {
|
|
1353
|
+
throw new UnsupportedWireTypeError("bigint");
|
|
1354
|
+
}
|
|
1355
|
+
};
|
|
1356
|
+
var isJsonOmittedValueType = (type) => (type.flags & (ts4.TypeFlags.Undefined | ts4.TypeFlags.Void | ts4.TypeFlags.ESSymbol | ts4.TypeFlags.UniqueESSymbol)) !== 0 || isFunctionValueType(type);
|
|
1357
|
+
var resolveWireConstituents = (type, checker) => {
|
|
1358
|
+
const queue = type.isUnion() ? [...type.types] : [type];
|
|
1359
|
+
const serializable = [];
|
|
1360
|
+
let omitted = false;
|
|
1361
|
+
let changed = false;
|
|
1362
|
+
for (const candidate of queue) {
|
|
1363
|
+
assertSupportedWireType(candidate, checker);
|
|
1364
|
+
if (isJsonOmittedValueType(candidate)) {
|
|
1365
|
+
omitted = true;
|
|
1366
|
+
changed = true;
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
const jsonType = resolveToJsonReturnType(candidate, checker);
|
|
1370
|
+
const effective = jsonType && jsonType !== candidate ? jsonType : candidate;
|
|
1371
|
+
if (effective !== candidate) changed = true;
|
|
1372
|
+
const effectiveTypes = effective.isUnion() ? effective.types : [effective];
|
|
1373
|
+
for (const effectiveType of effectiveTypes) {
|
|
1374
|
+
assertSupportedWireType(effectiveType, checker);
|
|
1375
|
+
if (isJsonOmittedValueType(effectiveType)) {
|
|
1376
|
+
omitted = true;
|
|
1377
|
+
changed = true;
|
|
1378
|
+
} else {
|
|
1379
|
+
serializable.push(effectiveType);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return changed ? { serializable, omitted } : { serializable: [type], omitted: false };
|
|
1384
|
+
};
|
|
1385
|
+
var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
1386
|
+
const expandState = state ?? { stackTypeIds: /* @__PURE__ */ new Set(), wireProjection: options?.wireProjection ?? false };
|
|
1263
1387
|
const typeId = type.id;
|
|
1264
1388
|
if (typeId !== void 0) {
|
|
1265
1389
|
if (expandState.stackTypeIds.has(typeId)) {
|
|
@@ -1271,6 +1395,12 @@ var expandTypeDetailed = (type, checker, depth = 0, state) => {
|
|
|
1271
1395
|
expandState.stackTypeIds.add(typeId);
|
|
1272
1396
|
}
|
|
1273
1397
|
try {
|
|
1398
|
+
if (expandState.wireProjection) {
|
|
1399
|
+
assertSupportedWireType(type, checker);
|
|
1400
|
+
if (isJsonOmittedValueType(type)) {
|
|
1401
|
+
throw new UnsupportedWireTypeError(checker.typeToString(type));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1274
1404
|
if (depth > DEPTH_LIMIT) {
|
|
1275
1405
|
return {
|
|
1276
1406
|
text: checker.typeToString(type),
|
|
@@ -1290,7 +1420,8 @@ var expandTypeDetailed = (type, checker, depth = 0, state) => {
|
|
|
1290
1420
|
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1291
1421
|
return expanded.text;
|
|
1292
1422
|
});
|
|
1293
|
-
|
|
1423
|
+
const uniqueTypes = [...new Set(expandedTypes)];
|
|
1424
|
+
return { text: uniqueTypes.join(" | "), unresolvedSymbols };
|
|
1294
1425
|
}
|
|
1295
1426
|
if (type.isIntersection()) {
|
|
1296
1427
|
let unresolvedSymbols = [];
|
|
@@ -1303,16 +1434,29 @@ var expandTypeDetailed = (type, checker, depth = 0, state) => {
|
|
|
1303
1434
|
}
|
|
1304
1435
|
if (type.flags & ts4.TypeFlags.Object) {
|
|
1305
1436
|
const objectType = type;
|
|
1306
|
-
|
|
1437
|
+
const tupleTarget = objectType.objectFlags & ts4.ObjectFlags.Reference ? objectType.target : objectType;
|
|
1438
|
+
if (tupleTarget.objectFlags & ts4.ObjectFlags.Tuple) {
|
|
1307
1439
|
const typeArgs = checker.getTypeArguments(objectType);
|
|
1308
1440
|
let unresolvedSymbols = [];
|
|
1309
1441
|
const tupleTypes = typeArgs.map((innerType) => {
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1442
|
+
const wire = expandState.wireProjection ? resolveWireConstituents(innerType, checker) : { serializable: [innerType], omitted: false };
|
|
1443
|
+
const texts = [];
|
|
1444
|
+
for (const serializableType of wire.serializable) {
|
|
1445
|
+
const expanded = expandTypeDetailed(serializableType, checker, depth + 1, expandState);
|
|
1446
|
+
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1447
|
+
texts.push(expanded.text);
|
|
1448
|
+
}
|
|
1449
|
+
if (wire.omitted) texts.push("null");
|
|
1450
|
+
return [...new Set(texts)].join(" | ");
|
|
1313
1451
|
});
|
|
1314
1452
|
return { text: `[${tupleTypes.join(", ")}]`, unresolvedSymbols };
|
|
1315
1453
|
}
|
|
1454
|
+
if (expandState.wireProjection) {
|
|
1455
|
+
const jsonType = resolveToJsonReturnType(type, checker);
|
|
1456
|
+
if (jsonType && jsonType !== type) {
|
|
1457
|
+
return expandTypeDetailed(jsonType, checker, depth + 1, expandState);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1316
1460
|
if (objectType.objectFlags & ts4.ObjectFlags.Reference) {
|
|
1317
1461
|
const refType = objectType;
|
|
1318
1462
|
const targetName = refType.target.symbol?.name ?? "";
|
|
@@ -1320,21 +1464,29 @@ var expandTypeDetailed = (type, checker, depth = 0, state) => {
|
|
|
1320
1464
|
const typeArgs = checker.getTypeArguments(refType);
|
|
1321
1465
|
const firstArg = typeArgs[0];
|
|
1322
1466
|
if (firstArg) {
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1467
|
+
const wire = expandState.wireProjection ? resolveWireConstituents(firstArg, checker) : { serializable: [firstArg], omitted: false };
|
|
1468
|
+
let unresolvedSymbols = [];
|
|
1469
|
+
const texts = [];
|
|
1470
|
+
for (const serializableType of wire.serializable) {
|
|
1471
|
+
const expanded = expandTypeDetailed(serializableType, checker, depth + 1, expandState);
|
|
1472
|
+
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1473
|
+
texts.push(expanded.text);
|
|
1474
|
+
}
|
|
1475
|
+
if (wire.omitted) texts.push("null");
|
|
1476
|
+
const expandedText = [...new Set(texts)].join(" | ");
|
|
1477
|
+
const elementType = /\s[|&]\s/.test(expandedText) ? `(${expandedText})` : expandedText;
|
|
1478
|
+
return { text: `${elementType}[]`, unresolvedSymbols };
|
|
1329
1479
|
}
|
|
1330
1480
|
}
|
|
1331
1481
|
if (SKIP_EXPANSION.has(targetName)) {
|
|
1332
|
-
|
|
1482
|
+
const projected = expandState.wireProjection ? WIRE_PROJECTED_TYPES.get(targetName) : void 0;
|
|
1483
|
+
return { text: projected ?? checker.typeToString(type), unresolvedSymbols: [] };
|
|
1333
1484
|
}
|
|
1334
1485
|
}
|
|
1335
|
-
const symbolName = type.symbol
|
|
1486
|
+
const symbolName = type.symbol?.name || (type.aliasSymbol?.name ?? "");
|
|
1336
1487
|
if (SKIP_EXPANSION.has(symbolName)) {
|
|
1337
|
-
|
|
1488
|
+
const projected = expandState.wireProjection ? WIRE_PROJECTED_TYPES.get(symbolName) : void 0;
|
|
1489
|
+
return { text: projected ?? checker.typeToString(type), unresolvedSymbols: [] };
|
|
1338
1490
|
}
|
|
1339
1491
|
const props = checker.getPropertiesOfType(type);
|
|
1340
1492
|
const indexInfos = checker.getIndexInfosOfType(type);
|
|
@@ -1344,22 +1496,34 @@ var expandTypeDetailed = (type, checker, depth = 0, state) => {
|
|
|
1344
1496
|
for (const prop of props) {
|
|
1345
1497
|
if (prop.getName().startsWith("__@")) continue;
|
|
1346
1498
|
const propType = checker.getTypeOfSymbol(prop);
|
|
1499
|
+
const wire = expandState.wireProjection ? resolveWireConstituents(propType, checker) : { serializable: [propType], omitted: false };
|
|
1500
|
+
if (wire.serializable.length === 0) continue;
|
|
1347
1501
|
const literalType = getLiteralTypeFromPropertySymbol(prop, checker, depth + 1);
|
|
1348
|
-
const isOptional = (prop.flags & ts4.SymbolFlags.Optional) !== 0;
|
|
1349
|
-
if (literalType) {
|
|
1502
|
+
const isOptional = (prop.flags & ts4.SymbolFlags.Optional) !== 0 || wire.omitted;
|
|
1503
|
+
if (literalType && !wire.omitted) {
|
|
1350
1504
|
fields.push(`${prop.name}${isOptional ? "?" : ""}: ${literalType}`);
|
|
1351
1505
|
continue;
|
|
1352
1506
|
}
|
|
1353
|
-
const
|
|
1354
|
-
|
|
1355
|
-
|
|
1507
|
+
const texts = [];
|
|
1508
|
+
for (const serializableType of wire.serializable) {
|
|
1509
|
+
const expandedProp = expandTypeDetailed(serializableType, checker, depth + 1, expandState);
|
|
1510
|
+
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expandedProp.unresolvedSymbols);
|
|
1511
|
+
texts.push(expandedProp.text);
|
|
1512
|
+
}
|
|
1513
|
+
fields.push(`${prop.name}${isOptional ? "?" : ""}: ${[...new Set(texts)].join(" | ")}`);
|
|
1356
1514
|
}
|
|
1357
1515
|
for (const indexInfo of indexInfos) {
|
|
1358
1516
|
const keyType = expandTypeDetailed(indexInfo.keyType, checker, depth + 1, expandState);
|
|
1359
|
-
const
|
|
1517
|
+
const wire = expandState.wireProjection ? resolveWireConstituents(indexInfo.type, checker) : { serializable: [indexInfo.type], omitted: false };
|
|
1518
|
+
if (wire.serializable.length === 0) continue;
|
|
1519
|
+
const valueTexts = [];
|
|
1520
|
+
for (const serializableType of wire.serializable) {
|
|
1521
|
+
const valueType = expandTypeDetailed(serializableType, checker, depth + 1, expandState);
|
|
1522
|
+
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, valueType.unresolvedSymbols);
|
|
1523
|
+
valueTexts.push(valueType.text);
|
|
1524
|
+
}
|
|
1360
1525
|
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, keyType.unresolvedSymbols);
|
|
1361
|
-
|
|
1362
|
-
fields.push(`[key: ${keyType.text}]: ${valueType.text}`);
|
|
1526
|
+
fields.push(`[key: ${keyType.text}]: ${[...new Set(valueTexts)].join(" | ")}`);
|
|
1363
1527
|
}
|
|
1364
1528
|
const indent = " ".repeat(depth + 1);
|
|
1365
1529
|
const outerIndent = " ".repeat(depth);
|
|
@@ -1504,7 +1668,7 @@ var collectReturnObjectTypeDetails = (funcNode, checker) => {
|
|
|
1504
1668
|
const visit = (node) => {
|
|
1505
1669
|
if (ts5.isReturnStatement(node) && node.expression && ts5.isObjectLiteralExpression(node.expression)) {
|
|
1506
1670
|
const type = checker.getTypeAtLocation(node.expression);
|
|
1507
|
-
const expanded = expandTypeDetailed(type, checker);
|
|
1671
|
+
const expanded = expandTypeDetailed(type, checker, 0, void 0, { wireProjection: true });
|
|
1508
1672
|
types.push(expanded.text);
|
|
1509
1673
|
unresolvedSymbols = mergeUnresolvedSymbols2(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1510
1674
|
unresolvedSymbols = mergeUnresolvedSymbols2(
|
|
@@ -1531,7 +1695,7 @@ var collectStreamCallPayloadTypeDetails = (funcNode, checker) => {
|
|
|
1531
1695
|
if (payloadArg) {
|
|
1532
1696
|
const argType = checker.getTypeAtLocation(payloadArg);
|
|
1533
1697
|
const nonNullableArgType = checker.getNonNullableType(argType);
|
|
1534
|
-
const expanded = expandTypeDetailed(nonNullableArgType, checker);
|
|
1698
|
+
const expanded = expandTypeDetailed(nonNullableArgType, checker, 0, void 0, { wireProjection: true });
|
|
1535
1699
|
if (expanded.text.trim().length > 0) {
|
|
1536
1700
|
types.push(expanded.text);
|
|
1537
1701
|
}
|
|
@@ -1553,11 +1717,34 @@ var unionTypes = (types) => {
|
|
|
1553
1717
|
const unique = [...new Set(types)];
|
|
1554
1718
|
return unique.length > 0 ? unique.join(" | ") : "";
|
|
1555
1719
|
};
|
|
1720
|
+
var UnsupportedTransportInputError = class extends Error {
|
|
1721
|
+
constructor(filePath) {
|
|
1722
|
+
super(`[TypeMapGenerator] ${filePath} declares Date in a transport input. JSON delivers an ISO string; declare string and validate/convert it explicitly.`);
|
|
1723
|
+
this.name = "UnsupportedTransportInputError";
|
|
1724
|
+
}
|
|
1725
|
+
};
|
|
1726
|
+
var assertTransportInputIsWireSafe = (typeText, filePath) => {
|
|
1727
|
+
const sourceFile = ts5.createSourceFile(
|
|
1728
|
+
"__luckystack_input_check.ts",
|
|
1729
|
+
`type __LuckyStackInput = ${typeText};`,
|
|
1730
|
+
ts5.ScriptTarget.Latest,
|
|
1731
|
+
true,
|
|
1732
|
+
ts5.ScriptKind.TS
|
|
1733
|
+
);
|
|
1734
|
+
const containsDate = (node) => {
|
|
1735
|
+
if (ts5.isTypeReferenceNode(node) && ts5.isIdentifier(node.typeName) && node.typeName.text === "Date") {
|
|
1736
|
+
return true;
|
|
1737
|
+
}
|
|
1738
|
+
return node.getChildren(sourceFile).some((child) => containsDate(child));
|
|
1739
|
+
};
|
|
1740
|
+
if (containsDate(sourceFile)) throw new UnsupportedTransportInputError(filePath);
|
|
1741
|
+
};
|
|
1556
1742
|
var getInputTypeFromFile = (filePath) => {
|
|
1557
1743
|
return getInputTypeDetailsFromFile(filePath).text;
|
|
1558
1744
|
};
|
|
1559
1745
|
var getInputTypeDetailsFromFile = (filePath) => {
|
|
1560
1746
|
const DEFAULT = "{ }";
|
|
1747
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "input", error: null });
|
|
1561
1748
|
try {
|
|
1562
1749
|
const program = getServerProgram();
|
|
1563
1750
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1571,9 +1758,12 @@ var getInputTypeDetailsFromFile = (filePath) => {
|
|
|
1571
1758
|
const dataType = getInterfacePropertyType(iface, "data", checker);
|
|
1572
1759
|
if (!dataType) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1573
1760
|
const expanded = expandTypeDetailed(dataType, checker);
|
|
1761
|
+
assertTransportInputIsWireSafe(expanded.text, filePath);
|
|
1574
1762
|
return { text: expanded.text || DEFAULT, unresolvedSymbols: expanded.unresolvedSymbols };
|
|
1575
1763
|
} catch (error) {
|
|
1764
|
+
if (error instanceof UnsupportedTransportInputError) throw error;
|
|
1576
1765
|
console.error(`[TypeMapGenerator] Error extracting input type from ${filePath}:`, error);
|
|
1766
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "input", error });
|
|
1577
1767
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1578
1768
|
}
|
|
1579
1769
|
};
|
|
@@ -1594,7 +1784,7 @@ var extractDeclaredStreamTypeFromApiParams = (sourceFile, checker) => {
|
|
|
1594
1784
|
const typeArg = member.type.typeArguments?.[0];
|
|
1595
1785
|
if (typeArg) {
|
|
1596
1786
|
const argType = checker.getNonNullableType(checker.getTypeFromTypeNode(typeArg));
|
|
1597
|
-
const expanded = expandTypeDetailed(argType, checker);
|
|
1787
|
+
const expanded = expandTypeDetailed(argType, checker, 0, void 0, { wireProjection: true });
|
|
1598
1788
|
if (expanded.text.trim().length > 0) {
|
|
1599
1789
|
result = { text: expanded.text, unresolvedSymbols: expanded.unresolvedSymbols };
|
|
1600
1790
|
return;
|
|
@@ -1610,6 +1800,7 @@ var extractDeclaredStreamTypeFromApiParams = (sourceFile, checker) => {
|
|
|
1610
1800
|
};
|
|
1611
1801
|
var getApiStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
1612
1802
|
const DEFAULT = "never";
|
|
1803
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "stream", error: null });
|
|
1613
1804
|
try {
|
|
1614
1805
|
const program = getServerProgram();
|
|
1615
1806
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1623,12 +1814,15 @@ var getApiStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
1623
1814
|
if (declared) return declared;
|
|
1624
1815
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1625
1816
|
} catch (error) {
|
|
1817
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1626
1818
|
console.error(`[TypeMapGenerator] Error extracting API stream payload type from ${filePath}:`, error);
|
|
1819
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "stream", error });
|
|
1627
1820
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1628
1821
|
}
|
|
1629
1822
|
};
|
|
1630
1823
|
var getOutputTypeDetailsFromFile = (filePath) => {
|
|
1631
1824
|
const DEFAULT = "{ status: string }";
|
|
1825
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "output", error: null });
|
|
1632
1826
|
try {
|
|
1633
1827
|
const program = getServerProgram();
|
|
1634
1828
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1639,7 +1833,9 @@ var getOutputTypeDetailsFromFile = (filePath) => {
|
|
|
1639
1833
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
1640
1834
|
return { text: details.text || DEFAULT, unresolvedSymbols: details.unresolvedSymbols };
|
|
1641
1835
|
} catch (error) {
|
|
1836
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1642
1837
|
console.error(`[TypeMapGenerator] Error extracting output type from ${filePath}:`, error);
|
|
1838
|
+
recordExtractionOutcome({ filePath, kind: "api", field: "output", error });
|
|
1643
1839
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1644
1840
|
}
|
|
1645
1841
|
};
|
|
@@ -1648,6 +1844,7 @@ var getSyncClientDataType = (filePath) => {
|
|
|
1648
1844
|
};
|
|
1649
1845
|
var getSyncClientDataTypeDetailsFromFile = (filePath) => {
|
|
1650
1846
|
const DEFAULT = "{ }";
|
|
1847
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientInput", error: null });
|
|
1651
1848
|
try {
|
|
1652
1849
|
const program = getServerProgram();
|
|
1653
1850
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1658,14 +1855,18 @@ var getSyncClientDataTypeDetailsFromFile = (filePath) => {
|
|
|
1658
1855
|
const dataType = getInterfacePropertyType(iface, "clientInput", checker) ?? getInterfacePropertyType(iface, "clientData", checker);
|
|
1659
1856
|
if (!dataType) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1660
1857
|
const expanded = expandTypeDetailed(dataType, checker);
|
|
1858
|
+
assertTransportInputIsWireSafe(expanded.text, filePath);
|
|
1661
1859
|
return { text: expanded.text || DEFAULT, unresolvedSymbols: expanded.unresolvedSymbols };
|
|
1662
1860
|
} catch (error) {
|
|
1861
|
+
if (error instanceof UnsupportedTransportInputError) throw error;
|
|
1663
1862
|
console.error(`[TypeMapGenerator] Error extracting sync clientData type from ${filePath}:`, error);
|
|
1863
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientInput", error });
|
|
1664
1864
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1665
1865
|
}
|
|
1666
1866
|
};
|
|
1667
1867
|
var getSyncServerStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
1668
1868
|
const DEFAULT = "never";
|
|
1869
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "serverStream", error: null });
|
|
1669
1870
|
try {
|
|
1670
1871
|
const program = getServerProgram();
|
|
1671
1872
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1676,12 +1877,15 @@ var getSyncServerStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
1676
1877
|
const details = collectStreamCallPayloadTypeDetails(mainFn, checker);
|
|
1677
1878
|
return { text: details.text || DEFAULT, unresolvedSymbols: details.unresolvedSymbols };
|
|
1678
1879
|
} catch (error) {
|
|
1880
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1679
1881
|
console.error(`[TypeMapGenerator] Error extracting sync server stream payload type from ${filePath}:`, error);
|
|
1882
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "serverStream", error });
|
|
1680
1883
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1681
1884
|
}
|
|
1682
1885
|
};
|
|
1683
1886
|
var getSyncServerOutputTypeDetailsFromFile = (filePath) => {
|
|
1684
1887
|
const DEFAULT = "{ status: string }";
|
|
1888
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "serverOutput", error: null });
|
|
1685
1889
|
try {
|
|
1686
1890
|
const program = getServerProgram();
|
|
1687
1891
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1692,12 +1896,15 @@ var getSyncServerOutputTypeDetailsFromFile = (filePath) => {
|
|
|
1692
1896
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
1693
1897
|
return { text: details.text || DEFAULT, unresolvedSymbols: details.unresolvedSymbols };
|
|
1694
1898
|
} catch (error) {
|
|
1899
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1695
1900
|
console.error(`[TypeMapGenerator] Error extracting sync serverOutput type from ${filePath}:`, error);
|
|
1901
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "serverOutput", error });
|
|
1696
1902
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1697
1903
|
}
|
|
1698
1904
|
};
|
|
1699
1905
|
var getSyncClientStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
1700
1906
|
const DEFAULT = "never";
|
|
1907
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientStream", error: null });
|
|
1701
1908
|
try {
|
|
1702
1909
|
const program = getServerProgram();
|
|
1703
1910
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1708,12 +1915,15 @@ var getSyncClientStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
1708
1915
|
const details = collectStreamCallPayloadTypeDetails(mainFn, checker);
|
|
1709
1916
|
return { text: details.text || DEFAULT, unresolvedSymbols: details.unresolvedSymbols };
|
|
1710
1917
|
} catch (error) {
|
|
1918
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1711
1919
|
console.error(`[TypeMapGenerator] Error extracting sync client stream payload type from ${filePath}:`, error);
|
|
1920
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientStream", error });
|
|
1712
1921
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1713
1922
|
}
|
|
1714
1923
|
};
|
|
1715
1924
|
var getSyncClientOutputTypeDetailsFromFile = (filePath) => {
|
|
1716
1925
|
const DEFAULT = "{ }";
|
|
1926
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientOutput", error: null });
|
|
1717
1927
|
try {
|
|
1718
1928
|
const program = getServerProgram();
|
|
1719
1929
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -1724,7 +1934,9 @@ var getSyncClientOutputTypeDetailsFromFile = (filePath) => {
|
|
|
1724
1934
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
1725
1935
|
return { text: details.text || DEFAULT, unresolvedSymbols: details.unresolvedSymbols };
|
|
1726
1936
|
} catch (error) {
|
|
1937
|
+
if (error instanceof UnsupportedWireTypeError) throw error;
|
|
1727
1938
|
console.error(`[TypeMapGenerator] Error extracting sync clientOutput type from ${filePath}:`, error);
|
|
1939
|
+
recordExtractionOutcome({ filePath, kind: "sync", field: "clientOutput", error });
|
|
1728
1940
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
1729
1941
|
}
|
|
1730
1942
|
};
|
|
@@ -1855,6 +2067,14 @@ var simplifyInferredType = (value) => {
|
|
|
1855
2067
|
return value;
|
|
1856
2068
|
};
|
|
1857
2069
|
var getGeneratedFileDir = () => path7.dirname(getGeneratedSocketTypesPath5());
|
|
2070
|
+
var sourceModuleSpecifier = (sourceFilePath) => {
|
|
2071
|
+
const relative = path7.relative(getGeneratedFileDir(), sourceFilePath).replaceAll("\\", "/").replace(/\.tsx?$/i, "");
|
|
2072
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
2073
|
+
};
|
|
2074
|
+
var portableInferredValueType = (inferred, sourceFilePath, exportName) => {
|
|
2075
|
+
if (!inferred.includes("typeof import(") && !inferred.includes("...")) return null;
|
|
2076
|
+
return `typeof import('${sourceModuleSpecifier(sourceFilePath)}')['${exportName}']`;
|
|
2077
|
+
};
|
|
1858
2078
|
var relativizeModuleSpecifier = (specifier, sourceFilePath) => {
|
|
1859
2079
|
if (!specifier.startsWith("./") && !specifier.startsWith("../")) {
|
|
1860
2080
|
return specifier;
|
|
@@ -1949,6 +2169,8 @@ var inferValueTypeForExport = ({
|
|
|
1949
2169
|
const programDeclaration = findProgramVariableDeclaration(resolvedSource, exportName);
|
|
1950
2170
|
if (!programDeclaration) return "any";
|
|
1951
2171
|
const inferred = resolvedChecker.typeToString(resolvedChecker.getTypeAtLocation(programDeclaration.name));
|
|
2172
|
+
const portable = portableInferredValueType(inferred, filePath, exportName);
|
|
2173
|
+
if (portable) return portable;
|
|
1952
2174
|
const simplified = simplifyInferredType(normalizeInlineType(inferred));
|
|
1953
2175
|
const localResolvedType = resolveLocalExportedTypes({
|
|
1954
2176
|
type: simplified,
|