@codeyam/codeyam-cli 0.1.25 → 0.1.27

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 (47) hide show
  1. package/analyzer-template/.build-info.json +6 -6
  2. package/analyzer-template/log.txt +3 -3
  3. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js +55 -0
  4. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js.map +1 -0
  5. package/codeyam-cli/src/commands/editor.js +61 -8
  6. package/codeyam-cli/src/commands/editor.js.map +1 -1
  7. package/codeyam-cli/src/data/techStacks.js +1 -1
  8. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +10 -0
  9. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  10. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +120 -0
  11. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
  12. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +84 -0
  13. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
  14. package/codeyam-cli/src/utils/__tests__/testRunner.test.js +0 -1
  15. package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -1
  16. package/codeyam-cli/src/utils/editorAudit.js +22 -5
  17. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  18. package/codeyam-cli/src/utils/editorScenarioSwitch.js +27 -12
  19. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
  20. package/codeyam-cli/src/utils/editorSeedAdapter.js +27 -14
  21. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
  22. package/codeyam-cli/src/utils/testRunner.js +1 -7
  23. package/codeyam-cli/src/utils/testRunner.js.map +1 -1
  24. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-CRxPi2BB.js +96 -0
  25. package/codeyam-cli/src/webserver/build/client/assets/globals-BsGHu8WX.css +1 -0
  26. package/codeyam-cli/src/webserver/build/client/assets/{manifest-7e749098.js → manifest-9032538f.js} +1 -1
  27. package/codeyam-cli/src/webserver/build/client/assets/{root-DGtly3mb.js → root-dKFRTYcy.js} +5 -5
  28. package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-CO8xocj3.js → analysisRunner-OLsM110H.js} +1 -1
  29. package/codeyam-cli/src/webserver/build/server/assets/{index-QKPqlUgg.js → index-WHdB6WTN.js} +1 -1
  30. package/codeyam-cli/src/webserver/build/server/assets/{init-DlspChIk.js → init-DbSiZoE6.js} +1 -1
  31. package/codeyam-cli/src/webserver/build/server/assets/{server-build-ChzicV-B.js → server-build-DZbLY6O_.js} +135 -134
  32. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  33. package/codeyam-cli/src/webserver/build-info.json +5 -5
  34. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +54 -5
  35. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +4 -2
  36. package/codeyam-cli/templates/expo-react-native/app/index.tsx +36 -0
  37. package/codeyam-cli/templates/expo-react-native/babel.config.js +1 -0
  38. package/codeyam-cli/templates/expo-react-native/gitignore +2 -0
  39. package/codeyam-cli/templates/expo-react-native/package.json +23 -18
  40. package/codeyam-cli/templates/expo-react-native/patches/expo-modules-autolinking+3.0.24.patch +29 -0
  41. package/codeyam-cli/templates/seed-adapters/supabase.ts +91 -8
  42. package/package.json +1 -1
  43. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DLM1-ZMt.js +0 -96
  44. package/codeyam-cli/src/webserver/build/client/assets/globals-9EkC9j9I.css +0 -1
  45. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +0 -33
  46. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +0 -12
  47. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +0 -12
