@luckystack/devkit 0.10.1 → 0.11.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/AGENTS.md +9 -0
- package/CHANGELOG.md +14 -1
- package/README.md +2 -37
- package/dist/cli/validateDeploy.d.ts +2 -0
- package/dist/functionRegistry.d.ts +72 -0
- package/dist/hotReload.d.ts +1 -0
- package/dist/importDependencyGraph.d.ts +2 -0
- package/dist/index.d.ts +15 -280
- package/dist/index.js +633 -435
- package/dist/index.js.map +1 -1
- package/dist/internal/mapUtils.d.ts +2 -0
- package/dist/loader.d.ts +11 -0
- package/dist/prismaClientCheck.d.ts +19 -0
- package/dist/routeConventions.d.ts +20 -0
- package/dist/routeNamingValidation.d.ts +46 -0
- package/dist/routingRules.d.ts +62 -0
- package/dist/runtimeTypeResolver.d.ts +15 -0
- package/dist/supervisor.d.ts +25 -0
- package/dist/templateInjector.d.ts +60 -0
- package/dist/templateRegistry.d.ts +78 -0
- package/dist/typeMap/apiMeta.d.ts +42 -0
- package/dist/typeMap/discovery.d.ts +3 -0
- package/dist/typeMap/emitterArtifacts.d.ts +94 -0
- package/dist/typeMap/extractionDiagnostics.d.ts +16 -0
- package/dist/typeMap/extractors.d.ts +18 -0
- package/dist/typeMap/functionsMeta.d.ts +5 -0
- package/dist/typeMap/routeMeta.d.ts +6 -0
- package/dist/typeMap/tsApi.d.ts +12 -0
- package/dist/typeMap/tsProgram.d.ts +41 -0
- package/dist/typeMap/typeContext.d.ts +21 -0
- package/dist/typeMap/zodEmitter.d.ts +8 -0
- package/dist/typeMapGenerator.d.ts +5 -0
- package/dist/validateDeploy.d.ts +25 -0
- package/docs/cli.md +3 -243
- package/docs/hot-reload.md +4 -362
- package/docs/loader-pipeline.md +3 -322
- package/docs/runtime-type-resolver.md +3 -256
- package/docs/supervisor.md +3 -290
- package/docs/template-customization.md +2 -133
- package/docs/ts-program-cache.md +4 -197
- package/docs/type-map-generation.md +5 -410
- package/package.json +5 -5
- package/CLAUDE.md +0 -135
package/dist/index.js
CHANGED
|
@@ -567,34 +567,98 @@ var extractSyncVersion = (filePath) => {
|
|
|
567
567
|
};
|
|
568
568
|
|
|
569
569
|
// src/typeMap/apiMeta.ts
|
|
570
|
-
import
|
|
571
|
-
import
|
|
570
|
+
import fs4 from "fs";
|
|
571
|
+
import {
|
|
572
|
+
getJSDocTags,
|
|
573
|
+
SyntaxKind
|
|
574
|
+
} from "typescript-7-api/ast";
|
|
575
|
+
import {
|
|
576
|
+
isArrayLiteralExpression,
|
|
577
|
+
isAsExpression,
|
|
578
|
+
isIdentifier,
|
|
579
|
+
isNumericLiteral,
|
|
580
|
+
isObjectLiteralExpression,
|
|
581
|
+
isParenthesizedExpression,
|
|
582
|
+
isPropertyAssignment,
|
|
583
|
+
isSatisfiesExpression,
|
|
584
|
+
isStringLiteral,
|
|
585
|
+
isVariableStatement
|
|
586
|
+
} from "typescript-7-api/ast/is";
|
|
572
587
|
import { inferHttpMethod, tryCatchSync } from "@luckystack/core";
|
|
588
|
+
|
|
589
|
+
// src/typeMap/tsApi.ts
|
|
590
|
+
import fs3 from "fs";
|
|
591
|
+
import path4 from "path";
|
|
592
|
+
import { API } from "typescript-7-api/sync";
|
|
593
|
+
import { ROOT_DIR as ROOT_DIR3 } from "@luckystack/core";
|
|
594
|
+
var api = null;
|
|
595
|
+
var serverSnapshot = null;
|
|
596
|
+
var serverProject = null;
|
|
597
|
+
var getTsApi = () => {
|
|
598
|
+
api ??= new API({ cwd: ROOT_DIR3 });
|
|
599
|
+
return api;
|
|
600
|
+
};
|
|
601
|
+
var openTsconfigProject = (tsconfigPath) => {
|
|
602
|
+
const tsApi = getTsApi();
|
|
603
|
+
const { fileNames, options } = tsApi.parseConfigFile(tsconfigPath);
|
|
604
|
+
const snapshot = tsApi.createSnapshot({ createPrograms: [{ rootFiles: fileNames, compilerOptions: options }] });
|
|
605
|
+
const [program] = snapshot.operation.createdPrograms;
|
|
606
|
+
return { project: program.getProject(), snapshot };
|
|
607
|
+
};
|
|
608
|
+
var getServerProgram = () => {
|
|
609
|
+
if (serverProject) return serverProject;
|
|
610
|
+
const tsconfigPath = path4.join(ROOT_DIR3, "tsconfig.server.json");
|
|
611
|
+
if (!fs3.existsSync(tsconfigPath)) throw new Error("[TypeProgram] tsconfig.server.json not found");
|
|
612
|
+
const { project, snapshot } = openTsconfigProject(tsconfigPath);
|
|
613
|
+
serverSnapshot = snapshot;
|
|
614
|
+
serverProject = project;
|
|
615
|
+
return project;
|
|
616
|
+
};
|
|
617
|
+
var invalidateProgramCache = () => {
|
|
618
|
+
serverSnapshot?.dispose();
|
|
619
|
+
serverSnapshot = null;
|
|
620
|
+
serverProject = null;
|
|
621
|
+
};
|
|
622
|
+
var disposeTsApi = () => {
|
|
623
|
+
invalidateProgramCache();
|
|
624
|
+
api?.close();
|
|
625
|
+
api = null;
|
|
626
|
+
};
|
|
627
|
+
var parseSourceText = (fileName, text, scriptKind) => {
|
|
628
|
+
const retained = getTsApi().createSourceFile(fileName, text, scriptKind === void 0 ? void 0 : { scriptKind });
|
|
629
|
+
retained.dispose();
|
|
630
|
+
return retained.sourceFile;
|
|
631
|
+
};
|
|
632
|
+
var transpileSourceText = (fileName, text) => {
|
|
633
|
+
return getTsApi().transpileModule(text, { fileName, reportDiagnostics: true });
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// src/typeMap/apiMeta.ts
|
|
573
637
|
var findExportedConst = (sourceFile, name) => {
|
|
574
638
|
for (const statement of sourceFile.statements) {
|
|
575
|
-
if (!
|
|
576
|
-
const hasExport = statement.modifiers?.some((m) => m.kind ===
|
|
639
|
+
if (!isVariableStatement(statement)) continue;
|
|
640
|
+
const hasExport = statement.modifiers?.some((m) => m.kind === SyntaxKind.ExportKeyword);
|
|
577
641
|
if (!hasExport) continue;
|
|
578
642
|
for (const decl of statement.declarationList.declarations) {
|
|
579
|
-
if (
|
|
643
|
+
if (isIdentifier(decl.name) && decl.name.text === name) return decl;
|
|
580
644
|
}
|
|
581
645
|
}
|
|
582
646
|
return null;
|
|
583
647
|
};
|
|
584
648
|
var unwrapExpression = (node) => {
|
|
585
649
|
let current = node;
|
|
586
|
-
while (
|
|
650
|
+
while (isAsExpression(current) || isSatisfiesExpression(current) || isParenthesizedExpression(current)) {
|
|
587
651
|
current = current.expression;
|
|
588
652
|
}
|
|
589
653
|
return current;
|
|
590
654
|
};
|
|
591
655
|
var extractHttpMethod = (filePath, apiName) => {
|
|
592
656
|
const [error, method] = tryCatchSync(() => {
|
|
593
|
-
const content =
|
|
594
|
-
const sourceFile =
|
|
657
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
658
|
+
const sourceFile = parseSourceText(filePath, content);
|
|
595
659
|
const decl = findExportedConst(sourceFile, "httpMethod");
|
|
596
660
|
const initializer = decl?.initializer ? unwrapExpression(decl.initializer) : void 0;
|
|
597
|
-
if (initializer &&
|
|
661
|
+
if (initializer && isStringLiteral(initializer)) {
|
|
598
662
|
const candidate = initializer.text.toUpperCase();
|
|
599
663
|
if (["GET", "POST", "PUT", "DELETE"].includes(candidate)) return candidate;
|
|
600
664
|
}
|
|
@@ -607,13 +671,13 @@ var extractHttpMethod = (filePath, apiName) => {
|
|
|
607
671
|
};
|
|
608
672
|
var extractRateLimit = (filePath) => {
|
|
609
673
|
const [error, rateLimit] = tryCatchSync(() => {
|
|
610
|
-
const content =
|
|
611
|
-
const sourceFile =
|
|
674
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
675
|
+
const sourceFile = parseSourceText(filePath, content);
|
|
612
676
|
const decl = findExportedConst(sourceFile, "rateLimit");
|
|
613
677
|
if (decl?.initializer) {
|
|
614
678
|
const initializer = unwrapExpression(decl.initializer);
|
|
615
|
-
if (initializer.kind ===
|
|
616
|
-
if (
|
|
679
|
+
if (initializer.kind === SyntaxKind.FalseKeyword) return false;
|
|
680
|
+
if (isNumericLiteral(initializer)) return Number(initializer.text);
|
|
617
681
|
}
|
|
618
682
|
return void 0;
|
|
619
683
|
});
|
|
@@ -624,16 +688,16 @@ var extractRateLimit = (filePath) => {
|
|
|
624
688
|
};
|
|
625
689
|
var readPrimitive = (rawNode) => {
|
|
626
690
|
const node = unwrapExpression(rawNode);
|
|
627
|
-
if (
|
|
628
|
-
if (
|
|
629
|
-
if (node.kind ===
|
|
630
|
-
if (node.kind ===
|
|
691
|
+
if (isStringLiteral(node)) return node.text;
|
|
692
|
+
if (isNumericLiteral(node)) return Number(node.text);
|
|
693
|
+
if (node.kind === SyntaxKind.TrueKeyword) return true;
|
|
694
|
+
if (node.kind === SyntaxKind.FalseKeyword) return false;
|
|
631
695
|
return void 0;
|
|
632
696
|
};
|
|
633
697
|
var parseAdditionalItem = (objectLiteral) => {
|
|
634
698
|
const item = {};
|
|
635
699
|
for (const prop of objectLiteral.properties) {
|
|
636
|
-
if (!
|
|
700
|
+
if (!isPropertyAssignment(prop) || !isIdentifier(prop.name)) continue;
|
|
637
701
|
const value = readPrimitive(prop.initializer);
|
|
638
702
|
if (value !== void 0) item[prop.name.text] = value;
|
|
639
703
|
}
|
|
@@ -653,8 +717,8 @@ var commentToString = (commentValue) => {
|
|
|
653
717
|
};
|
|
654
718
|
var extractDocsMeta = (filePath) => {
|
|
655
719
|
const [error, docsMeta] = tryCatchSync(() => {
|
|
656
|
-
const content =
|
|
657
|
-
const sourceFile =
|
|
720
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
721
|
+
const sourceFile = parseSourceText(filePath, content);
|
|
658
722
|
const result = {};
|
|
659
723
|
const consumeTag = (tag) => {
|
|
660
724
|
if (tag.tagName.text !== "docs") return;
|
|
@@ -673,7 +737,7 @@ var extractDocsMeta = (filePath) => {
|
|
|
673
737
|
}
|
|
674
738
|
};
|
|
675
739
|
for (const statement of sourceFile.statements) {
|
|
676
|
-
for (const tag of
|
|
740
|
+
for (const tag of getJSDocTags(statement)) {
|
|
677
741
|
consumeTag(tag);
|
|
678
742
|
}
|
|
679
743
|
}
|
|
@@ -690,25 +754,25 @@ var extractDocsMeta = (filePath) => {
|
|
|
690
754
|
};
|
|
691
755
|
var extractAuth = (filePath) => {
|
|
692
756
|
const [, auth] = tryCatchSync(() => {
|
|
693
|
-
const content =
|
|
694
|
-
const sourceFile =
|
|
757
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
758
|
+
const sourceFile = parseSourceText(filePath, content);
|
|
695
759
|
const decl = findExportedConst(sourceFile, "auth");
|
|
696
760
|
const authInitializer = decl?.initializer ? unwrapExpression(decl.initializer) : void 0;
|
|
697
|
-
if (!authInitializer || !
|
|
761
|
+
if (!authInitializer || !isObjectLiteralExpression(authInitializer)) return { login: false, hasAdditional: false };
|
|
698
762
|
let login = false;
|
|
699
763
|
let additional;
|
|
700
764
|
let hasAdditional = false;
|
|
701
765
|
for (const prop of authInitializer.properties) {
|
|
702
|
-
if (!
|
|
766
|
+
if (!isPropertyAssignment(prop) || !isIdentifier(prop.name)) continue;
|
|
703
767
|
const propInit = unwrapExpression(prop.initializer);
|
|
704
768
|
if (prop.name.text === "login") {
|
|
705
|
-
login = propInit.kind ===
|
|
769
|
+
login = propInit.kind === SyntaxKind.TrueKeyword;
|
|
706
770
|
}
|
|
707
|
-
if (prop.name.text === "additional" &&
|
|
771
|
+
if (prop.name.text === "additional" && isArrayLiteralExpression(propInit)) {
|
|
708
772
|
hasAdditional = propInit.elements.length > 0;
|
|
709
773
|
additional = [];
|
|
710
774
|
for (const element of propInit.elements) {
|
|
711
|
-
if (!
|
|
775
|
+
if (!isObjectLiteralExpression(element)) continue;
|
|
712
776
|
const item = parseAdditionalItem(element);
|
|
713
777
|
if (item) additional.push(item);
|
|
714
778
|
}
|
|
@@ -720,46 +784,78 @@ var extractAuth = (filePath) => {
|
|
|
720
784
|
};
|
|
721
785
|
|
|
722
786
|
// src/typeMap/emitterArtifacts.ts
|
|
723
|
-
import
|
|
724
|
-
import
|
|
725
|
-
import
|
|
787
|
+
import fs5 from "fs";
|
|
788
|
+
import path5 from "path";
|
|
789
|
+
import {
|
|
790
|
+
ScriptKind
|
|
791
|
+
} from "typescript-7-api/ast";
|
|
792
|
+
import {
|
|
793
|
+
isClassDeclaration,
|
|
794
|
+
isEnumDeclaration,
|
|
795
|
+
isFunctionDeclaration,
|
|
796
|
+
isIdentifier as isIdentifier3,
|
|
797
|
+
isImportDeclaration,
|
|
798
|
+
isInferTypeNode,
|
|
799
|
+
isInterfaceDeclaration,
|
|
800
|
+
isMappedTypeNode,
|
|
801
|
+
isNamedImports,
|
|
802
|
+
isNamespaceImport,
|
|
803
|
+
isQualifiedName,
|
|
804
|
+
isTypeAliasDeclaration as isTypeAliasDeclaration2,
|
|
805
|
+
isTypeReferenceNode as isTypeReferenceNode2
|
|
806
|
+
} from "typescript-7-api/ast/is";
|
|
726
807
|
import { getGeneratedApiDocsPath, getGeneratedApiSchemasPath, getGeneratedSocketTypesPath } from "@luckystack/core";
|
|
727
808
|
|
|
728
809
|
// src/typeMap/zodEmitter.ts
|
|
729
|
-
import
|
|
810
|
+
import { SyntaxKind as SyntaxKind2 } from "typescript-7-api/ast";
|
|
811
|
+
import {
|
|
812
|
+
isArrayTypeNode,
|
|
813
|
+
isIdentifier as isIdentifier2,
|
|
814
|
+
isIndexSignatureDeclaration,
|
|
815
|
+
isIntersectionTypeNode,
|
|
816
|
+
isLiteralTypeNode,
|
|
817
|
+
isNumericLiteral as isNumericLiteral2,
|
|
818
|
+
isParenthesizedTypeNode,
|
|
819
|
+
isPropertySignatureDeclaration,
|
|
820
|
+
isStringLiteral as isStringLiteral2,
|
|
821
|
+
isTypeAliasDeclaration,
|
|
822
|
+
isTypeLiteralNode,
|
|
823
|
+
isTypeReferenceNode,
|
|
824
|
+
isUnionTypeNode
|
|
825
|
+
} from "typescript-7-api/ast/is";
|
|
730
826
|
var wrapOptional = (inner) => `${inner}.optional()`;
|
|
731
827
|
var anyFallback = (reason) => `z.any() /* ${reason} */`;
|
|
732
828
|
var convertTypeNode = (node) => {
|
|
733
|
-
if (node.kind ===
|
|
734
|
-
if (node.kind ===
|
|
735
|
-
if (node.kind ===
|
|
736
|
-
if (node.kind ===
|
|
737
|
-
if (node.kind ===
|
|
738
|
-
if (node.kind ===
|
|
739
|
-
if (node.kind ===
|
|
740
|
-
if (node.kind ===
|
|
741
|
-
if (
|
|
829
|
+
if (node.kind === SyntaxKind2.StringKeyword) return "z.string()";
|
|
830
|
+
if (node.kind === SyntaxKind2.NumberKeyword) return "z.number()";
|
|
831
|
+
if (node.kind === SyntaxKind2.BooleanKeyword) return "z.boolean()";
|
|
832
|
+
if (node.kind === SyntaxKind2.NullKeyword) return "z.null()";
|
|
833
|
+
if (node.kind === SyntaxKind2.UndefinedKeyword) return "z.undefined()";
|
|
834
|
+
if (node.kind === SyntaxKind2.AnyKeyword) return "z.any()";
|
|
835
|
+
if (node.kind === SyntaxKind2.UnknownKeyword) return "z.unknown()";
|
|
836
|
+
if (node.kind === SyntaxKind2.NeverKeyword) return "z.never()";
|
|
837
|
+
if (isLiteralTypeNode(node)) {
|
|
742
838
|
const literal = node.literal;
|
|
743
|
-
if (
|
|
744
|
-
if (
|
|
745
|
-
if (literal.kind ===
|
|
746
|
-
if (literal.kind ===
|
|
747
|
-
if (literal.kind ===
|
|
839
|
+
if (isStringLiteral2(literal)) return `z.literal(${JSON.stringify(literal.text)})`;
|
|
840
|
+
if (isNumericLiteral2(literal)) return `z.literal(${literal.text})`;
|
|
841
|
+
if (literal.kind === SyntaxKind2.TrueKeyword) return "z.literal(true)";
|
|
842
|
+
if (literal.kind === SyntaxKind2.FalseKeyword) return "z.literal(false)";
|
|
843
|
+
if (literal.kind === SyntaxKind2.NullKeyword) return "z.null()";
|
|
748
844
|
return anyFallback("unknown literal");
|
|
749
845
|
}
|
|
750
|
-
if (
|
|
846
|
+
if (isArrayTypeNode(node)) {
|
|
751
847
|
return `z.array(${convertTypeNode(node.elementType)})`;
|
|
752
848
|
}
|
|
753
|
-
if (
|
|
849
|
+
if (isUnionTypeNode(node)) {
|
|
754
850
|
const members = node.types;
|
|
755
|
-
const hasUndefined = members.some((m) => m.kind ===
|
|
756
|
-
const nonUndef = members.filter((m) => m.kind !==
|
|
851
|
+
const hasUndefined = members.some((m) => m.kind === SyntaxKind2.UndefinedKeyword);
|
|
852
|
+
const nonUndef = members.filter((m) => m.kind !== SyntaxKind2.UndefinedKeyword);
|
|
757
853
|
if (nonUndef.length === 0) return "z.undefined()";
|
|
758
854
|
const firstNonUndef = nonUndef[0];
|
|
759
855
|
const innerSchema = nonUndef.length === 1 && firstNonUndef ? convertTypeNode(firstNonUndef) : `z.union([${nonUndef.map((m) => convertTypeNode(m)).join(", ")}])`;
|
|
760
856
|
return hasUndefined ? wrapOptional(innerSchema) : innerSchema;
|
|
761
857
|
}
|
|
762
|
-
if (
|
|
858
|
+
if (isTypeReferenceNode(node)) {
|
|
763
859
|
const name = node.typeName.getText();
|
|
764
860
|
const args = node.typeArguments ?? [];
|
|
765
861
|
switch (name) {
|
|
@@ -787,10 +883,10 @@ var convertTypeNode = (node) => {
|
|
|
787
883
|
}
|
|
788
884
|
}
|
|
789
885
|
}
|
|
790
|
-
if (
|
|
791
|
-
const indexSignatures = node.members.filter((m) =>
|
|
792
|
-
const propertySignatures = node.members.filter((m) =>
|
|
793
|
-
if (indexSignatures.length === 1 && propertySignatures.length === 0 && indexSignatures[0]?.type.kind ===
|
|
886
|
+
if (isTypeLiteralNode(node)) {
|
|
887
|
+
const indexSignatures = node.members.filter((m) => isIndexSignatureDeclaration(m));
|
|
888
|
+
const propertySignatures = node.members.filter((m) => isPropertySignatureDeclaration(m));
|
|
889
|
+
if (indexSignatures.length === 1 && propertySignatures.length === 0 && indexSignatures[0]?.type.kind === SyntaxKind2.NeverKeyword) {
|
|
794
890
|
return "z.object({}).strict()";
|
|
795
891
|
}
|
|
796
892
|
if (indexSignatures.length > 0 && propertySignatures.length === 0) {
|
|
@@ -802,21 +898,21 @@ var convertTypeNode = (node) => {
|
|
|
802
898
|
}
|
|
803
899
|
}
|
|
804
900
|
const entries = propertySignatures.map((prop) => {
|
|
805
|
-
if (!
|
|
901
|
+
if (!isIdentifier2(prop.name)) return null;
|
|
806
902
|
if (!prop.type) return null;
|
|
807
903
|
const name = prop.name.text;
|
|
808
904
|
let schema = convertTypeNode(prop.type);
|
|
809
|
-
if (prop.
|
|
905
|
+
if (prop.postfixToken?.kind === SyntaxKind2.QuestionToken && !schema.endsWith(".optional()")) {
|
|
810
906
|
schema = wrapOptional(schema);
|
|
811
907
|
}
|
|
812
908
|
return `${JSON.stringify(name)}: ${schema}`;
|
|
813
909
|
}).filter((entry) => entry !== null);
|
|
814
910
|
return `z.object({ ${entries.join(", ")} }).strict()`;
|
|
815
911
|
}
|
|
816
|
-
if (
|
|
912
|
+
if (isParenthesizedTypeNode(node)) {
|
|
817
913
|
return convertTypeNode(node.type);
|
|
818
914
|
}
|
|
819
|
-
if (
|
|
915
|
+
if (isIntersectionTypeNode(node)) {
|
|
820
916
|
return anyFallback("intersection not yet supported");
|
|
821
917
|
}
|
|
822
918
|
return anyFallback(`unsupported TypeNode kind=${String(node.kind)}`);
|
|
@@ -825,9 +921,9 @@ var typeTextToZodSource = (typeText) => {
|
|
|
825
921
|
const trimmed = typeText.trim();
|
|
826
922
|
if (!trimmed) return null;
|
|
827
923
|
const synthetic = `type __X = ${trimmed};`;
|
|
828
|
-
const source =
|
|
924
|
+
const source = parseSourceText("__zod.ts", synthetic);
|
|
829
925
|
const statement = source.statements[0];
|
|
830
|
-
if (!statement || !
|
|
926
|
+
if (!statement || !isTypeAliasDeclaration(statement)) return null;
|
|
831
927
|
return convertTypeNode(statement.type);
|
|
832
928
|
};
|
|
833
929
|
|
|
@@ -867,6 +963,75 @@ var findExtractionFailure = (route, kind, field) => {
|
|
|
867
963
|
};
|
|
868
964
|
|
|
869
965
|
// src/typeMap/emitterArtifacts.ts
|
|
966
|
+
var compareVersions = (a, b) => a.version.localeCompare(b.version, void 0, { numeric: true });
|
|
967
|
+
var renderRouteMetaFields = (authValue, rateLimit) => {
|
|
968
|
+
const auth = authValue && typeof authValue === "object" ? authValue : { login: false, hasAdditional: false };
|
|
969
|
+
const rateLimitPart = rateLimit === void 0 ? "" : `, rateLimit: ${rateLimit === false ? "false" : String(rateLimit)}`;
|
|
970
|
+
const additionalPart = auth.additional && auth.additional.length > 0 ? `, additional: ${JSON.stringify(auth.additional)}` : "";
|
|
971
|
+
return `auth: { login: ${auth.login ? "true" : "false"}${additionalPart}${auth.hasAdditional ? ", hasAdditional: true" : ""} }${rateLimitPart}`;
|
|
972
|
+
};
|
|
973
|
+
var inputSchemaSource = (typeText) => typeTextToZodSource(typeText) ?? "z.any() /* unparseable input type */";
|
|
974
|
+
var groupServerSyncRoutes = (syncTypesByPage) => {
|
|
975
|
+
const pages = [];
|
|
976
|
+
for (const pagePath of [...syncTypesByPage.keys()].toSorted()) {
|
|
977
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
978
|
+
for (const [syncKey, entry] of mustGet(syncTypesByPage, pagePath, "syncTypesByPage")) {
|
|
979
|
+
if (!entry.serverMeta) continue;
|
|
980
|
+
const { name, version } = splitVersionedKey(syncKey);
|
|
981
|
+
getOrInit(grouped, name, () => []).push({ version, clientInput: entry.clientInput, serverMeta: entry.serverMeta });
|
|
982
|
+
}
|
|
983
|
+
if (grouped.size === 0) continue;
|
|
984
|
+
pages.push([
|
|
985
|
+
pagePath,
|
|
986
|
+
[...grouped.keys()].toSorted().map((name) => [name, mustGet(grouped, name, "grouped").toSorted(compareVersions)])
|
|
987
|
+
]);
|
|
988
|
+
}
|
|
989
|
+
return pages;
|
|
990
|
+
};
|
|
991
|
+
var renderServerSyncRouteMap = (syncTypesByPage, renderValue) => {
|
|
992
|
+
let body = "";
|
|
993
|
+
for (const [pagePath, syncs] of groupServerSyncRoutes(syncTypesByPage)) {
|
|
994
|
+
body += ` '${pagePath}': {
|
|
995
|
+
`;
|
|
996
|
+
for (const [syncName, routes] of syncs) {
|
|
997
|
+
body += ` '${syncName}': {
|
|
998
|
+
`;
|
|
999
|
+
for (const route of routes) {
|
|
1000
|
+
body += ` '${route.version}': ${renderValue(route)},
|
|
1001
|
+
`;
|
|
1002
|
+
}
|
|
1003
|
+
body += ` },
|
|
1004
|
+
`;
|
|
1005
|
+
}
|
|
1006
|
+
body += ` },
|
|
1007
|
+
`;
|
|
1008
|
+
}
|
|
1009
|
+
return body;
|
|
1010
|
+
};
|
|
1011
|
+
var buildSyncMetaMapSource = (syncTypesByPage) => `export interface SyncMetaEntry {
|
|
1012
|
+
auth: { login: boolean; additional?: Record<string, unknown>[]; hasAdditional?: boolean };
|
|
1013
|
+
rateLimit?: number | false;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
export const syncMetaMap: Record<string, Record<string, Record<string, SyncMetaEntry>>> = {
|
|
1017
|
+
${renderServerSyncRouteMap(syncTypesByPage, (route) => `{ ${renderRouteMetaFields(route.serverMeta.auth, route.serverMeta.rateLimit)} }`)}};
|
|
1018
|
+
|
|
1019
|
+
export const getSyncMeta = (pagePath: string, syncName: string, version: string): SyncMetaEntry | undefined => {
|
|
1020
|
+
return syncMetaMap[pagePath]?.[syncName]?.[version];
|
|
1021
|
+
};
|
|
1022
|
+
`;
|
|
1023
|
+
var buildSyncInputSchemasSource = (syncTypesByPage) => `
|
|
1024
|
+
export const syncInputSchemas: Record<string, Record<string, Record<string, z.ZodTypeAny>>> = {
|
|
1025
|
+
${renderServerSyncRouteMap(syncTypesByPage, (route) => inputSchemaSource(route.clientInput))}};
|
|
1026
|
+
|
|
1027
|
+
export const getSyncInputSchema = (
|
|
1028
|
+
pagePath: string,
|
|
1029
|
+
syncName: string,
|
|
1030
|
+
version: string,
|
|
1031
|
+
): z.ZodTypeAny | undefined => {
|
|
1032
|
+
return syncInputSchemas[pagePath]?.[syncName]?.[version];
|
|
1033
|
+
};
|
|
1034
|
+
`;
|
|
870
1035
|
var buildImportStatements = ({
|
|
871
1036
|
namedImports,
|
|
872
1037
|
defaultImports
|
|
@@ -887,13 +1052,13 @@ var splitVersionedKey = (value) => {
|
|
|
887
1052
|
return { name: name ?? "", version: version ?? "v1" };
|
|
888
1053
|
};
|
|
889
1054
|
var writeFileIfChanged = (filePath, content) => {
|
|
890
|
-
if (
|
|
891
|
-
const currentContent =
|
|
1055
|
+
if (fs5.existsSync(filePath)) {
|
|
1056
|
+
const currentContent = fs5.readFileSync(filePath, "utf8");
|
|
892
1057
|
if (currentContent === content) {
|
|
893
1058
|
return false;
|
|
894
1059
|
}
|
|
895
1060
|
}
|
|
896
|
-
|
|
1061
|
+
fs5.writeFileSync(filePath, content, "utf8");
|
|
897
1062
|
return true;
|
|
898
1063
|
};
|
|
899
1064
|
var indentStr = (str, indentText) => {
|
|
@@ -932,7 +1097,7 @@ var stripSymbolKeyedMembers = (text) => {
|
|
|
932
1097
|
return result;
|
|
933
1098
|
};
|
|
934
1099
|
var validateGeneratedTypeIdentifiers = (content) => {
|
|
935
|
-
const sourceFile =
|
|
1100
|
+
const sourceFile = parseSourceText("apiTypes.generated.ts", content, ScriptKind.TS);
|
|
936
1101
|
const knownSymbols = /* @__PURE__ */ new Set();
|
|
937
1102
|
const referencedSymbols = /* @__PURE__ */ new Set();
|
|
938
1103
|
const builtIns = /* @__PURE__ */ new Set([
|
|
@@ -989,38 +1154,38 @@ var validateGeneratedTypeIdentifiers = (content) => {
|
|
|
989
1154
|
}
|
|
990
1155
|
};
|
|
991
1156
|
const collectKnownSymbols = (node) => {
|
|
992
|
-
if (
|
|
1157
|
+
if (isInferTypeNode(node)) {
|
|
993
1158
|
knownSymbols.add(node.typeParameter.name.text);
|
|
994
1159
|
}
|
|
995
|
-
if (
|
|
1160
|
+
if (isMappedTypeNode(node)) {
|
|
996
1161
|
knownSymbols.add(node.typeParameter.name.text);
|
|
997
1162
|
}
|
|
998
|
-
if (
|
|
1163
|
+
if (isImportDeclaration(node)) {
|
|
999
1164
|
const importClause = node.importClause;
|
|
1000
1165
|
if (importClause?.name) knownSymbols.add(importClause.name.text);
|
|
1001
|
-
if (importClause?.namedBindings &&
|
|
1166
|
+
if (importClause?.namedBindings && isNamedImports(importClause.namedBindings)) {
|
|
1002
1167
|
for (const importElement of importClause.namedBindings.elements) {
|
|
1003
1168
|
knownSymbols.add((importElement.propertyName ?? importElement.name).text);
|
|
1004
1169
|
}
|
|
1005
1170
|
}
|
|
1006
|
-
if (importClause?.namedBindings &&
|
|
1171
|
+
if (importClause?.namedBindings && isNamespaceImport(importClause.namedBindings)) {
|
|
1007
1172
|
knownSymbols.add(importClause.namedBindings.name.text);
|
|
1008
1173
|
}
|
|
1009
1174
|
}
|
|
1010
|
-
if (
|
|
1175
|
+
if (isInterfaceDeclaration(node) || isTypeAliasDeclaration2(node) || isClassDeclaration(node) || isEnumDeclaration(node) || isFunctionDeclaration(node)) {
|
|
1011
1176
|
addDeclaredName(node.name);
|
|
1012
1177
|
collectTypeParams(node);
|
|
1013
1178
|
}
|
|
1014
|
-
if (
|
|
1179
|
+
if (isTypeReferenceNode2(node)) {
|
|
1015
1180
|
const typeName = node.typeName;
|
|
1016
|
-
if (
|
|
1181
|
+
if (isIdentifier3(typeName)) {
|
|
1017
1182
|
referencedSymbols.add(typeName.text);
|
|
1018
1183
|
}
|
|
1019
|
-
if (
|
|
1184
|
+
if (isQualifiedName(typeName) && isIdentifier3(typeName.left)) {
|
|
1020
1185
|
referencedSymbols.add(typeName.left.text);
|
|
1021
1186
|
}
|
|
1022
1187
|
}
|
|
1023
|
-
|
|
1188
|
+
node.forEachChild(collectKnownSymbols);
|
|
1024
1189
|
};
|
|
1025
1190
|
collectKnownSymbols(sourceFile);
|
|
1026
1191
|
const unknown = [...referencedSymbols].filter((name) => !knownSymbols.has(name) && !builtIns.has(name)).toSorted();
|
|
@@ -1060,7 +1225,7 @@ var collectFallbacks = (typesByPage, syncTypesByPage) => {
|
|
|
1060
1225
|
for (const [syncKey, entry] of syncs) {
|
|
1061
1226
|
const { name, version } = splitVersionedKey(syncKey);
|
|
1062
1227
|
const route = `${pagePath}/${name}@${version}`;
|
|
1063
|
-
flagField(route, "sync", "clientInput", entry.clientInput);
|
|
1228
|
+
flagField(route, "sync", "clientInput", entry.clientInput, entry.serverMeta !== void 0);
|
|
1064
1229
|
flagField(route, "sync", "serverOutput", entry.serverOutput, false, !entry.hasServer);
|
|
1065
1230
|
flagField(route, "sync", "clientOutput", entry.clientOutput, false, !entry.hasClient);
|
|
1066
1231
|
flagField(route, "sync", "serverStream", entry.serverStream);
|
|
@@ -1254,10 +1419,7 @@ export const apiMetaMap: Record<string, Record<string, Record<string, ApiMetaEnt
|
|
|
1254
1419
|
content += ` '${apiName}': {
|
|
1255
1420
|
`;
|
|
1256
1421
|
for (const { version, entry } of mustGet(grouped, apiName, "grouped").toSorted((a, b) => a.version.localeCompare(b.version, void 0, { numeric: true }))) {
|
|
1257
|
-
|
|
1258
|
-
const rateLimitPart = entry.rateLimit === void 0 ? "" : `, rateLimit: ${entry.rateLimit === false ? "false" : String(entry.rateLimit)}`;
|
|
1259
|
-
const additionalPart = auth.additional && auth.additional.length > 0 ? `, additional: ${JSON.stringify(auth.additional)}` : "";
|
|
1260
|
-
content += ` '${version}': { method: '${entry.method}', auth: { login: ${auth.login ? "true" : "false"}${additionalPart}${auth.hasAdditional ? ", hasAdditional: true" : ""} }${rateLimitPart} },
|
|
1422
|
+
content += ` '${version}': { method: '${entry.method}', ${renderRouteMetaFields(entry.auth, entry.rateLimit)} },
|
|
1261
1423
|
`;
|
|
1262
1424
|
}
|
|
1263
1425
|
content += ` },
|
|
@@ -1272,6 +1434,7 @@ export const getApiMeta = (pagePath: string, apiName: string, version: string):
|
|
|
1272
1434
|
return apiMetaMap[pagePath]?.[apiName]?.[version];
|
|
1273
1435
|
};
|
|
1274
1436
|
|
|
1437
|
+
${buildSyncMetaMapSource(syncTypesByPage)}
|
|
1275
1438
|
// Sync Type Definitions
|
|
1276
1439
|
//
|
|
1277
1440
|
|
|
@@ -1371,7 +1534,7 @@ declare module '@luckystack/core/typemap' {
|
|
|
1371
1534
|
`;
|
|
1372
1535
|
content = stripSymbolKeyedMembers(content);
|
|
1373
1536
|
validateGeneratedTypeIdentifiers(content);
|
|
1374
|
-
const schemasContent = buildSchemasContent({ typesByPage });
|
|
1537
|
+
const schemasContent = buildSchemasContent({ typesByPage, syncTypesByPage });
|
|
1375
1538
|
const fallbacks = collectFallbacks(typesByPage, syncTypesByPage);
|
|
1376
1539
|
const totalRoutes = [...typesByPage.values()].reduce((n, m) => n + m.size, 0) + [...syncTypesByPage.values()].reduce((n, m) => n + m.size, 0);
|
|
1377
1540
|
const diagnosticsData = {
|
|
@@ -1383,11 +1546,13 @@ declare module '@luckystack/core/typemap' {
|
|
|
1383
1546
|
return { content, docsData, schemasContent, diagnosticsData };
|
|
1384
1547
|
};
|
|
1385
1548
|
var buildSchemasContent = ({
|
|
1386
|
-
typesByPage
|
|
1549
|
+
typesByPage,
|
|
1550
|
+
syncTypesByPage
|
|
1387
1551
|
}) => {
|
|
1388
1552
|
const sortedPages = [...typesByPage.keys()].toSorted();
|
|
1389
1553
|
let body = `/* eslint-disable */
|
|
1390
|
-
//? Auto-generated Zod schemas for every API input
|
|
1554
|
+
//? Auto-generated Zod schemas for every API input and every sync-server
|
|
1555
|
+
//? clientInput. Driven by the same walk
|
|
1391
1556
|
//? as apiTypes.generated.ts; see @luckystack/devkit/src/typeMap/zodEmitter.ts
|
|
1392
1557
|
//? for the TS-AST \xE2\u2020\u2019 Zod converter. Types that fall outside the converter's
|
|
1393
1558
|
//? scope emit \`z.any()\` with a TODO comment.
|
|
@@ -1412,8 +1577,7 @@ export const apiInputSchemas: Record<string, Record<string, Record<string, z.Zod
|
|
|
1412
1577
|
for (const { version, entry } of mustGet(grouped, apiName, "grouped").toSorted(
|
|
1413
1578
|
(a, b) => a.version.localeCompare(b.version, void 0, { numeric: true })
|
|
1414
1579
|
)) {
|
|
1415
|
-
|
|
1416
|
-
body += ` '${version}': ${schemaSrc},
|
|
1580
|
+
body += ` '${version}': ${inputSchemaSource(entry.input)},
|
|
1417
1581
|
`;
|
|
1418
1582
|
}
|
|
1419
1583
|
body += ` },
|
|
@@ -1432,6 +1596,7 @@ export const getApiInputSchema = (
|
|
|
1432
1596
|
return apiInputSchemas[pagePath]?.[apiName]?.[version];
|
|
1433
1597
|
};
|
|
1434
1598
|
`;
|
|
1599
|
+
body += buildSyncInputSchemasSource(syncTypesByPage);
|
|
1435
1600
|
return body;
|
|
1436
1601
|
};
|
|
1437
1602
|
var writeTypeMapArtifacts = ({
|
|
@@ -1453,9 +1618,9 @@ var writeTypeMapArtifacts = ({
|
|
|
1453
1618
|
}
|
|
1454
1619
|
}
|
|
1455
1620
|
const docsPath = getGeneratedApiDocsPath();
|
|
1456
|
-
const docsDir =
|
|
1457
|
-
if (!
|
|
1458
|
-
|
|
1621
|
+
const docsDir = path5.dirname(docsPath);
|
|
1622
|
+
if (!fs5.existsSync(docsDir)) {
|
|
1623
|
+
fs5.mkdirSync(docsDir, { recursive: true });
|
|
1459
1624
|
}
|
|
1460
1625
|
const docsContent = JSON.stringify(docsData, null, 2);
|
|
1461
1626
|
const hasUpdatedDocs = writeFileIfChanged(docsPath, docsContent);
|
|
@@ -1463,7 +1628,7 @@ var writeTypeMapArtifacts = ({
|
|
|
1463
1628
|
console.log("[TypeMapGenerator] Generated apiDocs.generated.json");
|
|
1464
1629
|
}
|
|
1465
1630
|
if (diagnosticsData !== void 0) {
|
|
1466
|
-
const diagnosticsPath =
|
|
1631
|
+
const diagnosticsPath = path5.join(path5.dirname(docsPath), "apiTypeDiagnostics.generated.json");
|
|
1467
1632
|
const diagnosticsContent = JSON.stringify(diagnosticsData, null, 2);
|
|
1468
1633
|
const hasUpdatedDiagnostics = writeFileIfChanged(diagnosticsPath, diagnosticsContent);
|
|
1469
1634
|
if (hasUpdatedDiagnostics) {
|
|
@@ -1479,30 +1644,46 @@ var writeTypeMapArtifacts = ({
|
|
|
1479
1644
|
};
|
|
1480
1645
|
|
|
1481
1646
|
// src/typeMap/extractors.ts
|
|
1482
|
-
import
|
|
1483
|
-
import
|
|
1647
|
+
import path7 from "path";
|
|
1648
|
+
import { SymbolFlags as SymbolFlags2 } from "typescript-7-api/sync";
|
|
1649
|
+
import {
|
|
1650
|
+
ScriptKind as ScriptKind2
|
|
1651
|
+
} from "typescript-7-api/ast";
|
|
1652
|
+
import {
|
|
1653
|
+
isArrowFunction,
|
|
1654
|
+
isCallExpression,
|
|
1655
|
+
isFunctionDeclaration as isFunctionDeclaration2,
|
|
1656
|
+
isFunctionExpression,
|
|
1657
|
+
isIdentifier as isIdentifier5,
|
|
1658
|
+
isInterfaceDeclaration as isInterfaceDeclaration2,
|
|
1659
|
+
isObjectLiteralExpression as isObjectLiteralExpression2,
|
|
1660
|
+
isPropertySignatureDeclaration as isPropertySignatureDeclaration2,
|
|
1661
|
+
isReturnStatement,
|
|
1662
|
+
isTypeReferenceNode as isTypeReferenceNode3,
|
|
1663
|
+
isVariableStatement as isVariableStatement2
|
|
1664
|
+
} from "typescript-7-api/ast/is";
|
|
1484
1665
|
|
|
1485
1666
|
// src/typeMap/tsProgram.ts
|
|
1486
|
-
import
|
|
1487
|
-
import
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
};
|
|
1667
|
+
import path6 from "path";
|
|
1668
|
+
import {
|
|
1669
|
+
ObjectFlags,
|
|
1670
|
+
SymbolFlags,
|
|
1671
|
+
TypeFlags
|
|
1672
|
+
} from "typescript-7-api/sync";
|
|
1673
|
+
import { SyntaxKind as SyntaxKind3 } from "typescript-7-api/ast";
|
|
1674
|
+
import {
|
|
1675
|
+
isAsExpression as isAsExpression2,
|
|
1676
|
+
isIdentifier as isIdentifier4,
|
|
1677
|
+
isNoSubstitutionTemplateLiteral,
|
|
1678
|
+
isNumericLiteral as isNumericLiteral3,
|
|
1679
|
+
isParenthesizedExpression as isParenthesizedExpression2,
|
|
1680
|
+
isPrefixUnaryExpression,
|
|
1681
|
+
isPropertyAssignment as isPropertyAssignment2,
|
|
1682
|
+
isShorthandPropertyAssignment,
|
|
1683
|
+
isStringLiteral as isStringLiteral3,
|
|
1684
|
+
isTypeAssertion
|
|
1685
|
+
} from "typescript-7-api/ast/is";
|
|
1686
|
+
import { getGeneratedSocketTypesPath as getGeneratedSocketTypesPath2 } from "@luckystack/core";
|
|
1506
1687
|
var DEPTH_LIMIT = 14;
|
|
1507
1688
|
var JSON_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
1508
1689
|
"Json",
|
|
@@ -1552,35 +1733,35 @@ var UnsupportedWireTypeError = class extends Error {
|
|
|
1552
1733
|
}
|
|
1553
1734
|
};
|
|
1554
1735
|
var isJsonLikeType = (type, checker) => {
|
|
1555
|
-
const symbolName = type.
|
|
1556
|
-
const aliasName = type.
|
|
1736
|
+
const symbolName = type.getSymbol()?.name ?? "";
|
|
1737
|
+
const aliasName = type.getAliasSymbol()?.name ?? "";
|
|
1557
1738
|
if (JSON_TYPE_NAMES.has(symbolName) || JSON_TYPE_NAMES.has(aliasName)) return true;
|
|
1558
1739
|
const rendered = checker.typeToString(type).trim();
|
|
1559
1740
|
return /^(?:Prisma\.)?(?:Input)?Json(?:Value|Object|Array)$/.test(rendered);
|
|
1560
1741
|
};
|
|
1561
1742
|
var getLiteralTypeFromExpression = (expression, checker, depth) => {
|
|
1562
|
-
if (
|
|
1743
|
+
if (isParenthesizedExpression2(expression)) {
|
|
1563
1744
|
return getLiteralTypeFromExpression(expression.expression, checker, depth);
|
|
1564
1745
|
}
|
|
1565
|
-
if (
|
|
1746
|
+
if (isAsExpression2(expression) || isTypeAssertion(expression)) {
|
|
1566
1747
|
return getLiteralTypeFromExpression(expression.expression, checker, depth);
|
|
1567
1748
|
}
|
|
1568
|
-
if (expression.kind ===
|
|
1569
|
-
if (expression.kind ===
|
|
1570
|
-
if (expression.kind ===
|
|
1571
|
-
if (
|
|
1749
|
+
if (expression.kind === SyntaxKind3.TrueKeyword) return "true";
|
|
1750
|
+
if (expression.kind === SyntaxKind3.FalseKeyword) return "false";
|
|
1751
|
+
if (expression.kind === SyntaxKind3.NullKeyword) return "null";
|
|
1752
|
+
if (isStringLiteral3(expression) || isNoSubstitutionTemplateLiteral(expression)) {
|
|
1572
1753
|
return `'${expression.text.replaceAll("\\", "\\\\").replaceAll("'", String.raw`\'`)}'`;
|
|
1573
1754
|
}
|
|
1574
|
-
if (
|
|
1755
|
+
if (isNumericLiteral3(expression)) {
|
|
1575
1756
|
return expression.text;
|
|
1576
1757
|
}
|
|
1577
|
-
if (
|
|
1758
|
+
if (isPrefixUnaryExpression(expression) && expression.operator === SyntaxKind3.MinusToken && isNumericLiteral3(expression.operand)) {
|
|
1578
1759
|
return `-${expression.operand.text}`;
|
|
1579
1760
|
}
|
|
1580
|
-
if (
|
|
1761
|
+
if (isIdentifier4(expression)) {
|
|
1581
1762
|
const identifierType = checker.getTypeAtLocation(expression);
|
|
1582
|
-
const isLiteralType = (identifierType.flags & (
|
|
1583
|
-
if (isLiteralType || identifierType.
|
|
1763
|
+
const isLiteralType = (identifierType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.BooleanLiteral | TypeFlags.Null | TypeFlags.Undefined)) !== 0;
|
|
1764
|
+
if (isLiteralType || identifierType.isUnionType()) {
|
|
1584
1765
|
const expanded = expandTypeDetailed(identifierType, checker, depth).text;
|
|
1585
1766
|
if (expanded.includes("'") || /\btrue\b|\bfalse\b|\bnull\b|\bundefined\b/.test(expanded)) {
|
|
1586
1767
|
return expanded;
|
|
@@ -1590,13 +1771,15 @@ var getLiteralTypeFromExpression = (expression, checker, depth) => {
|
|
|
1590
1771
|
return null;
|
|
1591
1772
|
};
|
|
1592
1773
|
var getLiteralTypeFromPropertySymbol = (symbol, checker, depth) => {
|
|
1593
|
-
const
|
|
1594
|
-
|
|
1595
|
-
|
|
1774
|
+
for (const handle of symbol.declarations) {
|
|
1775
|
+
if (handle.kind !== SyntaxKind3.PropertyAssignment && handle.kind !== SyntaxKind3.ShorthandPropertyAssignment) continue;
|
|
1776
|
+
const declaration = handle.resolve();
|
|
1777
|
+
if (!declaration) continue;
|
|
1778
|
+
if (isPropertyAssignment2(declaration)) {
|
|
1596
1779
|
const literal = getLiteralTypeFromExpression(declaration.initializer, checker, depth);
|
|
1597
1780
|
if (literal) return literal;
|
|
1598
1781
|
}
|
|
1599
|
-
if (
|
|
1782
|
+
if (isShorthandPropertyAssignment(declaration) && isIdentifier4(declaration.name)) {
|
|
1600
1783
|
const literal = getLiteralTypeFromExpression(declaration.name, checker, depth);
|
|
1601
1784
|
if (literal) return literal;
|
|
1602
1785
|
}
|
|
@@ -1604,10 +1787,10 @@ var getLiteralTypeFromPropertySymbol = (symbol, checker, depth) => {
|
|
|
1604
1787
|
return null;
|
|
1605
1788
|
};
|
|
1606
1789
|
var normalizeImportPath = (targetFilePath) => {
|
|
1607
|
-
const fromDir =
|
|
1790
|
+
const fromDir = path6.dirname(getGeneratedSocketTypesPath2());
|
|
1608
1791
|
const from = fromDir.replaceAll("\\", "/");
|
|
1609
1792
|
const to = targetFilePath.replaceAll("\\", "/");
|
|
1610
|
-
const normalized =
|
|
1793
|
+
const normalized = path6.posix.relative(from, to).replaceAll("\\", "/");
|
|
1611
1794
|
const withoutExtension = normalized.replace(/(\.d)?\.(ts|tsx|js|jsx)$/i, "");
|
|
1612
1795
|
if (withoutExtension.startsWith(".")) return withoutExtension;
|
|
1613
1796
|
return `./${withoutExtension}`;
|
|
@@ -1623,17 +1806,20 @@ var mergeUnresolvedSymbols = (left, right) => {
|
|
|
1623
1806
|
}
|
|
1624
1807
|
return merged;
|
|
1625
1808
|
};
|
|
1809
|
+
var isNodeModulesPath = (filePath) => filePath.includes("/node_modules/") || filePath.includes("\\node_modules\\");
|
|
1810
|
+
var getDeclarationFileName = (symbol) => {
|
|
1811
|
+
const handle = symbol.declarations[0];
|
|
1812
|
+
if (!handle || isNodeModulesPath(handle.path)) return void 0;
|
|
1813
|
+
const fileName = handle.resolve()?.getSourceFile().fileName;
|
|
1814
|
+
return fileName && !isNodeModulesPath(fileName) ? fileName : void 0;
|
|
1815
|
+
};
|
|
1626
1816
|
var collectTypeSymbolFallback = (type) => {
|
|
1627
|
-
const symbol = type.
|
|
1817
|
+
const symbol = type.getAliasSymbol() ?? type.getSymbol();
|
|
1628
1818
|
if (!symbol) return [];
|
|
1629
|
-
const name = symbol.
|
|
1819
|
+
const name = symbol.name;
|
|
1630
1820
|
if (!name || name.startsWith("__")) return [];
|
|
1631
|
-
const
|
|
1632
|
-
if (!
|
|
1633
|
-
const sourceFile = declaration.getSourceFile().fileName;
|
|
1634
|
-
if (!sourceFile || sourceFile.includes("/node_modules/") || sourceFile.includes("\\node_modules\\")) {
|
|
1635
|
-
return [{ name }];
|
|
1636
|
-
}
|
|
1821
|
+
const sourceFile = getDeclarationFileName(symbol);
|
|
1822
|
+
if (!sourceFile) return [{ name }];
|
|
1637
1823
|
return [{
|
|
1638
1824
|
name,
|
|
1639
1825
|
sourceFile,
|
|
@@ -1644,16 +1830,14 @@ var WIRE_PROJECTED_TYPES = /* @__PURE__ */ new Map([["Date", "string"]]);
|
|
|
1644
1830
|
var resolveToJsonReturnType = (type, checker) => {
|
|
1645
1831
|
const toJson = type.getProperty("toJSON");
|
|
1646
1832
|
if (!toJson) return null;
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
const signature = checker.getTypeOfSymbolAtLocation(toJson, declaration).getCallSignatures()[0];
|
|
1833
|
+
if (!toJson.valueDeclaration && toJson.declarations.length === 0) return null;
|
|
1834
|
+
const signature = checker.getNonMissingTypeOfSymbol(toJson).getCallSignatures()[0];
|
|
1650
1835
|
return signature ? signature.getReturnType() : null;
|
|
1651
1836
|
};
|
|
1652
1837
|
var isFunctionValueType = (type) => type.getCallSignatures().length > 0;
|
|
1653
1838
|
var typeNameOf = (type, checker) => {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
const targetName = objectType.target.getSymbol()?.name;
|
|
1839
|
+
if (type.isTypeReference()) {
|
|
1840
|
+
const targetName = type.getTarget().getSymbol()?.name;
|
|
1657
1841
|
if (targetName) return targetName;
|
|
1658
1842
|
}
|
|
1659
1843
|
return type.getSymbol()?.name ?? checker.typeToString(type);
|
|
@@ -1663,13 +1847,13 @@ var assertSupportedWireType = (type, checker) => {
|
|
|
1663
1847
|
if (TRANSPORT_DEPENDENT_BINARY_TYPES.has(typeName)) {
|
|
1664
1848
|
throw new UnsupportedWireTypeError(typeName);
|
|
1665
1849
|
}
|
|
1666
|
-
if ((type.flags & (
|
|
1850
|
+
if ((type.flags & (TypeFlags.BigInt | TypeFlags.BigIntLiteral)) !== 0) {
|
|
1667
1851
|
throw new UnsupportedWireTypeError("bigint");
|
|
1668
1852
|
}
|
|
1669
1853
|
};
|
|
1670
|
-
var isJsonOmittedValueType = (type) => (type.flags & (
|
|
1854
|
+
var isJsonOmittedValueType = (type) => (type.flags & (TypeFlags.Undefined | TypeFlags.Void | TypeFlags.ESSymbol | TypeFlags.UniqueESSymbol)) !== 0 || isFunctionValueType(type);
|
|
1671
1855
|
var resolveWireConstituents = (type, checker) => {
|
|
1672
|
-
const queue = type.
|
|
1856
|
+
const queue = type.isUnionType() ? [...type.getTypes()] : [type];
|
|
1673
1857
|
const serializable = [];
|
|
1674
1858
|
let omitted = false;
|
|
1675
1859
|
let changed = false;
|
|
@@ -1681,9 +1865,9 @@ var resolveWireConstituents = (type, checker) => {
|
|
|
1681
1865
|
continue;
|
|
1682
1866
|
}
|
|
1683
1867
|
const jsonType = resolveToJsonReturnType(candidate, checker);
|
|
1684
|
-
const effective = jsonType && jsonType !== candidate ? jsonType : candidate;
|
|
1868
|
+
const effective = jsonType && jsonType.id !== candidate.id ? jsonType : candidate;
|
|
1685
1869
|
if (effective !== candidate) changed = true;
|
|
1686
|
-
const effectiveTypes = effective.
|
|
1870
|
+
const effectiveTypes = effective.isUnionType() ? effective.getTypes() : [effective];
|
|
1687
1871
|
for (const effectiveType of effectiveTypes) {
|
|
1688
1872
|
assertSupportedWireType(effectiveType, checker);
|
|
1689
1873
|
if (isJsonOmittedValueType(effectiveType)) {
|
|
@@ -1699,15 +1883,13 @@ var resolveWireConstituents = (type, checker) => {
|
|
|
1699
1883
|
var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
1700
1884
|
const expandState = state ?? { stackTypeIds: /* @__PURE__ */ new Set(), wireProjection: options?.wireProjection ?? false };
|
|
1701
1885
|
const typeId = type.id;
|
|
1702
|
-
if (typeId
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
};
|
|
1708
|
-
}
|
|
1709
|
-
expandState.stackTypeIds.add(typeId);
|
|
1886
|
+
if (expandState.stackTypeIds.has(typeId)) {
|
|
1887
|
+
return {
|
|
1888
|
+
text: checker.typeToString(type),
|
|
1889
|
+
unresolvedSymbols: collectTypeSymbolFallback(type)
|
|
1890
|
+
};
|
|
1710
1891
|
}
|
|
1892
|
+
expandState.stackTypeIds.add(typeId);
|
|
1711
1893
|
try {
|
|
1712
1894
|
if (expandState.wireProjection) {
|
|
1713
1895
|
assertSupportedWireType(type, checker);
|
|
@@ -1722,14 +1904,14 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1722
1904
|
};
|
|
1723
1905
|
}
|
|
1724
1906
|
if (isJsonLikeType(type, checker)) return { text: "JsonValue", unresolvedSymbols: [] };
|
|
1725
|
-
if (type.
|
|
1726
|
-
if (type.
|
|
1727
|
-
if (type.flags & (
|
|
1907
|
+
if (type.isStringLiteralType()) return { text: `'${type.value.replaceAll("\\", "\\\\").replaceAll("'", String.raw`\'`)}'`, unresolvedSymbols: [] };
|
|
1908
|
+
if (type.isNumberLiteralType()) return { text: String(type.value), unresolvedSymbols: [] };
|
|
1909
|
+
if (type.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.Boolean | TypeFlags.BooleanLiteral | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.Any | TypeFlags.Unknown | TypeFlags.Never | TypeFlags.Void)) {
|
|
1728
1910
|
return { text: checker.typeToString(type), unresolvedSymbols: [] };
|
|
1729
1911
|
}
|
|
1730
|
-
if (type.
|
|
1912
|
+
if (type.isUnionType()) {
|
|
1731
1913
|
let unresolvedSymbols = [];
|
|
1732
|
-
const expandedTypes = type.
|
|
1914
|
+
const expandedTypes = type.getTypes().map((innerType) => {
|
|
1733
1915
|
const expanded = expandTypeDetailed(innerType, checker, depth + 1, expandState);
|
|
1734
1916
|
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1735
1917
|
return expanded.text;
|
|
@@ -1737,20 +1919,19 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1737
1919
|
const uniqueTypes = [...new Set(expandedTypes)];
|
|
1738
1920
|
return { text: uniqueTypes.join(" | "), unresolvedSymbols };
|
|
1739
1921
|
}
|
|
1740
|
-
if (type.
|
|
1922
|
+
if (type.isIntersectionType()) {
|
|
1741
1923
|
let unresolvedSymbols = [];
|
|
1742
|
-
const expandedTypes = type.
|
|
1924
|
+
const expandedTypes = type.getTypes().map((innerType) => {
|
|
1743
1925
|
const expanded = expandTypeDetailed(innerType, checker, depth + 1, expandState);
|
|
1744
1926
|
unresolvedSymbols = mergeUnresolvedSymbols(unresolvedSymbols, expanded.unresolvedSymbols);
|
|
1745
1927
|
return expanded.text;
|
|
1746
1928
|
});
|
|
1747
1929
|
return { text: expandedTypes.join(" & "), unresolvedSymbols };
|
|
1748
1930
|
}
|
|
1749
|
-
if (type.
|
|
1750
|
-
const
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
const typeArgs = checker.getTypeArguments(objectType);
|
|
1931
|
+
if (type.isObjectType()) {
|
|
1932
|
+
const tupleTarget = type.isTypeReference() ? type.getTarget() : type;
|
|
1933
|
+
if (tupleTarget.objectFlags & ObjectFlags.Tuple) {
|
|
1934
|
+
const typeArgs = type.isTypeReference() ? checker.getTypeArguments(type) : [];
|
|
1754
1935
|
let unresolvedSymbols = [];
|
|
1755
1936
|
const tupleTypes = typeArgs.map((innerType) => {
|
|
1756
1937
|
const wire = expandState.wireProjection ? resolveWireConstituents(innerType, checker) : { serializable: [innerType], omitted: false };
|
|
@@ -1767,15 +1948,14 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1767
1948
|
}
|
|
1768
1949
|
if (expandState.wireProjection) {
|
|
1769
1950
|
const jsonType = resolveToJsonReturnType(type, checker);
|
|
1770
|
-
if (jsonType && jsonType !== type) {
|
|
1951
|
+
if (jsonType && jsonType.id !== type.id) {
|
|
1771
1952
|
return expandTypeDetailed(jsonType, checker, depth + 1, expandState);
|
|
1772
1953
|
}
|
|
1773
1954
|
}
|
|
1774
|
-
if (
|
|
1775
|
-
const
|
|
1776
|
-
const targetName = refType.target.symbol?.name ?? "";
|
|
1955
|
+
if (type.isTypeReference()) {
|
|
1956
|
+
const targetName = type.getTarget().getSymbol()?.name ?? "";
|
|
1777
1957
|
if (targetName === "Array" || targetName === "ReadonlyArray") {
|
|
1778
|
-
const typeArgs = checker.getTypeArguments(
|
|
1958
|
+
const typeArgs = checker.getTypeArguments(type);
|
|
1779
1959
|
const firstArg = typeArgs[0];
|
|
1780
1960
|
if (firstArg) {
|
|
1781
1961
|
const wire = expandState.wireProjection ? resolveWireConstituents(firstArg, checker) : { serializable: [firstArg], omitted: false };
|
|
@@ -1797,7 +1977,7 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1797
1977
|
return { text: projected ?? checker.typeToString(type), unresolvedSymbols: [] };
|
|
1798
1978
|
}
|
|
1799
1979
|
}
|
|
1800
|
-
const symbolName = type.
|
|
1980
|
+
const symbolName = (type.getSymbol()?.name ?? "") || (type.getAliasSymbol()?.name ?? "");
|
|
1801
1981
|
if (SKIP_EXPANSION.has(symbolName)) {
|
|
1802
1982
|
const projected = expandState.wireProjection ? WIRE_PROJECTED_TYPES.get(symbolName) : void 0;
|
|
1803
1983
|
return { text: projected ?? checker.typeToString(type), unresolvedSymbols: [] };
|
|
@@ -1808,12 +1988,12 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1808
1988
|
const fields = [];
|
|
1809
1989
|
let unresolvedSymbols = [];
|
|
1810
1990
|
for (const prop of props) {
|
|
1811
|
-
if (prop.
|
|
1991
|
+
if (prop.name.startsWith("__@")) continue;
|
|
1812
1992
|
const propType = checker.getTypeOfSymbol(prop);
|
|
1813
1993
|
const wire = expandState.wireProjection ? resolveWireConstituents(propType, checker) : { serializable: [propType], omitted: false };
|
|
1814
1994
|
if (wire.serializable.length === 0) continue;
|
|
1815
1995
|
const literalType = getLiteralTypeFromPropertySymbol(prop, checker, depth + 1);
|
|
1816
|
-
const isOptional = (prop.flags &
|
|
1996
|
+
const isOptional = (prop.flags & SymbolFlags.Optional) !== 0 || wire.omitted;
|
|
1817
1997
|
if (literalType && !wire.omitted) {
|
|
1818
1998
|
fields.push(`${prop.name}${isOptional ? "?" : ""}: ${literalType}`);
|
|
1819
1999
|
continue;
|
|
@@ -1828,7 +2008,7 @@ var expandTypeDetailed = (type, checker, depth = 0, state, options) => {
|
|
|
1828
2008
|
}
|
|
1829
2009
|
for (const indexInfo of indexInfos) {
|
|
1830
2010
|
const keyType = expandTypeDetailed(indexInfo.keyType, checker, depth + 1, expandState);
|
|
1831
|
-
const wire = expandState.wireProjection ? resolveWireConstituents(indexInfo.
|
|
2011
|
+
const wire = expandState.wireProjection ? resolveWireConstituents(indexInfo.valueType, checker) : { serializable: [indexInfo.valueType], omitted: false };
|
|
1832
2012
|
if (wire.serializable.length === 0) continue;
|
|
1833
2013
|
const valueTexts = [];
|
|
1834
2014
|
for (const serializableType of wire.serializable) {
|
|
@@ -1856,9 +2036,7 @@ ${outerIndent}}`,
|
|
|
1856
2036
|
unresolvedSymbols: collectTypeSymbolFallback(type)
|
|
1857
2037
|
};
|
|
1858
2038
|
} finally {
|
|
1859
|
-
|
|
1860
|
-
expandState.stackTypeIds.delete(typeId);
|
|
1861
|
-
}
|
|
2039
|
+
expandState.stackTypeIds.delete(typeId);
|
|
1862
2040
|
}
|
|
1863
2041
|
};
|
|
1864
2042
|
var expandType = (type, checker, depth = 0) => {
|
|
@@ -1900,10 +2078,10 @@ var KNOWN_GLOBAL_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
|
1900
2078
|
"JsonPrimitive"
|
|
1901
2079
|
]);
|
|
1902
2080
|
var normalizeImportPath2 = (targetFilePath) => {
|
|
1903
|
-
const fromDir =
|
|
2081
|
+
const fromDir = path7.dirname(getGeneratedSocketTypesPath3());
|
|
1904
2082
|
const from = fromDir.replaceAll("\\", "/");
|
|
1905
2083
|
const to = targetFilePath.replaceAll("\\", "/");
|
|
1906
|
-
const normalized =
|
|
2084
|
+
const normalized = path7.posix.relative(from, to).replaceAll("\\", "/");
|
|
1907
2085
|
const withoutExtension = normalized.replace(/(\.d)?\.(ts|tsx|js|jsx)$/i, "");
|
|
1908
2086
|
if (withoutExtension.startsWith(".")) return withoutExtension;
|
|
1909
2087
|
return `./${withoutExtension}`;
|
|
@@ -1923,22 +2101,19 @@ var collectFallbackSymbolsFromTypeText = (typeText, scopeNode, checker) => {
|
|
|
1923
2101
|
const names = new Set((typeText.match(TYPE_NAME_PATTERN) ?? []).filter((name) => !KNOWN_GLOBAL_TYPE_NAMES.has(name)));
|
|
1924
2102
|
const symbolsInScope = checker.getSymbolsInScope(
|
|
1925
2103
|
scopeNode,
|
|
1926
|
-
|
|
2104
|
+
SymbolFlags2.TypeAlias | SymbolFlags2.Interface | SymbolFlags2.Class | SymbolFlags2.Enum | SymbolFlags2.Alias
|
|
1927
2105
|
);
|
|
1928
2106
|
const unresolvedSymbols = [];
|
|
1929
2107
|
for (const name of names) {
|
|
1930
2108
|
const localSymbol = symbolsInScope.find((symbol) => symbol.name === name);
|
|
1931
2109
|
if (!localSymbol) continue;
|
|
1932
|
-
const targetSymbol = (localSymbol.flags &
|
|
1933
|
-
|
|
1934
|
-
if (!declaration) {
|
|
2110
|
+
const targetSymbol = (localSymbol.flags & SymbolFlags2.Alias) === 0 ? localSymbol : checker.getAliasedSymbol(localSymbol);
|
|
2111
|
+
if (targetSymbol.declarations.length === 0) {
|
|
1935
2112
|
unresolvedSymbols.push({ name });
|
|
1936
2113
|
continue;
|
|
1937
2114
|
}
|
|
1938
|
-
const sourceFile =
|
|
1939
|
-
if (!sourceFile
|
|
1940
|
-
continue;
|
|
1941
|
-
}
|
|
2115
|
+
const sourceFile = getDeclarationFileName(targetSymbol);
|
|
2116
|
+
if (!sourceFile) continue;
|
|
1942
2117
|
unresolvedSymbols.push({
|
|
1943
2118
|
name,
|
|
1944
2119
|
sourceFile,
|
|
@@ -1949,13 +2124,13 @@ var collectFallbackSymbolsFromTypeText = (typeText, scopeNode, checker) => {
|
|
|
1949
2124
|
};
|
|
1950
2125
|
var findInterface = (sourceFile, name) => {
|
|
1951
2126
|
for (const stmt of sourceFile.statements) {
|
|
1952
|
-
if (
|
|
2127
|
+
if (isInterfaceDeclaration2(stmt) && stmt.name.text === name) return stmt;
|
|
1953
2128
|
}
|
|
1954
2129
|
return null;
|
|
1955
2130
|
};
|
|
1956
2131
|
var getInterfacePropertyType = (iface, propertyName, checker) => {
|
|
1957
2132
|
for (const member of iface.members) {
|
|
1958
|
-
if (
|
|
2133
|
+
if (isPropertySignatureDeclaration2(member) && isIdentifier5(member.name) && member.name.text === propertyName && member.type) {
|
|
1959
2134
|
return checker.getTypeFromTypeNode(member.type);
|
|
1960
2135
|
}
|
|
1961
2136
|
}
|
|
@@ -1963,14 +2138,14 @@ var getInterfacePropertyType = (iface, propertyName, checker) => {
|
|
|
1963
2138
|
};
|
|
1964
2139
|
var findMainFunction = (sourceFile) => {
|
|
1965
2140
|
for (const stmt of sourceFile.statements) {
|
|
1966
|
-
if (
|
|
2141
|
+
if (isVariableStatement2(stmt)) {
|
|
1967
2142
|
for (const decl of stmt.declarationList.declarations) {
|
|
1968
|
-
if (
|
|
2143
|
+
if (isIdentifier5(decl.name) && decl.name.text === "main" && decl.initializer && (isArrowFunction(decl.initializer) || isFunctionExpression(decl.initializer))) {
|
|
1969
2144
|
return decl.initializer;
|
|
1970
2145
|
}
|
|
1971
2146
|
}
|
|
1972
2147
|
}
|
|
1973
|
-
if (
|
|
2148
|
+
if (isFunctionDeclaration2(stmt) && stmt.name?.text === "main") {
|
|
1974
2149
|
return stmt;
|
|
1975
2150
|
}
|
|
1976
2151
|
}
|
|
@@ -1980,7 +2155,7 @@ var collectReturnObjectTypeDetails = (funcNode, checker) => {
|
|
|
1980
2155
|
const types = [];
|
|
1981
2156
|
let unresolvedSymbols = [];
|
|
1982
2157
|
const visit = (node) => {
|
|
1983
|
-
if (
|
|
2158
|
+
if (isReturnStatement(node) && node.expression && isObjectLiteralExpression2(node.expression)) {
|
|
1984
2159
|
const type = checker.getTypeAtLocation(node.expression);
|
|
1985
2160
|
const expanded = expandTypeDetailed(type, checker, 0, void 0, { wireProjection: true });
|
|
1986
2161
|
types.push(expanded.text);
|
|
@@ -1990,11 +2165,11 @@ var collectReturnObjectTypeDetails = (funcNode, checker) => {
|
|
|
1990
2165
|
collectFallbackSymbolsFromTypeText(expanded.text, node.expression, checker)
|
|
1991
2166
|
);
|
|
1992
2167
|
}
|
|
1993
|
-
if (!
|
|
1994
|
-
|
|
2168
|
+
if (!isArrowFunction(node) && !isFunctionExpression(node) && !isFunctionDeclaration2(node)) {
|
|
2169
|
+
node.forEachChild(visit);
|
|
1995
2170
|
}
|
|
1996
2171
|
};
|
|
1997
|
-
|
|
2172
|
+
funcNode.forEachChild(visit);
|
|
1998
2173
|
return { text: unionTypes(types), unresolvedSymbols };
|
|
1999
2174
|
};
|
|
2000
2175
|
var STREAM_EMIT_NAMES = /* @__PURE__ */ new Set(["stream", "broadcastStream", "streamTo"]);
|
|
@@ -2002,7 +2177,7 @@ var collectStreamCallPayloadTypeDetails = (funcNode, checker) => {
|
|
|
2002
2177
|
const types = [];
|
|
2003
2178
|
let unresolvedSymbols = [];
|
|
2004
2179
|
const visit = (node) => {
|
|
2005
|
-
if (
|
|
2180
|
+
if (isCallExpression(node) && isIdentifier5(node.expression) && STREAM_EMIT_NAMES.has(node.expression.text)) {
|
|
2006
2181
|
const callName = node.expression.text;
|
|
2007
2182
|
const payloadIndex = callName === "streamTo" ? 1 : 0;
|
|
2008
2183
|
const payloadArg = node.arguments[payloadIndex];
|
|
@@ -2020,11 +2195,11 @@ var collectStreamCallPayloadTypeDetails = (funcNode, checker) => {
|
|
|
2020
2195
|
);
|
|
2021
2196
|
}
|
|
2022
2197
|
}
|
|
2023
|
-
if (!
|
|
2024
|
-
|
|
2198
|
+
if (!isArrowFunction(node) && !isFunctionExpression(node) && !isFunctionDeclaration2(node)) {
|
|
2199
|
+
node.forEachChild(visit);
|
|
2025
2200
|
}
|
|
2026
2201
|
};
|
|
2027
|
-
|
|
2202
|
+
funcNode.forEachChild(visit);
|
|
2028
2203
|
return { text: unionTypes(types), unresolvedSymbols };
|
|
2029
2204
|
};
|
|
2030
2205
|
var unionTypes = (types) => {
|
|
@@ -2038,15 +2213,13 @@ var UnsupportedTransportInputError = class extends Error {
|
|
|
2038
2213
|
}
|
|
2039
2214
|
};
|
|
2040
2215
|
var assertTransportInputIsWireSafe = (typeText, filePath) => {
|
|
2041
|
-
const sourceFile =
|
|
2216
|
+
const sourceFile = parseSourceText(
|
|
2042
2217
|
"__luckystack_input_check.ts",
|
|
2043
2218
|
`type __LuckyStackInput = ${typeText};`,
|
|
2044
|
-
|
|
2045
|
-
true,
|
|
2046
|
-
ts5.ScriptKind.TS
|
|
2219
|
+
ScriptKind2.TS
|
|
2047
2220
|
);
|
|
2048
2221
|
const containsDate = (node) => {
|
|
2049
|
-
if (
|
|
2222
|
+
if (isTypeReferenceNode3(node) && isIdentifier5(node.typeName) && node.typeName.text === "Date") {
|
|
2050
2223
|
return true;
|
|
2051
2224
|
}
|
|
2052
2225
|
return node.getChildren(sourceFile).some((child) => containsDate(child));
|
|
@@ -2060,13 +2233,12 @@ var getInputTypeDetailsFromFile = (filePath) => {
|
|
|
2060
2233
|
const DEFAULT = "{ }";
|
|
2061
2234
|
recordExtractionOutcome({ filePath, kind: "api", field: "input", error: null });
|
|
2062
2235
|
try {
|
|
2063
|
-
const program = getServerProgram();
|
|
2236
|
+
const { program, checker } = getServerProgram();
|
|
2064
2237
|
const sourceFile = program.getSourceFile(filePath);
|
|
2065
2238
|
if (!sourceFile) {
|
|
2066
2239
|
console.warn(`[TypeMapGenerator] getSourceFile miss for ${filePath} \u2014 input types will default to { }`);
|
|
2067
2240
|
return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2068
2241
|
}
|
|
2069
|
-
const checker = program.getTypeChecker();
|
|
2070
2242
|
const iface = findInterface(sourceFile, "ApiParams");
|
|
2071
2243
|
if (!iface) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2072
2244
|
const dataType = getInterfacePropertyType(iface, "data", checker);
|
|
@@ -2092,9 +2264,9 @@ var extractDeclaredStreamTypeFromApiParams = (sourceFile, checker) => {
|
|
|
2092
2264
|
let result = null;
|
|
2093
2265
|
const visit = (node) => {
|
|
2094
2266
|
if (result) return;
|
|
2095
|
-
if (
|
|
2267
|
+
if (isInterfaceDeclaration2(node) && node.name.text.endsWith("Params")) {
|
|
2096
2268
|
for (const member of node.members) {
|
|
2097
|
-
if (
|
|
2269
|
+
if (isPropertySignatureDeclaration2(member) && isIdentifier5(member.name) && member.name.text === "stream" && member.type && isTypeReferenceNode3(member.type) && isIdentifier5(member.type.typeName) && STREAM_EMITTER_TYPE_NAMES.has(member.type.typeName.text)) {
|
|
2098
2270
|
const typeArg = member.type.typeArguments?.[0];
|
|
2099
2271
|
if (typeArg) {
|
|
2100
2272
|
const argType = checker.getNonNullableType(checker.getTypeFromTypeNode(typeArg));
|
|
@@ -2107,7 +2279,7 @@ var extractDeclaredStreamTypeFromApiParams = (sourceFile, checker) => {
|
|
|
2107
2279
|
}
|
|
2108
2280
|
}
|
|
2109
2281
|
}
|
|
2110
|
-
|
|
2282
|
+
node.forEachChild(visit);
|
|
2111
2283
|
};
|
|
2112
2284
|
visit(sourceFile);
|
|
2113
2285
|
return result;
|
|
@@ -2116,10 +2288,9 @@ var getApiStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
2116
2288
|
const DEFAULT = "never";
|
|
2117
2289
|
recordExtractionOutcome({ filePath, kind: "api", field: "stream", error: null });
|
|
2118
2290
|
try {
|
|
2119
|
-
const program = getServerProgram();
|
|
2291
|
+
const { program, checker } = getServerProgram();
|
|
2120
2292
|
const sourceFile = program.getSourceFile(filePath);
|
|
2121
2293
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2122
|
-
const checker = program.getTypeChecker();
|
|
2123
2294
|
const mainFn = findMainFunction(sourceFile);
|
|
2124
2295
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2125
2296
|
const details = collectStreamCallPayloadTypeDetails(mainFn, checker);
|
|
@@ -2138,10 +2309,9 @@ var getOutputTypeDetailsFromFile = (filePath) => {
|
|
|
2138
2309
|
const DEFAULT = "{ status: string }";
|
|
2139
2310
|
recordExtractionOutcome({ filePath, kind: "api", field: "output", error: null });
|
|
2140
2311
|
try {
|
|
2141
|
-
const program = getServerProgram();
|
|
2312
|
+
const { program, checker } = getServerProgram();
|
|
2142
2313
|
const sourceFile = program.getSourceFile(filePath);
|
|
2143
2314
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2144
|
-
const checker = program.getTypeChecker();
|
|
2145
2315
|
const mainFn = findMainFunction(sourceFile);
|
|
2146
2316
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2147
2317
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
@@ -2160,10 +2330,9 @@ var getSyncClientDataTypeDetailsFromFile = (filePath) => {
|
|
|
2160
2330
|
const DEFAULT = "{ }";
|
|
2161
2331
|
recordExtractionOutcome({ filePath, kind: "sync", field: "clientInput", error: null });
|
|
2162
2332
|
try {
|
|
2163
|
-
const program = getServerProgram();
|
|
2333
|
+
const { program, checker } = getServerProgram();
|
|
2164
2334
|
const sourceFile = program.getSourceFile(filePath);
|
|
2165
2335
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2166
|
-
const checker = program.getTypeChecker();
|
|
2167
2336
|
const iface = findInterface(sourceFile, "SyncParams");
|
|
2168
2337
|
if (!iface) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2169
2338
|
const dataType = getInterfacePropertyType(iface, "clientInput", checker) ?? getInterfacePropertyType(iface, "clientData", checker);
|
|
@@ -2182,10 +2351,9 @@ var getSyncServerStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
2182
2351
|
const DEFAULT = "never";
|
|
2183
2352
|
recordExtractionOutcome({ filePath, kind: "sync", field: "serverStream", error: null });
|
|
2184
2353
|
try {
|
|
2185
|
-
const program = getServerProgram();
|
|
2354
|
+
const { program, checker } = getServerProgram();
|
|
2186
2355
|
const sourceFile = program.getSourceFile(filePath);
|
|
2187
2356
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2188
|
-
const checker = program.getTypeChecker();
|
|
2189
2357
|
const mainFn = findMainFunction(sourceFile);
|
|
2190
2358
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2191
2359
|
const details = collectStreamCallPayloadTypeDetails(mainFn, checker);
|
|
@@ -2201,10 +2369,9 @@ var getSyncServerOutputTypeDetailsFromFile = (filePath) => {
|
|
|
2201
2369
|
const DEFAULT = "{ status: string }";
|
|
2202
2370
|
recordExtractionOutcome({ filePath, kind: "sync", field: "serverOutput", error: null });
|
|
2203
2371
|
try {
|
|
2204
|
-
const program = getServerProgram();
|
|
2372
|
+
const { program, checker } = getServerProgram();
|
|
2205
2373
|
const sourceFile = program.getSourceFile(filePath);
|
|
2206
2374
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2207
|
-
const checker = program.getTypeChecker();
|
|
2208
2375
|
const mainFn = findMainFunction(sourceFile);
|
|
2209
2376
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2210
2377
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
@@ -2220,10 +2387,9 @@ var getSyncClientStreamPayloadTypeDetailsFromFile = (filePath) => {
|
|
|
2220
2387
|
const DEFAULT = "never";
|
|
2221
2388
|
recordExtractionOutcome({ filePath, kind: "sync", field: "clientStream", error: null });
|
|
2222
2389
|
try {
|
|
2223
|
-
const program = getServerProgram();
|
|
2390
|
+
const { program, checker } = getServerProgram();
|
|
2224
2391
|
const sourceFile = program.getSourceFile(filePath);
|
|
2225
2392
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2226
|
-
const checker = program.getTypeChecker();
|
|
2227
2393
|
const mainFn = findMainFunction(sourceFile);
|
|
2228
2394
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2229
2395
|
const details = collectStreamCallPayloadTypeDetails(mainFn, checker);
|
|
@@ -2239,10 +2405,9 @@ var getSyncClientOutputTypeDetailsFromFile = (filePath) => {
|
|
|
2239
2405
|
const DEFAULT = "{ }";
|
|
2240
2406
|
recordExtractionOutcome({ filePath, kind: "sync", field: "clientOutput", error: null });
|
|
2241
2407
|
try {
|
|
2242
|
-
const program = getServerProgram();
|
|
2408
|
+
const { program, checker } = getServerProgram();
|
|
2243
2409
|
const sourceFile = program.getSourceFile(filePath);
|
|
2244
2410
|
if (!sourceFile) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2245
|
-
const checker = program.getTypeChecker();
|
|
2246
2411
|
const mainFn = findMainFunction(sourceFile);
|
|
2247
2412
|
if (!mainFn) return { text: DEFAULT, unresolvedSymbols: [] };
|
|
2248
2413
|
const details = collectReturnObjectTypeDetails(mainFn, checker);
|
|
@@ -2256,19 +2421,48 @@ var getSyncClientOutputTypeDetailsFromFile = (filePath) => {
|
|
|
2256
2421
|
};
|
|
2257
2422
|
|
|
2258
2423
|
// src/typeMap/functionsMeta.ts
|
|
2259
|
-
import
|
|
2260
|
-
import
|
|
2261
|
-
import
|
|
2424
|
+
import fs7 from "fs";
|
|
2425
|
+
import path10 from "path";
|
|
2426
|
+
import {
|
|
2427
|
+
createScanner,
|
|
2428
|
+
LanguageVariant,
|
|
2429
|
+
SyntaxKind as SyntaxKind5
|
|
2430
|
+
} from "typescript-7-api/ast";
|
|
2431
|
+
import {
|
|
2432
|
+
isArrowFunction as isArrowFunction2,
|
|
2433
|
+
isClassDeclaration as isClassDeclaration3,
|
|
2434
|
+
isEnumDeclaration as isEnumDeclaration3,
|
|
2435
|
+
isExportAssignment,
|
|
2436
|
+
isExportDeclaration,
|
|
2437
|
+
isFunctionDeclaration as isFunctionDeclaration3,
|
|
2438
|
+
isFunctionExpression as isFunctionExpression2,
|
|
2439
|
+
isIdentifier as isIdentifier6,
|
|
2440
|
+
isInterfaceDeclaration as isInterfaceDeclaration4,
|
|
2441
|
+
isNamedExports,
|
|
2442
|
+
isStringLiteral as isStringLiteral5,
|
|
2443
|
+
isTypeAliasDeclaration as isTypeAliasDeclaration4,
|
|
2444
|
+
isVariableStatement as isVariableStatement3
|
|
2445
|
+
} from "typescript-7-api/ast/is";
|
|
2262
2446
|
|
|
2263
2447
|
// src/typeMap/typeContext.ts
|
|
2264
|
-
import
|
|
2265
|
-
import
|
|
2448
|
+
import path8 from "path";
|
|
2449
|
+
import { SyntaxKind as SyntaxKind4 } from "typescript-7-api/ast";
|
|
2450
|
+
import {
|
|
2451
|
+
isClassDeclaration as isClassDeclaration2,
|
|
2452
|
+
isEnumDeclaration as isEnumDeclaration2,
|
|
2453
|
+
isImportDeclaration as isImportDeclaration2,
|
|
2454
|
+
isInterfaceDeclaration as isInterfaceDeclaration3,
|
|
2455
|
+
isNamedImports as isNamedImports2,
|
|
2456
|
+
isNamespaceImport as isNamespaceImport2,
|
|
2457
|
+
isStringLiteral as isStringLiteral4,
|
|
2458
|
+
isTypeAliasDeclaration as isTypeAliasDeclaration3
|
|
2459
|
+
} from "typescript-7-api/ast/is";
|
|
2266
2460
|
import { getGeneratedSocketTypesPath as getGeneratedSocketTypesPath4 } from "@luckystack/core";
|
|
2267
2461
|
var toGeneratedImportPath = (source, filePath) => {
|
|
2268
2462
|
if (!source.startsWith(".")) return source;
|
|
2269
|
-
const outputDir =
|
|
2270
|
-
const absoluteSource =
|
|
2271
|
-
let relPath =
|
|
2463
|
+
const outputDir = path8.dirname(getGeneratedSocketTypesPath4());
|
|
2464
|
+
const absoluteSource = path8.resolve(path8.dirname(filePath), source);
|
|
2465
|
+
let relPath = path8.relative(outputDir, absoluteSource).replaceAll("\\", "/");
|
|
2272
2466
|
relPath = relPath.replace(/\.tsx?$/, "");
|
|
2273
2467
|
if (!relPath.startsWith(".")) relPath = `./${relPath}`;
|
|
2274
2468
|
return relPath;
|
|
@@ -2276,23 +2470,18 @@ var toGeneratedImportPath = (source, filePath) => {
|
|
|
2276
2470
|
var parseFileTypeContext = (content) => {
|
|
2277
2471
|
const availableExports = /* @__PURE__ */ new Set();
|
|
2278
2472
|
const fileImports = /* @__PURE__ */ new Map();
|
|
2279
|
-
const sourceFile =
|
|
2280
|
-
"__temp__.ts",
|
|
2281
|
-
content,
|
|
2282
|
-
ts6.ScriptTarget.Latest,
|
|
2283
|
-
true
|
|
2284
|
-
);
|
|
2473
|
+
const sourceFile = parseSourceText("__temp__.ts", content);
|
|
2285
2474
|
for (const statement of sourceFile.statements) {
|
|
2286
|
-
if (
|
|
2287
|
-
const hasExport = statement.modifiers?.some((m) => m.kind ===
|
|
2475
|
+
if (isInterfaceDeclaration3(statement) || isTypeAliasDeclaration3(statement) || isClassDeclaration2(statement) || isEnumDeclaration2(statement)) {
|
|
2476
|
+
const hasExport = statement.modifiers?.some((m) => m.kind === SyntaxKind4.ExportKeyword);
|
|
2288
2477
|
if (hasExport && statement.name) {
|
|
2289
2478
|
availableExports.add(statement.name.text);
|
|
2290
2479
|
}
|
|
2291
2480
|
continue;
|
|
2292
2481
|
}
|
|
2293
|
-
if (!
|
|
2482
|
+
if (!isImportDeclaration2(statement)) continue;
|
|
2294
2483
|
const moduleSpecifier = statement.moduleSpecifier;
|
|
2295
|
-
if (!
|
|
2484
|
+
if (!isStringLiteral4(moduleSpecifier)) continue;
|
|
2296
2485
|
const source = moduleSpecifier.text;
|
|
2297
2486
|
const importClause = statement.importClause;
|
|
2298
2487
|
if (!importClause) continue;
|
|
@@ -2301,11 +2490,11 @@ var parseFileTypeContext = (content) => {
|
|
|
2301
2490
|
}
|
|
2302
2491
|
const namedBindings = importClause.namedBindings;
|
|
2303
2492
|
if (!namedBindings) continue;
|
|
2304
|
-
if (
|
|
2493
|
+
if (isNamespaceImport2(namedBindings)) {
|
|
2305
2494
|
fileImports.set(namedBindings.name.text, { source, isDefault: true });
|
|
2306
2495
|
continue;
|
|
2307
2496
|
}
|
|
2308
|
-
if (
|
|
2497
|
+
if (isNamedImports2(namedBindings)) {
|
|
2309
2498
|
for (const specifier of namedBindings.elements) {
|
|
2310
2499
|
const localName = specifier.name.text;
|
|
2311
2500
|
const originalName = specifier.propertyName?.text ?? localName;
|
|
@@ -2355,11 +2544,11 @@ var sanitizeTypeAndCollectImports = ({
|
|
|
2355
2544
|
import { getGeneratedSocketTypesPath as getGeneratedSocketTypesPath5, ROOT_DIR as ROOT_DIR5 } from "@luckystack/core";
|
|
2356
2545
|
|
|
2357
2546
|
// src/functionRegistry.ts
|
|
2358
|
-
import
|
|
2359
|
-
import
|
|
2547
|
+
import fs6 from "fs";
|
|
2548
|
+
import path9 from "path";
|
|
2360
2549
|
import { ROOT_DIR as ROOT_DIR4, getServerFunctionDirs, isTestFile as isTestFile2, isTestDirectory as isTestDirectory2 } from "@luckystack/core";
|
|
2361
2550
|
var normalizePath2 = (value) => value.replaceAll("\\", "/");
|
|
2362
|
-
var toWorkspaceRelative = (absolutePath) => normalizePath2(
|
|
2551
|
+
var toWorkspaceRelative = (absolutePath) => normalizePath2(path9.relative(ROOT_DIR4, absolutePath));
|
|
2363
2552
|
var formatFunctionKeyPath = (keyPath) => keyPath.join(".");
|
|
2364
2553
|
var functionModuleFileName = (keyPath) => {
|
|
2365
2554
|
const fileName = keyPath.at(-1);
|
|
@@ -2371,12 +2560,12 @@ var functionModuleFileName = (keyPath) => {
|
|
|
2371
2560
|
var formatFunctionKeyConflict = (keyPath, firstSourcePath, secondSourcePath) => `[function-injection] Conflict at \`functions.${formatFunctionKeyPath(keyPath)}\`: defined in both \`${firstSourcePath}\` and \`${secondSourcePath}\`. Delete one \u2014 \`shared/\` is the canonical location for framework re-exports.`;
|
|
2372
2561
|
var formatFunctionNamespaceConflict = (moduleKeyPath, moduleSourcePath, nestedKeyPath, nestedSourcePath) => `[function-injection] Conflict at \`functions.${formatFunctionKeyPath(moduleKeyPath)}\`: \`${moduleSourcePath}\` defines it as a module, but \`${nestedSourcePath}\` nests \`functions.${formatFunctionKeyPath(nestedKeyPath)}\` underneath it. Rename one \u2014 a key cannot be both a module and a namespace.`;
|
|
2373
2562
|
var walkFunctionRoot = (dir, rootDir, basePath, collected) => {
|
|
2374
|
-
const entries =
|
|
2563
|
+
const entries = fs6.readdirSync(dir).toSorted();
|
|
2375
2564
|
for (const entry of entries) {
|
|
2376
2565
|
if (entry === "node_modules") continue;
|
|
2377
|
-
const fullPath =
|
|
2566
|
+
const fullPath = path9.join(dir, entry);
|
|
2378
2567
|
if (getRoutingRules().ignore(toWorkspaceRelative(fullPath))) continue;
|
|
2379
|
-
if (
|
|
2568
|
+
if (fs6.statSync(fullPath).isDirectory()) {
|
|
2380
2569
|
if (isTestDirectory2(entry)) continue;
|
|
2381
2570
|
walkFunctionRoot(fullPath, rootDir, [...basePath, entry], collected);
|
|
2382
2571
|
continue;
|
|
@@ -2419,7 +2608,7 @@ var collectFunctionModules = (options = {}) => {
|
|
|
2419
2608
|
onConflict(message);
|
|
2420
2609
|
};
|
|
2421
2610
|
for (const root of functionRoots) {
|
|
2422
|
-
if (!
|
|
2611
|
+
if (!fs6.existsSync(root)) continue;
|
|
2423
2612
|
const fromThisRoot = [];
|
|
2424
2613
|
walkFunctionRoot(root, root, [], fromThisRoot);
|
|
2425
2614
|
for (const module of fromThisRoot) {
|
|
@@ -2493,17 +2682,16 @@ var stripDefaultValues = (params) => {
|
|
|
2493
2682
|
return params.replaceAll(/\s*=(?!>)[^,)]+/g, "");
|
|
2494
2683
|
};
|
|
2495
2684
|
var stripLineComments = (value) => {
|
|
2496
|
-
const scanner =
|
|
2497
|
-
ts7.ScriptTarget.Latest,
|
|
2685
|
+
const scanner = createScanner(
|
|
2498
2686
|
/* skipTrivia */
|
|
2499
2687
|
false,
|
|
2500
|
-
|
|
2688
|
+
LanguageVariant.Standard,
|
|
2501
2689
|
value
|
|
2502
2690
|
);
|
|
2503
2691
|
let result = "";
|
|
2504
2692
|
let token = scanner.scan();
|
|
2505
|
-
while (token !==
|
|
2506
|
-
result += token ===
|
|
2693
|
+
while (token !== SyntaxKind5.EndOfFile) {
|
|
2694
|
+
result += token === SyntaxKind5.SingleLineCommentTrivia ? " " : scanner.getTokenText();
|
|
2507
2695
|
token = scanner.scan();
|
|
2508
2696
|
}
|
|
2509
2697
|
return result;
|
|
@@ -2516,9 +2704,9 @@ var simplifyInferredType = (value) => {
|
|
|
2516
2704
|
if (/\bRedis\b/.test(value)) return "Redis";
|
|
2517
2705
|
return value;
|
|
2518
2706
|
};
|
|
2519
|
-
var getGeneratedFileDir = () =>
|
|
2707
|
+
var getGeneratedFileDir = () => path10.dirname(getGeneratedSocketTypesPath5());
|
|
2520
2708
|
var sourceModuleSpecifier = (sourceFilePath) => {
|
|
2521
|
-
const relative =
|
|
2709
|
+
const relative = path10.relative(getGeneratedFileDir(), sourceFilePath).replaceAll("\\", "/").replace(/\.tsx?$/i, "");
|
|
2522
2710
|
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
2523
2711
|
};
|
|
2524
2712
|
var portableInferredValueType = (inferred, sourceFilePath, exportName) => {
|
|
@@ -2529,16 +2717,16 @@ var relativizeModuleSpecifier = (specifier, sourceFilePath) => {
|
|
|
2529
2717
|
if (!specifier.startsWith("./") && !specifier.startsWith("../")) {
|
|
2530
2718
|
return specifier;
|
|
2531
2719
|
}
|
|
2532
|
-
const absolute =
|
|
2533
|
-
const rel =
|
|
2534
|
-
const normalized = rel.split(
|
|
2720
|
+
const absolute = path10.resolve(path10.dirname(sourceFilePath), specifier);
|
|
2721
|
+
const rel = path10.relative(getGeneratedFileDir(), absolute);
|
|
2722
|
+
const normalized = rel.split(path10.sep).join("/");
|
|
2535
2723
|
return normalized.startsWith(".") ? normalized : `./${normalized}`;
|
|
2536
2724
|
};
|
|
2537
2725
|
var findProgramVariableDeclaration = (sourceFile, exportName) => {
|
|
2538
2726
|
for (const statement of sourceFile.statements) {
|
|
2539
|
-
if (!
|
|
2727
|
+
if (!isVariableStatement3(statement)) continue;
|
|
2540
2728
|
for (const declaration of statement.declarationList.declarations) {
|
|
2541
|
-
if (
|
|
2729
|
+
if (isIdentifier6(declaration.name) && declaration.name.text === exportName) {
|
|
2542
2730
|
return declaration;
|
|
2543
2731
|
}
|
|
2544
2732
|
}
|
|
@@ -2547,10 +2735,10 @@ var findProgramVariableDeclaration = (sourceFile, exportName) => {
|
|
|
2547
2735
|
};
|
|
2548
2736
|
var findProgramTypeDeclaration = (sourceFile, typeName) => {
|
|
2549
2737
|
for (const statement of sourceFile.statements) {
|
|
2550
|
-
if (
|
|
2551
|
-
if (
|
|
2552
|
-
if (
|
|
2553
|
-
if (
|
|
2738
|
+
if (isInterfaceDeclaration4(statement) && statement.name.text === typeName) return statement;
|
|
2739
|
+
if (isTypeAliasDeclaration4(statement) && statement.name.text === typeName) return statement;
|
|
2740
|
+
if (isClassDeclaration3(statement) && statement.name?.text === typeName) return statement;
|
|
2741
|
+
if (isEnumDeclaration3(statement) && statement.name.text === typeName) return statement;
|
|
2554
2742
|
}
|
|
2555
2743
|
return null;
|
|
2556
2744
|
};
|
|
@@ -2567,7 +2755,7 @@ var resolveLocalExportedTypes = ({
|
|
|
2567
2755
|
if (!hasReference) continue;
|
|
2568
2756
|
const declaration = findProgramTypeDeclaration(programSource, exportName);
|
|
2569
2757
|
if (!declaration) continue;
|
|
2570
|
-
const declarationNode =
|
|
2758
|
+
const declarationNode = isClassDeclaration3(declaration) ? declaration.name ?? declaration : isTypeAliasDeclaration4(declaration) ? declaration.type : declaration;
|
|
2571
2759
|
const declarationType = checker.getTypeAtLocation(declarationNode);
|
|
2572
2760
|
const expanded = normalizeInlineType(expandType(declarationType, checker));
|
|
2573
2761
|
resolved = resolved.replaceAll(new RegExp(String.raw`\b${exportName}\b`, "g"), expanded);
|
|
@@ -2576,9 +2764,9 @@ var resolveLocalExportedTypes = ({
|
|
|
2576
2764
|
};
|
|
2577
2765
|
var findSourceVariableDeclaration = (sourceFile, exportName) => {
|
|
2578
2766
|
for (const statement of sourceFile.statements) {
|
|
2579
|
-
if (!
|
|
2767
|
+
if (!isVariableStatement3(statement)) continue;
|
|
2580
2768
|
for (const declaration of statement.declarationList.declarations) {
|
|
2581
|
-
if (
|
|
2769
|
+
if (isIdentifier6(declaration.name) && declaration.name.text === exportName) {
|
|
2582
2770
|
return declaration;
|
|
2583
2771
|
}
|
|
2584
2772
|
}
|
|
@@ -2596,8 +2784,8 @@ var inferValueTypeForExport = ({
|
|
|
2596
2784
|
checker,
|
|
2597
2785
|
programSource
|
|
2598
2786
|
}) => {
|
|
2599
|
-
const resolvedChecker = checker ?? getServerProgram().
|
|
2600
|
-
const resolvedSource = programSource ?? getServerProgram().getSourceFile(filePath);
|
|
2787
|
+
const resolvedChecker = checker ?? getServerProgram().checker;
|
|
2788
|
+
const resolvedSource = programSource ?? getServerProgram().program.getSourceFile(filePath);
|
|
2601
2789
|
if (declaration.type) {
|
|
2602
2790
|
const rawType = normalizeInlineType(rawContent.slice(declaration.type.pos, declaration.type.end).trim());
|
|
2603
2791
|
const localResolvedType = resolvedSource ? resolveLocalExportedTypes({
|
|
@@ -2646,7 +2834,7 @@ var extractSignatureFromNode = (node, rawContent, filePath, availableExports, fi
|
|
|
2646
2834
|
knownGenerics.add(typeParam.name.text);
|
|
2647
2835
|
}
|
|
2648
2836
|
}
|
|
2649
|
-
const isAsync = node.modifiers?.some((m) => m.kind ===
|
|
2837
|
+
const isAsync = node.modifiers?.some((m) => m.kind === SyntaxKind5.AsyncKeyword) ?? false;
|
|
2650
2838
|
const genericsClause = node.typeParameters ? `<${normalizeInlineType(rawContent.slice(node.typeParameters.pos, node.typeParameters.end))}>` : "";
|
|
2651
2839
|
const rawParams = node.parameters.map((p) => normalizeInlineType(rawContent.slice(p.pos, p.end).trim())).join(", ");
|
|
2652
2840
|
const cleanParams = normalizeInlineType(stripDefaultValues(`(${rawParams})`));
|
|
@@ -2689,38 +2877,38 @@ var extractSignatureFromNode = (node, rawContent, filePath, availableExports, fi
|
|
|
2689
2877
|
};
|
|
2690
2878
|
var findSignatureForExport = (name, sourceFile, rawContent, filePath, availableExports, fileImports, collectors, checker, programSource) => {
|
|
2691
2879
|
for (const statement of sourceFile.statements) {
|
|
2692
|
-
if (
|
|
2880
|
+
if (isVariableStatement3(statement)) {
|
|
2693
2881
|
for (const decl of statement.declarationList.declarations) {
|
|
2694
|
-
if (!
|
|
2695
|
-
if (
|
|
2882
|
+
if (!isIdentifier6(decl.name) || decl.name.text !== name || !decl.initializer) continue;
|
|
2883
|
+
if (isArrowFunction2(decl.initializer) || isFunctionExpression2(decl.initializer)) {
|
|
2696
2884
|
return extractSignatureFromNode(decl.initializer, rawContent, filePath, availableExports, fileImports, collectors, checker, programSource);
|
|
2697
2885
|
}
|
|
2698
2886
|
}
|
|
2699
2887
|
}
|
|
2700
|
-
if (
|
|
2888
|
+
if (isFunctionDeclaration3(statement) && statement.name?.text === name) {
|
|
2701
2889
|
return extractSignatureFromNode(statement, rawContent, filePath, availableExports, fileImports, collectors, checker, programSource);
|
|
2702
2890
|
}
|
|
2703
2891
|
}
|
|
2704
2892
|
return "any";
|
|
2705
2893
|
};
|
|
2894
|
+
var hasExportModifier = (statement) => (isVariableStatement3(statement) || isFunctionDeclaration3(statement)) && (statement.modifiers?.some((m) => m.kind === SyntaxKind5.ExportKeyword) ?? false);
|
|
2706
2895
|
var parseFunctionFile = (fullPath, collectors) => {
|
|
2707
2896
|
try {
|
|
2708
|
-
const rawContent =
|
|
2709
|
-
const sourceFile =
|
|
2897
|
+
const rawContent = fs7.readFileSync(fullPath, "utf8");
|
|
2898
|
+
const sourceFile = parseSourceText(fullPath, rawContent);
|
|
2710
2899
|
const { availableExports, fileImports } = parseFileTypeContext(rawContent);
|
|
2711
|
-
const program = getServerProgram();
|
|
2712
|
-
const checker = program.getTypeChecker();
|
|
2900
|
+
const { program, checker } = getServerProgram();
|
|
2713
2901
|
const programSource = program.getSourceFile(fullPath);
|
|
2714
2902
|
const exports = /* @__PURE__ */ new Map();
|
|
2715
2903
|
let defaultExportName = null;
|
|
2716
2904
|
let wildcardReExport = null;
|
|
2717
2905
|
for (const statement of sourceFile.statements) {
|
|
2718
|
-
const hasExport = statement
|
|
2719
|
-
if (
|
|
2906
|
+
const hasExport = hasExportModifier(statement);
|
|
2907
|
+
if (isVariableStatement3(statement) && hasExport) {
|
|
2720
2908
|
for (const decl of statement.declarationList.declarations) {
|
|
2721
|
-
if (
|
|
2909
|
+
if (isIdentifier6(decl.name)) {
|
|
2722
2910
|
const exportName = decl.name.text;
|
|
2723
|
-
if (decl.initializer && (
|
|
2911
|
+
if (decl.initializer && (isArrowFunction2(decl.initializer) || isFunctionExpression2(decl.initializer))) {
|
|
2724
2912
|
exports.set(exportName, findSignatureForExport(exportName, sourceFile, rawContent, fullPath, availableExports, fileImports, collectors, checker, programSource ?? void 0));
|
|
2725
2913
|
continue;
|
|
2726
2914
|
}
|
|
@@ -2738,11 +2926,11 @@ var parseFunctionFile = (fullPath, collectors) => {
|
|
|
2738
2926
|
}
|
|
2739
2927
|
}
|
|
2740
2928
|
}
|
|
2741
|
-
if (
|
|
2929
|
+
if (isFunctionDeclaration3(statement) && hasExport && statement.name) {
|
|
2742
2930
|
exports.set(statement.name.text, findSignatureForExport(statement.name.text, sourceFile, rawContent, fullPath, availableExports, fileImports, collectors, checker, programSource ?? void 0));
|
|
2743
2931
|
}
|
|
2744
|
-
if (
|
|
2745
|
-
const moduleSpecifier = statement.moduleSpecifier &&
|
|
2932
|
+
if (isExportDeclaration(statement) && statement.exportClause && isNamedExports(statement.exportClause)) {
|
|
2933
|
+
const moduleSpecifier = statement.moduleSpecifier && isStringLiteral5(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null;
|
|
2746
2934
|
for (const specifier of statement.exportClause.elements) {
|
|
2747
2935
|
const exportName = specifier.name.text;
|
|
2748
2936
|
const originalName = specifier.propertyName ? specifier.propertyName.text : exportName;
|
|
@@ -2757,7 +2945,7 @@ var parseFunctionFile = (fullPath, collectors) => {
|
|
|
2757
2945
|
continue;
|
|
2758
2946
|
}
|
|
2759
2947
|
const exportDeclaration = findSourceVariableDeclaration(sourceFile, originalName);
|
|
2760
|
-
if (exportDeclaration &&
|
|
2948
|
+
if (exportDeclaration && isIdentifier6(exportDeclaration.name)) {
|
|
2761
2949
|
exports.set(exportName, inferValueTypeForExport({
|
|
2762
2950
|
exportName: originalName,
|
|
2763
2951
|
declaration: exportDeclaration,
|
|
@@ -2774,10 +2962,10 @@ var parseFunctionFile = (fullPath, collectors) => {
|
|
|
2774
2962
|
exports.set(exportName, "any");
|
|
2775
2963
|
}
|
|
2776
2964
|
}
|
|
2777
|
-
if (
|
|
2965
|
+
if (isExportAssignment(statement) && !statement.isExportEquals && isIdentifier6(statement.expression)) {
|
|
2778
2966
|
defaultExportName = statement.expression.text;
|
|
2779
2967
|
}
|
|
2780
|
-
if (
|
|
2968
|
+
if (isExportDeclaration(statement) && !statement.exportClause && statement.moduleSpecifier && isStringLiteral5(statement.moduleSpecifier)) {
|
|
2781
2969
|
wildcardReExport = relativizeModuleSpecifier(statement.moduleSpecifier.text, fullPath);
|
|
2782
2970
|
}
|
|
2783
2971
|
}
|
|
@@ -2851,7 +3039,7 @@ var generateServerFunctions = (collectors) => {
|
|
|
2851
3039
|
if (modules.length === 0) return "";
|
|
2852
3040
|
const merged = { kind: "dir", children: /* @__PURE__ */ new Map(), sourcePath: "<merged>" };
|
|
2853
3041
|
for (const module of modules) {
|
|
2854
|
-
const absolutePath =
|
|
3042
|
+
const absolutePath = path10.resolve(ROOT_DIR5, module.sourcePath);
|
|
2855
3043
|
const parsed = parseFunctionFile(absolutePath, collectors);
|
|
2856
3044
|
if (!parsed) continue;
|
|
2857
3045
|
if (parsed.exports.size === 0 && parsed.defaultExportName === null && parsed.wildcardReExport === null) {
|
|
@@ -2971,12 +3159,14 @@ var collectSyncTypes = (syncServerFiles, syncClientFiles, collectors) => {
|
|
|
2971
3159
|
version: syncVersion,
|
|
2972
3160
|
hasServer: serverFile !== void 0,
|
|
2973
3161
|
hasClient: clientFile !== void 0,
|
|
2974
|
-
...syncMeta ? { meta: syncMeta } : {}
|
|
3162
|
+
...syncMeta ? { meta: syncMeta } : {},
|
|
3163
|
+
//? Same extractors as the API side, so `syncMetaMap` and `apiMetaMap` agree.
|
|
3164
|
+
...serverFile ? { serverMeta: { auth: extractAuth(serverFile), rateLimit: extractRateLimit(serverFile) } } : {}
|
|
2975
3165
|
});
|
|
2976
3166
|
}
|
|
2977
3167
|
return syncTypesByPage;
|
|
2978
3168
|
};
|
|
2979
|
-
var
|
|
3169
|
+
var runTypeMapGeneration = (options) => {
|
|
2980
3170
|
const { quiet = false } = options;
|
|
2981
3171
|
assertValidRouteNaming({
|
|
2982
3172
|
srcDir: getSrcDir2(),
|
|
@@ -3014,6 +3204,13 @@ var generateTypeMapFile = (options = {}) => {
|
|
|
3014
3204
|
});
|
|
3015
3205
|
writeTypeMapArtifacts({ content, docsData, schemasContent, diagnosticsData });
|
|
3016
3206
|
};
|
|
3207
|
+
var generateTypeMapFile = (options = {}) => {
|
|
3208
|
+
try {
|
|
3209
|
+
runTypeMapGeneration(options);
|
|
3210
|
+
} finally {
|
|
3211
|
+
disposeTsApi();
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3017
3214
|
|
|
3018
3215
|
// src/templateRegistry.ts
|
|
3019
3216
|
var BUILT_IN_TEMPLATE_KINDS = [
|
|
@@ -3087,13 +3284,29 @@ var registerDefaultTemplateRules = () => {
|
|
|
3087
3284
|
registerDefaultTemplateRules();
|
|
3088
3285
|
|
|
3089
3286
|
// src/loader.ts
|
|
3090
|
-
import
|
|
3091
|
-
import
|
|
3287
|
+
import fs8 from "fs";
|
|
3288
|
+
import path11 from "path";
|
|
3092
3289
|
import { pathToFileURL } from "url";
|
|
3093
3290
|
import { tryCatch, getSrcDir as getSrcDir3, ROOT_DIR as ROOT_DIR6, isTestFile as isTestFile3 } from "@luckystack/core";
|
|
3094
3291
|
|
|
3095
3292
|
// src/runtimeTypeResolver.ts
|
|
3096
|
-
import
|
|
3293
|
+
import { SymbolFlags as SymbolFlags3 } from "typescript-7-api/sync";
|
|
3294
|
+
import { SyntaxKind as SyntaxKind6 } from "typescript-7-api/ast";
|
|
3295
|
+
import {
|
|
3296
|
+
isEnumDeclaration as isEnumDeclaration4,
|
|
3297
|
+
isIdentifier as isIdentifier7,
|
|
3298
|
+
isImportDeclaration as isImportDeclaration3,
|
|
3299
|
+
isIndexSignatureDeclaration as isIndexSignatureDeclaration2,
|
|
3300
|
+
isInterfaceDeclaration as isInterfaceDeclaration5,
|
|
3301
|
+
isLiteralTypeNode as isLiteralTypeNode2,
|
|
3302
|
+
isNamedImports as isNamedImports3,
|
|
3303
|
+
isPropertySignatureDeclaration as isPropertySignatureDeclaration3,
|
|
3304
|
+
isStringLiteral as isStringLiteral6,
|
|
3305
|
+
isTypeAliasDeclaration as isTypeAliasDeclaration5,
|
|
3306
|
+
isTypeLiteralNode as isTypeLiteralNode2,
|
|
3307
|
+
isTypeReferenceNode as isTypeReferenceNode4,
|
|
3308
|
+
isUnionTypeNode as isUnionTypeNode2
|
|
3309
|
+
} from "typescript-7-api/ast/is";
|
|
3097
3310
|
var MAX_DEPTH = 20;
|
|
3098
3311
|
var unresolvedPrefix = "__RUNTIME_UNRESOLVED__::";
|
|
3099
3312
|
var PRIMITIVE_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -3173,9 +3386,9 @@ var splitTopLevel = (value, splitter) => {
|
|
|
3173
3386
|
};
|
|
3174
3387
|
var parseTypeNode = (typeText) => {
|
|
3175
3388
|
const synthetic = `type __RT = ${typeText};`;
|
|
3176
|
-
const source =
|
|
3389
|
+
const source = parseSourceText("__runtime_type.ts", synthetic);
|
|
3177
3390
|
const statement = source.statements[0];
|
|
3178
|
-
if (!statement || !
|
|
3391
|
+
if (!statement || !isTypeAliasDeclaration5(statement)) return null;
|
|
3179
3392
|
return statement.type;
|
|
3180
3393
|
};
|
|
3181
3394
|
var parseObjectFields = (typeText) => {
|
|
@@ -3184,30 +3397,30 @@ var parseObjectFields = (typeText) => {
|
|
|
3184
3397
|
return { fields: [], indexSignatures: [] };
|
|
3185
3398
|
}
|
|
3186
3399
|
const typeNode = parseTypeNode(clean);
|
|
3187
|
-
if (!typeNode || !
|
|
3400
|
+
if (!typeNode || !isTypeLiteralNode2(typeNode)) {
|
|
3188
3401
|
return { fields: [], indexSignatures: [] };
|
|
3189
3402
|
}
|
|
3190
3403
|
const fields = [];
|
|
3191
3404
|
const indexSignatures = [];
|
|
3192
3405
|
for (const member of typeNode.members) {
|
|
3193
|
-
if (
|
|
3406
|
+
if (isPropertySignatureDeclaration3(member) && member.type) {
|
|
3194
3407
|
let key = null;
|
|
3195
|
-
if (
|
|
3408
|
+
if (isIdentifier7(member.name)) {
|
|
3196
3409
|
key = member.name.text;
|
|
3197
|
-
} else if (
|
|
3410
|
+
} else if (isStringLiteral6(member.name)) {
|
|
3198
3411
|
key = member.name.text;
|
|
3199
3412
|
}
|
|
3200
3413
|
if (key === null) continue;
|
|
3201
3414
|
fields.push({
|
|
3202
3415
|
key,
|
|
3203
|
-
optional:
|
|
3416
|
+
optional: member.postfixToken?.kind === SyntaxKind6.QuestionToken,
|
|
3204
3417
|
type: member.type.getText().trim()
|
|
3205
3418
|
});
|
|
3206
3419
|
continue;
|
|
3207
3420
|
}
|
|
3208
|
-
if (
|
|
3421
|
+
if (isIndexSignatureDeclaration2(member)) {
|
|
3209
3422
|
const param = member.parameters[0];
|
|
3210
|
-
if (!param || !
|
|
3423
|
+
if (!param || !isIdentifier7(param.name) || !param.type) continue;
|
|
3211
3424
|
indexSignatures.push({
|
|
3212
3425
|
keyName: param.name.text,
|
|
3213
3426
|
keyType: param.type.getText().trim(),
|
|
@@ -3232,9 +3445,9 @@ var serializeObjectFields = ({
|
|
|
3232
3445
|
return `{ ${segments.join("; ")} }`;
|
|
3233
3446
|
};
|
|
3234
3447
|
var extractStringLiteralKey = (node) => {
|
|
3235
|
-
if (!
|
|
3448
|
+
if (!isLiteralTypeNode2(node)) return null;
|
|
3236
3449
|
const literal = node.literal;
|
|
3237
|
-
if (!
|
|
3450
|
+
if (!isStringLiteral6(literal)) return null;
|
|
3238
3451
|
return literal.text;
|
|
3239
3452
|
};
|
|
3240
3453
|
var parseLiteralUnionKeys = (value) => {
|
|
@@ -3242,7 +3455,7 @@ var parseLiteralUnionKeys = (value) => {
|
|
|
3242
3455
|
if (!trimmed) return null;
|
|
3243
3456
|
const typeNode = parseTypeNode(trimmed);
|
|
3244
3457
|
if (!typeNode) return null;
|
|
3245
|
-
if (
|
|
3458
|
+
if (isUnionTypeNode2(typeNode)) {
|
|
3246
3459
|
const keys = [];
|
|
3247
3460
|
for (const member of typeNode.types) {
|
|
3248
3461
|
const key = extractStringLiteralKey(member);
|
|
@@ -3258,25 +3471,24 @@ var resolveIdentifier = (identifier, filePath) => {
|
|
|
3258
3471
|
if (PRIMITIVE_TYPES.has(identifier.toLowerCase())) return identifier.toLowerCase();
|
|
3259
3472
|
if (SKIP_EXPANSION2.has(identifier)) return identifier;
|
|
3260
3473
|
try {
|
|
3261
|
-
const program = getServerProgram();
|
|
3474
|
+
const { program, checker } = getServerProgram();
|
|
3262
3475
|
const sourceFile = program.getSourceFile(filePath);
|
|
3263
3476
|
if (!sourceFile) return toUnresolved(`unresolved type ${identifier}`);
|
|
3264
|
-
const checker = program.getTypeChecker();
|
|
3265
3477
|
for (const stmt of sourceFile.statements) {
|
|
3266
|
-
if ((
|
|
3478
|
+
if ((isInterfaceDeclaration5(stmt) || isTypeAliasDeclaration5(stmt) || isEnumDeclaration4(stmt)) && stmt.name.text === identifier) {
|
|
3267
3479
|
const symbol = checker.getSymbolAtLocation(stmt.name);
|
|
3268
3480
|
if (symbol) {
|
|
3269
3481
|
return expandType(checker.getDeclaredTypeOfSymbol(symbol), checker);
|
|
3270
3482
|
}
|
|
3271
3483
|
}
|
|
3272
|
-
if (
|
|
3484
|
+
if (isImportDeclaration3(stmt) && stmt.importClause) {
|
|
3273
3485
|
const { namedBindings, name: defaultName } = stmt.importClause;
|
|
3274
|
-
if (namedBindings &&
|
|
3486
|
+
if (namedBindings && isNamedImports3(namedBindings)) {
|
|
3275
3487
|
for (const specifier of namedBindings.elements) {
|
|
3276
3488
|
if (specifier.name.text === identifier) {
|
|
3277
3489
|
const symbol = checker.getSymbolAtLocation(specifier.name);
|
|
3278
3490
|
if (symbol) {
|
|
3279
|
-
const target = symbol.flags &
|
|
3491
|
+
const target = symbol.flags & SymbolFlags3.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
3280
3492
|
return expandType(checker.getDeclaredTypeOfSymbol(target), checker);
|
|
3281
3493
|
}
|
|
3282
3494
|
}
|
|
@@ -3285,7 +3497,7 @@ var resolveIdentifier = (identifier, filePath) => {
|
|
|
3285
3497
|
if (defaultName?.text === identifier) {
|
|
3286
3498
|
const symbol = checker.getSymbolAtLocation(defaultName);
|
|
3287
3499
|
if (symbol) {
|
|
3288
|
-
const target = symbol.flags &
|
|
3500
|
+
const target = symbol.flags & SymbolFlags3.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
3289
3501
|
return expandType(checker.getDeclaredTypeOfSymbol(target), checker);
|
|
3290
3502
|
}
|
|
3291
3503
|
}
|
|
@@ -3419,7 +3631,7 @@ var resolveExpression = (typeText, filePath, depth, state) => {
|
|
|
3419
3631
|
});
|
|
3420
3632
|
} else {
|
|
3421
3633
|
const typeNode = parseTypeNode(type);
|
|
3422
|
-
const referenceInfo = typeNode &&
|
|
3634
|
+
const referenceInfo = typeNode && isTypeReferenceNode4(typeNode) && isIdentifier7(typeNode.typeName) ? { name: typeNode.typeName.text, args: typeNode.typeArguments } : null;
|
|
3423
3635
|
if (referenceInfo?.args && referenceInfo.args.length > 0) {
|
|
3424
3636
|
const { name: genericName, args: argNodes } = referenceInfo;
|
|
3425
3637
|
const args = argNodes.map((arg) => arg.getText().trim());
|
|
@@ -3470,7 +3682,7 @@ var devSyncs = {};
|
|
|
3470
3682
|
var devFunctions = {};
|
|
3471
3683
|
var normalizePath3 = (value) => value.replaceAll("\\", "/");
|
|
3472
3684
|
var isIgnoredPath = (absolutePath) => {
|
|
3473
|
-
const relativeFromRoot = normalizePath3(
|
|
3685
|
+
const relativeFromRoot = normalizePath3(path11.relative(ROOT_DIR6, absolutePath));
|
|
3474
3686
|
return getRoutingRules().ignore(relativeFromRoot);
|
|
3475
3687
|
};
|
|
3476
3688
|
var mapApiPageLocation = (pageLocation) => {
|
|
@@ -3480,7 +3692,7 @@ var mapSyncPageLocation = (pageLocation) => {
|
|
|
3480
3692
|
return pageLocation || "system";
|
|
3481
3693
|
};
|
|
3482
3694
|
var resolveApiRouteMetaFromPath = (filePath) => {
|
|
3483
|
-
const absolutePath =
|
|
3695
|
+
const absolutePath = path11.resolve(filePath);
|
|
3484
3696
|
const normalizedAbsolutePath = normalizePath3(absolutePath);
|
|
3485
3697
|
const normalizedSrcDir = normalizePath3(getSrcDir3());
|
|
3486
3698
|
if (!normalizedAbsolutePath.startsWith(normalizedSrcDir) || !normalizedAbsolutePath.endsWith(".ts")) {
|
|
@@ -3490,7 +3702,7 @@ var resolveApiRouteMetaFromPath = (filePath) => {
|
|
|
3490
3702
|
return null;
|
|
3491
3703
|
}
|
|
3492
3704
|
const rules2 = getRoutingRules();
|
|
3493
|
-
const relativePath = normalizePath3(
|
|
3705
|
+
const relativePath = normalizePath3(path11.relative(getSrcDir3(), absolutePath));
|
|
3494
3706
|
const segments = relativePath.split("/");
|
|
3495
3707
|
const apiIndex = segments.indexOf(rules2.apiMarker);
|
|
3496
3708
|
if (apiIndex === -1 || apiIndex === segments.length - 1) {
|
|
@@ -3510,7 +3722,7 @@ var resolveApiRouteMetaFromPath = (filePath) => {
|
|
|
3510
3722
|
return { routeKey, absolutePath };
|
|
3511
3723
|
};
|
|
3512
3724
|
var resolveSyncRouteMetaFromPath = (filePath) => {
|
|
3513
|
-
const absolutePath =
|
|
3725
|
+
const absolutePath = path11.resolve(filePath);
|
|
3514
3726
|
const normalizedAbsolutePath = normalizePath3(absolutePath);
|
|
3515
3727
|
const normalizedSrcDir = normalizePath3(getSrcDir3());
|
|
3516
3728
|
if (!normalizedAbsolutePath.startsWith(normalizedSrcDir) || !normalizedAbsolutePath.endsWith(".ts")) {
|
|
@@ -3520,7 +3732,7 @@ var resolveSyncRouteMetaFromPath = (filePath) => {
|
|
|
3520
3732
|
return null;
|
|
3521
3733
|
}
|
|
3522
3734
|
const rules2 = getRoutingRules();
|
|
3523
|
-
const relativePath = normalizePath3(
|
|
3735
|
+
const relativePath = normalizePath3(path11.relative(getSrcDir3(), absolutePath));
|
|
3524
3736
|
const segments = relativePath.split("/");
|
|
3525
3737
|
const syncIndex = segments.indexOf(rules2.syncMarker);
|
|
3526
3738
|
if (syncIndex === -1 || syncIndex === segments.length - 1) {
|
|
@@ -3564,13 +3776,13 @@ var importFile = async (absolutePath) => {
|
|
|
3564
3776
|
};
|
|
3565
3777
|
var collectTsFiles = (dir, relativeTo = "") => {
|
|
3566
3778
|
const results = [];
|
|
3567
|
-
const entries =
|
|
3779
|
+
const entries = fs8.readdirSync(dir);
|
|
3568
3780
|
for (const entry of entries) {
|
|
3569
3781
|
if (entry === "node_modules") continue;
|
|
3570
|
-
const entryPath =
|
|
3782
|
+
const entryPath = path11.join(dir, entry);
|
|
3571
3783
|
if (isIgnoredPath(entryPath)) continue;
|
|
3572
3784
|
const relPath = relativeTo ? `${relativeTo}/${entry}` : entry;
|
|
3573
|
-
if (
|
|
3785
|
+
if (fs8.statSync(entryPath).isDirectory()) {
|
|
3574
3786
|
if (isNonRouteDirectory(entry)) continue;
|
|
3575
3787
|
results.push(...collectTsFiles(entryPath, relPath));
|
|
3576
3788
|
} else if (entry.endsWith(".ts") && !isTestFile3(entry)) {
|
|
@@ -3602,16 +3814,16 @@ var resolveFunctionModule = (loadedModule, fileName) => {
|
|
|
3602
3814
|
var initializeApis = async () => {
|
|
3603
3815
|
for (const key of Object.keys(devApis)) delete devApis[key];
|
|
3604
3816
|
clearRuntimeTypeResolverCache();
|
|
3605
|
-
const srcFolder =
|
|
3817
|
+
const srcFolder = fs8.readdirSync(getSrcDir3());
|
|
3606
3818
|
for (const file of srcFolder) {
|
|
3607
3819
|
await scanApiFolder(file);
|
|
3608
3820
|
}
|
|
3609
3821
|
};
|
|
3610
3822
|
var upsertApiFromFile = async (filePath) => {
|
|
3611
|
-
if (isIgnoredPath(
|
|
3823
|
+
if (isIgnoredPath(path11.resolve(filePath))) return;
|
|
3612
3824
|
const routeMeta = resolveApiRouteMetaFromPath(filePath);
|
|
3613
3825
|
if (!routeMeta) {
|
|
3614
|
-
const normalized = normalizePath3(
|
|
3826
|
+
const normalized = normalizePath3(path11.resolve(filePath));
|
|
3615
3827
|
if (normalized.endsWith(".ts") && normalized.includes(apiMarkerSegment()) && isRouteSurfaceFile(normalized)) {
|
|
3616
3828
|
console.log(
|
|
3617
3829
|
`[loader][api] invalid filename: ${normalized}. Expected <name>_v<number>.ts. File will not be loaded.`,
|
|
@@ -3659,13 +3871,13 @@ var removeApiFromFile = (filePath) => {
|
|
|
3659
3871
|
delete devApis[routeMeta.routeKey];
|
|
3660
3872
|
};
|
|
3661
3873
|
var scanApiFolder = async (file, basePath = "") => {
|
|
3662
|
-
const fullPath =
|
|
3874
|
+
const fullPath = path11.join(getSrcDir3(), basePath, file);
|
|
3663
3875
|
if (isIgnoredPath(fullPath)) return;
|
|
3664
|
-
if (!
|
|
3876
|
+
if (!fs8.statSync(fullPath).isDirectory()) return;
|
|
3665
3877
|
if (file !== getRoutingRules().apiMarker) {
|
|
3666
|
-
const subFolders =
|
|
3878
|
+
const subFolders = fs8.readdirSync(fullPath);
|
|
3667
3879
|
for (const sub of subFolders) {
|
|
3668
|
-
await scanApiFolder(sub,
|
|
3880
|
+
await scanApiFolder(sub, path11.join(basePath, file));
|
|
3669
3881
|
}
|
|
3670
3882
|
return;
|
|
3671
3883
|
}
|
|
@@ -3678,7 +3890,7 @@ var scanApiFolder = async (file, basePath = "") => {
|
|
|
3678
3890
|
const versionMatch = rawApiName.match(apiRules.apiVersionRegex);
|
|
3679
3891
|
if (!versionMatch) {
|
|
3680
3892
|
console.log(
|
|
3681
|
-
`[loader][api] invalid filename: ${
|
|
3893
|
+
`[loader][api] invalid filename: ${path11.join(fullPath, relFile)}. Expected <name>_v<number>.ts. File will not be loaded.`,
|
|
3682
3894
|
"red"
|
|
3683
3895
|
);
|
|
3684
3896
|
continue;
|
|
@@ -3686,7 +3898,7 @@ var scanApiFolder = async (file, basePath = "") => {
|
|
|
3686
3898
|
const version = `v${versionMatch[1]}`;
|
|
3687
3899
|
const apiName = rawApiName.replace(apiRules.apiVersionRegex, "");
|
|
3688
3900
|
const routeKey = `api/${mappedPageLocation}/${apiName}/${version}`;
|
|
3689
|
-
const modulePath =
|
|
3901
|
+
const modulePath = path11.resolve(path11.join(fullPath, relFile));
|
|
3690
3902
|
const [err, module] = await tryCatch(async () => importFile(modulePath));
|
|
3691
3903
|
if (err) {
|
|
3692
3904
|
console.log(`[loader][api] failed to import ${routeKey} from ${modulePath}:`, err, "red");
|
|
@@ -3715,16 +3927,16 @@ var scanApiFolder = async (file, basePath = "") => {
|
|
|
3715
3927
|
var initializeSyncs = async () => {
|
|
3716
3928
|
for (const key of Object.keys(devSyncs)) delete devSyncs[key];
|
|
3717
3929
|
clearRuntimeTypeResolverCache();
|
|
3718
|
-
const srcFolder =
|
|
3930
|
+
const srcFolder = fs8.readdirSync(getSrcDir3());
|
|
3719
3931
|
for (const file of srcFolder) {
|
|
3720
3932
|
await scanSyncFolder(file);
|
|
3721
3933
|
}
|
|
3722
3934
|
};
|
|
3723
3935
|
var upsertSyncFromFile = async (filePath) => {
|
|
3724
|
-
if (isIgnoredPath(
|
|
3936
|
+
if (isIgnoredPath(path11.resolve(filePath))) return;
|
|
3725
3937
|
const routeMeta = resolveSyncRouteMetaFromPath(filePath);
|
|
3726
3938
|
if (!routeMeta) {
|
|
3727
|
-
const normalized = normalizePath3(
|
|
3939
|
+
const normalized = normalizePath3(path11.resolve(filePath));
|
|
3728
3940
|
if (normalized.endsWith(".ts") && normalized.includes(syncMarkerSegment()) && isRouteSurfaceFile(normalized)) {
|
|
3729
3941
|
console.log(
|
|
3730
3942
|
`[loader][sync] invalid filename: ${normalized}. Expected <name>_server_v<number>.ts or <name>_client_v<number>.ts. File will not be loaded.`,
|
|
@@ -3777,13 +3989,13 @@ var removeSyncFromFile = (filePath) => {
|
|
|
3777
3989
|
delete devSyncs[routeMeta.routeKey];
|
|
3778
3990
|
};
|
|
3779
3991
|
var scanSyncFolder = async (file, basePath = "") => {
|
|
3780
|
-
const fullPath =
|
|
3992
|
+
const fullPath = path11.join(getSrcDir3(), basePath, file);
|
|
3781
3993
|
if (isIgnoredPath(fullPath)) return;
|
|
3782
|
-
if (!
|
|
3994
|
+
if (!fs8.statSync(fullPath).isDirectory()) return;
|
|
3783
3995
|
if (file !== getRoutingRules().syncMarker) {
|
|
3784
|
-
const subFolders =
|
|
3996
|
+
const subFolders = fs8.readdirSync(fullPath);
|
|
3785
3997
|
for (const sub of subFolders) {
|
|
3786
|
-
await scanSyncFolder(sub,
|
|
3998
|
+
await scanSyncFolder(sub, path11.join(basePath, file));
|
|
3787
3999
|
}
|
|
3788
4000
|
return;
|
|
3789
4001
|
}
|
|
@@ -3795,7 +4007,7 @@ var scanSyncFolder = async (file, basePath = "") => {
|
|
|
3795
4007
|
const syncMatch = rawSyncFileName.match(syncRules.syncVersionRegex);
|
|
3796
4008
|
if (!syncMatch) {
|
|
3797
4009
|
console.log(
|
|
3798
|
-
`[loader][sync] invalid filename: ${
|
|
4010
|
+
`[loader][sync] invalid filename: ${path11.join(fullPath, relFile)}. Expected <name>_server_v<number>.ts or <name>_client_v<number>.ts. File will not be loaded.`,
|
|
3799
4011
|
"red"
|
|
3800
4012
|
);
|
|
3801
4013
|
continue;
|
|
@@ -3805,7 +4017,7 @@ var scanSyncFolder = async (file, basePath = "") => {
|
|
|
3805
4017
|
const syncName = rawSyncFileName.replace(syncRules.syncVersionRegex, "");
|
|
3806
4018
|
const mappedPageLocation = mapSyncPageLocation(pageLocation);
|
|
3807
4019
|
const routeBaseKey = `sync/${mappedPageLocation}/${syncName}/${version}`;
|
|
3808
|
-
const filePath =
|
|
4020
|
+
const filePath = path11.resolve(path11.join(fullPath, relFile));
|
|
3809
4021
|
const [fileError, fileResult] = await tryCatch(async () => importFile(filePath));
|
|
3810
4022
|
if (fileError) {
|
|
3811
4023
|
console.log(`[loader][sync] failed to import ${filePath}:`, fileError, "red");
|
|
@@ -3837,7 +4049,7 @@ var initializeFunctions = async () => {
|
|
|
3837
4049
|
}
|
|
3838
4050
|
});
|
|
3839
4051
|
for (const functionModule of modules) {
|
|
3840
|
-
const absolutePath =
|
|
4052
|
+
const absolutePath = path11.resolve(ROOT_DIR6, functionModule.sourcePath);
|
|
3841
4053
|
const [err, module] = await tryCatch(async () => importFile(absolutePath));
|
|
3842
4054
|
if (err) {
|
|
3843
4055
|
console.log(`[loader][function] failed to import ${absolutePath}:`, err, "red");
|
|
@@ -3860,19 +4072,25 @@ var initializeFunctions = async () => {
|
|
|
3860
4072
|
|
|
3861
4073
|
// src/hotReload.ts
|
|
3862
4074
|
import { watch } from "chokidar";
|
|
3863
|
-
import
|
|
3864
|
-
import
|
|
4075
|
+
import fs12 from "fs";
|
|
4076
|
+
import path15 from "path";
|
|
3865
4077
|
|
|
3866
4078
|
// src/templateInjector.ts
|
|
3867
|
-
import
|
|
3868
|
-
import
|
|
4079
|
+
import fs9 from "fs";
|
|
4080
|
+
import path12 from "path";
|
|
3869
4081
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
3870
|
-
import
|
|
4082
|
+
import { ScriptKind as ScriptKind3 } from "typescript-7-api/ast";
|
|
4083
|
+
import {
|
|
4084
|
+
isIdentifier as isIdentifier8,
|
|
4085
|
+
isInterfaceDeclaration as isInterfaceDeclaration6,
|
|
4086
|
+
isPropertySignatureDeclaration as isPropertySignatureDeclaration4,
|
|
4087
|
+
isTypeLiteralNode as isTypeLiteralNode3
|
|
4088
|
+
} from "typescript-7-api/ast/is";
|
|
3871
4089
|
import { ROOT_DIR as ROOT_DIR7, getGeneratedSocketTypesPath as getGeneratedSocketTypesPath6, getSrcDir as getSrcDir4 } from "@luckystack/core";
|
|
3872
4090
|
var __filename = fileURLToPath(import.meta.url);
|
|
3873
|
-
var __dirname =
|
|
3874
|
-
var templatesDir =
|
|
3875
|
-
var getConsumerTemplatesDir = () =>
|
|
4091
|
+
var __dirname = path12.dirname(__filename);
|
|
4092
|
+
var templatesDir = path12.join(__dirname, "templates");
|
|
4093
|
+
var getConsumerTemplatesDir = () => path12.join(ROOT_DIR7, ".luckystack", "templates");
|
|
3876
4094
|
var templateContentFilenames = (kind) => {
|
|
3877
4095
|
const builtIn = BUILT_IN_TEMPLATE_FILENAMES[kind];
|
|
3878
4096
|
if (builtIn) return [builtIn];
|
|
@@ -3881,10 +4099,10 @@ var templateContentFilenames = (kind) => {
|
|
|
3881
4099
|
var resolveTemplateContent = (kind) => {
|
|
3882
4100
|
const consumerDir = getConsumerTemplatesDir();
|
|
3883
4101
|
for (const fileName of templateContentFilenames(kind)) {
|
|
3884
|
-
const consumerFile =
|
|
3885
|
-
if (
|
|
4102
|
+
const consumerFile = path12.join(consumerDir, fileName);
|
|
4103
|
+
if (fs9.existsSync(consumerFile)) {
|
|
3886
4104
|
try {
|
|
3887
|
-
return
|
|
4105
|
+
return fs9.readFileSync(consumerFile, "utf8");
|
|
3888
4106
|
} catch (error) {
|
|
3889
4107
|
console.error(`[TemplateInjector] Could not read consumer template: ${consumerFile}`, error);
|
|
3890
4108
|
}
|
|
@@ -3894,9 +4112,9 @@ var resolveTemplateContent = (kind) => {
|
|
|
3894
4112
|
if (override !== null) return override;
|
|
3895
4113
|
const builtInName = BUILT_IN_TEMPLATE_FILENAMES[kind];
|
|
3896
4114
|
if (builtInName) {
|
|
3897
|
-
const bundled =
|
|
4115
|
+
const bundled = path12.join(templatesDir, builtInName);
|
|
3898
4116
|
try {
|
|
3899
|
-
return
|
|
4117
|
+
return fs9.readFileSync(bundled, "utf8");
|
|
3900
4118
|
} catch (error) {
|
|
3901
4119
|
console.error(`[TemplateInjector] Could not read bundled template: ${bundled}`, error);
|
|
3902
4120
|
return null;
|
|
@@ -3910,11 +4128,11 @@ var ensureConsumerTemplateConfigLoaded = () => {
|
|
|
3910
4128
|
consumerTemplateConfig ??= (async () => {
|
|
3911
4129
|
const dir = getConsumerTemplatesDir();
|
|
3912
4130
|
for (const fileName of ["templateRules.ts", "templateRules.mjs", "templateRules.js"]) {
|
|
3913
|
-
const rulesFile =
|
|
3914
|
-
if (!
|
|
3915
|
-
const resolvedRulesFile =
|
|
3916
|
-
const resolvedRoot =
|
|
3917
|
-
if (!resolvedRulesFile.startsWith(resolvedRoot +
|
|
4131
|
+
const rulesFile = path12.join(dir, fileName);
|
|
4132
|
+
if (!fs9.existsSync(rulesFile)) continue;
|
|
4133
|
+
const resolvedRulesFile = path12.resolve(rulesFile);
|
|
4134
|
+
const resolvedRoot = path12.resolve(ROOT_DIR7);
|
|
4135
|
+
if (!resolvedRulesFile.startsWith(resolvedRoot + path12.sep) && resolvedRulesFile !== resolvedRoot) {
|
|
3918
4136
|
console.warn(
|
|
3919
4137
|
`[TemplateInjector] Template rules file resolves outside project root \u2014 skipping: ${rulesFile}`
|
|
3920
4138
|
);
|
|
@@ -3932,7 +4150,7 @@ var ensureConsumerTemplateConfigLoaded = () => {
|
|
|
3932
4150
|
};
|
|
3933
4151
|
var isEmptyFile = (filePath) => {
|
|
3934
4152
|
try {
|
|
3935
|
-
const content =
|
|
4153
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
3936
4154
|
return content.trim().length === 0;
|
|
3937
4155
|
} catch {
|
|
3938
4156
|
return false;
|
|
@@ -3940,7 +4158,7 @@ var isEmptyFile = (filePath) => {
|
|
|
3940
4158
|
};
|
|
3941
4159
|
var isCommentOnlyFile = (filePath) => {
|
|
3942
4160
|
try {
|
|
3943
|
-
const content =
|
|
4161
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
3944
4162
|
const withoutBlockComments = content.replaceAll(/\/\*[\s\S]*?\*\//g, "");
|
|
3945
4163
|
const withoutLineComments = withoutBlockComments.replaceAll(/(^|\s)\/\/.*$/gm, "$1");
|
|
3946
4164
|
return withoutLineComments.trim().length === 0;
|
|
@@ -3974,7 +4192,7 @@ var isVersionedSyncFile = (filePath) => {
|
|
|
3974
4192
|
return isVersionedSyncFileName(filePath);
|
|
3975
4193
|
};
|
|
3976
4194
|
var getFileName = (filePath) => {
|
|
3977
|
-
return
|
|
4195
|
+
return path12.basename(filePath.replaceAll("\\", "/"));
|
|
3978
4196
|
};
|
|
3979
4197
|
var stripTsExtension = (fileName) => {
|
|
3980
4198
|
return fileName.replace(/\.ts$/, "");
|
|
@@ -4050,7 +4268,7 @@ var getInvalidVersionMessage = (filePath) => {
|
|
|
4050
4268
|
var computeSrcRelativePath = (filePath) => {
|
|
4051
4269
|
try {
|
|
4052
4270
|
const srcDir = getSrcDir4();
|
|
4053
|
-
const absolute =
|
|
4271
|
+
const absolute = path12.resolve(filePath);
|
|
4054
4272
|
const normalizedSrc = srcDir.replaceAll("\\", "/");
|
|
4055
4273
|
const normalizedAbs = absolute.replaceAll("\\", "/");
|
|
4056
4274
|
if (!normalizedAbs.startsWith(`${normalizedSrc}/`)) return null;
|
|
@@ -4098,7 +4316,7 @@ var getPairedSyncFile = (filePath) => {
|
|
|
4098
4316
|
var hasPairedFile = (filePath) => {
|
|
4099
4317
|
const pairedPath = getPairedSyncFile(filePath);
|
|
4100
4318
|
if (!pairedPath) return false;
|
|
4101
|
-
return
|
|
4319
|
+
return fs9.existsSync(pairedPath);
|
|
4102
4320
|
};
|
|
4103
4321
|
var extractSyncPagePath2 = (filePath) => {
|
|
4104
4322
|
const normalized = filePath.replaceAll("\\", "/");
|
|
@@ -4111,14 +4329,14 @@ var extractSyncName2 = (filePath) => {
|
|
|
4111
4329
|
const normalized = filePath.replaceAll("\\", "/");
|
|
4112
4330
|
const match = /_sync\/(.+)\.ts$/.exec(normalized);
|
|
4113
4331
|
if (!match) {
|
|
4114
|
-
const basename =
|
|
4332
|
+
const basename = path12.basename(filePath, ".ts");
|
|
4115
4333
|
return basename.replace(/_server_v\d+$/, "").replace(/_client_v\d+$/, "");
|
|
4116
4334
|
}
|
|
4117
4335
|
return (match[1] ?? "").replace(/_server_v\d+$/, "").replace(/_client_v\d+$/, "");
|
|
4118
4336
|
};
|
|
4119
4337
|
var extractClientInputFromFile = (filePath) => {
|
|
4120
4338
|
try {
|
|
4121
|
-
const content =
|
|
4339
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
4122
4340
|
const syncParamsMatch = /interface\s+SyncParams\s*\{/.exec(content);
|
|
4123
4341
|
if (!syncParamsMatch) return null;
|
|
4124
4342
|
const searchRegion = content.slice(syncParamsMatch.index + syncParamsMatch[0].length);
|
|
@@ -4149,7 +4367,7 @@ var extractClientInputFromFile = (filePath) => {
|
|
|
4149
4367
|
var extractClientInputFromGeneratedTypes = (pagePath, syncName) => {
|
|
4150
4368
|
try {
|
|
4151
4369
|
const generatedTypesPath = getGeneratedSocketTypesPath6();
|
|
4152
|
-
const content =
|
|
4370
|
+
const content = fs9.readFileSync(generatedTypesPath, "utf8");
|
|
4153
4371
|
const escapeRegex = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
4154
4372
|
const escapedPagePath = escapeRegex(pagePath);
|
|
4155
4373
|
const escapedSyncName = escapeRegex(syncName);
|
|
@@ -4195,7 +4413,7 @@ var calculateRelativePath = (filePath) => {
|
|
|
4195
4413
|
const srcRelative = computeSrcRelativePath(filePath);
|
|
4196
4414
|
if (srcRelative !== null) {
|
|
4197
4415
|
try {
|
|
4198
|
-
const srcDepthFromRoot =
|
|
4416
|
+
const srcDepthFromRoot = path12.relative(ROOT_DIR7, getSrcDir4()).replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0).length;
|
|
4199
4417
|
const dirSegmentsAfterSrc = Math.max(
|
|
4200
4418
|
0,
|
|
4201
4419
|
srcRelative.split("/").filter((segment) => segment.length > 0).length - 1
|
|
@@ -4274,7 +4492,7 @@ var getTemplate = (filePath) => {
|
|
|
4274
4492
|
var injectTemplate = async (filePath) => {
|
|
4275
4493
|
await ensureConsumerTemplateConfigLoaded();
|
|
4276
4494
|
if (getRouteFilenameValidationMessage(filePath)) {
|
|
4277
|
-
|
|
4495
|
+
fs9.writeFileSync(filePath, getInvalidVersionMessage(filePath), "utf8");
|
|
4278
4496
|
console.log(`[TemplateInjector] Invalid route filename, injected guidance: ${filePath}`);
|
|
4279
4497
|
return true;
|
|
4280
4498
|
}
|
|
@@ -4283,7 +4501,7 @@ var injectTemplate = async (filePath) => {
|
|
|
4283
4501
|
return false;
|
|
4284
4502
|
}
|
|
4285
4503
|
try {
|
|
4286
|
-
|
|
4504
|
+
fs9.writeFileSync(filePath, template, "utf8");
|
|
4287
4505
|
console.log(`[TemplateInjector] Injected template into: ${filePath}`);
|
|
4288
4506
|
return true;
|
|
4289
4507
|
} catch (error) {
|
|
@@ -4339,18 +4557,10 @@ var rewriteClientInputType = (content) => {
|
|
|
4339
4557
|
);
|
|
4340
4558
|
};
|
|
4341
4559
|
var rewriteClientInputTypeAst = (content, sourceFileName) => {
|
|
4342
|
-
const
|
|
4343
|
-
sourceFileName,
|
|
4344
|
-
src,
|
|
4345
|
-
ts9.ScriptTarget.Latest,
|
|
4346
|
-
/* setParentNodes */
|
|
4347
|
-
true,
|
|
4348
|
-
ts9.ScriptKind.TS
|
|
4349
|
-
);
|
|
4350
|
-
const sourceFile = parseSource(content);
|
|
4560
|
+
const sourceFile = parseSourceText(sourceFileName, content, ScriptKind3.TS);
|
|
4351
4561
|
let syncParamsInterface;
|
|
4352
4562
|
for (const stmt of sourceFile.statements) {
|
|
4353
|
-
if (
|
|
4563
|
+
if (isInterfaceDeclaration6(stmt) && stmt.name.text === "SyncParams") {
|
|
4354
4564
|
syncParamsInterface = stmt;
|
|
4355
4565
|
break;
|
|
4356
4566
|
}
|
|
@@ -4358,30 +4568,18 @@ var rewriteClientInputTypeAst = (content, sourceFileName) => {
|
|
|
4358
4568
|
if (!syncParamsInterface) return null;
|
|
4359
4569
|
let clientInputMember;
|
|
4360
4570
|
for (const member of syncParamsInterface.members) {
|
|
4361
|
-
if (
|
|
4571
|
+
if (isPropertySignatureDeclaration4(member) && isIdentifier8(member.name) && member.name.text === "clientInput") {
|
|
4362
4572
|
clientInputMember = member;
|
|
4363
4573
|
break;
|
|
4364
4574
|
}
|
|
4365
4575
|
}
|
|
4366
4576
|
if (!clientInputMember?.type) return null;
|
|
4367
|
-
if (!
|
|
4577
|
+
if (!isTypeLiteralNode3(clientInputMember.type)) return null;
|
|
4368
4578
|
const typeNode = clientInputMember.type;
|
|
4369
4579
|
const start = typeNode.getStart(sourceFile);
|
|
4370
4580
|
const end = typeNode.getEnd();
|
|
4371
4581
|
const rewritten = `${content.slice(0, start)}SyncClientInput<PagePath, SyncName>${content.slice(end)}`;
|
|
4372
|
-
const
|
|
4373
|
-
const verifyProgram = ts9.createProgram({
|
|
4374
|
-
rootNames: [sourceFileName],
|
|
4375
|
-
options: { noResolve: true, skipLibCheck: true },
|
|
4376
|
-
// Supply the in-memory source so `ts.createProgram` never touches the disk.
|
|
4377
|
-
host: {
|
|
4378
|
-
...ts9.createCompilerHost({}),
|
|
4379
|
-
getSourceFile: (name) => name === sourceFileName ? reparsedFile : void 0,
|
|
4380
|
-
fileExists: (name) => name === sourceFileName,
|
|
4381
|
-
readFile: (name) => name === sourceFileName ? rewritten : void 0
|
|
4382
|
-
}
|
|
4383
|
-
});
|
|
4384
|
-
const syntaxErrors = verifyProgram.getSyntacticDiagnostics(reparsedFile);
|
|
4582
|
+
const syntaxErrors = transpileSourceText(sourceFileName, rewritten).diagnostics ?? [];
|
|
4385
4583
|
if (syntaxErrors.length > 0) {
|
|
4386
4584
|
console.log(
|
|
4387
4585
|
`[TemplateInjector] AST rewrite produced invalid TypeScript for ${sourceFileName} \u2014 leaving untouched`,
|
|
@@ -4411,10 +4609,10 @@ var updateClientFileForPairedServer = async (clientFilePath) => {
|
|
|
4411
4609
|
try {
|
|
4412
4610
|
const pagePath = extractSyncPagePath2(clientFilePath);
|
|
4413
4611
|
const syncName = extractSyncName2(clientFilePath);
|
|
4414
|
-
let content =
|
|
4612
|
+
let content = fs9.readFileSync(clientFilePath, "utf8");
|
|
4415
4613
|
content = ensureImportedTypes(content, clientFilePath);
|
|
4416
4614
|
content = insertTypeAliases(content, pagePath, syncName);
|
|
4417
|
-
const astResult = rewriteClientInputTypeAst(content,
|
|
4615
|
+
const astResult = rewriteClientInputTypeAst(content, path12.basename(clientFilePath));
|
|
4418
4616
|
if (astResult === null) {
|
|
4419
4617
|
console.log(
|
|
4420
4618
|
`[TemplateInjector] AST clientInput rewrite unavailable for ${clientFilePath} \u2014 using regex fallback`,
|
|
@@ -4426,7 +4624,7 @@ var updateClientFileForPairedServer = async (clientFilePath) => {
|
|
|
4426
4624
|
}
|
|
4427
4625
|
content = addServerOutputToParams(content);
|
|
4428
4626
|
content = addServerOutputToDestructuring(content);
|
|
4429
|
-
|
|
4627
|
+
fs9.writeFileSync(clientFilePath, content, "utf8");
|
|
4430
4628
|
console.log(`[TemplateInjector] Updated client file to use paired types (preserved code): ${clientFilePath}`);
|
|
4431
4629
|
return true;
|
|
4432
4630
|
} catch (error) {
|
|
@@ -4467,7 +4665,7 @@ var splitAtMainBody = (content) => {
|
|
|
4467
4665
|
};
|
|
4468
4666
|
var updateClientFileForDeletedServer = async (clientFilePath, clientInputTypes) => {
|
|
4469
4667
|
try {
|
|
4470
|
-
let content =
|
|
4668
|
+
let content = fs9.readFileSync(clientFilePath, "utf8");
|
|
4471
4669
|
content = inlineClientInputType(content, clientInputTypes);
|
|
4472
4670
|
const [header, body] = splitAtMainBody(content);
|
|
4473
4671
|
const cleanedHeader = removeServerOutputFromDestructuring(removeServerOutputFromParams(header));
|
|
@@ -4475,7 +4673,7 @@ var updateClientFileForDeletedServer = async (clientFilePath, clientInputTypes)
|
|
|
4475
4673
|
content = removeGeneratedTypeImports(content);
|
|
4476
4674
|
content = removeTypeAliases(content);
|
|
4477
4675
|
content = content.replaceAll(/\n{3,}/g, "\n\n");
|
|
4478
|
-
|
|
4676
|
+
fs9.writeFileSync(clientFilePath, content, "utf8");
|
|
4479
4677
|
console.log(`[TemplateInjector] Updated client file for deleted server (preserved code): ${clientFilePath}`);
|
|
4480
4678
|
return true;
|
|
4481
4679
|
} catch (error) {
|
|
@@ -4501,7 +4699,7 @@ var injectServerTemplateWithClientInput = async (serverFilePath, clientInputType
|
|
|
4501
4699
|
/clientInput:\s*\{[^}]*\}/s,
|
|
4502
4700
|
(_match) => `clientInput: ${clientInputTypes}`
|
|
4503
4701
|
);
|
|
4504
|
-
|
|
4702
|
+
fs9.writeFileSync(serverFilePath, content, "utf8");
|
|
4505
4703
|
console.log(`[TemplateInjector] Injected server template with clientInput: ${serverFilePath}`);
|
|
4506
4704
|
return true;
|
|
4507
4705
|
} catch (error) {
|
|
@@ -4511,24 +4709,24 @@ var injectServerTemplateWithClientInput = async (serverFilePath, clientInputType
|
|
|
4511
4709
|
};
|
|
4512
4710
|
|
|
4513
4711
|
// src/importDependencyGraph.ts
|
|
4514
|
-
import
|
|
4515
|
-
import
|
|
4712
|
+
import fs10 from "fs";
|
|
4713
|
+
import path13 from "path";
|
|
4516
4714
|
import { ROOT_DIR as ROOT_DIR8, getServerFunctionDirs as getServerFunctionDirs2, getSharedDir, getSrcDir as getSrcDir5 } from "@luckystack/core";
|
|
4517
4715
|
var SUPPORTED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"];
|
|
4518
|
-
var normalizePath4 = (value) =>
|
|
4716
|
+
var normalizePath4 = (value) => path13.resolve(value).replaceAll("\\", "/");
|
|
4519
4717
|
var isSupportedScriptFile = (value) => {
|
|
4520
4718
|
return SUPPORTED_EXTENSIONS.some((extension) => value.endsWith(extension));
|
|
4521
4719
|
};
|
|
4522
4720
|
var existsFile = (value) => {
|
|
4523
4721
|
try {
|
|
4524
|
-
return
|
|
4722
|
+
return fs10.existsSync(value) && fs10.statSync(value).isFile();
|
|
4525
4723
|
} catch {
|
|
4526
4724
|
return false;
|
|
4527
4725
|
}
|
|
4528
4726
|
};
|
|
4529
4727
|
var existsDirectory = (value) => {
|
|
4530
4728
|
try {
|
|
4531
|
-
return
|
|
4729
|
+
return fs10.existsSync(value) && fs10.statSync(value).isDirectory();
|
|
4532
4730
|
} catch {
|
|
4533
4731
|
return false;
|
|
4534
4732
|
}
|
|
@@ -4539,16 +4737,16 @@ var collectScriptFiles = (dir, output, visited = /* @__PURE__ */ new Set()) => {
|
|
|
4539
4737
|
}
|
|
4540
4738
|
let realDir;
|
|
4541
4739
|
try {
|
|
4542
|
-
realDir =
|
|
4740
|
+
realDir = fs10.realpathSync(dir);
|
|
4543
4741
|
} catch {
|
|
4544
4742
|
return;
|
|
4545
4743
|
}
|
|
4546
4744
|
if (visited.has(realDir)) return;
|
|
4547
4745
|
visited.add(realDir);
|
|
4548
|
-
const entries =
|
|
4746
|
+
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
4549
4747
|
for (const entry of entries) {
|
|
4550
4748
|
if (entry.name === "node_modules") continue;
|
|
4551
|
-
const fullPath =
|
|
4749
|
+
const fullPath = path13.join(dir, entry.name);
|
|
4552
4750
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
4553
4751
|
if (existsDirectory(fullPath)) {
|
|
4554
4752
|
collectScriptFiles(fullPath, output, visited);
|
|
@@ -4567,7 +4765,7 @@ var SCOPED_FILES_TTL_MS = 1e3;
|
|
|
4567
4765
|
var extractImportSpecifiers = (filePath) => {
|
|
4568
4766
|
let mtimeMs = 0;
|
|
4569
4767
|
try {
|
|
4570
|
-
mtimeMs =
|
|
4768
|
+
mtimeMs = fs10.statSync(filePath).mtimeMs;
|
|
4571
4769
|
} catch {
|
|
4572
4770
|
specifiersCache.delete(filePath);
|
|
4573
4771
|
return [];
|
|
@@ -4577,7 +4775,7 @@ var extractImportSpecifiers = (filePath) => {
|
|
|
4577
4775
|
return cached.specifiers;
|
|
4578
4776
|
}
|
|
4579
4777
|
try {
|
|
4580
|
-
const source =
|
|
4778
|
+
const source = fs10.readFileSync(filePath, "utf8");
|
|
4581
4779
|
const specifiers = /* @__PURE__ */ new Set();
|
|
4582
4780
|
const importExportRegex = /(?:import|export)\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
4583
4781
|
const dynamicImportRegex = /import\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
@@ -4612,7 +4810,7 @@ var tryResolveWithExtensions = (basePath) => {
|
|
|
4612
4810
|
}
|
|
4613
4811
|
if (existsDirectory(basePath)) {
|
|
4614
4812
|
for (const extension of SUPPORTED_EXTENSIONS) {
|
|
4615
|
-
const indexFile =
|
|
4813
|
+
const indexFile = path13.join(basePath, `index${extension}`);
|
|
4616
4814
|
if (existsFile(indexFile)) {
|
|
4617
4815
|
return normalizePath4(indexFile);
|
|
4618
4816
|
}
|
|
@@ -4625,18 +4823,18 @@ var resolveImportToFile = (importerPath, specifier) => {
|
|
|
4625
4823
|
return null;
|
|
4626
4824
|
}
|
|
4627
4825
|
if (specifier === "config") {
|
|
4628
|
-
return tryResolveWithExtensions(
|
|
4826
|
+
return tryResolveWithExtensions(path13.join(ROOT_DIR8, "config"));
|
|
4629
4827
|
}
|
|
4630
4828
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
4631
|
-
const relativeBase =
|
|
4829
|
+
const relativeBase = path13.resolve(path13.dirname(importerPath), specifier);
|
|
4632
4830
|
return tryResolveWithExtensions(relativeBase);
|
|
4633
4831
|
}
|
|
4634
4832
|
if (specifier.startsWith("src/") || specifier.startsWith("@/")) {
|
|
4635
4833
|
const sourcePath = specifier.startsWith("@/") ? specifier.slice(2) : specifier.slice(4);
|
|
4636
|
-
return tryResolveWithExtensions(
|
|
4834
|
+
return tryResolveWithExtensions(path13.join(getSrcDir5(), sourcePath));
|
|
4637
4835
|
}
|
|
4638
4836
|
if (specifier.startsWith("shared/")) {
|
|
4639
|
-
return tryResolveWithExtensions(
|
|
4837
|
+
return tryResolveWithExtensions(path13.join(getSharedDir(), specifier.slice(7)));
|
|
4640
4838
|
}
|
|
4641
4839
|
return null;
|
|
4642
4840
|
};
|
|
@@ -4654,7 +4852,7 @@ var collectScopedFiles = () => {
|
|
|
4654
4852
|
for (const dir of getServerFunctionDirs2()) {
|
|
4655
4853
|
collectScriptFiles(dir, files);
|
|
4656
4854
|
}
|
|
4657
|
-
const configFile = tryResolveWithExtensions(
|
|
4855
|
+
const configFile = tryResolveWithExtensions(path13.join(ROOT_DIR8, "config"));
|
|
4658
4856
|
if (configFile) {
|
|
4659
4857
|
files.add(configFile);
|
|
4660
4858
|
}
|
|
@@ -4702,19 +4900,19 @@ var findDependentRouteFiles = (changedFilePath) => {
|
|
|
4702
4900
|
};
|
|
4703
4901
|
|
|
4704
4902
|
// src/prismaClientCheck.ts
|
|
4705
|
-
import
|
|
4706
|
-
import
|
|
4903
|
+
import fs11 from "fs";
|
|
4904
|
+
import path14 from "path";
|
|
4707
4905
|
import { spawn } from "child_process";
|
|
4708
4906
|
import { ROOT_DIR as ROOT_DIR9, tryCatch as tryCatch2 } from "@luckystack/core";
|
|
4709
|
-
var GENERATED_CLIENT_DIR =
|
|
4710
|
-
var GENERATED_CLIENT_MARKER =
|
|
4711
|
-
var DEFAULT_SCHEMA_PATH =
|
|
4712
|
-
var isPrismaClientMissing = () =>
|
|
4907
|
+
var GENERATED_CLIENT_DIR = path14.join(ROOT_DIR9, "node_modules", ".prisma", "client");
|
|
4908
|
+
var GENERATED_CLIENT_MARKER = path14.join(GENERATED_CLIENT_DIR, "schema.prisma");
|
|
4909
|
+
var DEFAULT_SCHEMA_PATH = path14.join(ROOT_DIR9, "prisma", "schema.prisma");
|
|
4910
|
+
var isPrismaClientMissing = () => fs11.existsSync(DEFAULT_SCHEMA_PATH) && !fs11.existsSync(GENERATED_CLIENT_MARKER);
|
|
4713
4911
|
var runPrismaGenerate = async () => tryCatch2(
|
|
4714
4912
|
() => new Promise((resolve, reject) => {
|
|
4715
4913
|
const localBinName = process.platform === "win32" ? "prisma.cmd" : "prisma";
|
|
4716
|
-
const localBin =
|
|
4717
|
-
const useLocal =
|
|
4914
|
+
const localBin = path14.join(ROOT_DIR9, "node_modules", ".bin", localBinName);
|
|
4915
|
+
const useLocal = fs11.existsSync(localBin);
|
|
4718
4916
|
const [cmd, args] = useLocal ? [localBin, ["generate"]] : [process.platform === "win32" ? "npx.cmd" : "npx", ["prisma", "generate"]];
|
|
4719
4917
|
const isWinShim = process.platform === "win32" && /\.(cmd|bat)$/i.test(cmd);
|
|
4720
4918
|
const child = isWinShim ? spawn(
|
|
@@ -4735,7 +4933,7 @@ var runPrismaGenerate = async () => tryCatch2(
|
|
|
4735
4933
|
|
|
4736
4934
|
// src/hotReload.ts
|
|
4737
4935
|
import { tryCatch as tryCatch3, getProjectConfig, getLocaleReloader, isProductionRuntime } from "@luckystack/core";
|
|
4738
|
-
var normalizeFsPath = (value) =>
|
|
4936
|
+
var normalizeFsPath = (value) => path15.resolve(value).replaceAll("\\", "/");
|
|
4739
4937
|
var isGeneratedPath = (normalizedPath) => {
|
|
4740
4938
|
return normalizedPath.includes("apiTypes.generated.ts") || normalizedPath.includes("apiDocs.generated.json");
|
|
4741
4939
|
};
|
|
@@ -4943,7 +5141,7 @@ var setupWatchers = () => {
|
|
|
4943
5141
|
if (shouldInjectTemplate(filePath, { isNewFile: true })) {
|
|
4944
5142
|
if (isSyncServerFile(normalizedPath)) {
|
|
4945
5143
|
const clientPath = getPairedSyncFile(normalizedPath);
|
|
4946
|
-
if (clientPath &&
|
|
5144
|
+
if (clientPath && fs12.existsSync(clientPath) && !isEmptyFile(clientPath)) {
|
|
4947
5145
|
const clientInputTypes = extractClientInputFromFile(clientPath);
|
|
4948
5146
|
if (clientInputTypes) {
|
|
4949
5147
|
await injectServerTemplateWithClientInput(filePath, clientInputTypes);
|
|
@@ -5106,7 +5304,7 @@ var setupWatchers = () => {
|
|
|
5106
5304
|
scheduleReload("sync", async () => {
|
|
5107
5305
|
if (isSyncServerFile(normalizedPath)) {
|
|
5108
5306
|
const clientPath = getPairedSyncFile(normalizedPath);
|
|
5109
|
-
if (clientPath &&
|
|
5307
|
+
if (clientPath && fs12.existsSync(clientPath)) {
|
|
5110
5308
|
const pagePath = extractSyncPagePath2(normalizedPath);
|
|
5111
5309
|
const syncName = extractSyncName2(normalizedPath);
|
|
5112
5310
|
const clientInputTypes = extractClientInputFromGeneratedTypes(pagePath, syncName);
|