@superblocksteam/sdk 2.0.96 → 2.0.97-next.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.
Files changed (24) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/cli-replacement/dev.d.mts.map +1 -1
  3. package/dist/cli-replacement/dev.mjs +125 -21
  4. package/dist/cli-replacement/dev.mjs.map +1 -1
  5. package/dist/parse-sdk-registry.d.mts.map +1 -1
  6. package/dist/parse-sdk-registry.mjs +5 -130
  7. package/dist/parse-sdk-registry.mjs.map +1 -1
  8. package/dist/parse-sdk-registry.test.mjs +11 -1
  9. package/dist/parse-sdk-registry.test.mjs.map +1 -1
  10. package/package.json +6 -6
  11. package/src/cli-replacement/dev.mts +136 -37
  12. package/src/parse-sdk-registry.mts +8 -181
  13. package/src/parse-sdk-registry.test.mts +17 -1
  14. package/tsconfig.tsbuildinfo +1 -1
  15. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.d.ts +0 -5
  16. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.d.ts.map +0 -1
  17. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.js +0 -61
  18. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.js.map +0 -1
  19. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.test.d.ts +0 -2
  20. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.test.d.ts.map +0 -1
  21. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.test.js +0 -32
  22. package/dist/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.test.js.map +0 -1
  23. package/src/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.test.ts +0 -60
  24. package/src/cli-replacement/assets/git-workflows/github-superblocks-sync-workflow.ts +0 -70
