fimo 0.14.0 → 0.15.0-staging.2
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 +1 -0
- package/assets/astro/components/Boolean.astro +14 -0
- package/assets/astro/components/Date.astro +23 -0
- package/assets/astro/components/Image.astro +79 -0
- package/assets/astro/components/Json.astro +14 -0
- package/assets/astro/components/RichText.astro +17 -0
- package/assets/astro/components/StaticImage.astro +66 -0
- package/assets/astro/components/Text.astro +23 -0
- package/assets/astro/components/Video.astro +47 -0
- package/assets/astro/components/index.d.ts +8 -0
- package/assets/astro/components/index.js +8 -0
- package/assets/content-templates/shared/server.eta +56 -0
- package/assets/content-templates/sveltekit/content.eta +86 -0
- package/assets/skills/fimo/SKILL.md +13 -4
- package/assets/skills/fimo-cli/SKILL.md +28 -28
- package/assets/skills/fimo-cli/references/account.md +0 -2
- package/assets/skills/fimo-cli/references/agent-setup.md +7 -9
- package/assets/skills/fimo-cli/references/agents.md +0 -2
- package/assets/skills/fimo-cli/references/analytics.md +0 -2
- package/assets/skills/fimo-cli/references/assets.md +2 -4
- package/assets/skills/fimo-cli/references/branches.md +14 -15
- package/assets/skills/fimo-cli/references/content.md +9 -11
- package/assets/skills/fimo-cli/references/credits.md +0 -2
- package/assets/skills/fimo-cli/references/deploy.md +6 -7
- package/assets/skills/fimo-cli/references/describe.md +1 -3
- package/assets/skills/fimo-cli/references/domains.md +0 -2
- package/assets/skills/fimo-cli/references/forms.md +5 -7
- package/assets/skills/fimo-cli/references/history.md +0 -2
- package/assets/skills/fimo-cli/references/init.md +34 -26
- package/assets/skills/fimo-cli/references/integrations/firecrawl.md +0 -2
- package/assets/skills/fimo-cli/references/integrations.md +0 -2
- package/assets/skills/fimo-cli/references/invite.md +0 -2
- package/assets/skills/fimo-cli/references/labels.md +5 -7
- package/assets/skills/fimo-cli/references/locales.md +2 -4
- package/assets/skills/fimo-cli/references/mcp.md +2 -4
- package/assets/skills/fimo-cli/references/media.md +0 -2
- package/assets/skills/fimo-cli/references/preview.md +0 -2
- package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +1 -3
- package/assets/skills/fimo-cli/references/projects.md +1 -3
- package/assets/skills/fimo-cli/references/schedules.md +0 -2
- package/assets/skills/fimo-cli/references/support.md +0 -2
- package/assets/skills/fimo-cli/references/webhooks.md +0 -2
- package/assets/skills/fimo-code/SKILL.md +11 -3
- package/assets/skills/fimo-code/references/assets.md +2 -2
- package/assets/skills/fimo-code/references/content/clients.md +5 -1
- package/assets/skills/fimo-code/references/content.md +3 -1
- package/assets/skills/fimo-code/references/frameworks/astro.md +127 -0
- package/assets/skills/fimo-code/references/frameworks/compatibility.md +19 -0
- package/assets/skills/fimo-code/references/frameworks/hosting.md +15 -3
- package/assets/skills/fimo-code/references/frameworks/react-router.md +37 -209
- package/assets/skills/fimo-code/references/frameworks/sveltekit.md +110 -0
- package/assets/skills/fimo-code/references/frameworks/vite-react.md +35 -166
- package/assets/skills/fimo-code/references/labels.md +16 -6
- package/assets/skills/fimo-code/references/locales.md +3 -1
- package/assets/skills/fimo-code/references/ui.md +19 -15
- package/assets/skills/fimo-migration/SKILL.md +99 -146
- package/assets/skills/fimo-migration/references/frameworks/nextjs.md +26 -0
- package/assets/skills/fimo-migration/references/inventory/coordinator.md +40 -0
- package/assets/skills/fimo-migration/references/inventory/locales/next-intl.md +39 -0
- package/assets/skills/fimo-migration/references/inventory/locales.md +41 -0
- package/assets/skills/fimo-migration/references/workflow.md +3 -2
- package/assets/skills/fimo-migration/scripts/inventory/locales/next-intl.mjs +459 -0
- package/assets/skills/fimo-studio/SKILL.md +1 -1
- package/assets/skills/fimo-studio/references/project-creation.md +10 -18
- package/assets/starters/fimo-site/template/.fimo/agents/content-guide/capabilities.yaml +0 -1
- package/assets/starters/fimo-site/template/.fimo/agents/site-review/capabilities.yaml +0 -1
- package/assets/sveltekit/components/Boolean.svelte +19 -0
- package/assets/sveltekit/components/Date.svelte +33 -0
- package/assets/sveltekit/components/FimoProvider.svelte +35 -0
- package/assets/sveltekit/components/Image.svelte +80 -0
- package/assets/sveltekit/components/Json.svelte +18 -0
- package/assets/sveltekit/components/Label.svelte +16 -0
- package/assets/sveltekit/components/Number.svelte +21 -0
- package/assets/sveltekit/components/RichText.svelte +19 -0
- package/assets/sveltekit/components/Text.svelte +30 -0
- package/assets/sveltekit/components/Video.svelte +37 -0
- package/assets/sveltekit/components/index.d.ts +10 -0
- package/assets/sveltekit/components/index.js +10 -0
- package/dist/build/astro/config.d.ts +4 -0
- package/dist/build/astro/config.js +64 -0
- package/dist/build/next/config.js +16 -0
- package/dist/build/sveltekit/config.d.ts +6 -0
- package/dist/build/sveltekit/config.js +8 -0
- package/dist/build/sveltekit/data-id.d.ts +3 -0
- package/dist/build/sveltekit/data-id.js +171 -0
- package/dist/build/sveltekit/vite.d.ts +13 -0
- package/dist/build/sveltekit/vite.js +15 -0
- package/dist/build/vite/index.js +2 -0
- package/dist/build/vite/plugins/data-id.d.ts +9 -0
- package/dist/build/vite/plugins/data-id.js +6 -1
- package/dist/build/vite/plugins/runtime-env.d.ts +21 -0
- package/dist/build/vite/plugins/runtime-env.js +68 -0
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +108 -101
- package/dist/runtime/app/FimoProviders.d.ts +1 -1
- package/dist/runtime/app/FimoProviders.js +11 -5
- package/dist/runtime/astro/internal.d.ts +6 -0
- package/dist/runtime/astro/internal.js +16 -0
- package/dist/runtime/astro/preview.d.ts +14 -0
- package/dist/runtime/astro/preview.js +103 -0
- package/dist/runtime/astro/render-rich-text.d.ts +2 -0
- package/dist/runtime/astro/render-rich-text.js +1 -0
- package/dist/runtime/astro/server-runtime.d.ts +3 -0
- package/dist/runtime/astro/server-runtime.js +20 -0
- package/dist/runtime/astro/server.d.ts +15 -0
- package/dist/runtime/astro/server.js +14 -0
- package/dist/runtime/content/client/collection-core.d.ts +2 -17
- package/dist/runtime/content/client/collection-core.js +15 -8
- package/dist/runtime/content/client/core-types.d.ts +96 -0
- package/dist/runtime/content/client/core-types.js +1 -0
- package/dist/runtime/content/client/internal.d.ts +4 -4
- package/dist/runtime/content/client/internal.js +4 -3
- package/dist/runtime/content/client/runtime.d.ts +1 -1
- package/dist/runtime/content/client/server-content-client.d.ts +3 -3
- package/dist/runtime/content/client/server-content-client.js +2 -29
- package/dist/runtime/content/client/singleton-core.d.ts +2 -9
- package/dist/runtime/content/client/singleton-core.js +9 -4
- package/dist/runtime/content/client/types.d.ts +5 -115
- package/dist/runtime/content/index.d.ts +3 -3
- package/dist/runtime/labels/fetch.js +5 -3
- package/dist/runtime/next/client.d.ts +2 -1
- package/dist/runtime/next/facade.d.ts +1 -1
- package/dist/runtime/next/provider.js +1 -1
- package/dist/runtime/next/server-runtime.js +1 -1
- package/dist/runtime/next/server.d.ts +5 -4
- package/dist/runtime/paths/get-fimo-paths.js +8 -3
- package/dist/runtime/preview/bridge.d.ts +8 -0
- package/dist/runtime/preview/bridge.js +20 -0
- package/dist/runtime/preview/location.d.ts +23 -0
- package/dist/runtime/preview/location.js +93 -0
- package/dist/runtime/preview/routes.d.ts +10 -0
- package/dist/runtime/preview/routes.js +29 -0
- package/dist/runtime/primitives/index.d.ts +4 -1
- package/dist/runtime/primitives/index.js +1 -0
- package/dist/runtime/primitives/lib/image-optimization.d.ts +27 -2
- package/dist/runtime/primitives/lib/image-optimization.js +40 -0
- package/dist/runtime/primitives/lib/index.d.ts +1 -1
- package/dist/runtime/primitives/lib/primitives.d.ts +0 -54
- package/dist/runtime/primitives/lib/primitives.js +6 -0
- package/dist/runtime/primitives/lib/render-rich-text.d.ts +3 -0
- package/dist/runtime/primitives/lib/render-rich-text.js +112 -0
- package/dist/runtime/react/primitives/contracts.d.ts +40 -2
- package/dist/runtime/react/primitives/renderers/ImageRenderer.js +15 -34
- package/dist/runtime/react/primitives/renderers/RichTextRenderer.d.ts +2 -1
- package/dist/runtime/react/primitives/renderers/StaticImage.js +13 -30
- package/dist/runtime/routing/AppRoutesProvider.js +20 -8
- package/dist/runtime/shared/env-identity.d.ts +43 -0
- package/dist/runtime/shared/env-identity.js +88 -0
- package/dist/runtime/shared/local-runtime-env.d.ts +65 -0
- package/dist/runtime/shared/local-runtime-env.js +169 -0
- package/dist/runtime/{react-router → shared}/preview-location.d.ts +7 -13
- package/dist/runtime/{react-router → shared}/preview-location.js +26 -27
- package/dist/runtime/sveltekit/content.d.ts +25 -0
- package/dist/runtime/sveltekit/content.js +33 -0
- package/dist/runtime/sveltekit/context-contract.d.ts +5 -0
- package/dist/runtime/sveltekit/context-contract.js +2 -0
- package/dist/runtime/sveltekit/context.d.ts +8 -0
- package/dist/runtime/sveltekit/context.js +25 -0
- package/dist/runtime/sveltekit/index.d.ts +7 -0
- package/dist/runtime/sveltekit/index.js +4 -0
- package/dist/runtime/sveltekit/internal.d.ts +6 -0
- package/dist/runtime/sveltekit/internal.js +12 -0
- package/dist/runtime/sveltekit/labels.d.ts +16 -0
- package/dist/runtime/sveltekit/labels.js +13 -0
- package/dist/runtime/sveltekit/preview.d.ts +19 -0
- package/dist/runtime/sveltekit/preview.js +77 -0
- package/dist/runtime/sveltekit/runtime.d.ts +8 -0
- package/dist/runtime/sveltekit/runtime.js +17 -0
- package/dist/runtime/templates.d.ts +1 -1
- package/dist/runtime/templates.js +1 -1
- package/dist/runtime/vite/Label.d.ts +13 -0
- package/dist/runtime/vite/Label.js +16 -0
- package/dist/scripts/extract-translations.js +103 -43
- package/dist/scripts/sync-forms.js +1 -1
- package/dist/scripts/sync-schemas.js +83 -16
- package/package.json +57 -2
- package/release.json +2 -2
- package/templates/nextjs/AGENTS.md +10 -5
- package/templates/nextjs/_gitignore +1 -0
- package/templates/react-router/AGENTS.md +4 -3
- package/templates/react-router/package.json +1 -1
- package/templates/sveltekit/.fimo/config.json +15 -0
- package/templates/sveltekit/AGENTS.md +36 -0
- package/templates/sveltekit/CLAUDE.md +5 -0
- package/templates/sveltekit/_gitignore +16 -0
- package/templates/sveltekit/package.json +28 -0
- package/templates/sveltekit/pnpm-workspace.yaml +4 -0
- package/templates/sveltekit/src/app.html +11 -0
- package/templates/sveltekit/src/routes/+layout.server.ts +8 -0
- package/templates/sveltekit/src/routes/+layout.svelte +12 -0
- package/templates/sveltekit/src/routes/+page.svelte +48 -0
- package/templates/sveltekit/svelte.config.js +5 -0
- package/templates/sveltekit/tsconfig.json +14 -0
- package/templates/sveltekit/vite.config.ts +5 -0
- /package/assets/content-templates/{form-template.eta → forms/react.eta} +0 -0
- /package/assets/content-templates/{next-client-template.eta → next/client.eta} +0 -0
- /package/assets/content-templates/{next-server-template.eta → next/server.eta} +0 -0
- /package/assets/content-templates/{hooks-template.eta → react/client.eta} +0 -0
- /package/assets/content-templates/{types-template.eta → shared/types.eta} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Extract label keys from
|
|
2
|
+
* Extract label keys from application source.
|
|
3
3
|
*
|
|
4
|
-
* Labels are DB-owned. This scanner reports literal `t("key")`
|
|
5
|
-
* `fimo validate` can verify
|
|
6
|
-
*
|
|
4
|
+
* Labels are DB-owned. This scanner reports literal `t("key")` calls and
|
|
5
|
+
* literal `<Label value="key">` elements so `fimo validate` can verify that
|
|
6
|
+
* the tenant DB contains visible values. It never writes label values.
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { parseSync } from 'oxc-parser';
|
|
11
|
-
function
|
|
11
|
+
function findSourceFiles(dir, files = []) {
|
|
12
12
|
if (!existsSync(dir)) {
|
|
13
13
|
return files;
|
|
14
14
|
}
|
|
@@ -20,67 +20,127 @@ function findReactFiles(dir, files = []) {
|
|
|
20
20
|
if (entry === 'ui' || entry === 'node_modules') {
|
|
21
21
|
continue;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
findSourceFiles(fullPath, files);
|
|
24
24
|
}
|
|
25
|
-
else if (/\.(ts|tsx|js|jsx)$/.test(entry)) {
|
|
25
|
+
else if (/\.(ts|tsx|js|jsx|svelte)$/.test(entry)) {
|
|
26
26
|
files.push(fullPath);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
return files;
|
|
30
30
|
}
|
|
31
|
-
function
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
31
|
+
function importedNames(body, source, importedName) {
|
|
32
|
+
const names = new Set();
|
|
33
|
+
for (const statement of body) {
|
|
34
|
+
if (statement.type !== 'ImportDeclaration' || statement.source.value !== source) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
for (const specifier of statement.specifiers) {
|
|
38
|
+
if (specifier.type === 'ImportSpecifier' &&
|
|
39
|
+
specifier.imported.type === 'Identifier' &&
|
|
40
|
+
specifier.imported.name === importedName) {
|
|
41
|
+
names.add(specifier.local.name);
|
|
40
42
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return names;
|
|
46
|
+
}
|
|
47
|
+
function extractFromModule(filePath, code, parsePath = filePath) {
|
|
48
|
+
const declarations = [];
|
|
49
|
+
const result = parseSync(parsePath, code);
|
|
50
|
+
const ast = result.program;
|
|
51
|
+
const fimoLabelNames = importedNames(ast.body, 'fimo/ui', 'Label');
|
|
52
|
+
function visit(node) {
|
|
53
|
+
if (!node || typeof node !== 'object') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (node.type === 'CallExpression') {
|
|
57
|
+
const callee = node.callee;
|
|
58
|
+
const isTranslationCall = (callee?.type === 'Identifier' && callee.name === 't') ||
|
|
59
|
+
(callee?.type === 'MemberExpression' &&
|
|
60
|
+
callee.computed === false &&
|
|
61
|
+
callee.object?.type === 'Identifier' &&
|
|
62
|
+
callee.object.name === 'labels' &&
|
|
63
|
+
callee.property?.type === 'Identifier' &&
|
|
64
|
+
callee.property.name === 't');
|
|
65
|
+
if (isTranslationCall) {
|
|
66
|
+
const args = node.arguments || [];
|
|
67
|
+
const firstArg = args[0];
|
|
68
|
+
if (firstArg?.type === 'Literal' && typeof firstArg.value === 'string') {
|
|
69
|
+
declarations.push({ key: firstArg.value, file: filePath });
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
}
|
|
73
|
+
if (node.type === 'JSXOpeningElement' &&
|
|
74
|
+
node.name?.type === 'JSXIdentifier' &&
|
|
75
|
+
fimoLabelNames.has(node.name.name)) {
|
|
76
|
+
for (const attribute of node.attributes ?? []) {
|
|
77
|
+
if (attribute?.type === 'JSXAttribute' &&
|
|
78
|
+
attribute.name?.type === 'JSXIdentifier' &&
|
|
79
|
+
attribute.name.name === 'value' &&
|
|
80
|
+
attribute.value?.type === 'Literal' &&
|
|
81
|
+
typeof attribute.value.value === 'string') {
|
|
82
|
+
declarations.push({ key: attribute.value.value, file: filePath });
|
|
65
83
|
}
|
|
66
|
-
|
|
67
|
-
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const key of Object.keys(node)) {
|
|
87
|
+
const child = node[key];
|
|
88
|
+
if (Array.isArray(child)) {
|
|
89
|
+
for (const item of child) {
|
|
90
|
+
visit(item);
|
|
68
91
|
}
|
|
69
92
|
}
|
|
93
|
+
else if (typeof child === 'object' && child !== null) {
|
|
94
|
+
visit(child);
|
|
95
|
+
}
|
|
70
96
|
}
|
|
71
|
-
|
|
97
|
+
}
|
|
98
|
+
visit(ast);
|
|
99
|
+
return declarations;
|
|
100
|
+
}
|
|
101
|
+
const SVELTE_SCRIPT = /<script\b[^>]*>([\s\S]*?)<\/script>/gi;
|
|
102
|
+
const SVELTE_COMMENT = /<!--[\s\S]*?-->/g;
|
|
103
|
+
const SVELTE_T_CALL_KEY = /(?:\blabels\.t|(?<![\w$.])t)\(\s*(['"])([^'"]*)\1/g;
|
|
104
|
+
function extractFromSvelte(filePath, code) {
|
|
105
|
+
const declarations = [];
|
|
106
|
+
const labelNames = new Set();
|
|
107
|
+
const markup = code
|
|
108
|
+
.replace(SVELTE_SCRIPT, (_script, contents) => {
|
|
109
|
+
const ast = parseSync(`${filePath}.ts`, contents).program;
|
|
110
|
+
for (const name of importedNames(ast.body, 'fimo/sveltekit/components', 'Label')) {
|
|
111
|
+
labelNames.add(name);
|
|
112
|
+
}
|
|
113
|
+
declarations.push(...extractFromModule(filePath, contents, `${filePath}.ts`));
|
|
114
|
+
return '';
|
|
115
|
+
})
|
|
116
|
+
.replace(SVELTE_COMMENT, '');
|
|
117
|
+
for (const name of labelNames) {
|
|
118
|
+
const labelKey = new RegExp(`<${name}\\b[^>]*?\\svalue=(?:"([^"]*)"|'([^']*)')`, 'g');
|
|
119
|
+
for (const match of markup.matchAll(labelKey)) {
|
|
120
|
+
declarations.push({ key: (match[1] ?? match[2]), file: filePath });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (const match of markup.matchAll(SVELTE_T_CALL_KEY)) {
|
|
124
|
+
declarations.push({ key: match[2], file: filePath });
|
|
125
|
+
}
|
|
126
|
+
return declarations;
|
|
127
|
+
}
|
|
128
|
+
function extractFromFile(filePath) {
|
|
129
|
+
try {
|
|
130
|
+
const code = readFileSync(filePath, 'utf-8');
|
|
131
|
+
return filePath.endsWith('.svelte') ? extractFromSvelte(filePath, code) : extractFromModule(filePath, code);
|
|
72
132
|
}
|
|
73
133
|
catch (error) {
|
|
74
134
|
console.error(`Failed to parse ${filePath}:`, error);
|
|
135
|
+
return [];
|
|
75
136
|
}
|
|
76
|
-
return declarations;
|
|
77
137
|
}
|
|
78
138
|
export function extractLabelKeys(options = {}) {
|
|
79
139
|
const cwd = options.cwd ?? process.cwd();
|
|
80
140
|
const srcDir = join(cwd, 'src');
|
|
81
141
|
const declarations = [];
|
|
82
142
|
const seen = new Set();
|
|
83
|
-
for (const file of
|
|
143
|
+
for (const file of findSourceFiles(srcDir)) {
|
|
84
144
|
for (const declaration of extractFromFile(file)) {
|
|
85
145
|
if (seen.has(declaration.key)) {
|
|
86
146
|
continue;
|
|
@@ -44,7 +44,7 @@ export function syncForms(options = {}) {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
const formsDir = resolve(cwd, FORMS_REL);
|
|
47
|
-
const templatePath = assetPath('content-templates', '
|
|
47
|
+
const templatePath = assetPath('content-templates', 'forms', 'react.eta');
|
|
48
48
|
const templateSource = readFileSync(templatePath, 'utf-8');
|
|
49
49
|
const eta = new Eta({ views: undefined, useWith: true, varName: 'it', autoEscape: false });
|
|
50
50
|
const formFiles = getFormFiles(formsDir);
|
|
@@ -5,7 +5,7 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
5
5
|
* hook files generated from the hooks template.
|
|
6
6
|
*
|
|
7
7
|
* - Scans `<cwd>/src/schemas/*.json`.
|
|
8
|
-
* - Renders shared types plus
|
|
8
|
+
* - Renders shared types plus the framework's React, Next, Astro, or SvelteKit facade.
|
|
9
9
|
* - Creates/updates `<Pascal>.types.ts` and `<Pascal>.ts`, plus `<Pascal>.client.ts` for Next; deletes orphans.
|
|
10
10
|
*/
|
|
11
11
|
import { camelCase, pascalCase } from 'change-case';
|
|
@@ -25,6 +25,14 @@ const SCHEMA_DEFINITION_SCHEMA = z.object({
|
|
|
25
25
|
i18n: z.object({ enabled: z.boolean().optional() }).optional(),
|
|
26
26
|
fields: z.record(z.string(), z.unknown()).optional(),
|
|
27
27
|
});
|
|
28
|
+
const CONTENT_TEMPLATE_PATHS = {
|
|
29
|
+
types: { current: 'shared/types.eta', legacy: 'types-template.eta' },
|
|
30
|
+
sharedServer: { current: 'shared/server.eta' },
|
|
31
|
+
reactClient: { current: 'react/client.eta', legacy: 'hooks-template.eta' },
|
|
32
|
+
nextServer: { current: 'next/server.eta' },
|
|
33
|
+
nextClient: { current: 'next/client.eta' },
|
|
34
|
+
svelteKitContent: { current: 'sveltekit/content.eta' },
|
|
35
|
+
};
|
|
28
36
|
function getSchemaFiles(schemasDir) {
|
|
29
37
|
if (!existsSync(schemasDir)) {
|
|
30
38
|
return [];
|
|
@@ -101,58 +109,117 @@ function resolveProjectRuntime(cwd) {
|
|
|
101
109
|
packageRoot: dirname(packagePath),
|
|
102
110
|
version,
|
|
103
111
|
providesNextRuntime: packageExportsSubpath(packageJson, './next') && packageExportsSubpath(packageJson, './next/client'),
|
|
112
|
+
providesAstroRuntime: packageExportsSubpath(packageJson, './astro'),
|
|
113
|
+
providesSvelteKitRuntime: packageExportsSubpath(packageJson, './sveltekit'),
|
|
104
114
|
};
|
|
105
115
|
}
|
|
106
116
|
function contentRuntimeImportFor(framework) {
|
|
107
|
-
|
|
117
|
+
if (framework === 'nextjs') {
|
|
118
|
+
return 'fimo/next';
|
|
119
|
+
}
|
|
120
|
+
if (framework === 'astro') {
|
|
121
|
+
return 'fimo/astro';
|
|
122
|
+
}
|
|
123
|
+
// @vercel/frameworks reports SvelteKit as `sveltekit-1`, while Fimo's
|
|
124
|
+
// public runtime profile is `sveltekit`. Both describe the same codegen
|
|
125
|
+
// target; callers may supply either the detector evidence or the profile.
|
|
126
|
+
if (framework === 'sveltekit' || framework === 'sveltekit-1') {
|
|
127
|
+
return 'fimo/sveltekit';
|
|
128
|
+
}
|
|
129
|
+
return 'fimo/ui';
|
|
108
130
|
}
|
|
109
|
-
function templatePath(runtime,
|
|
131
|
+
function templatePath(runtime, templateName) {
|
|
132
|
+
const template = CONTENT_TEMPLATE_PATHS[templateName];
|
|
110
133
|
if (runtime && !isVersionAtLeast(runtime.version, MINIMUM_THIN_CONTENT_CLIENT_RUNTIME_VERSION)) {
|
|
111
|
-
|
|
134
|
+
const legacyPath = 'legacy' in template ? template.legacy : template.current;
|
|
135
|
+
return join(runtime.packageRoot, 'assets', 'content-templates', legacyPath);
|
|
112
136
|
}
|
|
113
|
-
return assetPath('content-templates',
|
|
137
|
+
return assetPath('content-templates', template.current);
|
|
114
138
|
}
|
|
115
139
|
function resolveSchemaGenerationTarget(runtimeImport, runtime) {
|
|
116
140
|
if (runtimeImport === 'fimo/ui') {
|
|
117
141
|
return 'react';
|
|
118
142
|
}
|
|
119
|
-
if (!runtime.providesNextRuntime) {
|
|
143
|
+
if (runtimeImport === 'fimo/next' && !runtime.providesNextRuntime) {
|
|
120
144
|
throw new Error(`Cannot generate schema clients because project-local fimo@${runtime.version} does not provide the ` +
|
|
121
145
|
'fimo/next and fimo/next/client exports required by this Next.js project. ' +
|
|
122
146
|
`Run \`${CONTENT_CLIENT_RUNTIME_UPGRADE_COMMAND}\` in the project, then run \`npx fimo@latest validate\` again. ` +
|
|
123
147
|
'No generated files were changed.');
|
|
124
148
|
}
|
|
125
|
-
|
|
149
|
+
if (runtimeImport === 'fimo/astro' && !runtime.providesAstroRuntime) {
|
|
150
|
+
throw new Error(`Cannot generate schema clients because project-local fimo@${runtime.version} does not provide the ` +
|
|
151
|
+
'fimo/astro export required by this Astro project. ' +
|
|
152
|
+
`Run \`${CONTENT_CLIENT_RUNTIME_UPGRADE_COMMAND}\` in the project, then run \`npx fimo@latest validate\` again. ` +
|
|
153
|
+
'No generated files were changed.');
|
|
154
|
+
}
|
|
155
|
+
if (runtimeImport === 'fimo/sveltekit' && !runtime.providesSvelteKitRuntime) {
|
|
156
|
+
throw new Error(`Cannot generate schema clients because project-local fimo@${runtime.version} does not provide the ` +
|
|
157
|
+
'fimo/sveltekit export required by this SvelteKit project. ' +
|
|
158
|
+
`Run \`${CONTENT_CLIENT_RUNTIME_UPGRADE_COMMAND}\` in the project, then run \`npx fimo@latest validate\` again. ` +
|
|
159
|
+
'No generated files were changed.');
|
|
160
|
+
}
|
|
161
|
+
if (runtimeImport === 'fimo/next') {
|
|
162
|
+
return 'next';
|
|
163
|
+
}
|
|
164
|
+
return runtimeImport === 'fimo/astro' ? 'astro' : 'sveltekit';
|
|
126
165
|
}
|
|
127
166
|
function templatesForTarget(target, runtime, runtimeImport) {
|
|
128
167
|
if (target === 'next') {
|
|
129
168
|
return [
|
|
130
169
|
{
|
|
131
170
|
suffix: '.types.ts',
|
|
132
|
-
path: templatePath(runtime, 'types
|
|
171
|
+
path: templatePath(runtime, 'types'),
|
|
133
172
|
runtimeImport: 'fimo/next',
|
|
134
173
|
},
|
|
135
174
|
{
|
|
136
175
|
suffix: '.ts',
|
|
137
|
-
path: templatePath(runtime, '
|
|
176
|
+
path: templatePath(runtime, 'nextServer'),
|
|
138
177
|
runtimeImport: 'fimo/next',
|
|
139
178
|
},
|
|
140
179
|
{
|
|
141
180
|
suffix: '.client.ts',
|
|
142
|
-
path: templatePath(runtime, '
|
|
181
|
+
path: templatePath(runtime, 'nextClient'),
|
|
143
182
|
runtimeImport: 'fimo/next/client',
|
|
144
183
|
},
|
|
145
184
|
];
|
|
146
185
|
}
|
|
186
|
+
if (target === 'astro') {
|
|
187
|
+
return [
|
|
188
|
+
{
|
|
189
|
+
suffix: '.types.ts',
|
|
190
|
+
path: templatePath(runtime, 'types'),
|
|
191
|
+
runtimeImport: 'fimo/astro',
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
suffix: '.ts',
|
|
195
|
+
path: templatePath(runtime, 'sharedServer'),
|
|
196
|
+
runtimeImport: 'fimo/astro',
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
if (target === 'sveltekit') {
|
|
201
|
+
return [
|
|
202
|
+
{
|
|
203
|
+
suffix: '.types.ts',
|
|
204
|
+
path: templatePath(runtime, 'types'),
|
|
205
|
+
runtimeImport: 'fimo/sveltekit',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
suffix: '.ts',
|
|
209
|
+
path: templatePath(runtime, 'svelteKitContent'),
|
|
210
|
+
runtimeImport: 'fimo/sveltekit',
|
|
211
|
+
},
|
|
212
|
+
];
|
|
213
|
+
}
|
|
147
214
|
return [
|
|
148
215
|
{
|
|
149
216
|
suffix: '.types.ts',
|
|
150
|
-
path: templatePath(runtime, 'types
|
|
217
|
+
path: templatePath(runtime, 'types'),
|
|
151
218
|
runtimeImport,
|
|
152
219
|
},
|
|
153
220
|
{
|
|
154
221
|
suffix: '.ts',
|
|
155
|
-
path: templatePath(runtime, '
|
|
222
|
+
path: templatePath(runtime, 'reactClient'),
|
|
156
223
|
runtimeImport,
|
|
157
224
|
},
|
|
158
225
|
];
|
|
@@ -219,7 +286,7 @@ function renderContentRegistry(schemas) {
|
|
|
219
286
|
const imports = schemas.map(({ pascal }) => `import * as ${pascal} from "./${pascal}";`).join('\n');
|
|
220
287
|
const entries = schemas.map(({ pascal, registryKey }) => ` ${registryKey}: ${pascal},`).join('\n');
|
|
221
288
|
return `${GENERATED_REGISTRY_MARKER}
|
|
222
|
-
//
|
|
289
|
+
// Generated content registry for framework facades and project integrations.
|
|
223
290
|
|
|
224
291
|
${imports}
|
|
225
292
|
|
|
@@ -306,10 +373,10 @@ export function syncSchemas(options) {
|
|
|
306
373
|
const runtime = schemas.length > 0 || generatedFilesOnDisk.length > 0 ? resolveProjectRuntime(cwd) : null;
|
|
307
374
|
const runtimeImport = contentRuntimeImportFor(options.framework);
|
|
308
375
|
const generationTarget = runtime ? resolveSchemaGenerationTarget(runtimeImport, runtime) : null;
|
|
309
|
-
const
|
|
376
|
+
const needsContentRegistry = (generationTarget === 'next' || generationTarget === 'sveltekit') && schemas.length > 0;
|
|
310
377
|
const ownsExistingRegistry = existsSync(registryPath) && readFileSync(registryPath, 'utf-8').startsWith(GENERATED_REGISTRY_MARKER);
|
|
311
|
-
const shouldGenerateRegistry =
|
|
312
|
-
if (
|
|
378
|
+
const shouldGenerateRegistry = needsContentRegistry && (!existsSync(registryPath) || ownsExistingRegistry);
|
|
379
|
+
if (needsContentRegistry && !shouldGenerateRegistry) {
|
|
313
380
|
log(`Kept project-owned schema barrel: ${registryPath}`);
|
|
314
381
|
}
|
|
315
382
|
const templates = generationTarget && runtime ? templatesForTarget(generationTarget, runtime, runtimeImport) : [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fimo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0-staging.2",
|
|
4
4
|
"description": "Fimo CLI - create, deploy, and manage Fimo projects",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fimo": "dist/cli/index.js"
|
|
@@ -26,6 +26,22 @@
|
|
|
26
26
|
"types": "./dist/runtime/content/index.d.ts",
|
|
27
27
|
"import": "./dist/runtime/content/index.js"
|
|
28
28
|
},
|
|
29
|
+
"./astro": {
|
|
30
|
+
"types": "./dist/runtime/astro/server.d.ts",
|
|
31
|
+
"import": "./dist/runtime/astro/server.js"
|
|
32
|
+
},
|
|
33
|
+
"./astro/components": {
|
|
34
|
+
"types": "./assets/astro/components/index.d.ts",
|
|
35
|
+
"import": "./assets/astro/components/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./astro/config": {
|
|
38
|
+
"types": "./dist/build/astro/config.d.ts",
|
|
39
|
+
"import": "./dist/build/astro/config.js"
|
|
40
|
+
},
|
|
41
|
+
"./astro/internal": {
|
|
42
|
+
"types": "./dist/runtime/astro/internal.d.ts",
|
|
43
|
+
"import": "./dist/runtime/astro/internal.js"
|
|
44
|
+
},
|
|
29
45
|
"./next": {
|
|
30
46
|
"types": "./dist/runtime/next/server.d.ts",
|
|
31
47
|
"import": "./dist/runtime/next/server.js"
|
|
@@ -51,6 +67,27 @@
|
|
|
51
67
|
"types": "./dist/runtime/react-router/preset.d.ts",
|
|
52
68
|
"import": "./dist/runtime/react-router/preset.js"
|
|
53
69
|
},
|
|
70
|
+
"./sveltekit": {
|
|
71
|
+
"types": "./dist/runtime/sveltekit/index.d.ts",
|
|
72
|
+
"import": "./dist/runtime/sveltekit/index.js"
|
|
73
|
+
},
|
|
74
|
+
"./sveltekit/components": {
|
|
75
|
+
"types": "./assets/sveltekit/components/index.d.ts",
|
|
76
|
+
"svelte": "./assets/sveltekit/components/index.js",
|
|
77
|
+
"import": "./assets/sveltekit/components/index.js"
|
|
78
|
+
},
|
|
79
|
+
"./sveltekit/config": {
|
|
80
|
+
"types": "./dist/build/sveltekit/config.d.ts",
|
|
81
|
+
"import": "./dist/build/sveltekit/config.js"
|
|
82
|
+
},
|
|
83
|
+
"./sveltekit/internal": {
|
|
84
|
+
"types": "./dist/runtime/sveltekit/internal.d.ts",
|
|
85
|
+
"import": "./dist/runtime/sveltekit/internal.js"
|
|
86
|
+
},
|
|
87
|
+
"./sveltekit/vite": {
|
|
88
|
+
"types": "./dist/build/sveltekit/vite.d.ts",
|
|
89
|
+
"import": "./dist/build/sveltekit/vite.js"
|
|
90
|
+
},
|
|
54
91
|
"./paths": {
|
|
55
92
|
"types": "./dist/runtime/paths/index.d.ts",
|
|
56
93
|
"import": "./dist/runtime/paths/index.js"
|
|
@@ -84,12 +121,18 @@
|
|
|
84
121
|
"publish:dry-run": "npm publish --dry-run",
|
|
85
122
|
"postinstall": "node scripts/postinstall.mjs",
|
|
86
123
|
"test": "vitest run",
|
|
87
|
-
"test:integration:
|
|
124
|
+
"test:integration:astro": "vitest run --config vitest.integration.config.ts test/integration/astro-runtime.test.ts",
|
|
125
|
+
"test:integration:astro-compat": "vitest run --config vitest.integration.config.ts test/integration/astro-compat.test.ts",
|
|
126
|
+
"test:integration:frameworks": "vitest run --config vitest.integration.config.ts",
|
|
127
|
+
"test:integration:next": "vitest run --config vitest.integration.config.ts test/integration/next-runtime.test.ts",
|
|
128
|
+
"test:integration:sveltekit": "vitest run --config vitest.integration.config.ts test/integration/sveltekit-runtime.test.ts",
|
|
88
129
|
"test:watch": "vitest",
|
|
89
130
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
90
131
|
},
|
|
91
132
|
"dependencies": {
|
|
133
|
+
"@astrojs/vercel": "11.0.4",
|
|
92
134
|
"@rollup/pluginutils": "^5.1.0",
|
|
135
|
+
"@sveltejs/adapter-vercel": "6.3.4",
|
|
93
136
|
"change-case": "^5.4.4",
|
|
94
137
|
"eta": "^3.5.0",
|
|
95
138
|
"oxc-parser": "^0.118.0",
|
|
@@ -127,16 +170,25 @@
|
|
|
127
170
|
"yaml": "2.8.2"
|
|
128
171
|
},
|
|
129
172
|
"peerDependencies": {
|
|
173
|
+
"@sveltejs/kit": "^2.0.0",
|
|
130
174
|
"@tanstack/react-query": "^5.80.6",
|
|
175
|
+
"astro": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
131
176
|
"react": "^18.2.0 || ^19.0.0",
|
|
132
177
|
"react-dom": "^18.2.0 || ^19.0.0",
|
|
133
178
|
"react-router": "^7.0.0 || ^8.0.0",
|
|
179
|
+
"svelte": "^5.0.0",
|
|
134
180
|
"vite": "^7.0.0 || ^8.0.0"
|
|
135
181
|
},
|
|
136
182
|
"peerDependenciesMeta": {
|
|
137
183
|
"@tanstack/react-query": {
|
|
138
184
|
"optional": true
|
|
139
185
|
},
|
|
186
|
+
"@sveltejs/kit": {
|
|
187
|
+
"optional": true
|
|
188
|
+
},
|
|
189
|
+
"astro": {
|
|
190
|
+
"optional": true
|
|
191
|
+
},
|
|
140
192
|
"react": {
|
|
141
193
|
"optional": true
|
|
142
194
|
},
|
|
@@ -146,6 +198,9 @@
|
|
|
146
198
|
"react-router": {
|
|
147
199
|
"optional": true
|
|
148
200
|
},
|
|
201
|
+
"svelte": {
|
|
202
|
+
"optional": true
|
|
203
|
+
},
|
|
149
204
|
"vite": {
|
|
150
205
|
"optional": true
|
|
151
206
|
}
|
package/release.json
CHANGED
|
@@ -4,14 +4,18 @@ This is a Fimo project. Fimo connects content, media, forms, analytics, editing,
|
|
|
4
4
|
|
|
5
5
|
## Load the Fimo skills before doing Fimo work
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Before writing schema-driven code, running CLI/deploy workflows, or migrating content, load only the
|
|
8
|
+
skill relevant to the task. During onboarding, preserve the exact CLI invocation prefix from the
|
|
9
|
+
initiating prompt for every operational command; otherwise default to `npx fimo@latest`:
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
|
-
pnpm exec fimo skills get fimo-code # code
|
|
11
|
-
npx fimo@latest skills get fimo-cli #
|
|
12
|
+
pnpm exec fimo skills get fimo-code # match the lockfile; code + framework APIs come from this project runtime
|
|
13
|
+
npx fimo@latest skills get fimo-cli # default prefix; keep the onboarding prefix when one was supplied
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
Use
|
|
16
|
+
Use `npm exec fimo`, `yarn fimo`, or `bunx --no-install fimo` instead of `pnpm exec fimo` when that
|
|
17
|
+
matches the project lockfile. Add `--ref <doc>` for one reference at a time. Do not load `fimo-cli` for
|
|
18
|
+
a code-only task, or use `npx fimo@latest` for project-local code generation and validation.
|
|
15
19
|
|
|
16
20
|
## Never hardcode editable values
|
|
17
21
|
|
|
@@ -26,10 +30,11 @@ The scaffolded homepage is disposable. Replace it on the first real generation.
|
|
|
26
30
|
|
|
27
31
|
1. Start the application with the project package manager (`pnpm dev`, `npm run dev`, `yarn dev`, or `bun dev`).
|
|
28
32
|
2. Build and verify against the local server.
|
|
29
|
-
3.
|
|
33
|
+
3. When a unit of work is done, **offer** to deploy: `fimo deploy` for a hosted preview / shareable link, or `fimo deploy --publish` to go live. Deploy on the developer's request or confirmation. The one exception: new-project onboarding creates a single first hosted preview automatically unless the developer said not to deploy. Never publish without an explicit request.
|
|
30
34
|
|
|
31
35
|
## Project rules
|
|
32
36
|
|
|
37
|
+
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
33
38
|
- The application owns routes, locale resolution, links, HTML language/direction, and SEO. Fimo connects to those decisions.
|
|
34
39
|
- Do not add a second deployment platform.
|
|
35
40
|
- Never edit `.fimo/project.json`; it links this directory to the remote project.
|
|
@@ -9,11 +9,12 @@ When asked to create or manage an agent in this project, use Fimo's agent workfl
|
|
|
9
9
|
## Load the Fimo skills before doing Fimo work
|
|
10
10
|
|
|
11
11
|
Before writing schema-driven code, running CLI/deploy workflows, or migrating content, load only the
|
|
12
|
-
skill relevant to the task
|
|
12
|
+
skill relevant to the task. During onboarding, preserve the exact CLI invocation prefix from the
|
|
13
|
+
initiating prompt for every operational command; otherwise default to `npx fimo@latest`:
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
16
|
pnpm exec fimo skills get fimo-code # match the lockfile; code + framework APIs come from this project runtime
|
|
16
|
-
npx fimo@latest skills get fimo-cli #
|
|
17
|
+
npx fimo@latest skills get fimo-cli # default prefix; keep the onboarding prefix when one was supplied
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
Use `npm exec fimo`, `yarn fimo`, or `bunx --no-install fimo` instead of `pnpm exec fimo` when that
|
|
@@ -34,7 +35,7 @@ breaks that. Load `fimo-code` for the exact primitives, but the rule is:
|
|
|
34
35
|
|
|
35
36
|
1. Start the dev server with the project's package manager (`pnpm dev`, `npm run dev`, …) — live reload on localhost.
|
|
36
37
|
2. Make edits; the running server shows them instantly. No deploy needed to see local changes.
|
|
37
|
-
3. When a unit of work is done, **offer** to deploy: `fimo deploy` for a hosted preview / shareable link, or `fimo deploy --publish` to go live.
|
|
38
|
+
3. When a unit of work is done, **offer** to deploy: `fimo deploy` for a hosted preview / shareable link, or `fimo deploy --publish` to go live. Deploy on the developer's request or confirmation. The one exception: new-project onboarding creates a single first hosted preview automatically unless the developer said not to deploy. Never publish without an explicit request.
|
|
38
39
|
|
|
39
40
|
## Project rules
|
|
40
41
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Fimo project
|
|
2
|
+
|
|
3
|
+
This SvelteKit application is connected to Fimo for content, editing, environments, and hosting.
|
|
4
|
+
|
|
5
|
+
## Load the Fimo skills before doing Fimo work
|
|
6
|
+
|
|
7
|
+
Before writing schema-driven code, running CLI/deploy workflows, or migrating content, load only the
|
|
8
|
+
skill relevant to the task. During onboarding, preserve the exact CLI invocation prefix from the
|
|
9
|
+
initiating prompt for every operational command; otherwise default to `npx fimo@latest`:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm exec fimo skills get fimo-code
|
|
13
|
+
pnpm exec fimo skills get fimo-code --ref frameworks/sveltekit
|
|
14
|
+
npx fimo@latest skills get fimo-cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Use `npm exec fimo`, `yarn fimo`, or `bunx --no-install fimo` instead of `pnpm exec fimo` when that
|
|
18
|
+
matches the project lockfile. Add `--ref <doc>` for one reference at a time. Do not load `fimo-cli` for
|
|
19
|
+
a code-only task, or use `npx fimo@latest` for project-local code generation and validation.
|
|
20
|
+
|
|
21
|
+
## Development loop
|
|
22
|
+
|
|
23
|
+
1. Start the application with the project package manager (`pnpm dev`, `npm run dev`, `yarn dev`, or `bun dev`).
|
|
24
|
+
2. Build and verify against the local server.
|
|
25
|
+
3. When a unit of work is done, **offer** to deploy: `fimo deploy` for a hosted preview / shareable link, or `fimo deploy --publish` to go live. Deploy on the developer's request or confirmation. The one exception: new-project onboarding creates a single first hosted preview automatically unless the developer said not to deploy. Never publish without an explicit request.
|
|
26
|
+
|
|
27
|
+
## Project rules
|
|
28
|
+
|
|
29
|
+
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
30
|
+
- The application owns routes, locale resolution, links, HTML language/direction, and SEO. Fimo connects to those decisions.
|
|
31
|
+
- Do not add a second deployment platform.
|
|
32
|
+
- Never edit `.fimo/project.json`; it links this directory to the remote project.
|
|
33
|
+
- Keep secrets in the Fimo dashboard, not committed environment files.
|
|
34
|
+
- Pass flags to interactive Fimo commands when scripting them.
|
|
35
|
+
|
|
36
|
+
The scaffolded homepage is disposable. Replace it when building the requested site.
|