@@ -1 +1 @@
1
- import{aG as Z,aH as _,aw as $,ax as rr,aE as tr,ay as or,aA as ir,aB as pr,aD as mr,aC as ar,aF as sr,az as er}from"./assets/server-build-ChzicV-B.js";import"react/jsx-runtime";import"node:stream";import"@react-router/node";import"react-router";import"isbot";import"react-dom/server";import"react";import"lucide-react";import"fetch-retry";import"better-sqlite3";import"pg";import"fs";import"path";import"kysely";import"kysely/helpers/sqlite";import"kysely/helpers/postgres";import"typescript";import"fs/promises";import"os";import"prompts";import"chalk";import"crypto";import"child_process";import"url";import"util";import"dotenv";import"events";import"uuid";import"http";import"net";import"ws";import"node-pty";import"openai";import"p-queue";import"p-retry";import"@aws-sdk/client-dynamodb";import"lru-cache";import"pluralize";import"piscina";import"json5";import"@aws-sdk/util-dynamodb";import"v8";import"react-syntax-highlighter";import"react-syntax-highlighter/dist/cjs/styles/prism/index.js";import"node:crypto";import"minimatch";import"react-markdown";import"remark-gfm";import"react-diff-viewer-continued";export{Z as allowedActionOrigins,_ as assets,$ as assetsBuildDirectory,rr as basename,tr as entry,or as future,ir as isSpaMode,pr as prerender,mr as publicPath,ar as routeDiscovery,sr as routes,er as ssr};
1
+ import{aG as Z,aH as _,aw as $,ax as rr,aE as tr,ay as or,aA as ir,aB as pr,aD as mr,aC as ar,aF as sr,az as er}from"./assets/server-build-DZbLY6O_.js";import"react/jsx-runtime";import"node:stream";import"@react-router/node";import"react-router";import"isbot";import"react-dom/server";import"react";import"lucide-react";import"fetch-retry";import"better-sqlite3";import"pg";import"fs";import"path";import"kysely";import"kysely/helpers/sqlite";import"kysely/helpers/postgres";import"typescript";import"fs/promises";import"os";import"prompts";import"chalk";import"crypto";import"child_process";import"url";import"util";import"dotenv";import"events";import"uuid";import"http";import"net";import"ws";import"node-pty";import"openai";import"p-queue";import"p-retry";import"@aws-sdk/client-dynamodb";import"lru-cache";import"pluralize";import"piscina";import"json5";import"@aws-sdk/util-dynamodb";import"v8";import"react-syntax-highlighter";import"react-syntax-highlighter/dist/cjs/styles/prism/index.js";import"node:crypto";import"minimatch";import"react-markdown";import"remark-gfm";import"react-diff-viewer-continued";export{Z as allowedActionOrigins,_ as assets,$ as assetsBuildDirectory,rr as basename,tr as entry,or as future,ir as isSpaMode,pr as prerender,mr as publicPath,ar as routeDiscovery,sr as routes,er as ssr};
@@ -1,7 +1,7 @@
1
1
  {
2
- "buildTimestamp": "2026-03-27T13:51:52.839Z",
3
- "buildTime": 1774619512839,
4
- "buildNumber": 1279,
5
- "semanticVersion": "0.1.1279",
6
- "version": "0.1.1279 (2026-03-27T13:51)"
2
+ "buildTimestamp": "2026-03-28T18:03:48.783Z",
3
+ "buildTime": 1774721028783,
4
+ "buildNumber": 1296,
5
+ "semanticVersion": "0.1.1296",
6
+ "version": "0.1.1296 (2026-03-28T18:03)"
7
7
  }
@@ -29,14 +29,13 @@ npm start
29
29
 
30
30
  ```
31
31
  app/ # Expo Router file-based routes
32
- _layout.tsx # Root layout (status bar, navigation)
33
- (tabs)/ # Tab-based navigation group
34
- _layout.tsx # Tab bar configuration
35
- index.tsx # Home tab
36
- settings.tsx # Settings tab
32
+ _layout.tsx # Root layout (SafeAreaProvider, StatusBar)
33
+ index.tsx # Home screen (single entry point)
37
34
  components/ # Reusable components
38
35
  lib/
36
+ theme.ts # Design tokens (colors, spacing, typography)
39
37
  storage.ts # AsyncStorage wrapper for persistent data
38
+ __tests__/ # Test files (keep outside app/ — Expo Router treats all app/ files as routes)
40
39
  ```
41
40
 
42
41
  ## Key Patterns
@@ -171,6 +170,56 @@ npx jest app/hooks/useCounter.ts # Run specific test file
171
170
 
172
171
  The Jest config is in `package.json`. The `transformIgnorePatterns` is pre-configured to handle Expo and React Native module transforms — you should not need to modify it.
173
172
 
