@byline/cli 3.21.0 → 4.0.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/README.md +29 -3
- package/dist/cli.js +5 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +1 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +10 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/setup-checks.d.ts +9 -0
- package/dist/commands/setup-checks.d.ts.map +1 -1
- package/dist/commands/setup-checks.js +43 -18
- package/dist/commands/setup-checks.js.map +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +6 -0
- package/dist/context.js.map +1 -1
- package/dist/lib/dependency-version.d.ts +12 -0
- package/dist/lib/dependency-version.d.ts.map +1 -0
- package/dist/lib/dependency-version.js +101 -0
- package/dist/lib/dependency-version.js.map +1 -0
- package/dist/lib/planned-writes.d.ts +8 -0
- package/dist/lib/planned-writes.d.ts.map +1 -0
- package/dist/lib/planned-writes.js +177 -0
- package/dist/lib/planned-writes.js.map +1 -0
- package/dist/lib/planned-writes.test.d.ts +2 -0
- package/dist/lib/planned-writes.test.d.ts.map +1 -0
- package/dist/lib/planned-writes.test.js +113 -0
- package/dist/lib/planned-writes.test.js.map +1 -0
- package/dist/lib/release-policy.d.ts +12 -0
- package/dist/lib/release-policy.d.ts.map +1 -0
- package/dist/lib/release-policy.js +20 -0
- package/dist/lib/release-policy.js.map +1 -0
- package/dist/lib/release-policy.test.d.ts +2 -0
- package/dist/lib/release-policy.test.d.ts.map +1 -0
- package/dist/lib/release-policy.test.js +36 -0
- package/dist/lib/release-policy.test.js.map +1 -0
- package/dist/lib/route-config.d.ts +40 -0
- package/dist/lib/route-config.d.ts.map +1 -0
- package/dist/lib/route-config.js +322 -0
- package/dist/lib/route-config.js.map +1 -0
- package/dist/lib/static-config.d.ts +20 -0
- package/dist/lib/static-config.d.ts.map +1 -0
- package/dist/lib/static-config.js +444 -0
- package/dist/lib/static-config.js.map +1 -0
- package/dist/lib/static-config.test.d.ts +2 -0
- package/dist/lib/static-config.test.d.ts.map +1 -0
- package/dist/lib/static-config.test.js +105 -0
- package/dist/lib/static-config.test.js.map +1 -0
- package/dist/lib/template-hook-boundary.test.node.d.ts +2 -0
- package/dist/lib/template-hook-boundary.test.node.d.ts.map +1 -0
- package/dist/lib/template-hook-boundary.test.node.js +30 -0
- package/dist/lib/template-hook-boundary.test.node.js.map +1 -0
- package/dist/lib/template-path.d.ts +5 -0
- package/dist/lib/template-path.d.ts.map +1 -0
- package/dist/lib/template-path.js +9 -0
- package/dist/lib/template-path.js.map +1 -0
- package/dist/lib/workspace-root.d.ts +28 -0
- package/dist/lib/workspace-root.d.ts.map +1 -0
- package/dist/lib/workspace-root.js +205 -0
- package/dist/lib/workspace-root.js.map +1 -0
- package/dist/manifest/deps.d.ts +1 -1
- package/dist/manifest/deps.d.ts.map +1 -1
- package/dist/manifest/deps.js +18 -8
- package/dist/manifest/deps.js.map +1 -1
- package/dist/phases/deps.d.ts +14 -1
- package/dist/phases/deps.d.ts.map +1 -1
- package/dist/phases/deps.js +312 -137
- package/dist/phases/deps.js.map +1 -1
- package/dist/phases/deps.test.d.ts +2 -0
- package/dist/phases/deps.test.d.ts.map +1 -0
- package/dist/phases/deps.test.js +343 -0
- package/dist/phases/deps.test.js.map +1 -0
- package/dist/phases/preflight.d.ts.map +1 -1
- package/dist/phases/preflight.js +59 -11
- package/dist/phases/preflight.js.map +1 -1
- package/dist/phases/prompts.d.ts +2 -0
- package/dist/phases/prompts.d.ts.map +1 -1
- package/dist/phases/prompts.js +51 -2
- package/dist/phases/prompts.js.map +1 -1
- package/dist/phases/routes-ui.test.d.ts +2 -0
- package/dist/phases/routes-ui.test.d.ts.map +1 -0
- package/dist/phases/routes-ui.test.js +766 -0
- package/dist/phases/routes-ui.test.js.map +1 -0
- package/dist/phases/routes.d.ts +4 -1
- package/dist/phases/routes.d.ts.map +1 -1
- package/dist/phases/routes.js +610 -122
- package/dist/phases/routes.js.map +1 -1
- package/dist/phases/scaffold-smoke.test.d.ts +2 -0
- package/dist/phases/scaffold-smoke.test.d.ts.map +1 -0
- package/dist/phases/scaffold-smoke.test.js +168 -0
- package/dist/phases/scaffold-smoke.test.js.map +1 -0
- package/dist/phases/scaffold.d.ts +3 -2
- package/dist/phases/scaffold.d.ts.map +1 -1
- package/dist/phases/scaffold.js +268 -91
- package/dist/phases/scaffold.js.map +1 -1
- package/dist/phases/scaffold.test.js +171 -22
- package/dist/phases/scaffold.test.js.map +1 -1
- package/dist/phases/ui.d.ts +4 -1
- package/dist/phases/ui.d.ts.map +1 -1
- package/dist/phases/ui.js +51 -59
- package/dist/phases/ui.js.map +1 -1
- package/dist/phases/wire/index.d.ts.map +1 -1
- package/dist/phases/wire/index.js +10 -6
- package/dist/phases/wire/index.js.map +1 -1
- package/dist/phases/wire/shared.d.ts +4 -1
- package/dist/phases/wire/shared.d.ts.map +1 -1
- package/dist/phases/wire/vite-config.d.ts.map +1 -1
- package/dist/phases/wire/vite-config.js +69 -20
- package/dist/phases/wire/vite-config.js.map +1 -1
- package/dist/phases/wire/vite-config.test.d.ts +2 -0
- package/dist/phases/wire/vite-config.test.d.ts.map +1 -0
- package/dist/phases/wire/vite-config.test.js +97 -0
- package/dist/phases/wire/vite-config.test.js.map +1 -0
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +7 -2
- package/dist/prompts.js.map +1 -1
- package/dist/runner.js +1 -1
- package/dist/runner.js.map +1 -1
- package/dist/templates/byline/clients.server.ts +77 -0
- package/dist/templates/byline/collection-types.contract.ts +25 -0
- package/dist/templates/byline/collections/server-hooks.ts +7 -0
- package/dist/templates/byline/routes.ts +7 -6
- package/dist/templates/byline/server.config.ts +3 -1
- package/dist/templates/byline-examples/admin.config.ts +7 -12
- package/dist/templates/byline-examples/blocks/photo-block.ts +3 -2
- package/dist/templates/byline-examples/clients.server.ts +77 -0
- package/dist/templates/byline-examples/collection-types.contract.ts +25 -0
- package/dist/templates/byline-examples/collections/docs/hooks.ts +23 -13
- package/dist/templates/byline-examples/collections/docs/schema.ts +2 -11
- package/dist/templates/byline-examples/collections/media/components/media-list-view.tsx +11 -6
- package/dist/templates/byline-examples/collections/media/schema.ts +3 -0
- package/dist/templates/byline-examples/collections/news/schema.ts +4 -3
- package/dist/templates/byline-examples/collections/server-hooks.ts +8 -0
- package/dist/templates/byline-examples/fields/ai-text.ts +1 -1
- package/dist/templates/byline-examples/fields/ai-textarea.ts +1 -1
- package/dist/templates/byline-examples/fields/lexical-richtext-ai.tsx +3 -3
- package/dist/templates/byline-examples/routes.ts +7 -6
- package/dist/templates/byline-examples/scripts/backfill-version-locales.ts +1 -1
- package/dist/templates/byline-examples/scripts/import-docs.ts +11 -12
- package/dist/templates/byline-examples/scripts/lib/mdast-to-lexical.test.node.ts +93 -233
- package/dist/templates/byline-examples/scripts/lib/mdast-to-lexical.ts +2 -2
- package/dist/templates/byline-examples/scripts/lib/strip-leading-h1.test.node.ts +0 -4
- package/dist/templates/byline-examples/scripts/re-anchor.ts +3 -3
- package/dist/templates/byline-examples/scripts/regenerate-media.ts +6 -5
- package/dist/templates/byline-examples/server.config.ts +5 -4
- package/dist/templates/host/vite.config.ts +2 -0
- package/dist/templates/routes/_byline/route.lazy.tsx +1 -2
- package/dist/templates/routes/_byline/route.tsx +1 -1
- package/dist/templates/ui-byline/blocks/photo-block/index.tsx +18 -22
- package/dist/templates/ui-byline/components/admonition/index.tsx +11 -8
- package/dist/templates/ui-byline/components/code/code.tsx +6 -4
- package/dist/templates/ui-byline/components/link/lang-link.tsx +4 -8
- package/dist/templates/ui-byline/components/link/link-field.tsx +3 -2
- package/dist/templates/ui-byline/components/link/link-lexical.tsx +9 -8
- package/dist/templates/ui-byline/render-blocks.tsx +38 -34
- package/dist/templates/ui-byline/types/content.ts +25 -0
- package/dist/templates/ui-byline/types/i18n.ts +4 -8
- package/dist/test-helpers.d.ts +5 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +52 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/types.d.ts +21 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui-template-contract.test.d.ts +2 -0
- package/dist/ui-template-contract.test.d.ts.map +1 -0
- package/dist/ui-template-contract.test.js +130 -0
- package/dist/ui-template-contract.test.js.map +1 -0
- package/dist/workspace-root.test.d.ts +2 -0
- package/dist/workspace-root.test.d.ts.map +1 -0
- package/dist/workspace-root.test.js +307 -0
- package/dist/workspace-root.test.js.map +1 -0
- package/package.json +9 -1
- package/dist/templates/byline/client.server.ts +0 -32
- package/dist/templates/byline-examples/client.server.ts +0 -32
package/dist/phases/scaffold.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { applyPlannedWrites } from '../lib/planned-writes.js';
|
|
4
|
+
import { recognizeGeneratedRoutesSource, routesSourceAligned, validateRoutePaths, } from '../lib/route-config.js';
|
|
5
|
+
import { normalizeTemplateSource, toPosixTemplatePath } from '../lib/template-path.js';
|
|
3
6
|
const TARGET_DIR = 'byline';
|
|
4
7
|
const BASE_TEMPLATE = 'byline';
|
|
5
8
|
const EXAMPLES_TEMPLATE = 'byline-examples';
|
|
@@ -12,124 +15,298 @@ export const scaffoldPhase = {
|
|
|
12
15
|
title: 'Scaffold — copy byline/ config tree into the app root',
|
|
13
16
|
defaultMode: 'auto',
|
|
14
17
|
async detect(ctx) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return 'pending';
|
|
18
|
+
const inspection = inspectScaffold(ctx);
|
|
19
|
+
return inspection.complete ? 'done' : 'pending';
|
|
18
20
|
},
|
|
19
21
|
async plan(ctx) {
|
|
20
|
-
|
|
21
|
-
const entries = collectEntries(ctx, examples ?? true, importDocs ?? false);
|
|
22
|
-
const fromBase = entries.filter((e) => e.source === 'base' && e.status === 'create').length;
|
|
23
|
-
const fromExamples = entries.filter((e) => e.source === 'examples' && e.status === 'create').length;
|
|
24
|
-
const skipped = entries.filter((e) => e.status === 'skip-already-exists').length;
|
|
25
|
-
const notes = [
|
|
26
|
-
`target: ${ctx.resolve(TARGET_DIR)}/`,
|
|
27
|
-
`examples overlay: ${examples === undefined ? 'unanswered (assuming yes)' : examples ? 'yes' : 'no'}`,
|
|
28
|
-
`import-docs script: ${importDocs ? 'yes' : 'no'}`,
|
|
29
|
-
`${fromBase} base file(s), ${fromExamples} examples file(s), ${skipped} already-existing skipped`,
|
|
30
|
-
];
|
|
31
|
-
return { writes: [], commands: [], notes };
|
|
22
|
+
return buildScaffoldPlan(ctx);
|
|
32
23
|
},
|
|
33
|
-
async apply(
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
ctx.logger.error(
|
|
24
|
+
async apply(plan, ctx) {
|
|
25
|
+
const answers = ctx.state.get().answers;
|
|
26
|
+
const routes = validateRoutePaths(ctx, answers.adminPath, answers.signInPath);
|
|
27
|
+
if (!routes.ok) {
|
|
28
|
+
ctx.logger.error(routes.error);
|
|
38
29
|
return { state: 'blocked' };
|
|
39
30
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
writeFileSync(entry.toAbs, readFileSync(entry.fromAbs, 'utf8'), 'utf8');
|
|
49
|
-
written++;
|
|
31
|
+
ctx.state.patchAnswers({
|
|
32
|
+
adminPath: routes.value.adminPath,
|
|
33
|
+
signInPath: routes.value.signInPath,
|
|
34
|
+
});
|
|
35
|
+
const entries = collectTemplateEntries(ctx, answers.examples ?? true, (answers.examples ?? true) && (answers.importDocs ?? false));
|
|
36
|
+
if (entries.length === 0) {
|
|
37
|
+
ctx.logger.error('no scaffold templates found — was the CLI built with templates?');
|
|
38
|
+
return { state: 'blocked' };
|
|
50
39
|
}
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
ctx.logger.
|
|
40
|
+
const result = applyPlannedWrites(plan.writes);
|
|
41
|
+
if (result.written.length > 0) {
|
|
42
|
+
ctx.logger.success(`wrote ${result.written.length} planned scaffold file(s)`);
|
|
54
43
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
if (result.conflicts.length > 0) {
|
|
45
|
+
ctx.logger.warn('files changed after preview and were left untouched:');
|
|
46
|
+
for (const path of result.conflicts)
|
|
47
|
+
ctx.logger.raw(` - ${path}`);
|
|
48
|
+
return { state: 'partial' };
|
|
58
49
|
}
|
|
59
|
-
|
|
50
|
+
const inspection = inspectScaffold(ctx);
|
|
51
|
+
for (const note of inspection.manualNotes)
|
|
52
|
+
ctx.logger.warn(note);
|
|
53
|
+
return { state: inspection.complete ? 'done' : 'partial' };
|
|
60
54
|
},
|
|
61
55
|
};
|
|
62
|
-
export function
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
export function buildScaffoldPlan(ctx) {
|
|
57
|
+
const answers = ctx.state.get().answers;
|
|
58
|
+
const routes = validateRoutePaths(ctx, answers.adminPath, answers.signInPath);
|
|
59
|
+
if (!routes.ok)
|
|
60
|
+
return { writes: [], commands: [], notes: [routes.error] };
|
|
61
|
+
const examples = answers.examples ?? true;
|
|
62
|
+
const importDocs = examples && (answers.importDocs ?? false);
|
|
63
|
+
const entries = collectTemplateEntries(ctx, examples, importDocs);
|
|
64
|
+
const writes = [];
|
|
65
|
+
const notes = [
|
|
66
|
+
`target: ${ctx.resolve(TARGET_DIR)}/`,
|
|
67
|
+
`examples overlay: ${examples ? 'yes' : 'no'}`,
|
|
68
|
+
`import-docs script: ${importDocs ? 'yes' : 'no'}`,
|
|
69
|
+
];
|
|
70
|
+
let skipped = 0;
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
const path = ctx.resolve(TARGET_DIR, entry.rel);
|
|
73
|
+
const expected = transformTemplate(entry.rel, entry.contents, routes.value.adminPath, routes.value.signInPath);
|
|
74
|
+
if (!existsSync(path)) {
|
|
75
|
+
writes.push({ path, contents: expected, mode: 'create' });
|
|
71
76
|
continue;
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
}
|
|
78
|
+
const current = readFileSync(path, 'utf8');
|
|
79
|
+
if (entry.rel === 'routes.ts' &&
|
|
80
|
+
normalizeTemplateSource(current) !== normalizeTemplateSource(expected)) {
|
|
81
|
+
if (!routesSourceAligned(current, ctx, routes.value)) {
|
|
82
|
+
if (recognizeGeneratedRoutesSource(current, entry.contents)) {
|
|
83
|
+
notes.push(`${path}: generated route migration deferred atomically to the routes phase`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
notes.push(`${path}: manual — existing routes.ts is user-owned and does not match a generated predecessor`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
skipped++;
|
|
91
|
+
}
|
|
92
|
+
const packageScripts = planGenerationScripts(ctx);
|
|
93
|
+
if (packageScripts.write)
|
|
94
|
+
writes.push(packageScripts.write);
|
|
95
|
+
notes.push(...packageScripts.notes);
|
|
96
|
+
const turbo = planTurboGenerationCheck(ctx);
|
|
97
|
+
if (turbo.write)
|
|
98
|
+
writes.push(turbo.write);
|
|
99
|
+
if (turbo.note)
|
|
100
|
+
notes.push(turbo.note);
|
|
101
|
+
const ci = inspectCiGenerationCheck(ctx);
|
|
102
|
+
if (ci.note)
|
|
103
|
+
notes.push(ci.note);
|
|
104
|
+
notes.push(`${writes.length} planned write(s), ${skipped} existing scaffold file(s) preserved`);
|
|
105
|
+
if (entries.length === 0)
|
|
106
|
+
notes.push('no template files found — was the CLI built with templates?');
|
|
107
|
+
return { writes, commands: [], notes };
|
|
108
|
+
}
|
|
109
|
+
function inspectScaffold(ctx) {
|
|
110
|
+
const answers = ctx.state.get().answers;
|
|
111
|
+
const routes = validateRoutePaths(ctx, answers.adminPath, answers.signInPath);
|
|
112
|
+
if (!routes.ok)
|
|
113
|
+
return { complete: false, manualNotes: [routes.error] };
|
|
114
|
+
const entries = collectTemplateEntries(ctx, answers.examples ?? true, (answers.examples ?? true) && (answers.importDocs ?? false));
|
|
115
|
+
if (entries.length === 0)
|
|
116
|
+
return { complete: false, manualNotes: [] };
|
|
117
|
+
const missing = entries.filter((entry) => !existsSync(ctx.resolve(TARGET_DIR, entry.rel)));
|
|
118
|
+
const manualNotes = [];
|
|
119
|
+
const routeEntry = entries.find((entry) => entry.rel === 'routes.ts');
|
|
120
|
+
if (routeEntry) {
|
|
121
|
+
const path = ctx.resolve(TARGET_DIR, routeEntry.rel);
|
|
122
|
+
if (existsSync(path)) {
|
|
123
|
+
const expected = transformTemplate(routeEntry.rel, routeEntry.contents, routes.value.adminPath, routes.value.signInPath);
|
|
124
|
+
if (normalizeTemplateSource(readFileSync(path, 'utf8')) !== normalizeTemplateSource(expected)) {
|
|
125
|
+
const current = readFileSync(path, 'utf8');
|
|
126
|
+
if (!routesSourceAligned(current, ctx, routes.value) &&
|
|
127
|
+
!recognizeGeneratedRoutesSource(current, routeEntry.contents)) {
|
|
128
|
+
manualNotes.push(`${path}: manual update required so routes.admin and routes.signIn match ${routes.value.adminPath} and ${routes.value.signInPath}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
74
132
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
133
|
+
const scriptsComplete = generationScriptsComplete(ctx);
|
|
134
|
+
const packageNotes = planGenerationScripts(ctx).notes;
|
|
135
|
+
const turbo = inspectTurboGenerationCheck(ctx);
|
|
136
|
+
const ci = inspectCiGenerationCheck(ctx);
|
|
137
|
+
if (turbo.note)
|
|
138
|
+
manualNotes.push(turbo.note);
|
|
139
|
+
if (ci.note)
|
|
140
|
+
manualNotes.push(ci.note);
|
|
141
|
+
manualNotes.push(...packageNotes);
|
|
142
|
+
return {
|
|
143
|
+
complete: missing.length === 0 &&
|
|
144
|
+
scriptsComplete &&
|
|
145
|
+
turbo.complete &&
|
|
146
|
+
ci.complete &&
|
|
147
|
+
manualNotes.length === 0,
|
|
148
|
+
manualNotes,
|
|
149
|
+
};
|
|
79
150
|
}
|
|
80
|
-
function
|
|
81
|
-
const targetRoot = ctx.resolve(TARGET_DIR);
|
|
151
|
+
function collectTemplateEntries(ctx, examples, importDocs) {
|
|
82
152
|
const baseRoot = join(ctx.templatesDir(), BASE_TEMPLATE);
|
|
83
153
|
const examplesRoot = join(ctx.templatesDir(), EXAMPLES_TEMPLATE);
|
|
84
154
|
const allExamples = examples && existsSync(examplesRoot) ? walkFiles(examplesRoot) : [];
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// `regenerate-media.ts`) is part of the standard examples overlay.
|
|
90
|
-
const examplesFiles = importDocs
|
|
91
|
-
? allExamples
|
|
92
|
-
: allExamples.filter((abs) => {
|
|
93
|
-
const rel = relative(examplesRoot, abs);
|
|
94
|
-
return rel !== 'scripts/import-docs.ts' && !rel.startsWith('scripts/lib/');
|
|
95
|
-
});
|
|
96
|
-
const examplesRels = new Set(examplesFiles.map((abs) => relative(examplesRoot, abs)));
|
|
155
|
+
const exampleFiles = allExamples.filter((abs) => {
|
|
156
|
+
return shouldIncludeExampleTemplate(relative(examplesRoot, abs), importDocs);
|
|
157
|
+
});
|
|
158
|
+
const exampleRels = new Set(exampleFiles.map((abs) => toPosixTemplatePath(relative(examplesRoot, abs))));
|
|
97
159
|
const entries = [];
|
|
98
160
|
if (existsSync(baseRoot)) {
|
|
99
161
|
for (const abs of walkFiles(baseRoot)) {
|
|
100
|
-
const rel = relative(baseRoot, abs);
|
|
101
|
-
|
|
102
|
-
// (e.g. server.config.ts, admin.config.ts, seed.ts). Skip the base
|
|
103
|
-
// entry so we don't queue two writes for the same target file.
|
|
104
|
-
if (examplesRels.has(rel))
|
|
162
|
+
const rel = toPosixTemplatePath(relative(baseRoot, abs));
|
|
163
|
+
if (exampleRels.has(rel))
|
|
105
164
|
continue;
|
|
106
|
-
|
|
107
|
-
entries.push({
|
|
108
|
-
fromAbs: abs,
|
|
109
|
-
rel,
|
|
110
|
-
toAbs,
|
|
111
|
-
source: 'base',
|
|
112
|
-
status: existsSync(toAbs) ? 'skip-already-exists' : 'create',
|
|
113
|
-
});
|
|
165
|
+
entries.push({ rel, contents: readFileSync(abs, 'utf8') });
|
|
114
166
|
}
|
|
115
167
|
}
|
|
116
|
-
for (const abs of
|
|
117
|
-
const rel = relative(examplesRoot, abs);
|
|
118
|
-
const toAbs = join(targetRoot, rel);
|
|
168
|
+
for (const abs of exampleFiles) {
|
|
119
169
|
entries.push({
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
toAbs,
|
|
123
|
-
source: 'examples',
|
|
124
|
-
status: existsSync(toAbs) ? 'skip-already-exists' : 'create',
|
|
170
|
+
rel: toPosixTemplatePath(relative(examplesRoot, abs)),
|
|
171
|
+
contents: readFileSync(abs, 'utf8'),
|
|
125
172
|
});
|
|
126
173
|
}
|
|
127
|
-
return entries;
|
|
174
|
+
return entries.sort((a, b) => a.rel.localeCompare(b.rel));
|
|
175
|
+
}
|
|
176
|
+
export function shouldIncludeExampleTemplate(relativePath, importDocs) {
|
|
177
|
+
const rel = toPosixTemplatePath(relativePath);
|
|
178
|
+
if (rel.endsWith('.test.node.ts'))
|
|
179
|
+
return false;
|
|
180
|
+
if (importDocs)
|
|
181
|
+
return true;
|
|
182
|
+
return rel !== 'scripts/import-docs.ts' && !rel.startsWith('scripts/lib/');
|
|
183
|
+
}
|
|
184
|
+
function transformTemplate(rel, contents, adminPath, signInPath) {
|
|
185
|
+
if (toPosixTemplatePath(rel) !== 'routes.ts')
|
|
186
|
+
return contents;
|
|
187
|
+
return contents
|
|
188
|
+
.replace(/(admin\s*:\s*['"])[^'"]+(['"])/, `$1${adminPath}$2`)
|
|
189
|
+
.replace(/(signIn\s*:\s*['"])[^'"]+(['"])/, `$1${signInPath}$2`);
|
|
190
|
+
}
|
|
191
|
+
function planGenerationScripts(ctx) {
|
|
192
|
+
const path = ctx.resolve('package.json');
|
|
193
|
+
if (!existsSync(path))
|
|
194
|
+
return { notes: [`${path}: manual — package.json is missing`] };
|
|
195
|
+
const before = readFileSync(path, 'utf8');
|
|
196
|
+
let pkg;
|
|
197
|
+
try {
|
|
198
|
+
pkg = JSON.parse(before);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return { notes: [`${path}: manual — package.json is not valid JSON`] };
|
|
202
|
+
}
|
|
203
|
+
const scripts = { ...(pkg.scripts ?? {}) };
|
|
204
|
+
let changed = false;
|
|
205
|
+
const notes = [];
|
|
206
|
+
for (const [name, command] of Object.entries(GENERATION_SCRIPTS)) {
|
|
207
|
+
if (scripts[name] !== undefined) {
|
|
208
|
+
if (scripts[name] !== command) {
|
|
209
|
+
notes.push(`${path}: manual — existing ${name} script differs from the canonical command`);
|
|
210
|
+
}
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
scripts[name] = command;
|
|
214
|
+
changed = true;
|
|
215
|
+
}
|
|
216
|
+
if (!changed)
|
|
217
|
+
return { notes };
|
|
218
|
+
return {
|
|
219
|
+
write: {
|
|
220
|
+
path,
|
|
221
|
+
contents: `${JSON.stringify({ ...pkg, scripts }, null, 2)}\n`,
|
|
222
|
+
mode: 'patch',
|
|
223
|
+
before,
|
|
224
|
+
},
|
|
225
|
+
notes,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function generationScriptsComplete(ctx) {
|
|
229
|
+
try {
|
|
230
|
+
const pkg = JSON.parse(readFileSync(ctx.resolve('package.json'), 'utf8'));
|
|
231
|
+
return Object.entries(GENERATION_SCRIPTS).every(([name, command]) => pkg.scripts?.[name] === command);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function planTurboGenerationCheck(ctx) {
|
|
238
|
+
const path = ctx.resolveWorkspace('turbo.json');
|
|
239
|
+
if (!existsSync(path))
|
|
240
|
+
return {};
|
|
241
|
+
const before = readFileSync(path, 'utf8');
|
|
242
|
+
let config;
|
|
243
|
+
try {
|
|
244
|
+
config = JSON.parse(before);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return { note: `${path}: manual — add a byline:generate:check task; config is not plain JSON` };
|
|
248
|
+
}
|
|
249
|
+
if (!config.tasks || typeof config.tasks !== 'object' || Array.isArray(config.tasks)) {
|
|
250
|
+
return { note: `${path}: manual — add a byline:generate:check task under tasks` };
|
|
251
|
+
}
|
|
252
|
+
if (config.tasks['byline:generate:check'] !== undefined)
|
|
253
|
+
return {};
|
|
254
|
+
const tasks = { ...config.tasks, 'byline:generate:check': { outputs: [] } };
|
|
255
|
+
return {
|
|
256
|
+
write: {
|
|
257
|
+
path,
|
|
258
|
+
contents: `${JSON.stringify({ ...config, tasks }, null, 2)}\n`,
|
|
259
|
+
mode: 'patch',
|
|
260
|
+
before,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function inspectTurboGenerationCheck(ctx) {
|
|
265
|
+
const path = ctx.resolveWorkspace('turbo.json');
|
|
266
|
+
if (!existsSync(path))
|
|
267
|
+
return { complete: true };
|
|
268
|
+
let config;
|
|
269
|
+
try {
|
|
270
|
+
config = JSON.parse(readFileSync(path, 'utf8'));
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return {
|
|
274
|
+
complete: false,
|
|
275
|
+
note: `${path}: manual — add a byline:generate:check task; config is not plain JSON`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if (!config.tasks || typeof config.tasks !== 'object' || Array.isArray(config.tasks)) {
|
|
279
|
+
return {
|
|
280
|
+
complete: false,
|
|
281
|
+
note: `${path}: manual — add a byline:generate:check task under tasks`,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return { complete: config.tasks['byline:generate:check'] !== undefined };
|
|
285
|
+
}
|
|
286
|
+
function inspectCiGenerationCheck(ctx) {
|
|
287
|
+
const path = ctx.resolveWorkspace('.github/workflows/ci.yml');
|
|
288
|
+
if (!existsSync(path))
|
|
289
|
+
return { complete: true };
|
|
290
|
+
if (ciIncludesGenerationCheck(readFileSync(path, 'utf8')))
|
|
291
|
+
return { complete: true };
|
|
292
|
+
return {
|
|
293
|
+
complete: false,
|
|
294
|
+
note: `${path}: manual — add byline:generate:check to the existing CI workflow; arbitrary CI YAML is never rewritten`,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function ciIncludesGenerationCheck(source) {
|
|
298
|
+
return source.split(/\r?\n/).some((line) => {
|
|
299
|
+
const trimmed = line.trim();
|
|
300
|
+
return (trimmed.length > 0 &&
|
|
301
|
+
!trimmed.startsWith('#') &&
|
|
302
|
+
!trimmed.startsWith('name:') &&
|
|
303
|
+
trimmed.includes('byline:generate:check'));
|
|
304
|
+
});
|
|
128
305
|
}
|
|
129
306
|
function walkFiles(root) {
|
|
130
307
|
const out = [];
|
|
131
308
|
function walk(dir) {
|
|
132
|
-
for (const name of readdirSync(dir)) {
|
|
309
|
+
for (const name of readdirSync(dir).sort()) {
|
|
133
310
|
const abs = join(dir, name);
|
|
134
311
|
const st = statSync(abs);
|
|
135
312
|
if (st.isDirectory())
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/phases/scaffold.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/phases/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,178 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
2
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
|
|
3
|
+
import { createTestContext } from '../test-helpers.js';
|
|
4
|
+
import { buildRoutesPlan, routesPhase } from './routes.js';
|
|
5
|
+
import { buildScaffoldPlan, scaffoldPhase, shouldIncludeExampleTemplate } from './scaffold.js';
|
|
6
|
+
const contexts = [];
|
|
7
7
|
afterEach(() => {
|
|
8
|
-
for (const
|
|
9
|
-
rmSync(
|
|
10
|
-
}
|
|
8
|
+
for (const ctx of contexts.splice(0))
|
|
9
|
+
rmSync(ctx.cwd, { recursive: true, force: true });
|
|
11
10
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
expect(
|
|
21
|
-
|
|
22
|
-
expect(
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
function fixture(answers = {}) {
|
|
12
|
+
const ctx = createTestContext(answers);
|
|
13
|
+
contexts.push(ctx);
|
|
14
|
+
writeFileSync(ctx.resolve('package.json'), `${JSON.stringify({ name: 'fixture', scripts: { test: 'vitest' } }, null, 2)}\n`);
|
|
15
|
+
return ctx;
|
|
16
|
+
}
|
|
17
|
+
describe('scaffold planning', () => {
|
|
18
|
+
it('normalizes backslash paths before inventory filtering', () => {
|
|
19
|
+
expect(shouldIncludeExampleTemplate('scripts\\import-docs.ts', false)).toBe(false);
|
|
20
|
+
expect(shouldIncludeExampleTemplate('scripts\\lib\\helper.ts', false)).toBe(false);
|
|
21
|
+
expect(shouldIncludeExampleTemplate('scripts\\lib\\helper.ts', true)).toBe(true);
|
|
22
|
+
expect(shouldIncludeExampleTemplate('scripts\\lib\\helper.test.node.ts', true)).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it('plans concrete default-example writes and applies exactly their previewed contents', async () => {
|
|
25
|
+
const ctx = fixture({ examples: true, importDocs: false, adminPath: '/admin' });
|
|
26
|
+
const plan = buildScaffoldPlan(ctx);
|
|
27
|
+
expect(plan.writes.some((write) => write.path.endsWith('byline/routes.ts'))).toBe(true);
|
|
28
|
+
expect(plan.writes.some((write) => write.path.includes('import-docs'))).toBe(false);
|
|
29
|
+
expect((await scaffoldPhase.apply(plan, ctx)).state).toBe('done');
|
|
30
|
+
for (const write of plan.writes)
|
|
31
|
+
expect(readFileSync(write.path, 'utf8')).toBe(write.contents);
|
|
32
|
+
});
|
|
33
|
+
it('creates custom runtime routes and never overwrites a divergent routes.ts', async () => {
|
|
34
|
+
const ctx = fixture({ examples: false, adminPath: '/cms', signInPath: '/staff/login' });
|
|
35
|
+
const initial = buildScaffoldPlan(ctx);
|
|
36
|
+
const routesWrite = initial.writes.find((write) => write.path.endsWith('byline/routes.ts'));
|
|
37
|
+
expect(routesWrite?.contents).toContain("admin: '/cms'");
|
|
38
|
+
expect(routesWrite?.contents).toContain("signIn: '/staff/login'");
|
|
39
|
+
await scaffoldPhase.apply(initial, ctx);
|
|
40
|
+
writeFileSync(ctx.resolve('byline/routes.ts'), "export const routes = { admin: '/mine' }\n");
|
|
41
|
+
const rerun = buildScaffoldPlan(ctx);
|
|
42
|
+
expect(rerun.writes.some((write) => write.path.endsWith('byline/routes.ts'))).toBe(false);
|
|
43
|
+
expect(rerun.notes.join('\n')).toContain('manual');
|
|
44
|
+
expect((await scaffoldPhase.apply(rerun, ctx)).state).toBe('partial');
|
|
45
|
+
expect(readFileSync(ctx.resolve('byline/routes.ts'), 'utf8')).toContain("'/mine'");
|
|
46
|
+
});
|
|
47
|
+
it('counts matching user-owned routes as aligned without claiming write ownership', async () => {
|
|
48
|
+
const ctx = fixture({ examples: false, adminPath: '/cms', signInPath: '/staff/login' });
|
|
49
|
+
const path = ctx.resolve('byline/routes.ts');
|
|
50
|
+
const source = `
|
|
51
|
+
const values = { admin: '/cms', signIn: '/staff/login' } as const
|
|
52
|
+
export const routes = { api: '/rpc', ...values } satisfies Record<string, string>
|
|
53
|
+
// user-owned
|
|
54
|
+
`;
|
|
55
|
+
mkdirSync(ctx.resolve('byline'), { recursive: true });
|
|
56
|
+
writeFileSync(path, source);
|
|
57
|
+
const plan = buildScaffoldPlan(ctx);
|
|
58
|
+
expect(plan.writes.some((write) => write.path === path)).toBe(false);
|
|
59
|
+
expect(plan.notes.join('\n')).not.toContain('manual — existing routes.ts');
|
|
60
|
+
expect((await scaffoldPhase.apply(plan, ctx)).state).toBe('done');
|
|
61
|
+
expect(readFileSync(path, 'utf8')).toBe(source);
|
|
62
|
+
});
|
|
63
|
+
it('defers the literal previous-release config migration and completes it in routes', async () => {
|
|
64
|
+
const ctx = fixture({
|
|
65
|
+
examples: false,
|
|
66
|
+
importDocs: false,
|
|
67
|
+
adminPath: '/admin',
|
|
68
|
+
signInPath: '/staff/login',
|
|
25
69
|
});
|
|
26
|
-
|
|
70
|
+
const configPath = ctx.resolve('byline/routes.ts');
|
|
71
|
+
mkdirSync(ctx.resolve('byline'), { recursive: true });
|
|
72
|
+
writeFileSync(configPath, previousReleaseRoutesSource());
|
|
73
|
+
const scaffold = buildScaffoldPlan(ctx);
|
|
74
|
+
expect(scaffold.writes.some((write) => write.path === configPath)).toBe(false);
|
|
75
|
+
expect(scaffold.notes.join('\n')).toContain('deferred atomically to the routes phase');
|
|
76
|
+
expect((await scaffoldPhase.apply(scaffold, ctx)).state).toBe('done');
|
|
77
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('done');
|
|
78
|
+
expect(readFileSync(configPath, 'utf8')).not.toContain('signIn:');
|
|
79
|
+
expect((await routesPhase.apply(buildRoutesPlan(ctx), ctx)).state).toBe('done');
|
|
80
|
+
expect(readFileSync(configPath, 'utf8')).toContain("signIn: '/staff/login'");
|
|
81
|
+
expect(await routesPhase.detect(ctx)).toBe('done');
|
|
82
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('done');
|
|
83
|
+
});
|
|
84
|
+
it('excludes import helper tests while including the optional helper implementation', () => {
|
|
85
|
+
const ctx = fixture({ examples: true, importDocs: true });
|
|
86
|
+
const plan = buildScaffoldPlan(ctx);
|
|
87
|
+
expect(plan.writes.some((write) => write.path.endsWith('scripts/import-docs.ts'))).toBe(true);
|
|
88
|
+
expect(plan.writes.some((write) => write.path.includes('/scripts/') && write.path.endsWith('.test.node.ts'))).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
it('does not scaffold package-owned boundary tests or script helper tests', () => {
|
|
91
|
+
const ctx = fixture({ examples: true, importDocs: true });
|
|
92
|
+
const plan = buildScaffoldPlan(ctx);
|
|
93
|
+
expect(plan.writes.some((write) => write.path.endsWith('client-hook-boundary.test.node.ts') ||
|
|
94
|
+
(write.path.includes('/scripts/') && write.path.endsWith('.test.node.ts')))).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
it('patches a recognized Turbo task map and leaves unknown config manual', () => {
|
|
97
|
+
const ctx = fixture({ examples: false });
|
|
98
|
+
writeFileSync(ctx.resolve('turbo.json'), '{"tasks":{"typecheck":{"outputs":[]}}}\n');
|
|
99
|
+
let plan = buildScaffoldPlan(ctx);
|
|
100
|
+
const turboWrite = plan.writes.find((write) => write.path.endsWith('turbo.json'));
|
|
101
|
+
expect(turboWrite?.contents).toContain('byline:generate:check');
|
|
102
|
+
writeFileSync(ctx.resolve('turbo.json'), '{ // jsonc\n"tasks": {}\n}\n');
|
|
103
|
+
plan = buildScaffoldPlan(ctx);
|
|
104
|
+
expect(plan.writes.some((write) => write.path.endsWith('turbo.json'))).toBe(false);
|
|
105
|
+
expect(plan.notes.join('\n')).toContain('manual');
|
|
106
|
+
});
|
|
107
|
+
it('keeps known CI without generation checking partial across reruns', async () => {
|
|
108
|
+
const ctx = fixture({ examples: false });
|
|
109
|
+
mkdirSync(ctx.resolve('.github/workflows'), { recursive: true });
|
|
110
|
+
writeFileSync(ctx.resolve('.github/workflows/ci.yml'), 'steps:\n # TODO: add byline:generate:check\n - run: pnpm typecheck\n');
|
|
111
|
+
const plan = buildScaffoldPlan(ctx);
|
|
112
|
+
expect(plan.notes.join('\n')).toContain('manual');
|
|
113
|
+
expect((await scaffoldPhase.apply(plan, ctx)).state).toBe('partial');
|
|
114
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('pending');
|
|
115
|
+
writeFileSync(ctx.resolve('.github/workflows/ci.yml'), 'steps:\n - run: pnpm byline:generate:check\n');
|
|
116
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('done');
|
|
117
|
+
});
|
|
118
|
+
it('applies a recognized missing Turbo task but keeps unknown Turbo config partial', async () => {
|
|
119
|
+
const recognized = fixture({ examples: false });
|
|
120
|
+
writeFileSync(recognized.resolve('turbo.json'), '{"tasks":{"typecheck":{}}}\n');
|
|
121
|
+
expect((await scaffoldPhase.apply(buildScaffoldPlan(recognized), recognized)).state).toBe('done');
|
|
122
|
+
expect(await scaffoldPhase.detect(recognized)).toBe('done');
|
|
123
|
+
const unknown = fixture({ examples: false });
|
|
124
|
+
writeFileSync(unknown.resolve('turbo.json'), '{ // jsonc\n"tasks": {}\n}\n');
|
|
125
|
+
expect((await scaffoldPhase.apply(buildScaffoldPlan(unknown), unknown)).state).toBe('partial');
|
|
126
|
+
expect(await scaffoldPhase.detect(unknown)).toBe('pending');
|
|
127
|
+
});
|
|
128
|
+
it('preserves a divergent generation script and reports it as manual', () => {
|
|
129
|
+
const ctx = fixture({ examples: false });
|
|
130
|
+
writeFileSync(ctx.resolve('package.json'), `${JSON.stringify({ scripts: { 'byline:generate': 'custom-generator' } }, null, 2)}\n`);
|
|
131
|
+
const plan = buildScaffoldPlan(ctx);
|
|
132
|
+
const packageWrite = plan.writes.find((write) => write.path.endsWith('package.json'));
|
|
133
|
+
expect(packageWrite?.contents).toContain('custom-generator');
|
|
134
|
+
expect(packageWrite?.contents).toContain('byline:generate:check');
|
|
135
|
+
expect(plan.notes.join('\n')).toContain('manual');
|
|
136
|
+
});
|
|
137
|
+
it('structurally detects missing v3.21 artifacts despite a completed phase flag', async () => {
|
|
138
|
+
const ctx = fixture({ examples: false });
|
|
139
|
+
ctx.state.markPhaseComplete('scaffold');
|
|
140
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('pending');
|
|
141
|
+
const plan = buildScaffoldPlan(ctx);
|
|
142
|
+
await scaffoldPhase.apply(plan, ctx);
|
|
143
|
+
expect(existsSync(ctx.resolve('byline/generated/collection-types.ts'))).toBe(true);
|
|
144
|
+
expect(await scaffoldPhase.detect(ctx)).toBe('done');
|
|
27
145
|
});
|
|
28
146
|
});
|
|
147
|
+
function previousReleaseRoutesSource() {
|
|
148
|
+
return `/**
|
|
149
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
150
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
151
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
152
|
+
*
|
|
153
|
+
* Copyright (c) Infonomic Company Limited
|
|
154
|
+
*/
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* URL segments for admin and (future) public API routes. Defaults of
|
|
158
|
+
* \`/admin\` and \`/api\` are applied automatically by \`resolveRoutes()\` —
|
|
159
|
+
* keys only need to be set here when overriding either default.
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
import type { RoutesConfig } from '@byline/core'
|
|
163
|
+
|
|
164
|
+
export const routes: Partial<RoutesConfig> = {
|
|
165
|
+
admin: '/admin',
|
|
166
|
+
api: '/api',
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Fallback used by both server and admin entry points when no
|
|
171
|
+
* \`VITE_SERVER_URL\` env var is set. Each entry resolves the env var
|
|
172
|
+
* itself (Vite's \`import.meta.env\` on the client, Node's \`process.env\`
|
|
173
|
+
* on the server) and falls back to this literal.
|
|
174
|
+
*/
|
|
175
|
+
export const DEFAULT_SERVER_URL = 'http://localhost:5173/'
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
29
178
|
//# sourceMappingURL=scaffold.test.js.map
|