@frontman-ai/nextjs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js ADDED
@@ -0,0 +1,1062 @@
1
+ #!/usr/bin/env node
2
+ import * as Process from 'process';
3
+ import * as Fs2 from 'fs';
4
+ import * as Nodepath2 from 'path';
5
+
6
+ // ../../node_modules/@rescript/runtime/lib/es6/Primitive_option.js
7
+ function some(x) {
8
+ if (x === void 0) {
9
+ return {
10
+ BS_PRIVATE_NESTED_SOME_NONE: 0
11
+ };
12
+ } else if (x !== null && x.BS_PRIVATE_NESTED_SOME_NONE !== void 0) {
13
+ return {
14
+ BS_PRIVATE_NESTED_SOME_NONE: x.BS_PRIVATE_NESTED_SOME_NONE + 1 | 0
15
+ };
16
+ } else {
17
+ return x;
18
+ }
19
+ }
20
+ function fromNullable(x) {
21
+ if (x == null) {
22
+ return;
23
+ } else {
24
+ return some(x);
25
+ }
26
+ }
27
+ function valFromOption(x) {
28
+ if (x === null || x.BS_PRIVATE_NESTED_SOME_NONE === void 0) {
29
+ return x;
30
+ }
31
+ let depth = x.BS_PRIVATE_NESTED_SOME_NONE;
32
+ if (depth === 0) {
33
+ return;
34
+ } else {
35
+ return {
36
+ BS_PRIVATE_NESTED_SOME_NONE: depth - 1 | 0
37
+ };
38
+ }
39
+ }
40
+
41
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Option.js
42
+ function map(opt, f) {
43
+ if (opt !== void 0) {
44
+ return some(f(valFromOption(opt)));
45
+ }
46
+ }
47
+ function flatMap(opt, f) {
48
+ if (opt !== void 0) {
49
+ return f(valFromOption(opt));
50
+ }
51
+ }
52
+ function getOr(opt, $$default) {
53
+ if (opt !== void 0) {
54
+ return valFromOption(opt);
55
+ } else {
56
+ return $$default;
57
+ }
58
+ }
59
+ function isNone(x) {
60
+ return x === void 0;
61
+ }
62
+
63
+ // ../../node_modules/@rescript/runtime/lib/es6/Primitive_exceptions.js
64
+ function isExtension(e) {
65
+ if (e == null) {
66
+ return false;
67
+ } else {
68
+ return typeof e.RE_EXN_ID === "string";
69
+ }
70
+ }
71
+ function internalToException(e) {
72
+ if (isExtension(e)) {
73
+ return e;
74
+ } else {
75
+ return {
76
+ RE_EXN_ID: "JsExn",
77
+ _1: e
78
+ };
79
+ }
80
+ }
81
+
82
+ // ../bindings/src/ChildProcess.res.mjs
83
+ var execPromise = (async function(command, options) {
84
+ const { exec } = await import('child_process');
85
+ const { promisify } = await import('util');
86
+ const execP = promisify(exec);
87
+ return await execP(command, options);
88
+ });
89
+ var bufferToString = (function(value) {
90
+ if (value == null) return "";
91
+ if (typeof value === "string") return value;
92
+ if (Buffer.isBuffer(value)) return value.toString("utf8");
93
+ return String(value);
94
+ });
95
+ async function execWithOptions(command, options) {
96
+ try {
97
+ let newrecord = { ...options };
98
+ newrecord.maxBuffer = getOr(options.maxBuffer, 52428800);
99
+ let result = await execPromise(command, newrecord);
100
+ return {
101
+ TAG: "Ok",
102
+ _0: {
103
+ stdout: bufferToString(result.stdout),
104
+ stderr: bufferToString(result.stderr)
105
+ }
106
+ };
107
+ } catch (raw_exn) {
108
+ let exn = internalToException(raw_exn);
109
+ let actualError = getOr(fromNullable(exn._1), exn);
110
+ return {
111
+ TAG: "Error",
112
+ _0: {
113
+ code: fromNullable(actualError.code),
114
+ stdout: getOr(map(fromNullable(actualError.stdout), bufferToString), ""),
115
+ stderr: getOr(map(fromNullable(actualError.stderr), bufferToString), "")
116
+ }
117
+ };
118
+ }
119
+ }
120
+
121
+ // src/cli/FrontmanNextjs__Cli__Templates.res.mjs
122
+ function middlewareTemplate(host) {
123
+ return `import { createMiddleware } from '@frontman-ai/nextjs';
124
+ import { NextRequest, NextResponse } from 'next/server';
125
+
126
+ const frontman = createMiddleware({
127
+ host: '` + host + `',
128
+ });
129
+
130
+ export async function middleware(req: NextRequest) {
131
+ const response = await frontman(req);
132
+ if (response) return response;
133
+ return NextResponse.next();
134
+ }
135
+
136
+ export const config = {
137
+ matcher: ['/__frontman/:path*'],
138
+ };
139
+ `;
140
+ }
141
+ function proxyTemplate(host) {
142
+ return `import { createMiddleware } from '@frontman-ai/nextjs';
143
+ import { NextRequest, NextResponse } from 'next/server';
144
+
145
+ const frontman = createMiddleware({
146
+ host: '` + host + `',
147
+ });
148
+
149
+ export function proxy(req: NextRequest): NextResponse | Promise<NextResponse> {
150
+ if (req.nextUrl.pathname.startsWith('/__frontman')) {
151
+ return frontman(req) || NextResponse.next();
152
+ }
153
+ return NextResponse.next();
154
+ }
155
+ `;
156
+ }
157
+ function instrumentationTemplate() {
158
+ return `export async function register() {
159
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
160
+ const { NodeSDK } = await import('@opentelemetry/sdk-node');
161
+ const { setup } = await import('@frontman-ai/nextjs/Instrumentation');
162
+ const [logProcessor, spanProcessor] = setup();
163
+ new NodeSDK({
164
+ logRecordProcessors: [logProcessor],
165
+ spanProcessors: [spanProcessor],
166
+ }).start();
167
+ }
168
+ }
169
+ `;
170
+ }
171
+ function middlewareManualSetup(fileName) {
172
+ return `
173
+ Error: ` + fileName + ` already exists and requires manual modification.
174
+
175
+ Please add the following to your ` + fileName + `:
176
+
177
+ 1. Import at the top of the file:
178
+ import { createMiddleware } from '@frontman-ai/nextjs';
179
+
180
+ 2. Create the middleware instance:
181
+ const frontman = createMiddleware({
182
+ host: 'YOUR_FRONTMAN_HOST',
183
+ });
184
+
185
+ 3. In your middleware function, add before other logic:
186
+ const response = await frontman(req);
187
+ if (response) return response;
188
+
189
+ 4. Add to your matcher config:
190
+ matcher: ['/__frontman/:path*', ...yourExistingMatchers],
191
+
192
+ For full documentation, see: https://frontman.dev/docs/nextjs
193
+ `;
194
+ }
195
+ function instrumentationManualSetup(fileName) {
196
+ return `
197
+ Error: ` + fileName + ` already exists and requires manual modification.
198
+
199
+ Please add the following to your ` + fileName + `:
200
+
201
+ 1. Inside your register() function, add:
202
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
203
+ const { setup } = await import('@frontman-ai/nextjs/Instrumentation');
204
+ const [logProcessor, spanProcessor] = setup();
205
+
206
+ // Add to your NodeSDK configuration:
207
+ // logRecordProcessors: [logProcessor, ...yourExistingProcessors],
208
+ // spanProcessors: [spanProcessor, ...yourExistingProcessors],
209
+ }
210
+
211
+ For full documentation, see: https://frontman.dev/docs/nextjs
212
+ `;
213
+ }
214
+ var ErrorMessages = {
215
+ middlewareManualSetup,
216
+ proxyManualSetup: `
217
+ Error: proxy.ts already exists and requires manual modification.
218
+
219
+ Please add the following to your proxy.ts:
220
+
221
+ 1. Import at the top of the file:
222
+ import { createMiddleware } from '@frontman-ai/nextjs';
223
+
224
+ 2. Create the middleware instance:
225
+ const frontman = createMiddleware({
226
+ host: 'YOUR_FRONTMAN_HOST',
227
+ });
228
+
229
+ 3. In your proxy function, add at the beginning:
230
+ if (req.nextUrl.pathname.startsWith('/__frontman')) {
231
+ return frontman(req) || NextResponse.next();
232
+ }
233
+
234
+ For full documentation, see: https://frontman.dev/docs/nextjs
235
+ `,
236
+ instrumentationManualSetup
237
+ };
238
+ function fileCreated(fileName) {
239
+ return `Created: ` + fileName;
240
+ }
241
+ function fileSkipped(fileName) {
242
+ return `Skipped: ` + fileName + ` (already configured for Frontman)`;
243
+ }
244
+ function hostUpdated(fileName, oldHost, newHost) {
245
+ return `Updated: ` + fileName + ` (host changed from '` + oldHost + `' to '` + newHost + `')`;
246
+ }
247
+ function installComplete(host) {
248
+ return `
249
+ Frontman setup complete!
250
+
251
+ Next steps:
252
+ 1. Start your Next.js dev server: npm run dev
253
+ 2. Open your browser to: http://localhost:3000/__frontman
254
+ 3. Your app is now connected to: ` + host + `
255
+
256
+ For documentation, visit: https://frontman.dev/docs
257
+ `;
258
+ }
259
+ var SuccessMessages = {
260
+ fileCreated,
261
+ fileSkipped,
262
+ hostUpdated,
263
+ installComplete,
264
+ dryRunHeader: `
265
+ DRY RUN MODE - No files will be created
266
+
267
+ The following changes would be made:
268
+ `
269
+ };
270
+
271
+ // src/cli/FrontmanNextjs__Cli__Files.res.mjs
272
+ var hostPattern = /host:\s*['\"]([^'\"]+)['\"]/;
273
+ function updateHostInContent(content, newHost) {
274
+ return content.replace(hostPattern, `host: '` + newHost + `'`);
275
+ }
276
+ async function readFile(path) {
277
+ try {
278
+ return await Fs2.promises.readFile(path, "utf8");
279
+ } catch (exn) {
280
+ return;
281
+ }
282
+ }
283
+ async function writeFile(path, content) {
284
+ try {
285
+ await Fs2.promises.writeFile(path, content, "utf8");
286
+ return {
287
+ TAG: "Ok",
288
+ _0: void 0
289
+ };
290
+ } catch (exn) {
291
+ return {
292
+ TAG: "Error",
293
+ _0: `Failed to write ` + path
294
+ };
295
+ }
296
+ }
297
+ async function handleMiddleware(projectDir, host, existingFile, dryRun) {
298
+ let filePath = Nodepath2.join(projectDir, "middleware.ts");
299
+ let fileName = "middleware.ts";
300
+ if (typeof existingFile !== "object") {
301
+ if (existingFile !== "NotFound") {
302
+ return {
303
+ TAG: "Ok",
304
+ _0: {
305
+ TAG: "ManualEditRequired",
306
+ _0: ErrorMessages.middlewareManualSetup(fileName)
307
+ }
308
+ };
309
+ }
310
+ if (dryRun) {
311
+ return {
312
+ TAG: "Ok",
313
+ _0: {
314
+ TAG: "Created",
315
+ _0: fileName
316
+ }
317
+ };
318
+ }
319
+ let content = middlewareTemplate(host);
320
+ let e = await writeFile(filePath, content);
321
+ if (e.TAG === "Ok") {
322
+ return {
323
+ TAG: "Ok",
324
+ _0: {
325
+ TAG: "Created",
326
+ _0: fileName
327
+ }
328
+ };
329
+ } else {
330
+ return {
331
+ TAG: "Error",
332
+ _0: e._0
333
+ };
334
+ }
335
+ } else {
336
+ let existingHost = existingFile.host;
337
+ if (existingHost === host) {
338
+ return {
339
+ TAG: "Ok",
340
+ _0: {
341
+ TAG: "Skipped",
342
+ _0: fileName
343
+ }
344
+ };
345
+ }
346
+ if (dryRun) {
347
+ return {
348
+ TAG: "Ok",
349
+ _0: {
350
+ TAG: "Updated",
351
+ fileName,
352
+ oldHost: existingHost,
353
+ newHost: host
354
+ }
355
+ };
356
+ }
357
+ let content$1 = await readFile(filePath);
358
+ if (content$1 === void 0) {
359
+ return {
360
+ TAG: "Error",
361
+ _0: `Failed to read ` + fileName
362
+ };
363
+ }
364
+ let newContent = updateHostInContent(content$1, host);
365
+ let e$1 = await writeFile(filePath, newContent);
366
+ if (e$1.TAG === "Ok") {
367
+ return {
368
+ TAG: "Ok",
369
+ _0: {
370
+ TAG: "Updated",
371
+ fileName,
372
+ oldHost: existingHost,
373
+ newHost: host
374
+ }
375
+ };
376
+ } else {
377
+ return {
378
+ TAG: "Error",
379
+ _0: e$1._0
380
+ };
381
+ }
382
+ }
383
+ }
384
+ async function handleProxy(projectDir, host, existingFile, dryRun) {
385
+ let filePath = Nodepath2.join(projectDir, "proxy.ts");
386
+ let fileName = "proxy.ts";
387
+ if (typeof existingFile !== "object") {
388
+ if (existingFile !== "NotFound") {
389
+ return {
390
+ TAG: "Ok",
391
+ _0: {
392
+ TAG: "ManualEditRequired",
393
+ _0: ErrorMessages.proxyManualSetup
394
+ }
395
+ };
396
+ }
397
+ if (dryRun) {
398
+ return {
399
+ TAG: "Ok",
400
+ _0: {
401
+ TAG: "Created",
402
+ _0: fileName
403
+ }
404
+ };
405
+ }
406
+ let content = proxyTemplate(host);
407
+ let e = await writeFile(filePath, content);
408
+ if (e.TAG === "Ok") {
409
+ return {
410
+ TAG: "Ok",
411
+ _0: {
412
+ TAG: "Created",
413
+ _0: fileName
414
+ }
415
+ };
416
+ } else {
417
+ return {
418
+ TAG: "Error",
419
+ _0: e._0
420
+ };
421
+ }
422
+ } else {
423
+ let existingHost = existingFile.host;
424
+ if (existingHost === host) {
425
+ return {
426
+ TAG: "Ok",
427
+ _0: {
428
+ TAG: "Skipped",
429
+ _0: fileName
430
+ }
431
+ };
432
+ }
433
+ if (dryRun) {
434
+ return {
435
+ TAG: "Ok",
436
+ _0: {
437
+ TAG: "Updated",
438
+ fileName,
439
+ oldHost: existingHost,
440
+ newHost: host
441
+ }
442
+ };
443
+ }
444
+ let content$1 = await readFile(filePath);
445
+ if (content$1 === void 0) {
446
+ return {
447
+ TAG: "Error",
448
+ _0: `Failed to read ` + fileName
449
+ };
450
+ }
451
+ let newContent = updateHostInContent(content$1, host);
452
+ let e$1 = await writeFile(filePath, newContent);
453
+ if (e$1.TAG === "Ok") {
454
+ return {
455
+ TAG: "Ok",
456
+ _0: {
457
+ TAG: "Updated",
458
+ fileName,
459
+ oldHost: existingHost,
460
+ newHost: host
461
+ }
462
+ };
463
+ } else {
464
+ return {
465
+ TAG: "Error",
466
+ _0: e$1._0
467
+ };
468
+ }
469
+ }
470
+ }
471
+ async function handleInstrumentation(projectDir, hasSrcDir, existingFile, dryRun) {
472
+ let filePath = hasSrcDir ? Nodepath2.join(projectDir, "src", "instrumentation.ts") : Nodepath2.join(projectDir, "instrumentation.ts");
473
+ let fileName = hasSrcDir ? "src/instrumentation.ts" : "instrumentation.ts";
474
+ if (typeof existingFile === "object") {
475
+ return {
476
+ TAG: "Ok",
477
+ _0: {
478
+ TAG: "Skipped",
479
+ _0: fileName
480
+ }
481
+ };
482
+ }
483
+ if (existingFile !== "NotFound") {
484
+ return {
485
+ TAG: "Ok",
486
+ _0: {
487
+ TAG: "ManualEditRequired",
488
+ _0: ErrorMessages.instrumentationManualSetup(fileName)
489
+ }
490
+ };
491
+ }
492
+ if (dryRun) {
493
+ return {
494
+ TAG: "Ok",
495
+ _0: {
496
+ TAG: "Created",
497
+ _0: fileName
498
+ }
499
+ };
500
+ }
501
+ if (hasSrcDir) {
502
+ let srcDir = Nodepath2.join(projectDir, "src");
503
+ await Fs2.promises.mkdir(srcDir, {
504
+ recursive: true
505
+ });
506
+ }
507
+ let content = instrumentationTemplate();
508
+ let e = await writeFile(filePath, content);
509
+ if (e.TAG === "Ok") {
510
+ return {
511
+ TAG: "Ok",
512
+ _0: {
513
+ TAG: "Created",
514
+ _0: fileName
515
+ }
516
+ };
517
+ } else {
518
+ return {
519
+ TAG: "Error",
520
+ _0: e._0
521
+ };
522
+ }
523
+ }
524
+ function formatResult(result) {
525
+ switch (result.TAG) {
526
+ case "Created":
527
+ return SuccessMessages.fileCreated(result._0);
528
+ case "Updated":
529
+ return SuccessMessages.hostUpdated(result.fileName, result.oldHost, result.newHost);
530
+ case "Skipped":
531
+ return SuccessMessages.fileSkipped(result._0);
532
+ case "ManualEditRequired":
533
+ return result._0;
534
+ }
535
+ }
536
+ function isManualEditRequired(result) {
537
+ return result.TAG === "ManualEditRequired";
538
+ }
539
+
540
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Int.js
541
+ function fromString(x, radix) {
542
+ let maybeInt = parseInt(x);
543
+ if (Number.isNaN(maybeInt) || maybeInt > 2147483647 || maybeInt < -2147483648) {
544
+ return;
545
+ } else {
546
+ return maybeInt | 0;
547
+ }
548
+ }
549
+
550
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_JSON.js
551
+ function bool(json) {
552
+ if (typeof json === "boolean") {
553
+ return json;
554
+ }
555
+ }
556
+ function $$null(json) {
557
+ if (json === null) {
558
+ return null;
559
+ }
560
+ }
561
+ function string(json) {
562
+ if (typeof json === "string") {
563
+ return json;
564
+ }
565
+ }
566
+ function float(json) {
567
+ if (typeof json === "number") {
568
+ return json;
569
+ }
570
+ }
571
+ function object(json) {
572
+ if (typeof json === "object" && json !== null && !Array.isArray(json)) {
573
+ return json;
574
+ }
575
+ }
576
+ function array(json) {
577
+ if (Array.isArray(json)) {
578
+ return json;
579
+ }
580
+ }
581
+ var Decode = {
582
+ bool,
583
+ $$null,
584
+ string,
585
+ float,
586
+ object,
587
+ array
588
+ };
589
+
590
+ // src/cli/FrontmanNextjs__Cli__Detect.res.mjs
591
+ async function fileExists(path) {
592
+ try {
593
+ await Fs2.promises.access(path);
594
+ return true;
595
+ } catch (exn) {
596
+ return false;
597
+ }
598
+ }
599
+ async function dirExists(path) {
600
+ try {
601
+ await Fs2.promises.access(path);
602
+ return (await Fs2.promises.stat(path)).isDirectory();
603
+ } catch (exn) {
604
+ return false;
605
+ }
606
+ }
607
+ async function readFile2(path) {
608
+ try {
609
+ return await Fs2.promises.readFile(path, "utf8");
610
+ } catch (exn) {
611
+ return;
612
+ }
613
+ }
614
+ async function detectNextVersion(projectDir) {
615
+ let nextPkgPath = Nodepath2.join(projectDir, "node_modules", "next", "package.json");
616
+ let content = await readFile2(nextPkgPath);
617
+ if (content === void 0) {
618
+ return;
619
+ }
620
+ try {
621
+ let json = JSON.parse(content);
622
+ let match = flatMap(Decode.object(json), (obj) => obj["version"]);
623
+ if (match === void 0) {
624
+ return;
625
+ }
626
+ if (typeof match !== "string") {
627
+ return;
628
+ }
629
+ let parts = match.split(".");
630
+ let match$1 = parts[0];
631
+ let match$2 = parts[1];
632
+ if (match$1 === void 0) {
633
+ return;
634
+ }
635
+ if (match$2 === void 0) {
636
+ return;
637
+ }
638
+ let major = getOr(fromString(match$1, void 0), 0);
639
+ let minorClean = getOr(match$2.split("-")[0], "0");
640
+ let minor = getOr(fromString(minorClean, void 0), 0);
641
+ return {
642
+ major,
643
+ minor,
644
+ raw: match
645
+ };
646
+ } catch (exn) {
647
+ return;
648
+ }
649
+ }
650
+ async function detectPackageManager(projectDir) {
651
+ let bunLock = Nodepath2.join(projectDir, "bun.lockb");
652
+ let pnpmLock = Nodepath2.join(projectDir, "pnpm-lock.yaml");
653
+ let yarnLock = Nodepath2.join(projectDir, "yarn.lock");
654
+ let npmLock = Nodepath2.join(projectDir, "package-lock.json");
655
+ if (await fileExists(bunLock)) {
656
+ return "Bun";
657
+ } else if (await fileExists(pnpmLock)) {
658
+ return "Pnpm";
659
+ } else if (await fileExists(yarnLock)) {
660
+ return "Yarn";
661
+ } else {
662
+ await fileExists(npmLock);
663
+ return "Npm";
664
+ }
665
+ }
666
+ var frontmanImportPattern = /@frontman-ai\/nextjs/;
667
+ var hostPattern2 = /host:\s*['\"]([^'\"]+)['\"]/;
668
+ async function analyzeFile(filePath) {
669
+ let content = await readFile2(filePath);
670
+ if (content === void 0) {
671
+ return "NotFound";
672
+ }
673
+ if (!frontmanImportPattern.test(content)) {
674
+ return "NeedsManualEdit";
675
+ }
676
+ let result = hostPattern2.exec(content);
677
+ if (result == null) {
678
+ return {
679
+ TAG: "HasFrontman",
680
+ host: ""
681
+ };
682
+ }
683
+ let maybeHost = flatMap(result.slice(1)[0], (x) => x);
684
+ if (maybeHost !== void 0) {
685
+ return {
686
+ TAG: "HasFrontman",
687
+ host: maybeHost
688
+ };
689
+ } else {
690
+ return {
691
+ TAG: "HasFrontman",
692
+ host: ""
693
+ };
694
+ }
695
+ }
696
+ async function detectSrcDir(projectDir) {
697
+ return await dirExists(Nodepath2.join(projectDir, "src"));
698
+ }
699
+ async function hasPackageJson(projectDir) {
700
+ return await fileExists(Nodepath2.join(projectDir, "package.json"));
701
+ }
702
+ async function detect(projectDir) {
703
+ let hasPackage = await hasPackageJson(projectDir);
704
+ if (!hasPackage) {
705
+ return {
706
+ TAG: "Error",
707
+ _0: "No package.json found. Please run from your Next.js project root."
708
+ };
709
+ }
710
+ let nextVersion = await detectNextVersion(projectDir);
711
+ if (isNone(nextVersion)) {
712
+ return {
713
+ TAG: "Error",
714
+ _0: "Could not find Next.js in node_modules. Please run 'npm install' first or verify this is a Next.js project."
715
+ };
716
+ }
717
+ let middlewarePath = Nodepath2.join(projectDir, "middleware.ts");
718
+ let proxyPath = Nodepath2.join(projectDir, "proxy.ts");
719
+ let hasSrcDir = await detectSrcDir(projectDir);
720
+ let instrumentationPath = hasSrcDir ? Nodepath2.join(projectDir, "src", "instrumentation.ts") : Nodepath2.join(projectDir, "instrumentation.ts");
721
+ let middleware = await analyzeFile(middlewarePath);
722
+ let proxy = await analyzeFile(proxyPath);
723
+ let instrumentation = await analyzeFile(instrumentationPath);
724
+ let packageManager = await detectPackageManager(projectDir);
725
+ return {
726
+ TAG: "Ok",
727
+ _0: {
728
+ nextVersion,
729
+ middleware,
730
+ proxy,
731
+ instrumentation,
732
+ hasSrcDir,
733
+ packageManager
734
+ }
735
+ };
736
+ }
737
+ function isNextJs16Plus(info) {
738
+ let match = info.nextVersion;
739
+ if (match !== void 0) {
740
+ return match.major >= 16;
741
+ } else {
742
+ return false;
743
+ }
744
+ }
745
+ function getPackageManagerCommand(pm) {
746
+ switch (pm) {
747
+ case "Npm":
748
+ return "npm";
749
+ case "Yarn":
750
+ return "yarn";
751
+ case "Pnpm":
752
+ return "pnpm";
753
+ case "Bun":
754
+ return "bun";
755
+ }
756
+ }
757
+ function getInstallArgs(pm, isDevOpt) {
758
+ switch (pm) {
759
+ case "Npm":
760
+ {
761
+ return ["install"];
762
+ }
763
+ case "Yarn":
764
+ {
765
+ return ["add"];
766
+ }
767
+ case "Pnpm":
768
+ {
769
+ return ["add"];
770
+ }
771
+ case "Bun":
772
+ {
773
+ return ["add"];
774
+ }
775
+ }
776
+ }
777
+
778
+ // src/cli/FrontmanNextjs__Cli__Install.res.mjs
779
+ async function installDependencies(projectDir, packageManager, dryRun) {
780
+ if (dryRun) {
781
+ console.log("Would install: @frontman-ai/nextjs @opentelemetry/sdk-node");
782
+ return {
783
+ TAG: "Ok",
784
+ _0: void 0
785
+ };
786
+ }
787
+ let pm = getPackageManagerCommand(packageManager);
788
+ let args = getInstallArgs(packageManager);
789
+ let packages = [
790
+ "@frontman-ai/nextjs",
791
+ "@opentelemetry/sdk-node"
792
+ ];
793
+ let cmd = pm + ` ` + args.join(" ") + ` ` + packages.join(" ");
794
+ console.log(`Installing dependencies with ` + pm + `...`);
795
+ let err = await execWithOptions(cmd, {
796
+ cwd: projectDir
797
+ });
798
+ if (err.TAG === "Ok") {
799
+ console.log("Dependencies installed successfully");
800
+ return {
801
+ TAG: "Ok",
802
+ _0: void 0
803
+ };
804
+ }
805
+ let err$1 = err._0;
806
+ let stderr = err$1.stderr === "" ? "Unknown error" : err$1.stderr;
807
+ return {
808
+ TAG: "Error",
809
+ _0: `Failed to install dependencies: ` + stderr
810
+ };
811
+ }
812
+ function processFileResult(result, manualSteps) {
813
+ if (result.TAG === "Ok") {
814
+ let fileResult = result._0;
815
+ console.log(formatResult(fileResult));
816
+ if (isManualEditRequired(fileResult) && fileResult.TAG === "ManualEditRequired") {
817
+ manualSteps.push(fileResult._0);
818
+ }
819
+ return {
820
+ TAG: "Ok",
821
+ _0: void 0
822
+ };
823
+ }
824
+ let msg = result._0;
825
+ console.error(`Error: ` + msg);
826
+ return {
827
+ TAG: "Error",
828
+ _0: msg
829
+ };
830
+ }
831
+ async function run(options) {
832
+ let projectDir = getOr(options.prefix, process.cwd());
833
+ let host = options.server;
834
+ console.log("");
835
+ console.log(" Frontman Installer");
836
+ console.log(` Server: ` + host);
837
+ console.log("");
838
+ if (options.dryRun) {
839
+ console.log(SuccessMessages.dryRunHeader);
840
+ }
841
+ let msg = await detect(projectDir);
842
+ if (msg.TAG === "Ok") {
843
+ let info = msg._0;
844
+ let version = getOr(map(info.nextVersion, (v) => v.raw), "unknown");
845
+ let isNext16Plus = isNextJs16Plus(info);
846
+ console.log(`Detected Next.js ` + version);
847
+ console.log("");
848
+ if (!options.skipDeps) {
849
+ let msg$1 = await installDependencies(projectDir, info.packageManager, options.dryRun);
850
+ if (msg$1.TAG !== "Ok") {
851
+ console.error(msg$1._0);
852
+ }
853
+ }
854
+ let manualSteps = [];
855
+ let middlewareResult = isNext16Plus ? await handleProxy(projectDir, host, info.proxy, options.dryRun) : await handleMiddleware(projectDir, host, info.middleware, options.dryRun);
856
+ let msg$2 = processFileResult(middlewareResult, manualSteps);
857
+ if (msg$2.TAG !== "Ok") {
858
+ return {
859
+ TAG: "Failure",
860
+ _0: msg$2._0
861
+ };
862
+ }
863
+ let instrumentationResult = await handleInstrumentation(projectDir, info.hasSrcDir, info.instrumentation, options.dryRun);
864
+ let msg$3 = processFileResult(instrumentationResult, manualSteps);
865
+ if (msg$3.TAG === "Ok") {
866
+ if (manualSteps.length !== 0) {
867
+ console.log("");
868
+ console.log("Manual steps required:");
869
+ manualSteps.forEach((step) => {
870
+ console.log(step);
871
+ });
872
+ return {
873
+ TAG: "PartialSuccess",
874
+ manualStepsRequired: manualSteps
875
+ };
876
+ } else {
877
+ if (!options.dryRun) {
878
+ console.log(SuccessMessages.installComplete(host));
879
+ }
880
+ return "Success";
881
+ }
882
+ } else {
883
+ return {
884
+ TAG: "Failure",
885
+ _0: msg$3._0
886
+ };
887
+ }
888
+ }
889
+ let msg$4 = msg._0;
890
+ console.error(`Error: ` + msg$4);
891
+ return {
892
+ TAG: "Failure",
893
+ _0: msg$4
894
+ };
895
+ }
896
+
897
+ // src/cli/FrontmanNextjs__Cli.res.mjs
898
+ var helpText = `
899
+ Frontman NextJS CLI
900
+
901
+ Usage:
902
+ frontman-nextjs <command> [options]
903
+
904
+ Commands:
905
+ install Install Frontman in a Next.js project
906
+
907
+ Options:
908
+ --server <host> Frontman server host (required for install)
909
+ --prefix <path> Target directory (default: current directory)
910
+ --dry-run Preview changes without writing files
911
+ --skip-deps Skip dependency installation
912
+ --help Show this help message
913
+
914
+ Examples:
915
+ npx @frontman-ai/nextjs install --server frontman.company.com
916
+ npx @frontman-ai/nextjs install --server dev.frontman.io --dry-run
917
+ `;
918
+ function parseArgs(argv) {
919
+ let args = argv.slice(2, argv.length);
920
+ let _remaining = args;
921
+ let _result = {
922
+ command: void 0,
923
+ server: void 0,
924
+ prefix: void 0,
925
+ dryRun: false,
926
+ skipDeps: false,
927
+ help: false
928
+ };
929
+ while (true) {
930
+ let result = _result;
931
+ let remaining = _remaining;
932
+ let arg = remaining[0];
933
+ if (arg === void 0) {
934
+ return result;
935
+ }
936
+ let rest = remaining.slice(1, remaining.length);
937
+ switch (arg) {
938
+ case "--dry-run":
939
+ _result = {
940
+ command: result.command,
941
+ server: result.server,
942
+ prefix: result.prefix,
943
+ dryRun: true,
944
+ skipDeps: result.skipDeps,
945
+ help: result.help
946
+ };
947
+ _remaining = rest;
948
+ continue;
949
+ case "--prefix":
950
+ let value = rest[0];
951
+ let nextRest = rest.slice(1, rest.length);
952
+ _result = {
953
+ command: result.command,
954
+ server: result.server,
955
+ prefix: value,
956
+ dryRun: result.dryRun,
957
+ skipDeps: result.skipDeps,
958
+ help: result.help
959
+ };
960
+ _remaining = nextRest;
961
+ continue;
962
+ case "--server":
963
+ let value$1 = rest[0];
964
+ let nextRest$1 = rest.slice(1, rest.length);
965
+ _result = {
966
+ command: result.command,
967
+ server: value$1,
968
+ prefix: result.prefix,
969
+ dryRun: result.dryRun,
970
+ skipDeps: result.skipDeps,
971
+ help: result.help
972
+ };
973
+ _remaining = nextRest$1;
974
+ continue;
975
+ case "--skip-deps":
976
+ _result = {
977
+ command: result.command,
978
+ server: result.server,
979
+ prefix: result.prefix,
980
+ dryRun: result.dryRun,
981
+ skipDeps: true,
982
+ help: result.help
983
+ };
984
+ _remaining = rest;
985
+ continue;
986
+ case "--help":
987
+ case "-h":
988
+ break;
989
+ case "install":
990
+ _result = {
991
+ command: "install",
992
+ server: result.server,
993
+ prefix: result.prefix,
994
+ dryRun: result.dryRun,
995
+ skipDeps: result.skipDeps,
996
+ help: result.help
997
+ };
998
+ _remaining = rest;
999
+ continue;
1000
+ default:
1001
+ _remaining = rest;
1002
+ continue;
1003
+ }
1004
+ _result = {
1005
+ command: result.command,
1006
+ server: result.server,
1007
+ prefix: result.prefix,
1008
+ dryRun: result.dryRun,
1009
+ skipDeps: result.skipDeps,
1010
+ help: true
1011
+ };
1012
+ _remaining = rest;
1013
+ continue;
1014
+ }
1015
+ }
1016
+ async function main() {
1017
+ let args = parseArgs(process.argv);
1018
+ if (args.help) {
1019
+ console.log(helpText);
1020
+ Process.exit(0);
1021
+ }
1022
+ let cmd = args.command;
1023
+ if (cmd !== void 0) {
1024
+ if (cmd === "install") {
1025
+ let server = args.server;
1026
+ if (server !== void 0) {
1027
+ let result = await run({
1028
+ server,
1029
+ prefix: args.prefix,
1030
+ dryRun: args.dryRun,
1031
+ skipDeps: args.skipDeps
1032
+ });
1033
+ if (typeof result !== "object") {
1034
+ Process.exit(0);
1035
+ return;
1036
+ }
1037
+ if (result.TAG === "PartialSuccess") {
1038
+ Process.exit(0);
1039
+ return;
1040
+ }
1041
+ Process.exit(1);
1042
+ return;
1043
+ } else {
1044
+ console.error("Error: --server <host> is required for install command");
1045
+ console.log("");
1046
+ console.log("Usage: npx @frontman-ai/nextjs install --server <host>");
1047
+ Process.exit(1);
1048
+ return;
1049
+ }
1050
+ } else {
1051
+ console.error(`Unknown command: ` + cmd);
1052
+ console.log(helpText);
1053
+ Process.exit(1);
1054
+ return;
1055
+ }
1056
+ } else {
1057
+ console.log(helpText);
1058
+ Process.exit(0);
1059
+ return;
1060
+ }
1061
+ }
1062
+ main();