173
+ ## Building for a Real iOS Device
174
+
175
+ ### Prerequisites
176
+
177
+ - **Xcode 16.x** (Xcode 16.4 or later recommended)
178
+ - **Apple Developer account** (free is fine for personal devices)
179
+ - Device connected via USB or on the same Wi-Fi network
180
+
181
+ ### Steps
182
+
183
+ 1. Generate the native iOS project:
184
+
185
+ ```bash
186
+ npx expo prebuild --clean
187
+ ```
188
+
189
+ 2. Add Swift 5 enforcement to the generated Podfile. Open `ios/Podfile` and add this inside the `post_install` block, after `react_native_post_install(...)`:
190
+
191
+ ```ruby
192
+ # Fix Swift 6.1 (Xcode 16.4) strict concurrency errors
193
+ installer.pods_project.targets.each do |target|
194
+ target.build_configurations.each do |config|
195
+ config.build_settings['SWIFT_VERSION'] = '5.0'
196
+ end
197
+ end
198
+ ```
199
+
200
+ 3. Reinstall pods with the fix:
201
+
202
+ ```bash
203
+ cd ios && pod install && cd ..
204
+ ```
205
+
206
+ 4. Build and run on your device:
207
+
208
+ ```bash
209
+ npx expo run:ios --device
210
+ ```
211
+
212
+ ### Troubleshooting
213
+
214
+ - **"Missing factory in ExpoAppDelegate"** crash: The native project is stale. Run `npx expo prebuild --clean` to regenerate it.
215
+ - **"ambiguous implicit access level for import"** error: The `patch-package` fix wasn't applied. Run `npm install` to reapply, then `cd ios && pod install`.
216
+ - **"No script URL provided"**: Metro bundler isn't running or the device can't reach it. Start Metro with `npx expo start` in a separate terminal. Your phone and Mac must be on the same Wi-Fi network.
217
+
218
+ ### Notes
219
+
220
+ - The `ios/` and `android/` directories are gitignored — they're generated by `expo prebuild` and shouldn't be committed.
221
+ - The `patches/` directory IS committed — it contains a fix for Xcode 16.4 Swift compatibility that auto-applies on `npm install`.
222
+
174
223
  ## Web vs Native Differences
175
224
 
176
225
  The CodeYam editor previews your app via **Expo Web** (react-native-web in a browser). Some differences from native iOS/Android devices are expected:
@@ -1,12 +1,14 @@
1
1
  import '../global.css';
2
2
  import { Stack } from 'expo-router';
3
3
  import { StatusBar } from 'expo-status-bar';
4
- import { SafeAreaProvider } from 'react-native-safe-area-context';
4
+ import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
5
5
 
6
6
  export default function RootLayout() {
7
7
  return (
8
8
  <SafeAreaProvider>
9
- <Stack screenOptions={{ headerShown: false }} />
9
+ <SafeAreaView style={{ flex: 1 }}>
10
+ <Stack screenOptions={{ headerShown: false }} />
11
+ </SafeAreaView>
10
12
  <StatusBar style="auto" />
11
13
  </SafeAreaProvider>
12
14
  );
@@ -0,0 +1,36 @@
1
+ import { View, Text } from 'react-native';
2
+ import { theme } from '@/lib/theme';
3
+
4
+ export default function HomeScreen() {
5
+ return (
6
+ <View
7
+ style={{
8
+ flex: 1,
9
+ alignItems: 'center',
10
+ justifyContent: 'center',
11
+ backgroundColor: theme.colors.bgBase,
12
+ padding: theme.spacing.lg,
13
+ }}
14
+ >
15
+ <Text
16
+ style={{
17
+ fontSize: theme.fontSize['2xl'],
18
+ fontWeight: theme.fontWeight.bold,
19
+ color: theme.colors.textPrimary,
20
+ marginBottom: theme.spacing.sm,
21
+ }}
22
+ >
23
+ Welcome
24
+ </Text>
25
+ <Text
26
+ style={{
27
+ fontSize: theme.fontSize.base,
28
+ color: theme.colors.textSecondary,
29
+ textAlign: 'center',
30
+ }}
31
+ >
32
+ Your Expo app is ready. Start building!
33
+ </Text>
34
+ </View>
35
+ );
36
+ }
@@ -5,5 +5,6 @@ module.exports = function (api) {
5
5
  ['babel-preset-expo', { jsxImportSource: 'nativewind' }],
6
6
  'nativewind/babel',
7
7
  ],
8
+ plugins: ['react-native-reanimated/plugin'],
8
9
  };
