@vistagenic/vista 0.3.2 → 0.3.3
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/bin/vista.js +79 -109
- package/dist/ai/embeddings.d.ts +11 -11
- package/dist/ai/embeddings.js +71 -71
- package/dist/ai/index.d.ts +10 -10
- package/dist/ai/index.js +26 -26
- package/dist/ai/providers/base.js +85 -85
- package/dist/ai/react/react-server.d.ts +1 -1
- package/dist/ai/react/react-server.js +17 -17
- package/dist/ai/react/use-agent.js +138 -138
- package/dist/auth/core.d.ts +140 -140
- package/dist/auth/core.js +165 -165
- package/dist/auth/index.d.ts +20 -20
- package/dist/auth/index.js +369 -369
- package/dist/auth/react-server.d.ts +1 -1
- package/dist/auth/react-server.js +10 -10
- package/dist/auth/react.d.ts +18 -18
- package/dist/auth/react.js +71 -71
- package/dist/bin/build-rsc-flashpack.js +6 -0
- package/dist/bin/build-rsc.js +537 -492
- package/dist/bin/build.js +355 -353
- package/dist/bin/generate.js +513 -510
- package/dist/bin/webpack.config.js +4 -3
- package/dist/build/manifest.d.ts +169 -169
- package/dist/build/manifest.js +423 -423
- package/dist/build/rsc/client-manifest.d.ts +62 -62
- package/dist/build/rsc/client-manifest.js +295 -295
- package/dist/build/rsc/compiler.js +5 -4
- package/dist/build/rsc/native-scanner.d.ts +135 -135
- package/dist/build/rsc/native-scanner.js +203 -203
- package/dist/build/rsc/react-client-reference-manifest.d.ts +28 -28
- package/dist/build/rsc/react-client-reference-manifest.js +240 -240
- package/dist/build/standalone.js +260 -254
- package/dist/client/dynamic.react-server.d.ts +2 -2
- package/dist/client/dynamic.react-server.js +23 -23
- package/dist/client/link.react-server.d.ts +2 -2
- package/dist/client/link.react-server.js +11 -11
- package/dist/client/navigation.react-server.d.ts +1 -1
- package/dist/client/navigation.react-server.js +17 -17
- package/dist/client/router.react-server.d.ts +1 -1
- package/dist/client/router.react-server.js +17 -17
- package/dist/client/rsc-router.react-server.d.ts +1 -1
- package/dist/client/rsc-router.react-server.js +17 -17
- package/dist/client/script.react-server.d.ts +2 -2
- package/dist/client/script.react-server.js +23 -23
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -7
- package/dist/deploy/adapters/cloudflare.js +43 -19
- package/dist/deploy/adapters/docker.d.ts +1 -0
- package/dist/deploy/adapters/docker.js +5 -4
- package/dist/deploy/adapters/netlify.js +62 -17
- package/dist/deploy/adapters/vercel.js +80 -50
- package/dist/deploy/preflight.js +4 -3
- package/dist/deploy/runtime-pack.d.ts +11 -0
- package/dist/deploy/runtime-pack.js +300 -0
- package/dist/deploy/utils.d.ts +1 -1
- package/dist/deploy/utils.js +31 -2
- package/dist/flashpack/command.js +1 -0
- package/dist/flashpack/runtime.js +2 -1
- package/dist/index.d.ts +23 -23
- package/dist/index.js +61 -61
- package/dist/server/app-dir.d.ts +22 -0
- package/dist/server/app-dir.js +77 -0
- package/dist/server/cookie-parse.d.ts +4 -4
- package/dist/server/cookie-parse.js +14 -14
- package/dist/server/engine.js +5 -5
- package/dist/server/image-optimizer.js +2 -1
- package/dist/server/index.d.ts +109 -109
- package/dist/server/index.js +315 -315
- package/dist/server/middleware-runner.d.ts +125 -125
- package/dist/server/middleware-runner.js +607 -615
- package/dist/server/middleware-security.d.ts +36 -36
- package/dist/server/middleware-security.js +183 -183
- package/dist/server/module-compile-hook.js +695 -695
- package/dist/server/root-resolver.js +6 -5
- package/dist/server/rsc-engine-flashpack.d.ts +3 -1
- package/dist/server/rsc-engine-flashpack.js +12 -1
- package/dist/server/rsc-engine.d.ts +6 -1
- package/dist/server/rsc-engine.js +203 -219
- package/dist/server/rsc-upstream.js +893 -892
- package/dist/server/static-generator.js +4 -3
- package/dist/server/structure-validator.js +2 -1
- package/dist/server/structure-watch.js +2 -0
- package/dist/server/typed-api-runtime.js +639 -635
- package/dist/server/vista-import-map.js +134 -134
- package/dist/stack/index.d.ts +34 -34
- package/dist/stack/index.js +49 -49
- package/dist/stack/server/caller.d.ts +13 -13
- package/dist/stack/server/caller.js +42 -42
- package/dist/stack/server/executor.d.ts +40 -40
- package/dist/stack/server/executor.js +222 -222
- package/dist/stack/server/index.d.ts +11 -11
- package/dist/stack/server/index.js +24 -24
- package/dist/stack/server/procedure.d.ts +20 -20
- package/dist/stack/server/procedure.js +66 -66
- package/dist/stack/server/types.d.ts +113 -113
- package/dist/theme/react-server.d.ts +10 -10
- package/dist/theme/react-server.js +16 -16
- package/package.json +1 -1
package/dist/bin/generate.js
CHANGED
|
@@ -1,510 +1,513 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.runGenerateCommand = runGenerateCommand;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.
|
|
13
|
-
.replace(/[
|
|
14
|
-
.replace(
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'',
|
|
45
|
-
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
''
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'
|
|
71
|
-
'',
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'',
|
|
78
|
-
'
|
|
79
|
-
'',
|
|
80
|
-
'
|
|
81
|
-
'',
|
|
82
|
-
'
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'',
|
|
86
|
-
'
|
|
87
|
-
'',
|
|
88
|
-
'
|
|
89
|
-
'- `
|
|
90
|
-
'- `
|
|
91
|
-
'',
|
|
92
|
-
|
|
93
|
-
'',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'
|
|
130
|
-
'
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'
|
|
134
|
-
'}
|
|
135
|
-
'',
|
|
136
|
-
'
|
|
137
|
-
'',
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
"import {
|
|
169
|
-
'',
|
|
170
|
-
'
|
|
171
|
-
'',
|
|
172
|
-
'
|
|
173
|
-
'',
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
"import {
|
|
180
|
-
'',
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'
|
|
184
|
-
'
|
|
185
|
-
'}',
|
|
186
|
-
'',
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
'',
|
|
199
|
-
|
|
200
|
-
`
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
'}',
|
|
204
|
-
'',
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
'',
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
`
|
|
217
|
-
|
|
218
|
-
'
|
|
219
|
-
'
|
|
220
|
-
'}',
|
|
221
|
-
'',
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
'',
|
|
228
|
-
'
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
'
|
|
232
|
-
'
|
|
233
|
-
'
|
|
234
|
-
'
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
'
|
|
238
|
-
'
|
|
239
|
-
'
|
|
240
|
-
'
|
|
241
|
-
'
|
|
242
|
-
'
|
|
243
|
-
'
|
|
244
|
-
'
|
|
245
|
-
'}
|
|
246
|
-
'',
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
'',
|
|
253
|
-
'
|
|
254
|
-
'',
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
'',
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
'
|
|
265
|
-
'
|
|
266
|
-
'
|
|
267
|
-
'
|
|
268
|
-
'',
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
'',
|
|
275
|
-
|
|
276
|
-
"import {
|
|
277
|
-
'',
|
|
278
|
-
'
|
|
279
|
-
'
|
|
280
|
-
'}',
|
|
281
|
-
'',
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
'',
|
|
288
|
-
|
|
289
|
-
"import {
|
|
290
|
-
'',
|
|
291
|
-
'
|
|
292
|
-
|
|
293
|
-
" const [
|
|
294
|
-
'',
|
|
295
|
-
'
|
|
296
|
-
'
|
|
297
|
-
'
|
|
298
|
-
' <
|
|
299
|
-
'
|
|
300
|
-
'
|
|
301
|
-
|
|
302
|
-
'
|
|
303
|
-
'
|
|
304
|
-
'
|
|
305
|
-
'
|
|
306
|
-
'
|
|
307
|
-
'
|
|
308
|
-
'
|
|
309
|
-
'
|
|
310
|
-
'
|
|
311
|
-
'
|
|
312
|
-
'
|
|
313
|
-
'
|
|
314
|
-
'
|
|
315
|
-
'
|
|
316
|
-
'
|
|
317
|
-
'
|
|
318
|
-
'
|
|
319
|
-
'
|
|
320
|
-
'
|
|
321
|
-
'
|
|
322
|
-
'
|
|
323
|
-
'
|
|
324
|
-
'
|
|
325
|
-
'
|
|
326
|
-
'
|
|
327
|
-
'
|
|
328
|
-
'
|
|
329
|
-
'
|
|
330
|
-
'
|
|
331
|
-
'
|
|
332
|
-
'',
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
'',
|
|
339
|
-
'
|
|
340
|
-
'
|
|
341
|
-
'
|
|
342
|
-
'
|
|
343
|
-
'
|
|
344
|
-
'
|
|
345
|
-
'
|
|
346
|
-
'
|
|
347
|
-
' <
|
|
348
|
-
'
|
|
349
|
-
'
|
|
350
|
-
'
|
|
351
|
-
'',
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
'
|
|
358
|
-
'
|
|
359
|
-
'
|
|
360
|
-
'
|
|
361
|
-
'',
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const absolutePath = path_1.default.join(cwd,
|
|
367
|
-
if (!fs_1.default.existsSync(absolutePath)) {
|
|
368
|
-
return { path: absolutePath, patched: false };
|
|
369
|
-
}
|
|
370
|
-
let source = fs_1.default.readFileSync(absolutePath, 'utf8');
|
|
371
|
-
if (source.includes('AuthSessionProvider')) {
|
|
372
|
-
return { path: absolutePath, patched: false };
|
|
373
|
-
}
|
|
374
|
-
if (!source.includes('<ThemeProvider')) {
|
|
375
|
-
return { path: absolutePath, patched: false };
|
|
376
|
-
}
|
|
377
|
-
if (!source.includes("from '../components/auth-session-provider'")) {
|
|
378
|
-
source = source.replace(/from 'vista\/theme';/, "from 'vista/theme';\nimport { AuthSessionProvider } from '../components/auth-session-provider';");
|
|
379
|
-
}
|
|
380
|
-
const next = source.replace(/<ThemeProvider([^>]*)>\{children\}<\/ThemeProvider>/, '<ThemeProvider$1><AuthSessionProvider>{children}</AuthSessionProvider></ThemeProvider>');
|
|
381
|
-
if (next === source) {
|
|
382
|
-
return { path: absolutePath, patched: false };
|
|
383
|
-
}
|
|
384
|
-
fs_1.default.writeFileSync(absolutePath, next, 'utf8');
|
|
385
|
-
return { path: absolutePath, patched: true };
|
|
386
|
-
}
|
|
387
|
-
function printGenerateUsage(log) {
|
|
388
|
-
log('Vista generator usage:');
|
|
389
|
-
log(' vista g api-init');
|
|
390
|
-
log(' vista g router <name>');
|
|
391
|
-
log(' vista g procedure <name> [get|post]');
|
|
392
|
-
log(' vista g agent <name>');
|
|
393
|
-
log(' vista g auth');
|
|
394
|
-
}
|
|
395
|
-
async function runGenerateCommand(args, options = {}) {
|
|
396
|
-
const cwd = options.cwd ?? process.cwd();
|
|
397
|
-
const log = options.log ?? console.log;
|
|
398
|
-
const error = options.error ?? console.error;
|
|
399
|
-
const command = (args[0] || '').toLowerCase();
|
|
400
|
-
if (!command || !['api-init', 'router', 'procedure', 'agent', 'auth'].includes(command)) {
|
|
401
|
-
printGenerateUsage(log);
|
|
402
|
-
return 1;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
log(
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
log('
|
|
420
|
-
}
|
|
421
|
-
else if (configState === '
|
|
422
|
-
log('
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
writeFileIfMissing(cwd,
|
|
493
|
-
writeFileIfMissing(cwd, path_1.default.join('
|
|
494
|
-
writeFileIfMissing(cwd,
|
|
495
|
-
writeFileIfMissing(cwd,
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runGenerateCommand = runGenerateCommand;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const app_dir_1 = require("../server/app-dir");
|
|
10
|
+
function toKebabCase(value) {
|
|
11
|
+
return value
|
|
12
|
+
.trim()
|
|
13
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
14
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
15
|
+
.replace(/^-+|-+$/g, '')
|
|
16
|
+
.toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function toPascalCase(value) {
|
|
19
|
+
return toKebabCase(value)
|
|
20
|
+
.split('-')
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.map((segment) => segment[0].toUpperCase() + segment.slice(1))
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
function toCamelCase(value) {
|
|
26
|
+
const pascal = toPascalCase(value);
|
|
27
|
+
return pascal ? pascal[0].toLowerCase() + pascal.slice(1) : '';
|
|
28
|
+
}
|
|
29
|
+
function ensureDirectory(targetDir) {
|
|
30
|
+
fs_1.default.mkdirSync(targetDir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
function writeFileIfMissing(baseDir, relativePath, content) {
|
|
33
|
+
const absolutePath = path_1.default.join(baseDir, relativePath);
|
|
34
|
+
if (fs_1.default.existsSync(absolutePath)) {
|
|
35
|
+
return { path: absolutePath, created: false };
|
|
36
|
+
}
|
|
37
|
+
ensureDirectory(path_1.default.dirname(absolutePath));
|
|
38
|
+
fs_1.default.writeFileSync(absolutePath, content, 'utf8');
|
|
39
|
+
return { path: absolutePath, created: true };
|
|
40
|
+
}
|
|
41
|
+
function renderAgent(kebabName) {
|
|
42
|
+
const camelName = toCamelCase(kebabName);
|
|
43
|
+
return [
|
|
44
|
+
"import { agent, tool } from 'vista/ai';",
|
|
45
|
+
'',
|
|
46
|
+
`export const ${camelName}Agent = agent({`,
|
|
47
|
+
` name: '${kebabName}',`,
|
|
48
|
+
" model: process.env.VISTA_AI_MODEL || 'openai:gpt-4o',",
|
|
49
|
+
` systemPrompt: 'You are a helpful AI assistant for ${kebabName}.',`,
|
|
50
|
+
' tools: [',
|
|
51
|
+
' tool({',
|
|
52
|
+
" name: 'ping',",
|
|
53
|
+
" description: 'Check agent connectivity',",
|
|
54
|
+
' execute: async () => ({ status: \"ok\", time: new Date().toISOString() }),',
|
|
55
|
+
' }),',
|
|
56
|
+
' ],',
|
|
57
|
+
' memory: true,',
|
|
58
|
+
'});',
|
|
59
|
+
'',
|
|
60
|
+
].join('\n');
|
|
61
|
+
}
|
|
62
|
+
function renderAgentRoute(kebabName) {
|
|
63
|
+
const camelName = toCamelCase(kebabName);
|
|
64
|
+
return [
|
|
65
|
+
`import { ${camelName}Agent } from '../../agents/${kebabName}/agent';`,
|
|
66
|
+
'',
|
|
67
|
+
'export async function POST(req: Request) {',
|
|
68
|
+
' const { prompt, messages, sessionId } = await req.json();',
|
|
69
|
+
` const stream = ${camelName}Agent.stream({ prompt, messages, sessionId });`,
|
|
70
|
+
' return stream.toDataStreamResponse();',
|
|
71
|
+
'}',
|
|
72
|
+
'',
|
|
73
|
+
].join('\n');
|
|
74
|
+
}
|
|
75
|
+
function renderAppAgentsGuide() {
|
|
76
|
+
return [
|
|
77
|
+
'# App agents',
|
|
78
|
+
'',
|
|
79
|
+
'Runtime Vista agents live in `app/agents/<name>/agent.ts` and stream from `app/api/agents/<name>/route.ts`.',
|
|
80
|
+
'',
|
|
81
|
+
'Generate one with:',
|
|
82
|
+
'',
|
|
83
|
+
'```bash',
|
|
84
|
+
'vista g agent support',
|
|
85
|
+
'```',
|
|
86
|
+
'',
|
|
87
|
+
'Model strings use `provider:model`. Free-tier friendly options:',
|
|
88
|
+
'',
|
|
89
|
+
'- `groq:llama-3.1-8b-instant` (`GROQ_API_KEY`)',
|
|
90
|
+
'- `nvidia:meta/llama-3.1-8b-instruct` (`NVIDIA_API_KEY`)',
|
|
91
|
+
'- `openai:gpt-4o` (`OPENAI_API_KEY`)',
|
|
92
|
+
'',
|
|
93
|
+
"Embeddings: `import { embedText } from 'vista/ai'` then pass `embed: embedText` to `createRetrieverTool`.",
|
|
94
|
+
'',
|
|
95
|
+
].join('\n');
|
|
96
|
+
}
|
|
97
|
+
function findMatchingBrace(source, openBraceIndex) {
|
|
98
|
+
let depth = 0;
|
|
99
|
+
for (let i = openBraceIndex; i < source.length; i++) {
|
|
100
|
+
const char = source[i];
|
|
101
|
+
if (char === '{')
|
|
102
|
+
depth++;
|
|
103
|
+
if (char === '}')
|
|
104
|
+
depth--;
|
|
105
|
+
if (depth === 0)
|
|
106
|
+
return i;
|
|
107
|
+
}
|
|
108
|
+
return -1;
|
|
109
|
+
}
|
|
110
|
+
function insertTypedApiConfigIntoObject(source, objectStartIndex) {
|
|
111
|
+
const openBraceIndex = source.indexOf('{', objectStartIndex);
|
|
112
|
+
if (openBraceIndex < 0) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const closeBraceIndex = findMatchingBrace(source, openBraceIndex);
|
|
116
|
+
if (closeBraceIndex < 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const before = source.slice(0, closeBraceIndex);
|
|
120
|
+
const after = source.slice(closeBraceIndex);
|
|
121
|
+
const insertion = `\n experimental: {\n typedApi: {\n enabled: true,\n },\n },`;
|
|
122
|
+
return `${before}${insertion}${after}`;
|
|
123
|
+
}
|
|
124
|
+
function ensureTypedApiEnabledInConfig(cwd) {
|
|
125
|
+
const tsPath = path_1.default.join(cwd, 'vista.config.ts');
|
|
126
|
+
const jsPath = path_1.default.join(cwd, 'vista.config.js');
|
|
127
|
+
if (!fs_1.default.existsSync(tsPath) && !fs_1.default.existsSync(jsPath)) {
|
|
128
|
+
const configSource = [
|
|
129
|
+
'const config = {',
|
|
130
|
+
' experimental: {',
|
|
131
|
+
' typedApi: {',
|
|
132
|
+
' enabled: true,',
|
|
133
|
+
' },',
|
|
134
|
+
' },',
|
|
135
|
+
'};',
|
|
136
|
+
'',
|
|
137
|
+
'export default config;',
|
|
138
|
+
'',
|
|
139
|
+
].join('\n');
|
|
140
|
+
fs_1.default.writeFileSync(tsPath, configSource, 'utf8');
|
|
141
|
+
return 'created';
|
|
142
|
+
}
|
|
143
|
+
const targetPath = fs_1.default.existsSync(tsPath) ? tsPath : jsPath;
|
|
144
|
+
const source = fs_1.default.readFileSync(targetPath, 'utf8');
|
|
145
|
+
if (/\btypedApi\b/.test(source) && /\benabled\s*:\s*true\b/.test(source)) {
|
|
146
|
+
return 'unchanged';
|
|
147
|
+
}
|
|
148
|
+
const constConfigIndex = source.indexOf('const config');
|
|
149
|
+
if (constConfigIndex >= 0) {
|
|
150
|
+
const updated = insertTypedApiConfigIntoObject(source, constConfigIndex);
|
|
151
|
+
if (updated) {
|
|
152
|
+
fs_1.default.writeFileSync(targetPath, updated, 'utf8');
|
|
153
|
+
return 'updated';
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const exportDefaultIndex = source.indexOf('export default');
|
|
157
|
+
if (exportDefaultIndex >= 0) {
|
|
158
|
+
const updated = insertTypedApiConfigIntoObject(source, exportDefaultIndex);
|
|
159
|
+
if (updated) {
|
|
160
|
+
fs_1.default.writeFileSync(targetPath, updated, 'utf8');
|
|
161
|
+
return 'updated';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return 'manual';
|
|
165
|
+
}
|
|
166
|
+
function renderApiInitEntrypoint() {
|
|
167
|
+
return [
|
|
168
|
+
"import { vstack } from 'vista/stack';",
|
|
169
|
+
"import { createRootRouter } from './routers';",
|
|
170
|
+
'',
|
|
171
|
+
'const v = vstack.init();',
|
|
172
|
+
'',
|
|
173
|
+
'export const router = createRootRouter(v);',
|
|
174
|
+
'',
|
|
175
|
+
].join('\n');
|
|
176
|
+
}
|
|
177
|
+
function renderRootRouter() {
|
|
178
|
+
return [
|
|
179
|
+
"import type { VStackInstance } from 'vista/stack';",
|
|
180
|
+
"import { healthProcedure } from '../procedures/health';",
|
|
181
|
+
'',
|
|
182
|
+
'export function createRootRouter(v: VStackInstance<any, any>) {',
|
|
183
|
+
' return v.router({',
|
|
184
|
+
' health: healthProcedure(v),',
|
|
185
|
+
' });',
|
|
186
|
+
'}',
|
|
187
|
+
'',
|
|
188
|
+
].join('\n');
|
|
189
|
+
}
|
|
190
|
+
function renderProcedure(name, method) {
|
|
191
|
+
const safeName = toCamelCase(name);
|
|
192
|
+
const functionName = `${safeName}Procedure`;
|
|
193
|
+
const procedureMethod = method === 'post' ? 'mutation' : 'query';
|
|
194
|
+
const sampleResult = method === 'post'
|
|
195
|
+
? " ok: true,\n message: 'Mutation executed',"
|
|
196
|
+
: " ok: true,\n message: 'Query executed',";
|
|
197
|
+
return [
|
|
198
|
+
"import type { VStackInstance } from 'vista/stack';",
|
|
199
|
+
'',
|
|
200
|
+
`export function ${functionName}(v: VStackInstance<any, any>) {`,
|
|
201
|
+
` return v.procedure.${procedureMethod}(() => ({`,
|
|
202
|
+
sampleResult,
|
|
203
|
+
' }));',
|
|
204
|
+
'}',
|
|
205
|
+
'',
|
|
206
|
+
].join('\n');
|
|
207
|
+
}
|
|
208
|
+
function renderRouter(name) {
|
|
209
|
+
const pascal = toPascalCase(name);
|
|
210
|
+
const camel = toCamelCase(name);
|
|
211
|
+
return [
|
|
212
|
+
"import type { VStackInstance } from 'vista/stack';",
|
|
213
|
+
'',
|
|
214
|
+
`export function create${pascal}Router(v: VStackInstance<any, any>) {`,
|
|
215
|
+
' return v.router({',
|
|
216
|
+
` ${camel}: v.procedure.query(() => ({`,
|
|
217
|
+
` route: '${toKebabCase(name)}',`,
|
|
218
|
+
' ok: true,',
|
|
219
|
+
' })),',
|
|
220
|
+
' });',
|
|
221
|
+
'}',
|
|
222
|
+
'',
|
|
223
|
+
].join('\n');
|
|
224
|
+
}
|
|
225
|
+
function renderAuthConfig() {
|
|
226
|
+
return [
|
|
227
|
+
"import VistaAuth, { Credentials, GitHub, Google } from 'vista/auth';",
|
|
228
|
+
'',
|
|
229
|
+
'export const { handlers, auth, signIn, signOut, authMiddleware } = VistaAuth({',
|
|
230
|
+
" pages: { signIn: '/signin' },",
|
|
231
|
+
' providers: [',
|
|
232
|
+
' GitHub({}),',
|
|
233
|
+
' Google({}),',
|
|
234
|
+
' Credentials({',
|
|
235
|
+
' authorize: async (credentials) => {',
|
|
236
|
+
" if (!credentials.email || !credentials.password) return null;",
|
|
237
|
+
' return { id: credentials.email, email: credentials.email, name: credentials.email };',
|
|
238
|
+
' },',
|
|
239
|
+
' }),',
|
|
240
|
+
' ],',
|
|
241
|
+
' callbacks: {',
|
|
242
|
+
' jwt: async ({ token }) => token,',
|
|
243
|
+
' session: async ({ session }) => session,',
|
|
244
|
+
' redirect: async ({ url }) => url,',
|
|
245
|
+
' },',
|
|
246
|
+
'});',
|
|
247
|
+
'',
|
|
248
|
+
].join('\n');
|
|
249
|
+
}
|
|
250
|
+
function renderAuthRoute() {
|
|
251
|
+
return [
|
|
252
|
+
"import { handlers } from '../../../../auth';",
|
|
253
|
+
'',
|
|
254
|
+
'export const { GET, POST } = handlers;',
|
|
255
|
+
'',
|
|
256
|
+
].join('\n');
|
|
257
|
+
}
|
|
258
|
+
function renderAuthMiddleware() {
|
|
259
|
+
return [
|
|
260
|
+
"import { authMiddleware } from './auth';",
|
|
261
|
+
'',
|
|
262
|
+
"export default authMiddleware(({ auth, request }) => {",
|
|
263
|
+
' const pathname = new URL(request.url).pathname;',
|
|
264
|
+
" if (pathname.startsWith('/account') && !auth) {",
|
|
265
|
+
' return false;',
|
|
266
|
+
' }',
|
|
267
|
+
' return true;',
|
|
268
|
+
'});',
|
|
269
|
+
'',
|
|
270
|
+
].join('\n');
|
|
271
|
+
}
|
|
272
|
+
function renderAuthSessionProvider() {
|
|
273
|
+
return [
|
|
274
|
+
"'use client';",
|
|
275
|
+
'',
|
|
276
|
+
"import type { ReactNode } from 'react';",
|
|
277
|
+
"import { SessionProvider } from 'vista/auth/react';",
|
|
278
|
+
'',
|
|
279
|
+
'export function AuthSessionProvider({ children }: { children: ReactNode }) {',
|
|
280
|
+
' return <SessionProvider>{children}</SessionProvider>;',
|
|
281
|
+
'}',
|
|
282
|
+
'',
|
|
283
|
+
].join('\n');
|
|
284
|
+
}
|
|
285
|
+
function renderSignInPage() {
|
|
286
|
+
return [
|
|
287
|
+
"'use client';",
|
|
288
|
+
'',
|
|
289
|
+
"import { useState } from 'react';",
|
|
290
|
+
"import { signIn } from 'vista/auth/react';",
|
|
291
|
+
'',
|
|
292
|
+
'export default function SignInPage() {',
|
|
293
|
+
" const [email, setEmail] = useState('');",
|
|
294
|
+
" const [password, setPassword] = useState('');",
|
|
295
|
+
'',
|
|
296
|
+
' return (',
|
|
297
|
+
' <main style={{ maxWidth: 360, margin: "4rem auto", display: "grid", gap: 12 }}>',
|
|
298
|
+
' <h1>Sign in</h1>',
|
|
299
|
+
' <form',
|
|
300
|
+
' onSubmit={(event) => {',
|
|
301
|
+
' event.preventDefault();',
|
|
302
|
+
" void signIn('credentials', { email, password, callbackUrl: '/account' });",
|
|
303
|
+
' }}',
|
|
304
|
+
' style={{ display: "grid", gap: 8 }}',
|
|
305
|
+
' >',
|
|
306
|
+
' <input',
|
|
307
|
+
' type="email"',
|
|
308
|
+
' name="email"',
|
|
309
|
+
' placeholder="Email"',
|
|
310
|
+
' value={email}',
|
|
311
|
+
' onChange={(event) => setEmail(event.target.value)}',
|
|
312
|
+
' required',
|
|
313
|
+
' />',
|
|
314
|
+
' <input',
|
|
315
|
+
' type="password"',
|
|
316
|
+
' name="password"',
|
|
317
|
+
' placeholder="Password"',
|
|
318
|
+
' value={password}',
|
|
319
|
+
' onChange={(event) => setPassword(event.target.value)}',
|
|
320
|
+
' required',
|
|
321
|
+
' />',
|
|
322
|
+
' <button type="submit">Continue with email</button>',
|
|
323
|
+
' </form>',
|
|
324
|
+
' <button type="button" onClick={() => void signIn("github", { callbackUrl: "/account" })}>',
|
|
325
|
+
' Continue with GitHub',
|
|
326
|
+
' </button>',
|
|
327
|
+
' <button type="button" onClick={() => void signIn("google", { callbackUrl: "/account" })}>',
|
|
328
|
+
' Continue with Google',
|
|
329
|
+
' </button>',
|
|
330
|
+
' </main>',
|
|
331
|
+
' );',
|
|
332
|
+
'}',
|
|
333
|
+
'',
|
|
334
|
+
].join('\n');
|
|
335
|
+
}
|
|
336
|
+
function renderAccountPage() {
|
|
337
|
+
return [
|
|
338
|
+
"import { auth } from '../../auth';",
|
|
339
|
+
'',
|
|
340
|
+
'export default async function AccountPage() {',
|
|
341
|
+
' const session = await auth();',
|
|
342
|
+
' if (!session?.user) {',
|
|
343
|
+
' return <p>Not signed in.</p>;',
|
|
344
|
+
' }',
|
|
345
|
+
' return (',
|
|
346
|
+
' <main style={{ maxWidth: 480, margin: "4rem auto" }}>',
|
|
347
|
+
' <h1>Account</h1>',
|
|
348
|
+
' <p>Signed in as {session.user.email || session.user.name || session.user.id}</p>',
|
|
349
|
+
' </main>',
|
|
350
|
+
' );',
|
|
351
|
+
'}',
|
|
352
|
+
'',
|
|
353
|
+
].join('\n');
|
|
354
|
+
}
|
|
355
|
+
function renderEnvExample() {
|
|
356
|
+
return [
|
|
357
|
+
'AUTH_SECRET=',
|
|
358
|
+
'AUTH_GITHUB_ID=',
|
|
359
|
+
'AUTH_GITHUB_SECRET=',
|
|
360
|
+
'AUTH_GOOGLE_ID=',
|
|
361
|
+
'AUTH_GOOGLE_SECRET=',
|
|
362
|
+
'',
|
|
363
|
+
].join('\n');
|
|
364
|
+
}
|
|
365
|
+
function patchRootWithSessionProvider(cwd) {
|
|
366
|
+
const absolutePath = path_1.default.join((0, app_dir_1.resolveAppDir)(cwd), 'root.tsx');
|
|
367
|
+
if (!fs_1.default.existsSync(absolutePath)) {
|
|
368
|
+
return { path: absolutePath, patched: false };
|
|
369
|
+
}
|
|
370
|
+
let source = fs_1.default.readFileSync(absolutePath, 'utf8');
|
|
371
|
+
if (source.includes('AuthSessionProvider')) {
|
|
372
|
+
return { path: absolutePath, patched: false };
|
|
373
|
+
}
|
|
374
|
+
if (!source.includes('<ThemeProvider')) {
|
|
375
|
+
return { path: absolutePath, patched: false };
|
|
376
|
+
}
|
|
377
|
+
if (!source.includes("from '../components/auth-session-provider'")) {
|
|
378
|
+
source = source.replace(/from 'vista\/theme';/, "from 'vista/theme';\nimport { AuthSessionProvider } from '../components/auth-session-provider';");
|
|
379
|
+
}
|
|
380
|
+
const next = source.replace(/<ThemeProvider([^>]*)>\{children\}<\/ThemeProvider>/, '<ThemeProvider$1><AuthSessionProvider>{children}</AuthSessionProvider></ThemeProvider>');
|
|
381
|
+
if (next === source) {
|
|
382
|
+
return { path: absolutePath, patched: false };
|
|
383
|
+
}
|
|
384
|
+
fs_1.default.writeFileSync(absolutePath, next, 'utf8');
|
|
385
|
+
return { path: absolutePath, patched: true };
|
|
386
|
+
}
|
|
387
|
+
function printGenerateUsage(log) {
|
|
388
|
+
log('Vista generator usage:');
|
|
389
|
+
log(' vista g api-init');
|
|
390
|
+
log(' vista g router <name>');
|
|
391
|
+
log(' vista g procedure <name> [get|post]');
|
|
392
|
+
log(' vista g agent <name>');
|
|
393
|
+
log(' vista g auth');
|
|
394
|
+
}
|
|
395
|
+
async function runGenerateCommand(args, options = {}) {
|
|
396
|
+
const cwd = options.cwd ?? process.cwd();
|
|
397
|
+
const log = options.log ?? console.log;
|
|
398
|
+
const error = options.error ?? console.error;
|
|
399
|
+
const command = (args[0] || '').toLowerCase();
|
|
400
|
+
if (!command || !['api-init', 'router', 'procedure', 'agent', 'auth'].includes(command)) {
|
|
401
|
+
printGenerateUsage(log);
|
|
402
|
+
return 1;
|
|
403
|
+
}
|
|
404
|
+
// Write generated files into the resolved app/components dirs (supports src/app layout).
|
|
405
|
+
const appDirRelative = path_1.default.relative(cwd, (0, app_dir_1.resolveAppDir)(cwd));
|
|
406
|
+
const componentsDirRelative = path_1.default.relative(cwd, (0, app_dir_1.resolveComponentsDir)(cwd));
|
|
407
|
+
if (command === 'api-init') {
|
|
408
|
+
const writes = [
|
|
409
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'typed.ts'), renderApiInitEntrypoint()),
|
|
410
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'routers', 'index.ts'), renderRootRouter()),
|
|
411
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'procedures', 'health.ts'), renderProcedure('health', 'get')),
|
|
412
|
+
];
|
|
413
|
+
const configState = ensureTypedApiEnabledInConfig(cwd);
|
|
414
|
+
writes.forEach((result) => {
|
|
415
|
+
const relativePath = path_1.default.relative(cwd, result.path).replace(/\\/g, '/');
|
|
416
|
+
log(`${result.created ? 'created' : 'skipped'} ${relativePath}`);
|
|
417
|
+
});
|
|
418
|
+
if (configState === 'created') {
|
|
419
|
+
log('created vista.config.ts with experimental.typedApi.enabled = true');
|
|
420
|
+
}
|
|
421
|
+
else if (configState === 'updated') {
|
|
422
|
+
log('updated vista.config.* to enable experimental typed API');
|
|
423
|
+
}
|
|
424
|
+
else if (configState === 'unchanged') {
|
|
425
|
+
log('typed API config already enabled');
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
error('Could not update vista.config automatically. Please enable experimental.typedApi.enabled manually.');
|
|
429
|
+
return 1;
|
|
430
|
+
}
|
|
431
|
+
return 0;
|
|
432
|
+
}
|
|
433
|
+
if (command === 'router') {
|
|
434
|
+
const rawName = args[1];
|
|
435
|
+
if (!rawName) {
|
|
436
|
+
error('Missing router name. Example: vista g router users');
|
|
437
|
+
return 1;
|
|
438
|
+
}
|
|
439
|
+
const safeName = toKebabCase(rawName);
|
|
440
|
+
if (!safeName) {
|
|
441
|
+
error(`Invalid router name "${rawName}".`);
|
|
442
|
+
return 1;
|
|
443
|
+
}
|
|
444
|
+
const result = writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'routers', `${safeName}.ts`), renderRouter(safeName));
|
|
445
|
+
const relativePath = path_1.default.relative(cwd, result.path).replace(/\\/g, '/');
|
|
446
|
+
log(`${result.created ? 'created' : 'skipped'} ${relativePath}`);
|
|
447
|
+
return 0;
|
|
448
|
+
}
|
|
449
|
+
if (command === 'procedure') {
|
|
450
|
+
const rawName = args[1];
|
|
451
|
+
if (!rawName) {
|
|
452
|
+
error('Missing procedure name. Example: vista g procedure list-users get');
|
|
453
|
+
return 1;
|
|
454
|
+
}
|
|
455
|
+
const methodArg = (args[2] || 'get').toLowerCase();
|
|
456
|
+
if (methodArg !== 'get' && methodArg !== 'post') {
|
|
457
|
+
error(`Invalid procedure method "${methodArg}". Use "get" or "post".`);
|
|
458
|
+
return 1;
|
|
459
|
+
}
|
|
460
|
+
const safeName = toKebabCase(rawName);
|
|
461
|
+
if (!safeName) {
|
|
462
|
+
error(`Invalid procedure name "${rawName}".`);
|
|
463
|
+
return 1;
|
|
464
|
+
}
|
|
465
|
+
const result = writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'procedures', `${safeName}.ts`), renderProcedure(safeName, methodArg));
|
|
466
|
+
const relativePath = path_1.default.relative(cwd, result.path).replace(/\\/g, '/');
|
|
467
|
+
log(`${result.created ? 'created' : 'skipped'} ${relativePath}`);
|
|
468
|
+
return 0;
|
|
469
|
+
}
|
|
470
|
+
if (command === 'agent') {
|
|
471
|
+
const rawName = args[1];
|
|
472
|
+
if (!rawName) {
|
|
473
|
+
error('Missing agent name. Example: vista g agent support');
|
|
474
|
+
return 1;
|
|
475
|
+
}
|
|
476
|
+
const safeName = toKebabCase(rawName);
|
|
477
|
+
if (!safeName) {
|
|
478
|
+
error(`Invalid agent name "${rawName}".`);
|
|
479
|
+
return 1;
|
|
480
|
+
}
|
|
481
|
+
const agentFile = writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'agents', safeName, 'agent.ts'), renderAgent(safeName));
|
|
482
|
+
const routeFile = writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'agents', safeName, 'route.ts'), renderAgentRoute(safeName));
|
|
483
|
+
const guideFile = writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'AGENTS.md'), renderAppAgentsGuide());
|
|
484
|
+
[agentFile, routeFile, guideFile].forEach((res) => {
|
|
485
|
+
const relativePath = path_1.default.relative(cwd, res.path).replace(/\\/g, '/');
|
|
486
|
+
log(`${res.created ? 'created' : 'skipped'} ${relativePath}`);
|
|
487
|
+
});
|
|
488
|
+
return 0;
|
|
489
|
+
}
|
|
490
|
+
if (command === 'auth') {
|
|
491
|
+
const writes = [
|
|
492
|
+
writeFileIfMissing(cwd, 'auth.ts', renderAuthConfig()),
|
|
493
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'api', 'auth', '[...vista]', 'route.ts'), renderAuthRoute()),
|
|
494
|
+
writeFileIfMissing(cwd, 'middleware.ts', renderAuthMiddleware()),
|
|
495
|
+
writeFileIfMissing(cwd, path_1.default.join(componentsDirRelative, 'auth-session-provider.tsx'), renderAuthSessionProvider()),
|
|
496
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'signin', 'page.tsx'), renderSignInPage()),
|
|
497
|
+
writeFileIfMissing(cwd, path_1.default.join(appDirRelative, 'account', 'page.tsx'), renderAccountPage()),
|
|
498
|
+
writeFileIfMissing(cwd, '.env.example', renderEnvExample()),
|
|
499
|
+
];
|
|
500
|
+
writes.forEach((result) => {
|
|
501
|
+
const relativePath = path_1.default.relative(cwd, result.path).replace(/\\/g, '/');
|
|
502
|
+
log(`${result.created ? 'created' : 'skipped'} ${relativePath}`);
|
|
503
|
+
});
|
|
504
|
+
const rootPatch = patchRootWithSessionProvider(cwd);
|
|
505
|
+
const rootRelative = path_1.default.relative(cwd, rootPatch.path).replace(/\\/g, '/');
|
|
506
|
+
log(rootPatch.patched ? `updated ${rootRelative}` : `skipped ${rootRelative}`);
|
|
507
|
+
log('Set AUTH_SECRET, AUTH_GITHUB_ID/SECRET, AUTH_GOOGLE_ID/SECRET in your environment.');
|
|
508
|
+
log('Credentials sign-in POSTs from /signin. OAuth honors callbackUrl. /account is auth-gated.');
|
|
509
|
+
return 0;
|
|
510
|
+
}
|
|
511
|
+
printGenerateUsage(log);
|
|
512
|
+
return 1;
|
|
513
|
+
}
|