@codeyam/codeyam-cli 0.1.0-staging.ad31e3e → 0.1.0-staging.bbe4da9

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 (161) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/packages/ai/index.ts +4 -1
  4. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +18 -0
  5. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +56 -0
  6. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +64 -1
  7. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +2 -0
  8. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +29 -2
  9. package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -1
  10. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExportedNodes.ts +4 -2
  11. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +5 -3
  12. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +21 -33
  13. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +75 -10
  14. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +26 -0
  15. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +12 -2
  16. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.d.ts.map +1 -1
  17. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.js +2 -2
  18. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.js.map +1 -1
  19. package/analyzer-template/packages/aws/src/lib/s3/getPresignedUrl.ts +2 -2
  20. package/analyzer-template/packages/github/dist/supabase/src/lib/scenarioToDb.d.ts.map +1 -1
  21. package/analyzer-template/packages/github/dist/supabase/src/lib/scenarioToDb.js +1 -1
  22. package/analyzer-template/packages/github/dist/supabase/src/lib/scenarioToDb.js.map +1 -1
  23. package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
  24. package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js +39 -5
  25. package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js.map +1 -1
  26. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  27. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +17 -0
  28. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  29. package/analyzer-template/packages/supabase/src/lib/scenarioToDb.ts +1 -0
  30. package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
  31. package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js +39 -5
  32. package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js.map +1 -1
  33. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  34. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +17 -0
  35. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  36. package/analyzer-template/packages/utils/src/lib/applyUniversalMocks.ts +46 -7
  37. package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +16 -0
  38. package/analyzer-template/project/constructMockCode.ts +29 -3
  39. package/analyzer-template/project/runMultiScenarioServer.ts +0 -4
  40. package/analyzer-template/project/runScenarioServer.ts +0 -4
  41. package/analyzer-template/project/start.ts +1 -11
  42. package/analyzer-template/project/startServer.ts +50 -70
  43. package/analyzer-template/project/writeMockDataTsx.ts +66 -3
  44. package/analyzer-template/project/writeScenarioComponents.ts +451 -25
  45. package/analyzer-template/scripts/postbuild.cjs +12 -1
  46. package/background/src/lib/virtualized/project/constructMockCode.js +25 -4
  47. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  48. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +0 -3
  49. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  50. package/background/src/lib/virtualized/project/start.js +1 -8
  51. package/background/src/lib/virtualized/project/start.js.map +1 -1
  52. package/background/src/lib/virtualized/project/startServer.js +40 -68
  53. package/background/src/lib/virtualized/project/startServer.js.map +1 -1
  54. package/background/src/lib/virtualized/project/writeMockDataTsx.js +61 -3
  55. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  56. package/background/src/lib/virtualized/project/writeScenarioComponents.js +296 -20
  57. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  58. package/codeyam-cli/src/commands/debug.js +3 -2
  59. package/codeyam-cli/src/commands/debug.js.map +1 -1
  60. package/codeyam-cli/src/commands/setup-sandbox.js +2 -1
  61. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  62. package/codeyam-cli/src/commands/test-startup.js +14 -5
  63. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  64. package/codeyam-cli/src/utils/analysisRunner.js +2 -1
  65. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  66. package/codeyam-cli/src/utils/analyzer.js +8 -16
  67. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  68. package/codeyam-cli/src/utils/generateReport.js +12 -6
  69. package/codeyam-cli/src/utils/generateReport.js.map +1 -1
  70. package/codeyam-cli/src/utils/queue/job.js +5 -4
  71. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  72. package/codeyam-cli/src/utils/sandbox.js +190 -0
  73. package/codeyam-cli/src/utils/sandbox.js.map +1 -0
  74. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-D5ZHFomX.js → EntityTypeIcon-Dp_FTAs1.js} +1 -1
  75. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-TlHocYno.js +26 -0
  76. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-BYVx9KFp.js → LibraryFunctionPreview-CVMmGuIc.js} +1 -1
  77. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CRcT5fOZ.js → LogViewer-JkfQ-VaI.js} +1 -1
  78. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-Cqce0_KG.js +1 -0
  79. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Bual6h18.js → SafeScreenshot-BrMAP1nP.js} +1 -1
  80. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bi-__7HT.js +6 -0
  81. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-4D2vLLJz.js → ScenarioViewer-XmIpHcLJ.js} +1 -1
  82. package/codeyam-cli/src/webserver/build/client/assets/_index-BmfhU6CA.js +1 -0
  83. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-Dm8lM73z.js +10 -0
  84. package/codeyam-cli/src/webserver/build/client/assets/{chart-column-B8fb6wnw.js → chart-column-kA4jn9if.js} +1 -1
  85. package/codeyam-cli/src/webserver/build/client/assets/{chunk-WWGJGFF6-De6i8FUT.js → chunk-WWGJGFF6-CgXbbZRx.js} +1 -1
  86. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BACUUf75.js → circle-check-B2oHQ-zo.js} +1 -1
  87. package/codeyam-cli/src/webserver/build/client/assets/{clock-vWeoCemX.js → clock-BAfbP_iK.js} +1 -1
  88. package/codeyam-cli/src/webserver/build/client/assets/codeyam-name-logo-CvKwUgHo.svg +9 -0
  89. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-CS7XDrKv.js → createLucideIcon-BBYuR56H.js} +1 -1
  90. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-DIOEw_3i.js → dev.empty-BgPXZbm0.js} +1 -1
  91. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-C6fctQ5v.js → entity._sha._-BkoAXaOa.js} +10 -10
  92. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-C3FZJx1w.js → entity._sha_.create-scenario-Bj5GHkhb.js} +1 -1
  93. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-YJz_igar.js → entity._sha_.edit._scenarioId-eW5z9AyZ.js} +1 -1
  94. package/codeyam-cli/src/webserver/build/client/assets/{entityStatus-BEqj2qBy.js → entityStatus-C5Okl18j.js} +1 -1
  95. package/codeyam-cli/src/webserver/build/client/assets/{entityVersioning-Bk_YB1jM.js → entityVersioning-CU_Lchhc.js} +1 -1
  96. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-DiP0q291.js → entry.client-B9tSboXM.js} +2 -2
  97. package/codeyam-cli/src/webserver/build/client/assets/{file-text-LM0mgxXE.js → file-text-18aYHZGd.js} +1 -1
  98. package/codeyam-cli/src/webserver/build/client/assets/files-Df79EyEb.js +1 -0
  99. package/codeyam-cli/src/webserver/build/client/assets/git-CDEwTVH_.js +12 -0
  100. package/codeyam-cli/src/webserver/build/client/assets/globals-DXRB6jBc.css +1 -0
  101. package/codeyam-cli/src/webserver/build/client/assets/{index-D-zYbzFZ.js → index-_LjBsTxX.js} +1 -1
  102. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BXPKbHEb.js → loader-circle-D_EGChhq.js} +1 -1
  103. package/codeyam-cli/src/webserver/build/client/assets/manifest-3e0ffbcc.js +1 -0
  104. package/codeyam-cli/src/webserver/build/client/assets/{root-D0s7DnXb.js → root-CGyT4J4b.js} +3 -3
  105. package/codeyam-cli/src/webserver/build/client/assets/{settings-5zF_GOcS.js → settings-CEPbAsom.js} +1 -1
  106. package/codeyam-cli/src/webserver/build/client/assets/settings-R8QF_mHX.js +1 -0
  107. package/codeyam-cli/src/webserver/build/client/assets/simulations-B_PXvFom.js +1 -0
  108. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-D7k-ArFa.js → triangle-alert-BthANBVv.js} +1 -1
  109. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-AlhS7g5F.js → useLastLogLine-Blr5oZDE.js} +1 -1
  110. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-CANr3QJ5.js +1 -0
  111. package/codeyam-cli/src/webserver/build/client/assets/{useToast-Ddo4UQv7.js → useToast-Bbf4Hokd.js} +1 -1
  112. package/codeyam-cli/src/webserver/build/server/assets/{index-iaMjuNME.js → index-vf1FETCO.js} +1 -1
  113. package/codeyam-cli/src/webserver/build/server/assets/server-build-B5s58TvB.js +169 -0
  114. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  115. package/codeyam-cli/src/webserver/build-info.json +5 -5
  116. package/package.json +1 -1
  117. package/packages/ai/index.js +1 -1
  118. package/packages/ai/index.js.map +1 -1
  119. package/packages/ai/src/lib/astScopes/processExpression.js +12 -0
  120. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  121. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +38 -0
  122. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  123. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +55 -1
  124. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  125. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  126. package/packages/analyze/src/lib/FileAnalyzer.js +22 -2
  127. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  128. package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -1
  129. package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
  130. package/packages/analyze/src/lib/asts/sourceFiles/getAllExportedNodes.js +3 -2
  131. package/packages/analyze/src/lib/asts/sourceFiles/getAllExportedNodes.js.map +1 -1
  132. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +4 -3
  133. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  134. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +18 -23
  135. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  136. package/packages/analyze/src/lib/files/getImportedExports.js +56 -4
  137. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  138. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +24 -0
  139. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  140. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +8 -2
  141. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  142. package/packages/supabase/src/lib/scenarioToDb.js +1 -1
  143. package/packages/supabase/src/lib/scenarioToDb.js.map +1 -1
  144. package/packages/utils/src/lib/applyUniversalMocks.js +39 -5
  145. package/packages/utils/src/lib/applyUniversalMocks.js.map +1 -1
  146. package/packages/utils/src/lib/lightweightEntityExtractor.js +17 -0
  147. package/packages/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  148. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-XDSzQLOY.js +0 -26
  149. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-BORLgi0X.js +0 -1
  150. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bi-YUMa-.js +0 -6
  151. package/codeyam-cli/src/webserver/build/client/assets/_index-BC200mfN.js +0 -1
  152. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CxvZPkCv.js +0 -10
  153. package/codeyam-cli/src/webserver/build/client/assets/circle-alert-IdsgAK39.js +0 -1
  154. package/codeyam-cli/src/webserver/build/client/assets/files-Dxh9CcaV.js +0 -1
  155. package/codeyam-cli/src/webserver/build/client/assets/git-BXmqrWCH.js +0 -12
  156. package/codeyam-cli/src/webserver/build/client/assets/globals-BGS74ED-.css +0 -1
  157. package/codeyam-cli/src/webserver/build/client/assets/manifest-e039ab42.js +0 -1
  158. package/codeyam-cli/src/webserver/build/client/assets/settings-Dc4MlMpK.js +0 -1
  159. package/codeyam-cli/src/webserver/build/client/assets/simulations-BQ-02-jB.js +0 -1
  160. package/codeyam-cli/src/webserver/build/client/assets/zap-_jw-9DCp.js +0 -1
  161. package/codeyam-cli/src/webserver/build/server/assets/server-build-CpyX1FZX.js +0 -169