9
10
  };
@@ -2,6 +2,8 @@ node_modules/
2
2
  .expo/
3
3
  dist/
4
4
  web-build/
5
+ ios/
6
+ android/
5
7
  *.jks
6
8
  *.p8
7
9
  *.p12
@@ -7,42 +7,47 @@
7
7
  "setup": "npm install",
8
8
  "dev": "expo start --web",
9
9
  "start": "expo start",
10
- "android": "expo start --android",
11
- "ios": "expo start --ios",
10
+ "android": "expo run:android",
11
+ "ios": "expo run:ios",
12
12
  "build:web": "expo export --platform web",
13
- "test": "jest"
13
+ "test": "jest",
14
+ "postinstall": "patch-package"
14
15
  },
15
16
  "dependencies": {
16
- "expo": "~55.0.5",
17
- "expo-router": "~55.0.4",
18
- "expo-status-bar": "~55.0.4",
19
- "expo-linking": "~55.0.7",
20
- "expo-constants": "~55.0.7",
21
- "expo-font": "~55.0.4",
22
- "react": "19.2.4",
23
- "react-dom": "19.2.4",
24
- "react-native": "0.83.2",
17
+ "expo": "~54.0.0",
18
+ "expo-router": "~6.0.23",
19
+ "expo-status-bar": "~3.0.9",
20
+ "expo-linking": "~8.0.11",
21
+ "expo-constants": "~18.0.13",
22
+ "expo-font": "~14.0.11",
23
+ "react": "19.1.0",
24
+ "react-dom": "19.1.0",
25
+ "react-native": "0.81.5",
25
26
  "react-native-web": "^0.21.0",
26
27
  "react-native-safe-area-context": "~5.6.2",
27
- "react-native-screens": "~4.23.0",
28
+ "react-native-screens": "~4.16.0",
29
+ "react-native-reanimated": "^4.3.0",
30
+ "react-native-worklets": "^0.8.1",
31
+ "react-refresh": "^0.18.0",
28
32
  "@react-navigation/native": "^7.1.33",
29
33
  "@expo/vector-icons": "^15.0.2",
30
34
  "@react-native-async-storage/async-storage": "2.2.0",
31
35
  "nativewind": "^4.2.2",
32
- "tailwindcss": "^3.4.19"
36
+ "tailwindcss": "^3.4.19",
37
+ "patch-package": "^8.0.0"
33
38
  },
34
39
  "devDependencies": {
35
- "@types/react": "~19.2.2",
36
- "babel-preset-expo": "^55.0.10",
40
+ "@types/react": "~19.1.10",
41
+ "babel-preset-expo": "~54.0.10",
37
42
  "typescript": "~5.9.2",
38
43
  "jest": "^29.7.0",
39
- "jest-expo": "~55.0.5",
44
+ "jest-expo": "~54.0.17",
40
45
  "@testing-library/react-native": "^13.2.0"
41
46
  },
42
47
  "jest": {
43
48
  "preset": "jest-expo",
44
49
  "transformIgnorePatterns": [
45
- "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|nativewind)"
50
+ "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|nativewind|react-native-reanimated|react-native-worklets)"
46
51
  ]
47
52
  }
48
53
  }
