fimo 0.9.0-experimental.1 → 0.9.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/assets/skills/fimo/SKILL.md +17 -54
- package/assets/skills/fimo-cli/SKILL.md +15 -15
- package/assets/skills/fimo-cli/references/agent-setup.md +36 -53
- package/assets/skills/fimo-cli/references/agents.md +4 -4
- package/assets/skills/fimo-cli/references/content.md +2 -2
- package/assets/skills/fimo-cli/references/deploy.md +1 -1
- package/assets/skills/fimo-cli/references/forms.md +1 -1
- package/assets/skills/fimo-cli/references/init.md +16 -24
- package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +14 -11
- package/assets/skills/fimo-cli/references/projects.md +1 -1
- package/assets/skills/fimo-cli/references/support.md +11 -9
- package/assets/skills/fimo-cli/references/webhooks.md +3 -1
- package/assets/skills/fimo-code/SKILL.md +67 -0
- package/assets/skills/fimo-migration/SKILL.md +2 -22
- package/assets/skills/fimo-migration/references/content.md +0 -24
- package/assets/skills/fimo-migration/references/manifest.md +0 -35
- package/assets/skills/fimo-migration/references/qa.md +2 -24
- package/assets/skills/fimo-migration/references/workflow.md +1 -12
- package/assets/skills/fimo-studio/references/visual-editing.md +3 -5
- package/assets/skills/fimo-studio/references/webhooks.md +1 -1
- package/dist/build/vite/plugins/translations.d.ts +8 -2
- package/dist/build/vite/plugins/translations.js +121 -3
- package/dist/cli/bundle.json +2 -2
- package/dist/cli/index.js +311 -1209
- package/dist/runtime/app/FimoProviders.d.ts +11 -1
- package/dist/runtime/app/FimoProviders.js +23 -2
- package/dist/runtime/content/client/createContentClient.js +2 -1
- package/dist/runtime/i18n/FimoLocaleContext.js +0 -1
- package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts +3 -5
- package/dist/runtime/primitives/lib/useFimoLiveValue.js +4 -11
- package/dist/runtime/primitives/translations.d.ts +27 -1
- package/dist/runtime/primitives/translations.js +85 -7
- package/dist/runtime/shared/fimo-config.server.js +0 -1
- package/dist/runtime/shared/fimo-config.types.d.ts +0 -2
- package/dist/scripts/extract-translations.js +11 -16
- package/dist/scripts/lib/validation-report.d.ts +0 -1
- package/dist/scripts/lib/validation-report.js +0 -3
- package/dist/scripts/validate-route-metadata.js +0 -11
- package/package.json +4 -84
- package/release.json +2 -2
- package/scripts/postinstall.mjs +11 -65
- package/templates/react-router/AGENTS.md +44 -0
- package/templates/react-router/CLAUDE.md +5 -0
- package/templates/react-router/package.json +1 -1
- package/assets/agents-starter/AGENTS.md +0 -66
- package/assets/skills/fimo-migration/references/wrap.md +0 -617
- package/dist/runtime/astro/index.d.ts +0 -2
- package/dist/runtime/astro/index.js +0 -3
- package/dist/runtime/astro/server.d.ts +0 -3
- package/dist/runtime/astro/server.js +0 -6
- package/dist/runtime/next/FimoNextProviders.d.ts +0 -24
- package/dist/runtime/next/FimoNextProviders.js +0 -20
- package/dist/runtime/next/FimoNextScripts.d.ts +0 -10
- package/dist/runtime/next/FimoNextScripts.js +0 -19
- package/dist/runtime/next/index.d.ts +0 -14
- package/dist/runtime/next/index.js +0 -14
- package/dist/runtime/next/server.d.ts +0 -2
- package/dist/runtime/next/server.js +0 -4
- package/dist/runtime/nuxt/composables.d.ts +0 -9
- package/dist/runtime/nuxt/composables.js +0 -57
- package/dist/runtime/nuxt/index.d.ts +0 -3
- package/dist/runtime/nuxt/index.js +0 -6
- package/dist/runtime/nuxt/server.d.ts +0 -3
- package/dist/runtime/nuxt/server.js +0 -6
- package/dist/runtime/primitives/labels-hook.d.ts +0 -33
- package/dist/runtime/primitives/labels-hook.js +0 -41
- package/dist/runtime/primitives/labels-store.d.ts +0 -12
- package/dist/runtime/primitives/labels-store.js +0 -60
- package/dist/runtime/react/FimoSpaProviders.d.ts +0 -36
- package/dist/runtime/react/FimoSpaProviders.js +0 -63
- package/dist/runtime/react/index.d.ts +0 -33
- package/dist/runtime/react/index.js +0 -39
- package/dist/runtime/remix/FimoRemixProviders.d.ts +0 -16
- package/dist/runtime/remix/FimoRemixProviders.js +0 -12
- package/dist/runtime/remix/FimoRemixScripts.d.ts +0 -10
- package/dist/runtime/remix/FimoRemixScripts.js +0 -19
- package/dist/runtime/remix/index.d.ts +0 -12
- package/dist/runtime/remix/index.js +0 -11
- package/dist/runtime/remix/server.d.ts +0 -2
- package/dist/runtime/remix/server.js +0 -2
- package/dist/runtime/shared/display-routes.d.ts +0 -14
- package/dist/runtime/shared/display-routes.js +0 -25
- package/dist/runtime/shared/i18n-messages.d.ts +0 -29
- package/dist/runtime/shared/i18n-messages.js +0 -79
- package/dist/runtime/shared/labels-fetch.pure.d.ts +0 -17
- package/dist/runtime/shared/labels-fetch.pure.js +0 -71
- package/dist/runtime/shared/labels-fetch.server.d.ts +0 -7
- package/dist/runtime/shared/labels-fetch.server.js +0 -97
- package/dist/runtime/shared/labels-t.pure.d.ts +0 -2
- package/dist/runtime/shared/labels-t.pure.js +0 -10
- package/dist/runtime/strapi/client.d.ts +0 -30
- package/dist/runtime/strapi/client.js +0 -89
- package/dist/runtime/strapi/index.d.ts +0 -5
- package/dist/runtime/strapi/index.js +0 -6
- package/dist/runtime/strapi/reshape.d.ts +0 -46
- package/dist/runtime/strapi/reshape.js +0 -114
- package/dist/runtime/svelte/index.d.ts +0 -3
- package/dist/runtime/svelte/index.js +0 -7
- package/dist/runtime/svelte/server.d.ts +0 -3
- package/dist/runtime/svelte/server.js +0 -6
- package/dist/runtime/vue/index.d.ts +0 -3
- package/dist/runtime/vue/index.js +0 -5
- package/dist/runtime/vue/server.d.ts +0 -3
- package/dist/runtime/vue/server.js +0 -6
- package/dist/runtime/wrapped/FimoFileLink.d.ts +0 -17
- package/dist/runtime/wrapped/FimoFileLink.js +0 -19
- package/dist/runtime/wrapped/FimoMediaImage.d.ts +0 -14
- package/dist/runtime/wrapped/FimoMediaImage.js +0 -20
- package/dist/runtime/wrapped/FimoMediaVideo.d.ts +0 -14
- package/dist/runtime/wrapped/FimoMediaVideo.js +0 -20
- package/dist/runtime/wrapped/FimoRichTextBlock.d.ts +0 -23
- package/dist/runtime/wrapped/FimoRichTextBlock.js +0 -22
- package/dist/runtime/wrapped/FimoText.d.ts +0 -22
- package/dist/runtime/wrapped/FimoText.js +0 -20
- package/dist/runtime/wrapped/WrappedContentContext.d.ts +0 -28
- package/dist/runtime/wrapped/WrappedContentContext.js +0 -30
- package/dist/runtime/wrapped/WrappedProviders.d.ts +0 -33
- package/dist/runtime/wrapped/WrappedProviders.js +0 -101
- package/dist/runtime/wrapped/dom.d.ts +0 -4
- package/dist/runtime/wrapped/dom.js +0 -23
- package/dist/runtime/wrapped/server.d.ts +0 -77
- package/dist/runtime/wrapped/server.js +0 -237
- package/dist/scripts/apply-wrap-templates.d.ts +0 -61
- package/dist/scripts/apply-wrap-templates.js +0 -132
- package/dist/scripts/apply-wrap.d.ts +0 -46
- package/dist/scripts/apply-wrap.js +0 -278
- package/dist/scripts/cms/discover.d.ts +0 -2
- package/dist/scripts/cms/discover.js +0 -17
- package/dist/scripts/cms/example-content.d.ts +0 -33
- package/dist/scripts/cms/example-content.js +0 -162
- package/dist/scripts/cms/strapi/detect.d.ts +0 -2
- package/dist/scripts/cms/strapi/detect.js +0 -186
- package/dist/scripts/cms/strapi/index.d.ts +0 -3
- package/dist/scripts/cms/strapi/index.js +0 -25
- package/dist/scripts/cms/strapi/list-source.d.ts +0 -17
- package/dist/scripts/cms/strapi/list-source.js +0 -90
- package/dist/scripts/cms/strapi/schema-map.d.ts +0 -9
- package/dist/scripts/cms/strapi/schema-map.js +0 -277
- package/dist/scripts/cms/strapi/shapes.d.ts +0 -23
- package/dist/scripts/cms/strapi/shapes.js +0 -38
- package/dist/scripts/cms/strapi/touchpoints.d.ts +0 -31
- package/dist/scripts/cms/strapi/touchpoints.js +0 -145
- package/dist/scripts/cms/strapi/wire-client.d.ts +0 -15
- package/dist/scripts/cms/strapi/wire-client.js +0 -107
- package/dist/scripts/cms/strapi/wiring.d.ts +0 -17
- package/dist/scripts/cms/strapi/wiring.js +0 -46
- package/dist/scripts/cms/types.d.ts +0 -145
- package/dist/scripts/cms/types.js +0 -11
- package/dist/scripts/detect-framework.d.ts +0 -39
- package/dist/scripts/detect-framework.js +0 -133
- package/dist/scripts/draft-rows.d.ts +0 -19
- package/dist/scripts/draft-rows.js +0 -135
- package/dist/scripts/draft-schemas.d.ts +0 -27
- package/dist/scripts/draft-schemas.js +0 -188
- package/dist/scripts/frameworks/astro/routes.d.ts +0 -3
- package/dist/scripts/frameworks/astro/routes.js +0 -55
- package/dist/scripts/frameworks/astro/template-style.d.ts +0 -7
- package/dist/scripts/frameworks/astro/template-style.js +0 -19
- package/dist/scripts/frameworks/discover.d.ts +0 -70
- package/dist/scripts/frameworks/discover.js +0 -178
- package/dist/scripts/frameworks/next/rewire.d.ts +0 -30
- package/dist/scripts/frameworks/next/rewire.js +0 -258
- package/dist/scripts/frameworks/next/routes.d.ts +0 -17
- package/dist/scripts/frameworks/next/routes.js +0 -134
- package/dist/scripts/frameworks/next/wiring.d.ts +0 -33
- package/dist/scripts/frameworks/next/wiring.js +0 -186
- package/dist/scripts/frameworks/nuxt/routes.d.ts +0 -3
- package/dist/scripts/frameworks/nuxt/routes.js +0 -54
- package/dist/scripts/frameworks/nuxt/template-style.d.ts +0 -9
- package/dist/scripts/frameworks/nuxt/template-style.js +0 -27
- package/dist/scripts/frameworks/remix/routes.d.ts +0 -3
- package/dist/scripts/frameworks/remix/routes.js +0 -50
- package/dist/scripts/frameworks/support.d.ts +0 -75
- package/dist/scripts/frameworks/support.js +0 -165
- package/dist/scripts/frameworks/sveltekit/routes.d.ts +0 -3
- package/dist/scripts/frameworks/sveltekit/routes.js +0 -50
- package/dist/scripts/frameworks/sveltekit/template-style.d.ts +0 -9
- package/dist/scripts/frameworks/sveltekit/template-style.js +0 -54
- package/dist/scripts/frameworks/vite/routes.d.ts +0 -15
- package/dist/scripts/frameworks/vite/routes.js +0 -93
- package/dist/scripts/frameworks/vite/wiring.d.ts +0 -10
- package/dist/scripts/frameworks/vite/wiring.js +0 -99
- package/dist/scripts/i18n-namespace.d.ts +0 -27
- package/dist/scripts/i18n-namespace.js +0 -155
- package/dist/scripts/render-parity/capture.d.ts +0 -56
- package/dist/scripts/render-parity/capture.js +0 -366
- package/dist/scripts/render-parity/compare.d.ts +0 -59
- package/dist/scripts/render-parity/compare.js +0 -0
- package/dist/scripts/render-parity/normalize-html.d.ts +0 -13
- package/dist/scripts/render-parity/normalize-html.js +0 -223
- package/dist/scripts/render-parity/types.d.ts +0 -41
- package/dist/scripts/render-parity/types.js +0 -1
- package/dist/scripts/scan-wrappable.d.ts +0 -196
- package/dist/scripts/scan-wrappable.js +0 -1232
- /package/assets/skills/{fimo → fimo-code}/assets/react-router-locales/navigation.tsx +0 -0
- /package/assets/skills/{fimo → fimo-code}/assets/react-router-locales/routes.ts +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/assets.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/content.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/design.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/forms.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/labels.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/locales.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/setup-plain-vite.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/setup-react-router.md +0 -0
- /package/assets/skills/{fimo → fimo-code}/references/ui.md +0 -0
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { WrapScanResult } from './scan-wrappable.js';
|
|
2
|
-
/**
|
|
3
|
-
* Machine-typed schema DRAFTS for every detected collection. The forensic
|
|
4
|
-
* timeline of a real 43-minute agent migration showed ~26 minutes spent
|
|
5
|
-
* deliberating and re-probing type behavior before the first schema file
|
|
6
|
-
* appeared — while the scanner already knew every field, its sampled values,
|
|
7
|
-
* and the reference targets. This module turns that knowledge into pushable
|
|
8
|
-
* draft files so the agent's job collapses to what only an agent can do:
|
|
9
|
-
* CLASSIFY the candidate and NAME the type. Names emitted here are
|
|
10
|
-
* PROVISIONAL by contract (mechanical singular/PascalCase of the source
|
|
11
|
-
* name); the drafts never touch src/schemas — the agent reviews, renames,
|
|
12
|
-
* copies, pushes.
|
|
13
|
-
*/
|
|
14
|
-
export interface SchemaDraft {
|
|
15
|
-
file: string;
|
|
16
|
-
uid: string;
|
|
17
|
-
/** Original candidate/source name (pre-rename), for cross-artifact maps. */
|
|
18
|
-
sourceName: string;
|
|
19
|
-
source: string;
|
|
20
|
-
fields: Record<string, unknown>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Write `.fimo/migration/schema-drafts/<Provisional>.json` (exact pushable
|
|
24
|
-
* shape) for every detected collection, plus a README stating the contract.
|
|
25
|
-
* Regenerated on every run — drafts are machine output, never hand-edited.
|
|
26
|
-
*/
|
|
27
|
-
export declare function writeSchemaDrafts(rootDir: string, scan: WrapScanResult): SchemaDraft[];
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
const ISO_DATE = /^\d{4}-\d{2}-\d{2}([T ].*)?$/;
|
|
4
|
-
const MEDIA_PATH = /^\/(images|img|videos|video|media|assets|files|docs|documents)\//i;
|
|
5
|
-
const MEDIA_EXT = /\.(png|jpe?g|gif|webp|avif|svg|mp4|webm|mov|mp3|wav|pdf|zip|docx?)$/i;
|
|
6
|
-
function singularPascal(name) {
|
|
7
|
-
const base = name
|
|
8
|
-
.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase())
|
|
9
|
-
.replace(/^(.)/, (c) => c.toUpperCase());
|
|
10
|
-
if (/ies$/i.test(base)) {
|
|
11
|
-
return base.replace(/ies$/i, 'y');
|
|
12
|
-
}
|
|
13
|
-
if (/[^aeiou](ses|xes|zes)$/i.test(base) || /(ches|shes)$/i.test(base)) {
|
|
14
|
-
// Classes -> Class, Boxes -> Box — but vowel+ses words (Releases,
|
|
15
|
-
// Cases) are plain plurals and only drop the trailing s below.
|
|
16
|
-
return base.replace(/es$/i, '');
|
|
17
|
-
}
|
|
18
|
-
if (/s$/i.test(base) && !/ss$/i.test(base)) {
|
|
19
|
-
return base.replace(/s$/i, '');
|
|
20
|
-
}
|
|
21
|
-
return base;
|
|
22
|
-
}
|
|
23
|
-
function inferScalarType(sampleValue, stringValues) {
|
|
24
|
-
if (typeof sampleValue === 'boolean') {
|
|
25
|
-
return { type: 'boolean' };
|
|
26
|
-
}
|
|
27
|
-
if (typeof sampleValue === 'number') {
|
|
28
|
-
return { type: 'number' };
|
|
29
|
-
}
|
|
30
|
-
const values = stringValues.length > 0 ? stringValues : typeof sampleValue === 'string' ? [sampleValue] : [];
|
|
31
|
-
if (values.length > 0) {
|
|
32
|
-
const nonEmpty = values.filter(Boolean);
|
|
33
|
-
if (nonEmpty.length > 0 && nonEmpty.every((value) => ISO_DATE.test(value))) {
|
|
34
|
-
return { type: 'date' };
|
|
35
|
-
}
|
|
36
|
-
if (nonEmpty.length > 0 && nonEmpty.every((value) => MEDIA_PATH.test(value) || MEDIA_EXT.test(value))) {
|
|
37
|
-
return { type: 'media' };
|
|
38
|
-
}
|
|
39
|
-
// Multi-paragraph prose reads as rich text; single lines stay strings.
|
|
40
|
-
if (nonEmpty.some((value) => value.includes('\n\n'))) {
|
|
41
|
-
return { type: 'richtext' };
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return { type: 'string' };
|
|
45
|
-
}
|
|
46
|
-
function referenceField(reference, provisionalNames) {
|
|
47
|
-
const targets = reference.targets.map((target) => provisionalNames.get(target) ?? singularPascal(target));
|
|
48
|
-
const base = targets.length > 1 ? { type: 'reference', targets } : { type: 'reference', target: targets[0] };
|
|
49
|
-
return reference.many ? { ...base, many: true } : base;
|
|
50
|
-
}
|
|
51
|
-
function collectSources(scan) {
|
|
52
|
-
const sources = [];
|
|
53
|
-
for (const candidate of scan.collections) {
|
|
54
|
-
sources.push({
|
|
55
|
-
sourceName: candidate.name,
|
|
56
|
-
sourceLabel: `${candidate.file}:${candidate.line}`,
|
|
57
|
-
rowCount: candidate.count,
|
|
58
|
-
fields: candidate.fields,
|
|
59
|
-
typedSample: candidate.typedSample ?? {},
|
|
60
|
-
fieldValues: candidate.fieldValues ?? {},
|
|
61
|
-
references: candidate.references ?? [],
|
|
62
|
-
manyFields: candidate.manyFields ?? [],
|
|
63
|
-
verbatimFields: [],
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
for (const dataFile of scan.dataFiles) {
|
|
67
|
-
for (const collection of dataFile.collections) {
|
|
68
|
-
const stem = dataFile.file.replace(/^.*\//, '').replace(/\.[a-z]+$/i, '');
|
|
69
|
-
const pathName = (collection.path ?? '').replace(/^\$\.?/, '').replace(/^\.+$/, '');
|
|
70
|
-
const name = pathName || stem;
|
|
71
|
-
sources.push({
|
|
72
|
-
sourceName: name,
|
|
73
|
-
sourceLabel: dataFile.file,
|
|
74
|
-
rowCount: collection.length,
|
|
75
|
-
fields: Object.keys(collection.typedSample ?? {}),
|
|
76
|
-
typedSample: collection.typedSample ?? {},
|
|
77
|
-
fieldValues: collection.fieldValues ?? {},
|
|
78
|
-
references: collection.references ?? [],
|
|
79
|
-
manyFields: collection.manyFields ?? [],
|
|
80
|
-
verbatimFields: collection.verbatimFields ?? [],
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return sources;
|
|
85
|
-
}
|
|
86
|
-
/** Compact per-field preview so classification/naming never needs the
|
|
87
|
-
* source files: one representative value, long strings truncated. */
|
|
88
|
-
function sampleFor(typedSample) {
|
|
89
|
-
const sample = {};
|
|
90
|
-
for (const [field, value] of Object.entries(typedSample)) {
|
|
91
|
-
if (typeof value === 'string' && value.length > 80) {
|
|
92
|
-
sample[field] = `${value.slice(0, 77)}…`;
|
|
93
|
-
}
|
|
94
|
-
else if (Array.isArray(value)) {
|
|
95
|
-
sample[field] = value.slice(0, 3);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
sample[field] = value;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return sample;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Write `.fimo/migration/schema-drafts/<Provisional>.json` (exact pushable
|
|
105
|
-
* shape) for every detected collection, plus a README stating the contract.
|
|
106
|
-
* Regenerated on every run — drafts are machine output, never hand-edited.
|
|
107
|
-
*/
|
|
108
|
-
export function writeSchemaDrafts(rootDir, scan) {
|
|
109
|
-
const sources = collectSources(scan);
|
|
110
|
-
const draftsDir = join(rootDir, '.fimo', 'migration', 'schema-drafts');
|
|
111
|
-
rmSync(draftsDir, { recursive: true, force: true });
|
|
112
|
-
if (sources.length === 0) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
mkdirSync(draftsDir, { recursive: true });
|
|
116
|
-
const provisionalNames = new Map();
|
|
117
|
-
for (const source of sources) {
|
|
118
|
-
provisionalNames.set(source.sourceName, singularPascal(source.sourceName));
|
|
119
|
-
}
|
|
120
|
-
const drafts = [];
|
|
121
|
-
for (const source of sources) {
|
|
122
|
-
const uid = provisionalNames.get(source.sourceName);
|
|
123
|
-
const referenceByField = new Map(source.references.map((reference) => [reference.field, reference]));
|
|
124
|
-
const fields = {};
|
|
125
|
-
// candidate.fields only lists STRING fields; booleans and numbers live
|
|
126
|
-
// in the typed sample — union both so no field is dropped.
|
|
127
|
-
const fieldNames = [...new Set([...source.fields, ...Object.keys(source.typedSample)])];
|
|
128
|
-
for (const field of fieldNames) {
|
|
129
|
-
if (field === 'slug') {
|
|
130
|
-
continue; // reserved entry metadata: set inside data on create
|
|
131
|
-
}
|
|
132
|
-
const reference = referenceByField.get(field);
|
|
133
|
-
if (reference) {
|
|
134
|
-
fields[field] = referenceField(reference, provisionalNames);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (source.verbatimFields.includes(field)) {
|
|
138
|
-
// Markdown/MDX body: keep the raw source string so the user's own
|
|
139
|
-
// renderer still handles it — never reshape to richtext.
|
|
140
|
-
fields[field] = { type: 'string' };
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (source.manyFields.includes(field)) {
|
|
144
|
-
// String array with no reference target (a free tag list): `many` is
|
|
145
|
-
// reference-only on the server, so model it as json — the array
|
|
146
|
-
// round-trips verbatim and stays editable.
|
|
147
|
-
fields[field] = { type: 'json' };
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
fields[field] = inferScalarType(source.typedSample[field], source.fieldValues[field] ?? []);
|
|
151
|
-
}
|
|
152
|
-
// `source`, `rowCount`, and `sample` exist so the classify/name decision
|
|
153
|
-
// can be made from this file ALONE; adopt-drafts strips them on copy
|
|
154
|
-
// (only uid/name/fields are pushed).
|
|
155
|
-
const draft = {
|
|
156
|
-
uid,
|
|
157
|
-
name: uid,
|
|
158
|
-
source: source.sourceLabel,
|
|
159
|
-
rowCount: source.rowCount,
|
|
160
|
-
sample: sampleFor(source.typedSample),
|
|
161
|
-
fields,
|
|
162
|
-
};
|
|
163
|
-
const file = join(draftsDir, `${uid}.json`);
|
|
164
|
-
writeFileSync(file, `${JSON.stringify(draft, null, 2)}\n`);
|
|
165
|
-
drafts.push({ file, uid, sourceName: source.sourceName, source: source.sourceLabel, fields });
|
|
166
|
-
}
|
|
167
|
-
writeFileSync(join(draftsDir, 'README.md'), [
|
|
168
|
-
'# Machine-typed schema drafts (regenerated by `fimo migrate`)',
|
|
169
|
-
'',
|
|
170
|
-
'Field TYPES here are inferred from the actual source values (dates,',
|
|
171
|
-
'booleans, numbers, media paths, prose, reference targets) and are',
|
|
172
|
-
'reliable. Each draft carries its `source`, `rowCount`, and a `sample`',
|
|
173
|
-
'row — everything needed to classify and name WITHOUT opening the',
|
|
174
|
-
'source files. The NAMES are PROVISIONAL mechanical guesses — that',
|
|
175
|
-
'judgment is yours, and it is TWO commands total:',
|
|
176
|
-
'',
|
|
177
|
-
'1. `npx fimo schemas adopt-drafts --rename "Prov=Final,…" --drop "Junk,…"`',
|
|
178
|
-
' (copies kept drafts to src/schemas, rewrites reference targets and',
|
|
179
|
-
' staged rows files through the renames, and pushes in dependency order).',
|
|
180
|
-
'2. `npx fimo migrate seed` (seeds every staged rows file in reference',
|
|
181
|
-
' order; the server resolves reference slugs to documentIds).',
|
|
182
|
-
'',
|
|
183
|
-
'Do not edit files in this directory: they are overwritten on every',
|
|
184
|
-
'`fimo migrate` run.',
|
|
185
|
-
'',
|
|
186
|
-
].join('\n'));
|
|
187
|
-
return drafts;
|
|
188
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { readdirSync, statSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
const titleCase = (seg) => seg
|
|
4
|
-
.replace(/[_\-]+/g, ' ')
|
|
5
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
6
|
-
.split(/\s+/)
|
|
7
|
-
.filter(Boolean)
|
|
8
|
-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
|
9
|
-
.join(' ');
|
|
10
|
-
function pushRoute(routes, parts) {
|
|
11
|
-
const routePath = `/${parts.join('/')}`.replace(/\/+/g, '/');
|
|
12
|
-
const lastStatic = [...parts].reverse().find((part) => !part.startsWith(':'));
|
|
13
|
-
routes.push({
|
|
14
|
-
id: routePath === '/' ? 'home' : parts.map((part) => part.replace(/^:/, '')).join('-'),
|
|
15
|
-
path: routePath,
|
|
16
|
-
label: routePath === '/' ? 'Home' : titleCase(lastStatic ?? parts[parts.length - 1] ?? routePath),
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
const PAGE_EXT = /\.(astro|md|mdx|html)$/;
|
|
20
|
-
const toSegment = (name) => name.replace(/^\[\.\.\.(.+)\]$/, ':$1').replace(/^\[(.+)\]$/, ':$1');
|
|
21
|
-
/** Astro file-based routes under src/pages (index files map to the dir path). */
|
|
22
|
-
export function discoverAstroRoutes(pagesDir) {
|
|
23
|
-
const routes = [];
|
|
24
|
-
const walk = (dir, segments) => {
|
|
25
|
-
let entries;
|
|
26
|
-
try {
|
|
27
|
-
entries = readdirSync(dir);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
for (const entry of entries) {
|
|
33
|
-
const full = join(dir, entry);
|
|
34
|
-
let isDir = false;
|
|
35
|
-
try {
|
|
36
|
-
isDir = statSync(full).isDirectory();
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (isDir) {
|
|
42
|
-
walk(full, [...segments, toSegment(entry)]);
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
if (!PAGE_EXT.test(entry) || entry.startsWith('_')) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
const base = entry.replace(PAGE_EXT, '');
|
|
49
|
-
pushRoute(routes, base === 'index' ? segments : [...segments, toSegment(base)]);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
walk(pagesDir, []);
|
|
53
|
-
routes.sort((a, b) => a.path.localeCompare(b.path));
|
|
54
|
-
return routes;
|
|
55
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { TemplateWrapStyle } from '../../apply-wrap-templates.js';
|
|
2
|
-
/**
|
|
3
|
-
* Astro template wraps: t() resolves in the frontmatter (server-only, so the
|
|
4
|
-
* server barrel is safe to import there), values interpolate as {t(...)}.
|
|
5
|
-
* Files without a frontmatter fence get one — Astro allows an empty fence.
|
|
6
|
-
*/
|
|
7
|
-
export declare const astroTemplateWrapStyle: TemplateWrapStyle;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Astro template wraps: t() resolves in the frontmatter (server-only, so the
|
|
3
|
-
* server barrel is safe to import there), values interpolate as {t(...)}.
|
|
4
|
-
* Files without a frontmatter fence get one — Astro allows an empty fence.
|
|
5
|
-
*/
|
|
6
|
-
export const astroTemplateWrapStyle = {
|
|
7
|
-
ext: '.astro',
|
|
8
|
-
head: 'import { loadFimoT } from "fimo/astro/server";\nconst t = await loadFimoT();',
|
|
9
|
-
headMarker: /loadFimoT/,
|
|
10
|
-
open: '{t(',
|
|
11
|
-
close: ')}',
|
|
12
|
-
injectHead: (code, head) => {
|
|
13
|
-
const fence = code.match(/^---\r?\n/);
|
|
14
|
-
if (fence) {
|
|
15
|
-
return `${code.slice(0, fence[0].length)}${head}\n${code.slice(fence[0].length)}`;
|
|
16
|
-
}
|
|
17
|
-
return `---\n${head}\n---\n${code}`;
|
|
18
|
-
},
|
|
19
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { TemplateWrapStyle } from '../apply-wrap-templates.js';
|
|
2
|
-
import type { FrameworkDetection } from '../detect-framework.js';
|
|
3
|
-
import { type CollectionRewireResult } from './next/rewire.js';
|
|
4
|
-
import { type DiscoveredRoute } from './next/routes.js';
|
|
5
|
-
import { type RootWiringResult } from './next/wiring.js';
|
|
6
|
-
/**
|
|
7
|
-
* Route discovery for any detected framework — the single registry generic
|
|
8
|
-
* code calls. Frameworks without a file convention (vue SPA, plain vite)
|
|
9
|
-
* return [] and rely on fimo-config routes.
|
|
10
|
-
*/
|
|
11
|
-
export declare function discoverFrameworkRoutes(cwd: string, detection: FrameworkDetection): DiscoveredRoute[];
|
|
12
|
-
/**
|
|
13
|
-
* Extra directories the framework keeps page COPY in, outside any source
|
|
14
|
-
* root (data-file scanning). Part of the framework registry so generic
|
|
15
|
-
* scanners never carry framework names.
|
|
16
|
-
*/
|
|
17
|
-
export declare function frameworkDataDirs(framework: string | null | undefined): string[];
|
|
18
|
-
/**
|
|
19
|
-
* The wrapper-import module for frameworks whose .jsx/.tsx is guaranteed
|
|
20
|
-
* React — the only ones the --apply JSX codemod may touch. Template
|
|
21
|
-
* frameworks return null: a .tsx island there may be Solid or Preact, and
|
|
22
|
-
* injecting a React wrapper import breaks the build (bento dogfood). Bare
|
|
23
|
-
* Vite qualifies only with the detection's `react` flag (a react dependency
|
|
24
|
-
* pins the JSX runtime); the SPA primitives live in fimo/react and are
|
|
25
|
-
* fallback-safe before the providers are wired.
|
|
26
|
-
*/
|
|
27
|
-
export declare function frameworkJsxWrapperModule(detection: Pick<FrameworkDetection, 'framework' | 'react'>): string | null;
|
|
28
|
-
/**
|
|
29
|
-
* The template-wrap style for frameworks whose template files the --apply
|
|
30
|
-
* codemod may touch (plain text nodes only). Vue SPA stays null: without a
|
|
31
|
-
* server data path there is no deterministic t() wiring to inject.
|
|
32
|
-
*/
|
|
33
|
-
export declare function frameworkTemplateWrapStyle(framework: string | null | undefined): TemplateWrapStyle | null;
|
|
34
|
-
/**
|
|
35
|
-
* The one-time root-wiring codemod for frameworks whose providers mount in a
|
|
36
|
-
* single well-known file (Next.js app router: the root layout; Vite React
|
|
37
|
-
* SPA: the entry). Runs during --apply, AFTER the baseline capture — the
|
|
38
|
-
* pre-wrap dev-server boot must not require the fimo package, and providers
|
|
39
|
-
* are render-transparent so the parity check stays clean. Template
|
|
40
|
-
* frameworks wire through their TemplateWrapStyle.ensureWiring hooks instead.
|
|
41
|
-
*/
|
|
42
|
-
export declare function frameworkRootWiring(detection: Pick<FrameworkDetection, 'framework' | 'react' | 'appDir'>): ((cwd: string) => RootWiringResult) | null;
|
|
43
|
-
/**
|
|
44
|
-
* Collection-page rewiring: pages that render a machine-staged collection get
|
|
45
|
-
* their data source switched to `wrapCollection` (Fimo overlay over the
|
|
46
|
-
* retained source rows) mechanically, with per-page bail reasons. Runs during
|
|
47
|
-
* --apply after drafts are staged; adopt-drafts renames the call-site uids.
|
|
48
|
-
* Next.js app router only for now.
|
|
49
|
-
*/
|
|
50
|
-
export declare function frameworkCollectionRewire(detection: Pick<FrameworkDetection, 'framework' | 'appDir'>): ((cwd: string, scan: unknown, drafts: Array<{
|
|
51
|
-
uid: string;
|
|
52
|
-
sourceName: string;
|
|
53
|
-
source: string;
|
|
54
|
-
}>) => CollectionRewireResult) | null;
|
|
55
|
-
export interface WiringMarker {
|
|
56
|
-
/** Candidate files, relative to the project root; ONE must contain the marker. */
|
|
57
|
-
files: string[];
|
|
58
|
-
marker: RegExp;
|
|
59
|
-
/** Human hint rendered when the marker is missing. */
|
|
60
|
-
hint: string;
|
|
61
|
-
/** Missing marker warns instead of failing (no automated recipe yet). */
|
|
62
|
-
warnOnly?: boolean;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* How `wrap --check` proves the root wiring exists: without providers the
|
|
66
|
-
* wrapped values render fallbacks forever, and neither coverage (counts
|
|
67
|
-
* wraps), parity (fallbacks render identically), nor seeding (DB-side)
|
|
68
|
-
* notices — editability would ship silently broken.
|
|
69
|
-
*/
|
|
70
|
-
export declare function frameworkWiringMarker(detection: Pick<FrameworkDetection, 'framework' | 'react' | 'appDir'>, cwd?: string): WiringMarker | null;
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { join, relative } from 'node:path';
|
|
2
|
-
import { discoverAstroRoutes } from './astro/routes.js';
|
|
3
|
-
import { astroTemplateWrapStyle } from './astro/template-style.js';
|
|
4
|
-
import { rewireNextCollectionPages } from './next/rewire.js';
|
|
5
|
-
import { discoverNextPagesRoutes, discoverNextRoutes } from './next/routes.js';
|
|
6
|
-
import { ensureNextLayoutWiring, nextRootLayoutFiles } from './next/wiring.js';
|
|
7
|
-
import { discoverNuxtRoutes } from './nuxt/routes.js';
|
|
8
|
-
import { nuxtTemplateWrapStyle } from './nuxt/template-style.js';
|
|
9
|
-
import { discoverRemixRoutes } from './remix/routes.js';
|
|
10
|
-
import { discoverSvelteKitRoutes } from './sveltekit/routes.js';
|
|
11
|
-
import { svelteTemplateWrapStyle } from './sveltekit/template-style.js';
|
|
12
|
-
import { discoverReactRouterDomRoutes } from './vite/routes.js';
|
|
13
|
-
import { ensureSpaEntryWiring } from './vite/wiring.js';
|
|
14
|
-
/**
|
|
15
|
-
* Route discovery for any detected framework — the single registry generic
|
|
16
|
-
* code calls. Frameworks without a file convention (vue SPA, plain vite)
|
|
17
|
-
* return [] and rely on fimo-config routes.
|
|
18
|
-
*/
|
|
19
|
-
export function discoverFrameworkRoutes(cwd, detection) {
|
|
20
|
-
if (detection.framework === 'vite' && detection.react) {
|
|
21
|
-
return discoverReactRouterDomRoutes(cwd);
|
|
22
|
-
}
|
|
23
|
-
switch (detection.framework) {
|
|
24
|
-
case 'next':
|
|
25
|
-
return [
|
|
26
|
-
...(detection.appDir ? discoverNextRoutes(join(cwd, detection.appDir)) : []),
|
|
27
|
-
...(detection.pagesDir ? discoverNextPagesRoutes(join(cwd, detection.pagesDir)) : []),
|
|
28
|
-
];
|
|
29
|
-
case 'remix':
|
|
30
|
-
return detection.pagesDir ? discoverRemixRoutes(join(cwd, detection.pagesDir)) : [];
|
|
31
|
-
case 'astro':
|
|
32
|
-
return detection.pagesDir ? discoverAstroRoutes(join(cwd, detection.pagesDir)) : [];
|
|
33
|
-
case 'nuxt':
|
|
34
|
-
return detection.pagesDir ? discoverNuxtRoutes(join(cwd, detection.pagesDir)) : [];
|
|
35
|
-
case 'sveltekit':
|
|
36
|
-
return detection.pagesDir ? discoverSvelteKitRoutes(join(cwd, detection.pagesDir)) : [];
|
|
37
|
-
default:
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Extra directories the framework keeps page COPY in, outside any source
|
|
43
|
-
* root (data-file scanning). Part of the framework registry so generic
|
|
44
|
-
* scanners never carry framework names.
|
|
45
|
-
*/
|
|
46
|
-
export function frameworkDataDirs(framework) {
|
|
47
|
-
switch (framework) {
|
|
48
|
-
case 'nuxt':
|
|
49
|
-
return ['content']; // Nuxt Content convention (.yml/.md page documents)
|
|
50
|
-
default:
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* The wrapper-import module for frameworks whose .jsx/.tsx is guaranteed
|
|
56
|
-
* React — the only ones the --apply JSX codemod may touch. Template
|
|
57
|
-
* frameworks return null: a .tsx island there may be Solid or Preact, and
|
|
58
|
-
* injecting a React wrapper import breaks the build (bento dogfood). Bare
|
|
59
|
-
* Vite qualifies only with the detection's `react` flag (a react dependency
|
|
60
|
-
* pins the JSX runtime); the SPA primitives live in fimo/react and are
|
|
61
|
-
* fallback-safe before the providers are wired.
|
|
62
|
-
*/
|
|
63
|
-
export function frameworkJsxWrapperModule(detection) {
|
|
64
|
-
switch (detection.framework) {
|
|
65
|
-
case 'next':
|
|
66
|
-
return 'fimo/next';
|
|
67
|
-
case 'remix':
|
|
68
|
-
return 'fimo/remix';
|
|
69
|
-
case 'vite':
|
|
70
|
-
return detection.react ? 'fimo/react' : null;
|
|
71
|
-
default:
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* The template-wrap style for frameworks whose template files the --apply
|
|
77
|
-
* codemod may touch (plain text nodes only). Vue SPA stays null: without a
|
|
78
|
-
* server data path there is no deterministic t() wiring to inject.
|
|
79
|
-
*/
|
|
80
|
-
export function frameworkTemplateWrapStyle(framework) {
|
|
81
|
-
switch (framework) {
|
|
82
|
-
case 'astro':
|
|
83
|
-
return astroTemplateWrapStyle;
|
|
84
|
-
case 'nuxt':
|
|
85
|
-
return nuxtTemplateWrapStyle;
|
|
86
|
-
case 'sveltekit':
|
|
87
|
-
return svelteTemplateWrapStyle;
|
|
88
|
-
default:
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* The one-time root-wiring codemod for frameworks whose providers mount in a
|
|
94
|
-
* single well-known file (Next.js app router: the root layout; Vite React
|
|
95
|
-
* SPA: the entry). Runs during --apply, AFTER the baseline capture — the
|
|
96
|
-
* pre-wrap dev-server boot must not require the fimo package, and providers
|
|
97
|
-
* are render-transparent so the parity check stays clean. Template
|
|
98
|
-
* frameworks wire through their TemplateWrapStyle.ensureWiring hooks instead.
|
|
99
|
-
*/
|
|
100
|
-
export function frameworkRootWiring(detection) {
|
|
101
|
-
switch (detection.framework) {
|
|
102
|
-
case 'next':
|
|
103
|
-
return (cwd) => ensureNextLayoutWiring(cwd, detection);
|
|
104
|
-
case 'vite':
|
|
105
|
-
return detection.react ? ensureSpaEntryWiring : null;
|
|
106
|
-
default:
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Collection-page rewiring: pages that render a machine-staged collection get
|
|
112
|
-
* their data source switched to `wrapCollection` (Fimo overlay over the
|
|
113
|
-
* retained source rows) mechanically, with per-page bail reasons. Runs during
|
|
114
|
-
* --apply after drafts are staged; adopt-drafts renames the call-site uids.
|
|
115
|
-
* Next.js app router only for now.
|
|
116
|
-
*/
|
|
117
|
-
export function frameworkCollectionRewire(detection) {
|
|
118
|
-
switch (detection.framework) {
|
|
119
|
-
case 'next':
|
|
120
|
-
return (cwd, scan, drafts) => rewireNextCollectionPages(cwd, detection, scan, drafts);
|
|
121
|
-
default:
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* How `wrap --check` proves the root wiring exists: without providers the
|
|
127
|
-
* wrapped values render fallbacks forever, and neither coverage (counts
|
|
128
|
-
* wraps), parity (fallbacks render identically), nor seeding (DB-side)
|
|
129
|
-
* notices — editability would ship silently broken.
|
|
130
|
-
*/
|
|
131
|
-
export function frameworkWiringMarker(detection, cwd) {
|
|
132
|
-
switch (detection.framework) {
|
|
133
|
-
case 'next': {
|
|
134
|
-
if (!detection.appDir) {
|
|
135
|
-
return {
|
|
136
|
-
files: ['pages/_app.tsx', 'pages/_app.jsx', 'src/pages/_app.tsx', 'src/pages/_app.jsx'],
|
|
137
|
-
marker: /FimoNextProviders/,
|
|
138
|
-
hint: 'mount FimoNextProviders in pages/_app (pages router has no automated recipe yet)',
|
|
139
|
-
warnOnly: true,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
// Resolve the real root layout(s), including the next-intl `[locale]`
|
|
143
|
-
// segment; fall back to the direct path when nothing is on disk yet.
|
|
144
|
-
const resolved = cwd ? nextRootLayoutFiles(cwd, detection.appDir).map((file) => relative(cwd, file)) : [];
|
|
145
|
-
const files = resolved.length > 0
|
|
146
|
-
? resolved
|
|
147
|
-
: [`${detection.appDir}/layout.tsx`, `${detection.appDir}/layout.jsx`, `${detection.appDir}/layout.js`];
|
|
148
|
-
return {
|
|
149
|
-
files,
|
|
150
|
-
marker: /FimoNextProviders/,
|
|
151
|
-
hint: `mount FimoNextProviders + FimoNextScripts in ${detection.appDir}/layout (agent prompt section 0)`,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
case 'vite':
|
|
155
|
-
if (!detection.react) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
files: ['src/main.tsx', 'src/main.jsx', 'src/index.tsx', 'src/index.jsx'],
|
|
160
|
-
marker: /FimoSpaProviders/,
|
|
161
|
-
hint: 'wrap the root render with FimoSpaProviders from fimo/react (agent prompt section 0)',
|
|
162
|
-
};
|
|
163
|
-
case 'remix':
|
|
164
|
-
return {
|
|
165
|
-
files: ['app/root.tsx', 'app/root.jsx'],
|
|
166
|
-
marker: /FimoRemixProviders/,
|
|
167
|
-
hint: 'mount FimoRemixProviders in app/root (agent prompt section 0)',
|
|
168
|
-
};
|
|
169
|
-
case 'sveltekit':
|
|
170
|
-
return {
|
|
171
|
-
files: ['src/routes/+layout.server.js', 'src/routes/+layout.server.ts'],
|
|
172
|
-
marker: /fimoLabels/,
|
|
173
|
-
hint: 'return fimoLabels from the root +layout.server load (wrap.md SvelteKit notes)',
|
|
174
|
-
};
|
|
175
|
-
default:
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { FrameworkDetection } from '../../detect-framework.js';
|
|
2
|
-
import type { WrapScanResult } from '../../scan-wrappable.js';
|
|
3
|
-
/**
|
|
4
|
-
* Page rewiring for wrap-migrated collections: make each page that renders a
|
|
5
|
-
* machine-staged collection read from Fimo through `wrapCollection` while
|
|
6
|
-
* KEEPING its source rows as the render fallback. Two safe shapes:
|
|
7
|
-
*
|
|
8
|
-
* - an in-code array literal (`const clients = [...]`) rendered by the
|
|
9
|
-
* page's default-export function → the literal is extracted byte-faithful
|
|
10
|
-
* to `src/data/<name>.json` (it becomes the fallback file) and the
|
|
11
|
-
* component fetches `wrapCollection('<Uid>', clientsSource)`;
|
|
12
|
-
* - a data-file default import (`import posts from '../src/data/posts.json'`)
|
|
13
|
-
* → the import becomes `postsSource` and the component fetches
|
|
14
|
-
* `wrapCollection('<Uid>', postsSource)`.
|
|
15
|
-
*
|
|
16
|
-
* Everything else bails with a reason that flows into the agent prompt.
|
|
17
|
-
* Uids are the PROVISIONAL draft names; `schemas adopt-drafts` rewrites the
|
|
18
|
-
* call sites through its renames.
|
|
19
|
-
*/
|
|
20
|
-
export interface CollectionRewireResult {
|
|
21
|
-
changes: string[];
|
|
22
|
-
warnings: string[];
|
|
23
|
-
/** Pages successfully rewired. */
|
|
24
|
-
rewired: number;
|
|
25
|
-
}
|
|
26
|
-
export declare function rewireNextCollectionPages(cwd: string, detection: Pick<FrameworkDetection, 'appDir'>, scan: WrapScanResult, drafts: Array<{
|
|
27
|
-
uid: string;
|
|
28
|
-
sourceName: string;
|
|
29
|
-
source: string;
|
|
30
|
-
}>): CollectionRewireResult;
|