@@ -1,25 +1,32 @@
1
1
  import getPort from 'get-port';
2
2
  import execAsync from '../common/execAsync';
3
- import { ProjectFramework, ServerCommand } from '~codeyam/types';
3
+ import { ServerCommand } from '~codeyam/types';
4
4
  import { Socket } from 'net';
5
5
  import { awsLogDebugLevel } from '~codeyam/utils';
6
6
 
7
7
  export interface StartServerArgs {
8
- startCommand?: ServerCommand;
9
- packageManager: string;
10
- exitAfterSuccessfulAppStart?: boolean;
8
+ startCommand: ServerCommand;
11
9
  onStart: (port: number) => Promise<void>;
12
10
  onError: (data: string) => Promise<void>;
13
- framework: ProjectFramework;
14
11
  projectPort?: number;
15
12
  }
16
13
 
14
+ /**
15
+ * Start the project's dev server.
16
+ *
17
+ * Requires a complete startCommand with $PORT placeholder in args.
18
+ * The startCommand should be fully specified in the project's webapp configuration,
19
+ * including any package manager invocation and framework-specific flags.
20
+ *
21
+ * Examples of valid startCommand configurations:
22
+ * - npm: { command: 'npm', args: ['run', 'dev', '--', '--port', '$PORT'] }
23
+ * - pnpm: { command: 'pnpm', args: ['dev', '--port', '$PORT'] }
24
+ * - monorepo: { command: 'sh', args: ['-c', 'cd subdir && pnpm dev --port $PORT'] }
25
+ */
17
26
  export async function startServer({
18
27
  startCommand,
19
- packageManager,
20
28
  onStart,
21
29
  onError,
22
- framework,
23
30
  projectPort,
24
31
  }: StartServerArgs) {
25
32
  const acceptableErrorsRegexes = [
@@ -27,7 +34,7 @@ export async function startServer({
27
34
  /favicon\.ico/,
28
35
  /DeprecationWarning/,
29
36
  /warn deprecated/,
30
- /One of your dependencies, babel-preset-react-app, is importing the/, // This error is thrown in CRA and is not a problem. TODO: How to not throw for warnings
37
+ /One of your dependencies, babel-preset-react-app, is importing the/,
31
38
  /No route matches URL/,
32
39
  /Browserslist: caniuse-lite is outdated/,
33
40
  /npx update-browserslist-db@latest/,
@@ -37,8 +44,27 @@ export async function startServer({
37
44
  ];
38
45
 
39
46
  try {
40
- // both 'undefined' and 0 triggers port auto-selection, which we do here as late as
41
- // possible to mimimise the risk of race conditions & port conflicts downstream
47
+ // Validate startCommand
48
+ if (!startCommand?.command) {
49
+ throw new Error(
50
+ 'startCommand.command is required. ' +
51
+ 'Please configure a complete startCommand in the webapp configuration.',
52
+ );
53
+ }
54
+ if (!startCommand.args?.length) {
55
+ throw new Error(
56
+ 'startCommand.args is required and must be non-empty. ' +
57
+ 'Please configure startCommand.args with $PORT placeholder.',
58
+ );
59
+ }
60
+ if (!startCommand.args.some((arg) => arg.includes('$PORT'))) {
61
+ throw new Error(
62
+ 'startCommand.args must include $PORT placeholder. ' +
63
+ 'Example: ["run", "dev", "--", "--port", "$PORT"]',
64
+ );
65
+ }
66
+
67
+ // Port auto-selection (as late as possible to minimize race conditions)
42
68
  if (!projectPort) {
43
69
  projectPort = await getPort();
44
70
  console.log(`CodeYam: Auto-selected project port: ${projectPort}`);
@@ -68,7 +94,6 @@ export async function startServer({
68
94
 
69
95
  socket.connect(port, 'localhost');
70
96
 
71
- // Don't leave socket hanging
72
97
  timer.current = setTimeout(() => {
73
98
  console.log(`CodeYam: checkPort: Timeout`);
74
99
  socket.destroy();
@@ -89,66 +114,22 @@ export async function startServer({
89
114
  }
90
115
  };
91
116
 
92
- // figure out the right CLI invocation for starting the server
93
- const command = startCommand?.command ?? packageManager;
94
- let args = startCommand?.args;
95
-
96
- if (args) {
97
- // Custom startCommand provided - clone and process it
98
- args = [...args];
99
-
100
- // Replace any $PORT placeholders with the actual port
101
- let hasPort = false;
102
- for (let i = 0; i < args.length; i++) {
103
- if (args[i].includes('$PORT')) {
104
- args[i] = args[i].replace('$PORT', projectPort.toString());
105
- hasPort = true;
106
- } else if (args[i] === '--port' || args[i] === '-p') {
107
- hasPort = true;
108
- }
109
- }
117
+ // Build command from startCommand (substituting $PORT)
118
+ const command = startCommand.command;
119
+ const args = startCommand.args.map((arg) =>
120
+ arg.replace(/\$PORT/g, projectPort.toString()),
121
+ );
110
122
 
111
- // If no port argument exists, add it.
112
- // Use -- separator for compatibility with Turbo-based projects.
113
- if (!hasPort) {
114
- if (framework === ProjectFramework.Remix) {
115
- args.push('--', '--port', projectPort.toString(), '--strictPort');
116
- } else {
117
- args.push('--', '--port', projectPort.toString());
118
- }
119
- }
120
- } else {
121
- if (framework === ProjectFramework.CodeYam) {
122
- args = ['start', projectPort.toString()];
123
- } else {
124
- // there's no guarantee that the logic below will work for all frameworks, and
125
- // certainly no guarantee that it'll work on any one individual project... but
126
- // it's a reasonable default, and we have `startCommand` for anything bespoke
127
- //
128
- // All package managers support -- to pass arguments to scripts.
129
- // npm requires it, and Turbo-based projects (monorepos) also require it.
130
- // Using -- universally is safe and ensures compatibility.
131
- args = ['run', 'dev', '--', '--port', projectPort.toString()];
132
- if (framework === ProjectFramework.Remix) {
133
- args.push('--strictPort');
134
- }
135
- }
136
- }
137
- let env = startCommand?.env;
138
- if (!env) {
139
- env = {
140
- LOCAL: 'local',
141
- PORT: projectPort.toString(),
142
- };
143
- if (framework === ProjectFramework.CRA) {
144
- env.BROWSER = 'none';
145
- }
146
- } else {
147
- // Replace $PORT placeholders in env values
148
- env = { ...env };
123
+ // Handle env: $PORT substitution
124
+ let env: Record<string, string> = {
125
+ LOCAL: 'local',
126
+ PORT: projectPort.toString(),
127
+ };
128
+ if (startCommand.env) {
129
+ env = { ...env, ...startCommand.env };
149
130
  for (const key of Object.keys(env)) {
150
131
  if (typeof env[key] === 'string' && env[key].includes('$PORT')) {
151
- env[key] = env[key].replace('$PORT', projectPort.toString());
132
+ env[key] = env[key].replace(/\$PORT/g, projectPort.toString());
152
133
  }
153
134
  }
154
135
  }
@@ -166,7 +147,6 @@ export async function startServer({
166
147
  env,
167
148
  workingDir: '../project',
168
149
  acceptableErrorsRegexes,
169
- // logErrors: false, // we do more selective logging ourselves
170
150
  onError,
171
151
  processName: 'local-project-server',
172
152
  }),
@@ -183,6 +163,6 @@ export async function startServer({
183
163
  console.log(
184
164
  `CodeYam Error: Error executing start script: ${error.message}`,
185
165
  );
186
- throw error; // Rethrow the error to be caught in the main function
166
+ throw error;
187
167
  }
188
168
  }
@@ -248,6 +248,21 @@ const jsonToCode = (
248
248
  // e.g., submit({ a }) and submit({ b }) should both become "submit" once
249
249
  const seenNormalizedFuncNames = new Set<string>();
250
250
 
251
+ // Pre-scan to identify plain keys that have function-call versions
252
+ // These plain keys should be skipped because the function-call version
253
+ // will be normalized to the same key name
254
+ // e.g., if both "push" and "push(`/path`)" exist, skip the plain "push"
255
+ const plainKeysWithFunctionCallVersions = new Set<string>();
256
+ for (const key of Object.keys(jsonObj)) {
257
+ if (key.includes('(') && key.endsWith(')')) {
258
+ const funcName = key.split('(')[0];
259
+ // Check if a plain key with this name exists
260
+ if (funcName in jsonObj && !funcName.includes('(')) {
261
+ plainKeysWithFunctionCallVersions.add(funcName);
262
+ }
263
+ }
264
+ }
265
+
251
266
  for (const key of Object.keys(jsonObj)) {
252
267
  if (jsonObj[key] === undefined || jsonObj[key] === null) continue;
253
268
 
@@ -459,11 +474,28 @@ const jsonToCode = (
459
474
  `${levelSpacing}"${safeString(funcName, level)}": ${outputValue}`,
460
475
  );
461
476
  } else {
477
+ // Skip plain keys that have function-call versions (at the same nesting level where
478
+ // function-call keys get normalized). The function-call version will be output instead.
479
+ // e.g., if both "push" and "push(`/path`)" exist, skip "push" - the other normalizes to "push"
480
+ if (level > 2 && plainKeysWithFunctionCallVersions.has(key)) {
481
+ console.log(
482
+ `CodeYam: Skipping plain key "${key}" (has function-call version that will be normalized)`,
483
+ );
484
+ continue;
485
+ }
462
486
  keyStrings.push(
463
487
  `${levelSpacing}"${safeString(key, level)}": "${safeString(stringValue, level)}"`,
464
488
  );
465
489
  }
466
490
  } else {
491
+ // Skip plain keys that have function-call versions (at the same nesting level where
492
+ // function-call keys get normalized)
493
+ if (level > 2 && plainKeysWithFunctionCallVersions.has(key)) {
494
+ console.log(
495
+ `CodeYam: Skipping plain key "${key}" (has function-call version that will be normalized)`,
496
+ );
497
+ continue;
498
+ }
467
499
  keyStrings.push(
468
500
  `${levelSpacing}"${safeString(key, level)}": ${safeString(String(jsonObj[key]), level)}`,
469
501
  );
@@ -638,13 +670,44 @@ function serialize(obj) {
638
670
 
639
671
  // Handle functions
640
672
  if (typeof value === 'function') {
641
- const fnStr = value.toString();
673
+ let fnStr;
674
+ try {
675
+ fnStr = value.toString();
676
+ } catch (toStringErr) {
677
+ console.warn('CodeYam: Function.toString() threw error:', toStringErr, 'function name:', value.name);
678
+ return {
679
+ __type: TYPE_MARKERS.FUNCTION,
680
+ value: '() => {}',
681
+ name: value.name || 'anonymous'
682
+ };
683
+ }
684
+
685
+ // Defensive check: ensure fnStr is actually a string
686
+ if (typeof fnStr !== 'string') {
687
+ console.warn('CodeYam: Function.toString() returned non-string:', typeof fnStr, fnStr, 'function name:', value.name);
688
+ return {
689
+ __type: TYPE_MARKERS.FUNCTION,
690
+ value: '() => {}',
691
+ name: value.name || 'anonymous'
692
+ };
693
+ }
694
+
642
695
  // Check if it's an arrow function
643
696
  if (fnStr.includes('=>')) {
697
+ const arrowIndex = fnStr.indexOf('=>');
698
+ // Extra safety: verify indexOf returned a valid index
699
+ if (arrowIndex === -1) {
700
+ console.warn('CodeYam: Arrow function detection inconsistency - includes found => but indexOf returned -1. fnStr:', fnStr);
701
+ return {
702
+ __type: TYPE_MARKERS.FUNCTION,
703
+ value: fnStr,
704
+ name: value.name
705
+ };
706
+ }
644
707
  return {
645
708
  __type: TYPE_MARKERS.ARROW_FUNCTION,
646
- params: fnStr.substring(0, fnStr.indexOf('=>')).trim(),
647
- body: fnStr.substring(fnStr.indexOf('=>') + 2).trim()
709
+ params: fnStr.substring(0, arrowIndex).trim(),
710
+ body: fnStr.substring(arrowIndex + 2).trim()
648
711
  };
649
712
  }
650
713
  return {