@@ -0,0 +1,29 @@
1
+ diff --git a/node_modules/expo-modules-autolinking/build/platforms/apple/apple.js b/node_modules/expo-modules-autolinking/build/platforms/apple/apple.js
2
+ index 47487c0..58a6069 100644
3
+ --- a/node_modules/expo-modules-autolinking/build/platforms/apple/apple.js
4
+ +++ b/node_modules/expo-modules-autolinking/build/platforms/apple/apple.js
5
+ @@ -113,7 +113,7 @@ async function generatePackageListFileContentAsync(modules, className, entitleme
6
+ * but only these that are written in Swift and use the new API for creating Expo modules.
7
+ */
8
+
9
+ -import ExpoModulesCore
10
+ +public import ExpoModulesCore
11
+ ${generateCommonImportList(swiftModules)}
12
+ ${generateDebugOnlyImportList(debugOnlySwiftModules)}
13
+ @objc(${className})
14
+ @@ -137,13 +137,13 @@ ${generateReactDelegateHandlers(reactDelegateHandlerModules, debugOnlyReactDeleg
15
+ `;
16
+ }
17
+ function generateCommonImportList(swiftModules) {
18
+ - return swiftModules.map((moduleName) => `import ${moduleName}`).join('\n');
19
+ + return swiftModules.map((moduleName) => `public import ${moduleName}`).join('\n');
20
+ }
21
+ function generateDebugOnlyImportList(swiftModules) {
22
+ if (!swiftModules.length) {
23
+ return '';
24
+ }
25
+ - return (wrapInDebugConfigurationCheck(0, swiftModules.map((moduleName) => `import ${moduleName}`).join('\n')) + '\n');
26
+ + return (wrapInDebugConfigurationCheck(0, swiftModules.map((moduleName) => `public import ${moduleName}`).join('\n')) + '\n');
27
+ }
28
+ function generateModuleClasses(classNames, debugOnlyClassName) {
29
+ const commonClassNames = formatArrayOfClassNames(classNames);
@@ -109,22 +109,42 @@ function getProjectRef(): string {
109
109
  }
110
110
  }
111
111
 
112
+ /**
113
+ * Build a mapping from lowercased seed-data keys to actual PostgreSQL table names.
114
+ * Prisma creates tables with the model name (PascalCase) unless @@map is used.
115
+ * PostgREST requires the exact table name, so we need this translation.
116
+ */
117
+ function buildTableNameMap(): Record<string, string> {
118
+ const map: Record<string, string> = {};
119
+ for (const model of Prisma.dmmf.datamodel.models) {
120
+ // dbName is set when @@map is used, otherwise null → use model name
121
+ const dbName = (model as any).dbName || model.name;
122
+ // Map lowercased model name → actual table name
123
+ const lowered = model.name.charAt(0).toLowerCase() + model.name.slice(1);
124
+ map[lowered] = dbName;
125
+ map[model.name] = dbName; // Also map PascalCase for safety
126
+ }
127
+ return map;
128
+ }
129
+
112
130
  async function seedTables(seed: Record<string, unknown[]>) {
113
131
  if (Object.keys(seed).length === 0) return;
114
132
 
133
+ const tableMap = buildTableNameMap();
134
+
115
135
  // Discover ALL models from the Prisma schema — not just the tables in the seed data.
116
136
  // This ensures FK-dependent tables are cleared even when the seed only contains
117
137
  // the parent table's data. Every editor project has Prisma installed.
118
- const allModels = Prisma.dmmf.datamodel.models.map(
119
- (m) => m.name.charAt(0).toLowerCase() + m.name.slice(1),
138
+ const allTables = Prisma.dmmf.datamodel.models.map(
139
+ (m) => (m as any).dbName || m.name,
120
140
  );
121
141
 
122
142
  console.log(
123
- `Clearing ${allModels.length} tables, seeding: ${Object.keys(seed).join(', ')}`,
143
+ `Clearing ${allTables.length} tables, seeding: ${Object.keys(seed).join(', ')}`,
124
144
  );
125
145
 
126
146
  // Clear ALL tables in reverse order (children before parents for FK safety)
127
- for (const table of [...allModels].reverse()) {
147
+ for (const table of [...allTables].reverse()) {
128
148
  const { error } = await supabase.from(table).delete().gte('id', 0);
129
149
  if (error) {
130
150
  const { error: error2 } = await supabase
@@ -141,9 +161,10 @@ async function seedTables(seed: Record<string, unknown[]>) {
141
161
  }
142
162
  }
143
163
 
144
- // Insert seed data
145
- for (const [table, rows] of Object.entries(seed)) {
164
+ // Insert seed data — translate seed keys to actual table names
165
+ for (const [seedKey, rows] of Object.entries(seed)) {
146
166
  if (!Array.isArray(rows) || rows.length === 0) continue;
167
+ const table = tableMap[seedKey] || seedKey;
147
168
  const { error } = await supabase.from(table).insert(rows);
148
169
  if (error) {
149
170
  console.error(` Failed to seed ${table}: ${error.message}`);
@@ -153,6 +174,42 @@ async function seedTables(seed: Record<string, unknown[]>) {
153
174
  }
154
175
  }
155
176
 
177
+ /**
178
+ * Build a minimal JWT with a far-future expiry.
179
+ * The signature is fake — it doesn't matter because the CodeYam preload module
180
+ * intercepts the Supabase auth validation endpoint and returns mock data.
181
+ */
182
+ function buildFakeJwt(userId: string, email: string): string {
183
+ const header = { alg: 'HS256', typ: 'JWT' };
184
+ const payload = {
185
+ sub: userId,
186
+ email,
187
+ role: 'authenticated',
188
+ aud: 'authenticated',
189
+ exp: 9999999999,
190
+ iat: Math.floor(Date.now() / 1000),
191
+ };
192
+ const encode = (obj: object) =>
193
+ Buffer.from(JSON.stringify(obj)).toString('base64url');
194
+ return `${encode(header)}.${encode(payload)}.codeyam-mock-signature`;
195
+ }
196
+
197
+ /**
198
+ * Build a Supabase user response object matching the /auth/v1/user endpoint format.
199
+ */
200
+ function buildUserResponse(user: { id: string; email?: string }) {
201
+ return {
202
+ id: user.id,
203
+ aud: 'authenticated',
204
+ role: 'authenticated',
205
+ email: user.email || '',
206
+ email_confirmed_at: new Date().toISOString(),
207
+ app_metadata: { provider: 'email', providers: ['email'] },
208
+ user_metadata: {},
209
+ created_at: new Date().toISOString(),
210
+ };
211
+ }
212
+
156
213
  /**
157
214
  * Handle auth: create user, sign in, write session cookies.
158
215
  * Returns the user ID so callers can replace __AUTH_USER_ID__ placeholders in seed data.
@@ -211,7 +268,13 @@ async function handleAuth(auth: {
211
268
  const userId = signInData.user.id;
212
269
  console.log(` Signed in as ${email} (user: ${userId})`);
213
270
 
214
- // Write session cookies for the proxy to inject
271
+ // Use the REAL JWT from Supabase sign-in for the session cookie so auth
272
+ // works immediately against the real Supabase API. The externalApis below
273
+ // provide a fallback for when the CLI supports preload-based auth
274
+ // interception (no real Supabase calls needed at render time).
275
+ const fakeJwt = buildFakeJwt(userId, email);
276
+ const userResponse = buildUserResponse(signInData.user);
277
+
215
278
  const projectRef = getProjectRef();
216
279
  const sessionOutput = {
217
280
  cookies: [
@@ -228,13 +291,33 @@ async function handleAuth(auth: {
228
291
  sameSite: 'Lax' as const,
229
292
  },
230
293
  ],
294
+ // External API mocks — when the CLI supports propagating these, the
295
+ // preload module will intercept server-side getUser() calls so Next.js
296
+ // middleware returns the mock user without hitting real Supabase.
297
+ externalApis: {
298
+ [`${supabaseUrl}/auth/v1/user`]: {
299
+ body: userResponse,
300
+ status: 200,
301
+ },
302
+ [`${supabaseUrl}/auth/v1/token`]: {
303
+ body: {
304
+ access_token: fakeJwt,
305
+ token_type: 'bearer',
306
+ expires_in: 315360000,
307
+ expires_at: 9999999999,
308
+ refresh_token: 'codeyam-mock-refresh-token',
309
+ user: userResponse,
310
+ },
311
+ status: 200,
312
+ },
313
+ },
231
314
  };
232
315
 
233
316
  const outputDir = path.join(process.cwd(), '.codeyam', 'tmp');
234
317
  fs.mkdirSync(outputDir, { recursive: true });
235
318
  const outputPath = path.join(outputDir, 'seed-session.json');
236
319
  fs.writeFileSync(outputPath, JSON.stringify(sessionOutput, null, 2));
237
- console.log(` Session cookies written to ${outputPath}`);
320
+ console.log(` Session cookies + auth mocks written to ${outputPath}`);
238
321
 
239
322
  return userId;
240
323
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeyam/codeyam-cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Local development CLI for CodeYam analysis",
5
5
  "type": "module",
6
6
  "bin": {