@@ -1 +1 @@
1
- {"version":3,"file":"parse-sdk-registry.test.mjs","sourceRoot":"","sources":["../src/parse-sdk-registry.test.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse-sdk-registry.test.mjs","sourceRoot":"","sources":["../src/parse-sdk-registry.test.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/sdk",
3
- "version": "2.0.96",
3
+ "version": "2.0.97-next.0",
4
4
  "description": "Superblocks JS SDK",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "license": "Superblocks Community Software License",
@@ -48,11 +48,11 @@
48
48
  "vite-tsconfig-paths": "^6.0.4",
49
49
  "winston": "^3.17.0",
50
50
  "yaml": "^2.7.1",
51
- "@superblocksteam/library-shared": "2.0.96",
52
- "@superblocksteam/shared": "0.9567.4",
53
- "@superblocksteam/telemetry": "2.0.96",
54
- "@superblocksteam/util": "2.0.96",
55
- "@superblocksteam/vite-plugin-file-sync": "2.0.96"
51
+ "@superblocksteam/library-shared": "2.0.97-next.0",
52
+ "@superblocksteam/shared": "0.9568.0",
53
+ "@superblocksteam/telemetry": "2.0.97-next.0",
54
+ "@superblocksteam/util": "2.0.97-next.0",
55
+ "@superblocksteam/vite-plugin-file-sync": "2.0.97-next.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@eslint/js": "^9.39.2",
@@ -5,7 +5,9 @@ import * as readline from "node:readline";
5
5
  import { promisify } from "node:util";
6
6
  import { SpanStatusCode } from "@opentelemetry/api";
7
7
  import {
8
+ buildGithubSuperblocksSyncWorkflow,
8
9
  ConflictError,
10
+ isGitHubRemoteUrl,
9
11
  NotFoundError,
10
12
  SUPERBLOCKS_LIVE_GIT_BRANCH,
11
13
  } from "@superblocksteam/shared";
@@ -33,7 +35,6 @@ import { createDevServer } from "../dev-utils/dev-server.mjs";
33
35
  import { AUTO_UPGRADE_EXIT_CODE } from "../index.js";
34
36
  import { getTracer } from "../telemetry/index.js";
35
37
  import { getErrorMeta, getLogger, type Logger } from "../telemetry/logging.js";
36
- import { buildGithubSuperblocksSyncWorkflow } from "./assets/git-workflows/github-superblocks-sync-workflow.js";
37
38
  import { checkVersionsAndWritePackageJson } from "./automatic-upgrades.js";
38
39
  import { getCurrentCliVersion } from "./version-detection.js";
39
40
  import type {
@@ -51,6 +52,7 @@ import type { DraftInterface } from "@superblocksteam/vite-plugin-file-sync/draf
51
52
  import type { GitService } from "@superblocksteam/vite-plugin-file-sync/git-service";
52
53
 
53
54
  const exec = promisify(child_process.exec);
55
+
54
56
  const passErrorToVSCode = (message: string | undefined, logger: Logger) => {
55
57
  if (message && process.env.SUPERBLOCKS_VSCODE === "true") {
56
58
  // Prefixing with `clierr:` will make the VS code extension capture this message and show it to the user.
@@ -479,18 +481,17 @@ export async function dev(options: {
479
481
  process.env.SUPERBLOCKS_APP_TEMPLATE_NAME ??
480
482
  options.prefetchedApplication?.application?.templateName;
481
483
  const sdkApiEnabled = isSdkApiTemplate(templateName);
484
+ const isAppFullstackTemplate = templateName === "app-fullstack";
485
+ const rawFlagBootstrap = currentUser.flagBootstrap as
486
+ | Record<string, unknown>
487
+ | undefined;
482
488
  const flagBootstrap = {
483
- ...(currentUser.flagBootstrap as
484
- | Record<string, unknown>
485
- | undefined),
489
+ ...rawFlagBootstrap,
486
490
  "clark.sdk-api.enabled": sdkApiEnabled,
487
491
  "superblocks.native-git.enabled":
488
- sdkApiEnabled &&
489
- !!(
490
- currentUser.flagBootstrap as
491
- | Record<string, unknown>
492
- | undefined
493
- )?.["superblocks.native-git.enabled"],
492
+ (isAppFullstackTemplate &&
493
+ !!rawFlagBootstrap?.["superblocks.native-git.enabled"]) ||
494
+ !!rawFlagBootstrap?.["superblocks.native-git.forced"],
494
495
  };
495
496
 
496
497
  aiService = new AiService({
@@ -572,7 +573,14 @@ export async function dev(options: {
572
573
  });
573
574
 
574
575
  if (!bootstrappedGitService) {
575
- logger.info("No git remote configured, skipping git sync");
576
+ logger.info("[git] startup git sync skipped", {
577
+ gitCategory: "setup",
578
+ gitOperation: "bootstrap",
579
+ gitOutcome: "skipped",
580
+ gitReason: "no_remote_configured",
581
+ applicationId: applicationConfig.id,
582
+ workDir: cwd,
583
+ });
576
584
  gitSpan.end();
577
585
  return;
578
586
  }
@@ -607,14 +615,30 @@ export async function dev(options: {
607
615
  );
608
616
  } catch (syncError) {
609
617
  logger.warn(
610
- `Git remote sync failed (local repo still usable): ${syncError instanceof Error ? syncError.message : String(syncError)}`,
618
+ "[git] startup remote sync failed but local repo remains usable",
619
+ {
620
+ gitCategory: "setup",
621
+ gitOperation: "fetch-and-ensure-live-branch",
622
+ gitOutcome: "failed",
623
+ applicationId: applicationConfig.id,
624
+ workDir: cwd,
625
+ ...getGitErrorFields(syncError),
626
+ },
611
627
  );
612
628
  }
613
629
  } catch (gitError) {
614
630
  // Init/configure/ensureGitRepo failed — repo is not usable
615
631
  gitService = undefined;
616
632
  logger.warn(
617
- `Git setup failed, continuing without git: ${gitError instanceof Error ? gitError.message : String(gitError)}`,
633
+ "[git] startup git setup failed, continuing without git",
634
+ {
635
+ gitCategory: "setup",
636
+ gitOperation: "bootstrap",
637
+ gitOutcome: "failed",
638
+ applicationId: applicationConfig.id,
639
+ workDir: cwd,
640
+ ...getGitErrorFields(gitError),
641
+ },
618
642
  );
619
643
  gitSpan.setStatus({
620
644
  code: SpanStatusCode.ERROR,
@@ -748,10 +772,22 @@ export async function dev(options: {
748
772
  () => false,
749
773
  );
750
774
  if (!hasGit) {
751
- logger.warn(
752
- "[git] activateRuntimeGitService: .git directory disappeared, clearing cached git service",
753
- );
775
+ logger.warn("[git] runtime git service cache invalidated", {
776
+ gitCategory: "setup",
777
+ gitOperation: "activate-runtime-service",
778
+ gitOutcome: "failed",
779
+ gitReason: "missing_git_directory",
780
+ workDir: cwd,
781
+ });
754
782
  gitService = undefined;
783
+ activeDbfsBranchName = await ensureRuntimeDbfsBranchConsistency({
784
+ sdk,
785
+ applicationConfig,
786
+ logger,
787
+ lockService,
788
+ syncService,
789
+ currentBranchName: activeDbfsBranchName,
790
+ });
755
791
  return undefined;
756
792
  }
757
793
 
@@ -776,6 +812,16 @@ export async function dev(options: {
776
812
  userEmail: gitUserEmail,
777
813
  });
778
814
  if (!runtimeGitService) {
815
+ // Git may have been disconnected while this dev server is running.
816
+ // Reconcile lock/sync branch context back to non-git runtime state.
817
+ activeDbfsBranchName = await ensureRuntimeDbfsBranchConsistency({
818
+ sdk,
819
+ applicationConfig,
820
+ logger,
821
+ lockService,
822
+ syncService,
823
+ currentBranchName: activeDbfsBranchName,
824
+ });
779
825
  return undefined;
780
826
  }
781
827
 
@@ -800,9 +846,14 @@ export async function dev(options: {
800
846
  gitService = runtimeGitService;
801
847
  return gitService;
802
848
  } catch (error) {
803
- logger.warn(
804
- `Git runtime bootstrap failed: ${error instanceof Error ? error.message : String(error)}`,
805
- );
849
+ logger.warn("[git] runtime bootstrap failed", {
850
+ gitCategory: "setup",
851
+ gitOperation: "runtime-bootstrap",
852
+ gitOutcome: "failed",
853
+ applicationId: applicationConfig.id,
854
+ workDir: cwd,
855
+ ...getGitErrorFields(error),
856
+ });
806
857
  return undefined;
807
858
  }
808
859
  };
@@ -818,6 +869,7 @@ export async function dev(options: {
818
869
  syncService: syncService,
819
870
  lockService: lockService,
820
871
  aiService: aiService,
872
+ gitService: gitService,
821
873
  activateGitService: activateRuntimeGitService,
822
874
  snapshotManager: snapshotManager,
823
875
  logger: options.logger,
@@ -864,6 +916,17 @@ export async function dev(options: {
864
916
  // Git sync helpers
865
917
  // ---------------------------------------------------------------------------
866
918
 
919
+ function getGitErrorFields(error: unknown): {
920
+ gitErrorKind: string;
921
+ gitErrorMessage: string;
922
+ } {
923
+ const meta = getErrorMeta(error);
924
+ return {
925
+ gitErrorKind: meta.error.kind,
926
+ gitErrorMessage: meta.error.message,
927
+ };
928
+ }
929
+
867
930
  async function bootstrapGitService({
868
931
  sdk,
869
932
  applicationId,
@@ -897,10 +960,12 @@ async function bootstrapGitService({
897
960
 
898
961
  const service = createGitService(cwd);
899
962
  let credentials: { username: string; token: string } | undefined;
963
+ let gitRemoteHost: string | undefined;
900
964
 
901
965
  if (gitConfig.hasCredential) {
902
966
  try {
903
967
  const host = new URL(gitConfig.gitRemoteUrl).hostname;
968
+ gitRemoteHost = host;
904
969
  const freshToken = await gitConfigSdk.getGitFreshToken(
905
970
  host,
906
971
  applicationId,
@@ -908,8 +973,16 @@ async function bootstrapGitService({
908
973
  if (freshToken) {
909
974
  credentials = freshToken;
910
975
  }
911
- } catch {
912
- logger.warn("Could not fetch git credentials, continuing without auth");
976
+ } catch (error) {
977
+ logger.warn("[git] credential fetch failed, continuing without auth", {
978
+ gitCategory: "setup",
979
+ gitOperation: "fetch-credentials",
980
+ gitOutcome: "failed",
981
+ applicationId,
982
+ gitRemoteHost,
983
+ gitRemoteUrl: gitConfig.gitRemoteUrl,
984
+ ...getGitErrorFields(error),
985
+ });
913
986
  }
914
987
  }
915
988
 
@@ -928,9 +1001,14 @@ async function fetchAndEnsureLiveBranch(
928
1001
  await git.fetch();
929
1002
  } catch (error) {
930
1003
  fetchError = error;
931
- getLogger().warn(
932
- `${errorPrefix}: ${error instanceof Error ? error.message : String(error)}`,
933
- );
1004
+ getLogger().warn("[git] fetch and ensure live branch failed", {
1005
+ gitCategory: "setup",
1006
+ gitOperation: "fetch-and-ensure-live-branch",
1007
+ gitOutcome: "failed",
1008
+ gitReason: errorPrefix,
1009
+ workDir: git.workDir,
1010
+ ...getGitErrorFields(error),
1011
+ });
934
1012
  }
935
1013
  // Always ensure the local superblocks/live branch exists,
936
1014
  // even if fetch failed (remote may not be reachable yet).
@@ -961,9 +1039,15 @@ async function ensureGitRepo(
961
1039
  `refs/heads/${SUPERBLOCKS_LIVE_GIT_BRANCH}`,
962
1040
  ])
963
1041
  .catch((err) => {
964
- getLogger().warn(
965
- `[git] ensureGitRepo: ls-remote failed (remote may be unreachable): ${err instanceof Error ? err.message : String(err)}`,
966
- );
1042
+ getLogger().warn("[git] ensure repo ls-remote failed", {
1043
+ gitCategory: "setup",
1044
+ gitOperation: "ensure-repo",
1045
+ gitOutcome: "failed",
1046
+ gitRemote: "origin",
1047
+ gitBranch: SUPERBLOCKS_LIVE_GIT_BRANCH,
1048
+ gitRemoteUrl: remoteUrl,
1049
+ ...getGitErrorFields(err),
1050
+ });
967
1051
  return "";
968
1052
  });
969
1053
 
@@ -1003,17 +1087,36 @@ async function ensureGitRepo(
1003
1087
  const remotes = await git.getRemotes(true);
1004
1088
  const origin = remotes.find((r) => r.name === "origin");
1005
1089
  if (origin && origin.refs.fetch !== remoteUrl) {
1006
- getLogger().warn(
1007
- `[git] ensureGitRepo: remote URL changed from "${origin.refs.fetch}" to "${remoteUrl}", updating`,
1008
- );
1090
+ getLogger().warn("[git] ensure repo remote url changed", {
1091
+ gitCategory: "setup",
1092
+ gitOperation: "ensure-repo",
1093
+ gitOutcome: "fallback",
1094
+ gitRemote: "origin",
1095
+ gitPreviousRemoteUrl: origin.refs.fetch,
1096
+ gitRemoteUrl: remoteUrl,
1097
+ });
1009
1098
  await git.remote(["set-url", "origin", remoteUrl]);
1010
1099
  } else if (!origin) {
1011
- getLogger().warn("[git] ensureGitRepo: no origin remote found, adding");
1100
+ getLogger().warn("[git] ensure repo origin remote missing, adding", {
1101
+ gitCategory: "setup",
1102
+ gitOperation: "ensure-repo",
1103
+ gitOutcome: "fallback",
1104
+ gitRemote: "origin",
1105
+ gitRemoteUrl: remoteUrl,
1106
+ });
1012
1107
  await git.addRemote("origin", remoteUrl);
1013
1108
  }
1014
1109
  } catch (remoteErr) {
1015
1110
  getLogger().warn(
1016
- `[git] ensureGitRepo: failed to inspect/update remotes, attempting fallback: ${remoteErr instanceof Error ? remoteErr.message : String(remoteErr)}`,
1111
+ "[git] ensure repo remote inspection failed, attempting fallback",
1112
+ {
1113
+ gitCategory: "setup",
1114
+ gitOperation: "ensure-repo",
1115
+ gitOutcome: "failed",
1116
+ gitRemote: "origin",
1117
+ gitRemoteUrl: remoteUrl,
1118
+ ...getGitErrorFields(remoteErr),
1119
+ },
1017
1120
  );
1018
1121
  try {
1019
1122
  await git.addRemote("origin", remoteUrl);
@@ -1028,15 +1131,11 @@ async function ensureGitRepo(
1028
1131
  await seedGithubWorkflowIfNeeded(git.workDir, remoteUrl);
1029
1132
  }
1030
1133
 
1031
- function isGithubRemote(remoteUrl: string): boolean {
1032
- return remoteUrl.includes("github.com");
1033
- }
1034
-
1035
1134
  async function seedGithubWorkflowIfNeeded(
1036
1135
  workDir: string,
1037
1136
  remoteUrl: string,
1038
1137
  ): Promise<void> {
1039
- if (!isGithubRemote(remoteUrl)) {
1138
+ if (!isGitHubRemoteUrl(remoteUrl)) {
1040
1139
  return;
1041
1140
  }
1042
1141
 
@@ -1,9 +1,10 @@
1
1
  import path from "node:path";
2
- import { parse } from "@babel/parser";
2
+ import { parseSdkRegistryFromContent } from "@superblocksteam/vite-plugin-file-sync/parsing";
3
3
 
4
4
  export type RegistryKeyToPath = Map<string, string>;
5
5
 
6
6
  type PathExists = (p: string) => Promise<boolean>;
7
+ const RESOLUTION_EXTENSIONS = [".ts", ".tsx", ".js"] as const;
7
8
 
8
9
  /**
9
10
  * Parse server/apis/index.ts to extract the mapping from registry key (used in
@@ -26,84 +27,9 @@ export async function parseSdkRegistry(
26
27
  root: string,
27
28
  pathExists: PathExists,
28
29
  ): Promise<RegistryKeyToPath> {
29
- const result = new Map<string, string>();
30
-
31
- let ast: ReturnType<typeof parse>;
32
- try {
33
- ast = parse(registryContent, {
34
- sourceType: "module",
35
- plugins: ["typescript"],
36
- });
37
- } catch {
38
- return result;
39
- }
40
-
41
- const body = ast.program.body;
42
-
43
- // Build import map: local name -> resolved path (relative to root)
44
- const importMap = new Map<string, string>();
45
- for (const node of body) {
46
- if (node.type !== "ImportDeclaration") continue;
47
- const imp = node;
48
- const specifier = imp.specifiers[0];
49
- if (!specifier || specifier.type !== "ImportDefaultSpecifier") continue;
50
- const localName = specifier.local?.name;
51
- const source = imp.source?.value;
52
- if (typeof localName !== "string" || typeof source !== "string") continue;
53
- const resolved = await resolveImportPath(
54
- source,
55
- registryDir,
56
- root,
57
- pathExists,
58
- );
59
- if (resolved) importMap.set(localName, resolved);
60
- }
61
-
62
- // Find the exported object
63
- const exportedObject = findExportedObject(ast);
64
- if (!exportedObject) return result;
65
-
66
- for (const prop of exportedObject.properties) {
67
- if (prop.type !== "ObjectProperty") continue;
68
- const key = getPropertyKey(
69
- prop as { key: { type: string; name?: string; value?: string } },
70
- );
71
- if (!key) continue;
72
-
73
- const value = prop.value as {
74
- type: string;
75
- name?: string;
76
- body?: { type: string };
77
- };
78
- let resolvedPath: string | undefined;
79
-
80
- if (value.type === "Identifier") {
81
- resolvedPath = importMap.get(value.name ?? "");
82
- } else if (value.type === "CallExpression") {
83
- resolvedPath = await resolveImportPathFromCall(
84
- value as unknown as Parameters<typeof resolveImportPathFromCall>[0],
85
- registryDir,
86
- root,
87
- pathExists,
88
- );
89
- }
90
- // ObjectProperty with ArrowFunctionExpression: () => import('./x')
91
- else if (value.type === "ArrowFunctionExpression") {
92
- const body = value.body;
93
- if (body?.type === "CallExpression") {
94
- resolvedPath = await resolveImportPathFromCall(
95
- body as unknown as Parameters<typeof resolveImportPathFromCall>[0],
96
- registryDir,
97
- root,
98
- pathExists,
99
- );
100
- }
101
- }
102
-
103
- if (resolvedPath) result.set(key, resolvedPath);
104
- }
105
-
106
- return result;
30
+ return parseSdkRegistryFromContent(registryContent, (importPath) =>
31
+ resolveImportPath(importPath, registryDir, root, pathExists),
32
+ );
107
33
  }
108
34
 
109
35
  async function resolveImportPath(
@@ -116,112 +42,13 @@ async function resolveImportPath(
116
42
  const absoluteBase = path
117
43
  .normalize(path.join(registryDir, importPath))
118
44
  .replace(/\.(js|ts|tsx)$/, "");
119
- for (const ext of [".ts", ".tsx"]) {
120
- const candidate = absoluteBase + ext;
45
+
46
+ for (const extension of RESOLUTION_EXTENSIONS) {
47
+ const candidate = absoluteBase + extension;
121
48
  if (await pathExists(candidate)) {
122
49
  return path.relative(root, candidate).replace(/\\/g, "/");
123
50
  }
124
51
  }
125
- return undefined;
126
- }
127
52
 
128
- async function resolveImportPathFromCall(
129
- call: {
130
- callee: { type: string };
131
- arguments: Array<{ type: string; value?: string }>;
132
- },
133
- registryDir: string,
134
- root: string,
135
- pathExists: PathExists,
136
- ): Promise<string | undefined> {
137
- const callee = call.callee;
138
- if (callee.type !== "Import") return undefined;
139
- const arg = call.arguments[0];
140
- if (arg?.type !== "StringLiteral" || typeof arg.value !== "string")
141
- return undefined;
142
- return resolveImportPath(arg.value, registryDir, root, pathExists);
143
- }
144
-
145
- function getPropertyKey(prop: {
146
- key: { type: string; name?: string; value?: string };
147
- }): string | undefined {
148
- const key = prop.key;
149
- if (key.type === "Identifier") return key.name;
150
- if (key.type === "StringLiteral") return key.value;
151
- return undefined;
152
- }
153
-
154
- function findExportedObject(
155
- ast: ReturnType<typeof parse>,
156
- ):
157
- | { properties: Array<{ type: string; key: unknown; value: unknown }> }
158
- | undefined {
159
- for (const node of ast.program.body) {
160
- if (node.type !== "ExportDefaultDeclaration") continue;
161
- const decl = node.declaration as { type: string; name?: string };
162
-
163
- const obj = getObjectExpression(
164
- decl as { type: string; expression?: unknown; properties?: unknown[] },
165
- );
166
- if (obj) {
167
- return obj as {
168
- properties: Array<{ type: string; key: unknown; value: unknown }>;
169
- };
170
- }
171
- if (decl.type === "Identifier") {
172
- const varName = decl.name;
173
- if (!varName) continue;
174
- const def = findVariableDeclaration(ast, varName);
175
- if (def?.init) {
176
- return def.init as unknown as {
177
- properties: Array<{ type: string; key: unknown; value: unknown }>;
178
- };
179
- }
180
- }
181
- }
182
- return undefined;
183
- }
184
-
185
- function getObjectExpression(node: {
186
- type: string;
187
- expression?: unknown;
188
- properties?: unknown[];
189
- }): { properties: unknown[] } | undefined {
190
- if (node.type === "ObjectExpression") {
191
- return node as { properties: unknown[] };
192
- }
193
- // TypeScript: { x } as const → TSAsExpression or TSSatisfiesExpression
194
- if (
195
- (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") &&
196
- "expression" in node
197
- ) {
198
- const inner = node.expression as { type: string; properties?: unknown[] };
199
- if (inner?.type === "ObjectExpression") {
200
- return inner as { properties: unknown[] };
201
- }
202
- }
203
- return undefined;
204
- }
205
-
206
- function findVariableDeclaration(
207
- ast: ReturnType<typeof parse>,
208
- name: string,
209
- ): { init: { properties: unknown[] } } | undefined {
210
- for (const node of ast.program.body) {
211
- if (node.type !== "VariableDeclaration") continue;
212
- const decl = node;
213
- for (const declarator of decl.declarations) {
214
- if (
215
- declarator.id.type === "Identifier" &&
216
- declarator.id.name === name &&
217
- declarator.init
218
- ) {
219
- const obj = getObjectExpression(
220
- declarator.init as { type: string; expression?: unknown },
221
- );
222
- if (obj) return { init: obj };
223
- }
224
- }
225
- }
226
53
  return undefined;
227
54
  }
@@ -10,7 +10,8 @@ describe("parseSdkRegistry", () => {
10
10
  return (
11
11
  rel === "server/apis/GetUsers/api.ts" ||
12
12
  rel === "server/apis/v2/GetUsers/api.ts" ||
13
- rel === "server/apis/CreateOrder/api.ts"
13
+ rel === "server/apis/CreateOrder/api.ts" ||
14
+ rel === "server/apis/JsOnly/api.js"
14
15
  );
15
16
  };
16
17
 
@@ -130,4 +131,19 @@ export default { GetUsers } as const;
130
131
  );
131
132
  expect(result.size).toBe(0);
132
133
  });
134
+
135
+ it("resolves .js files when .ts/.tsx are missing", async () => {
136
+ const content = `
137
+ import JsOnly from './JsOnly/api.js';
138
+ export default { JsOnly };
139
+ `;
140
+ const result = await parseSdkRegistry(
141
+ content,
142
+ registryDir,
143
+ root,
144
+ pathExists,
145
+ );
146
+ expect(result.get("JsOnly")).toBe("server/apis/JsOnly/api.js");
147
+ expect(result.size).toBe(1);
148
+ });
133
149
  });