@mantajs/cli 0.2.0-beta.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/bin/manta.mjs +20 -0
- package/bin/manta.ts +13 -0
- package/dist/admin/generate-admin-config.d.ts +8 -0
- package/dist/admin/generate-admin-config.d.ts.map +1 -0
- package/dist/admin/generate-admin-config.js +127 -0
- package/dist/admin/generate-admin-config.js.map +1 -0
- package/dist/ai/chat-handler.d.ts +10 -0
- package/dist/ai/chat-handler.d.ts.map +1 -0
- package/dist/ai/chat-handler.js +1353 -0
- package/dist/ai/chat-handler.js.map +1 -0
- package/dist/bootstrap/boot.d.ts +25 -0
- package/dist/bootstrap/boot.d.ts.map +1 -0
- package/dist/bootstrap/boot.js +344 -0
- package/dist/bootstrap/boot.js.map +1 -0
- package/dist/bootstrap/bootstrap-app.d.ts +71 -0
- package/dist/bootstrap/bootstrap-app.d.ts.map +1 -0
- package/dist/bootstrap/bootstrap-app.js +308 -0
- package/dist/bootstrap/bootstrap-app.js.map +1 -0
- package/dist/bootstrap/bootstrap-context.d.ts +76 -0
- package/dist/bootstrap/bootstrap-context.d.ts.map +1 -0
- package/dist/bootstrap/bootstrap-context.js +4 -0
- package/dist/bootstrap/bootstrap-context.js.map +1 -0
- package/dist/bootstrap/bootstrap-helpers.d.ts +71 -0
- package/dist/bootstrap/bootstrap-helpers.d.ts.map +1 -0
- package/dist/bootstrap/bootstrap-helpers.js +373 -0
- package/dist/bootstrap/bootstrap-helpers.js.map +1 -0
- package/dist/bootstrap/generate-types.d.ts +7 -0
- package/dist/bootstrap/generate-types.d.ts.map +1 -0
- package/dist/bootstrap/generate-types.js +832 -0
- package/dist/bootstrap/generate-types.js.map +1 -0
- package/dist/bootstrap/phases/assemble/index.d.ts +5 -0
- package/dist/bootstrap/phases/assemble/index.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble/index.js +5 -0
- package/dist/bootstrap/phases/assemble/index.js.map +1 -0
- package/dist/bootstrap/phases/assemble/load-links.d.ts +3 -0
- package/dist/bootstrap/phases/assemble/load-links.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble/load-links.js +160 -0
- package/dist/bootstrap/phases/assemble/load-links.js.map +1 -0
- package/dist/bootstrap/phases/assemble/load-modules.d.ts +3 -0
- package/dist/bootstrap/phases/assemble/load-modules.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble/load-modules.js +163 -0
- package/dist/bootstrap/phases/assemble/load-modules.js.map +1 -0
- package/dist/bootstrap/phases/assemble/load-resources.d.ts +3 -0
- package/dist/bootstrap/phases/assemble/load-resources.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble/load-resources.js +270 -0
- package/dist/bootstrap/phases/assemble/load-resources.js.map +1 -0
- package/dist/bootstrap/phases/assemble/wire-commands.d.ts +3 -0
- package/dist/bootstrap/phases/assemble/wire-commands.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble/wire-commands.js +408 -0
- package/dist/bootstrap/phases/assemble/wire-commands.js.map +1 -0
- package/dist/bootstrap/phases/assemble-modules.d.ts +3 -0
- package/dist/bootstrap/phases/assemble-modules.d.ts.map +1 -0
- package/dist/bootstrap/phases/assemble-modules.js +14 -0
- package/dist/bootstrap/phases/assemble-modules.js.map +1 -0
- package/dist/bootstrap/phases/build-app.d.ts +3 -0
- package/dist/bootstrap/phases/build-app.d.ts.map +1 -0
- package/dist/bootstrap/phases/build-app.js +15 -0
- package/dist/bootstrap/phases/build-app.js.map +1 -0
- package/dist/bootstrap/phases/discover-resources.d.ts +3 -0
- package/dist/bootstrap/phases/discover-resources.d.ts.map +1 -0
- package/dist/bootstrap/phases/discover-resources.js +60 -0
- package/dist/bootstrap/phases/discover-resources.js.map +1 -0
- package/dist/bootstrap/phases/index.d.ts +7 -0
- package/dist/bootstrap/phases/index.d.ts.map +1 -0
- package/dist/bootstrap/phases/index.js +7 -0
- package/dist/bootstrap/phases/index.js.map +1 -0
- package/dist/bootstrap/phases/init-infra.d.ts +3 -0
- package/dist/bootstrap/phases/init-infra.d.ts.map +1 -0
- package/dist/bootstrap/phases/init-infra.js +193 -0
- package/dist/bootstrap/phases/init-infra.js.map +1 -0
- package/dist/bootstrap/phases/seed-dev-users.d.ts +3 -0
- package/dist/bootstrap/phases/seed-dev-users.d.ts.map +1 -0
- package/dist/bootstrap/phases/seed-dev-users.js +93 -0
- package/dist/bootstrap/phases/seed-dev-users.js.map +1 -0
- package/dist/bootstrap/phases/wire/auth-helpers.d.ts +12 -0
- package/dist/bootstrap/phases/wire/auth-helpers.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/auth-helpers.js +25 -0
- package/dist/bootstrap/phases/wire/auth-helpers.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/context-registry.d.ts +4 -0
- package/dist/bootstrap/phases/wire/contexts/context-registry.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/context-registry.js +96 -0
- package/dist/bootstrap/phases/wire/contexts/context-registry.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/cqrs-routes.d.ts +3 -0
- package/dist/bootstrap/phases/wire/contexts/cqrs-routes.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/cqrs-routes.js +138 -0
- package/dist/bootstrap/phases/wire/contexts/cqrs-routes.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/index.d.ts +6 -0
- package/dist/bootstrap/phases/wire/contexts/index.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/index.js +6 -0
- package/dist/bootstrap/phases/wire/contexts/index.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/query-endpoints.d.ts +3 -0
- package/dist/bootstrap/phases/wire/contexts/query-endpoints.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/query-endpoints.js +116 -0
- package/dist/bootstrap/phases/wire/contexts/query-endpoints.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/spa-warnings.d.ts +3 -0
- package/dist/bootstrap/phases/wire/contexts/spa-warnings.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/spa-warnings.js +17 -0
- package/dist/bootstrap/phases/wire/contexts/spa-warnings.js.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/user-routes.d.ts +3 -0
- package/dist/bootstrap/phases/wire/contexts/user-routes.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/contexts/user-routes.js +83 -0
- package/dist/bootstrap/phases/wire/contexts/user-routes.js.map +1 -0
- package/dist/bootstrap/phases/wire/index.d.ts +5 -0
- package/dist/bootstrap/phases/wire/index.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/index.js +5 -0
- package/dist/bootstrap/phases/wire/index.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-adapter.d.ts +12 -0
- package/dist/bootstrap/phases/wire/wire-adapter.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-adapter.js +156 -0
- package/dist/bootstrap/phases/wire/wire-adapter.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-auth.d.ts +3 -0
- package/dist/bootstrap/phases/wire/wire-auth.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-auth.js +46 -0
- package/dist/bootstrap/phases/wire/wire-auth.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-contexts.d.ts +3 -0
- package/dist/bootstrap/phases/wire/wire-contexts.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-contexts.js +15 -0
- package/dist/bootstrap/phases/wire/wire-contexts.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-cron-routes.d.ts +3 -0
- package/dist/bootstrap/phases/wire/wire-cron-routes.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-cron-routes.js +102 -0
- package/dist/bootstrap/phases/wire/wire-cron-routes.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-extras.d.ts +3 -0
- package/dist/bootstrap/phases/wire/wire-extras.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-extras.js +305 -0
- package/dist/bootstrap/phases/wire/wire-extras.js.map +1 -0
- package/dist/bootstrap/phases/wire/wire-workflow-routes.d.ts +3 -0
- package/dist/bootstrap/phases/wire/wire-workflow-routes.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire/wire-workflow-routes.js +212 -0
- package/dist/bootstrap/phases/wire/wire-workflow-routes.js.map +1 -0
- package/dist/bootstrap/phases/wire-http.d.ts +3 -0
- package/dist/bootstrap/phases/wire-http.d.ts.map +1 -0
- package/dist/bootstrap/phases/wire-http.js +10 -0
- package/dist/bootstrap/phases/wire-http.js.map +1 -0
- package/dist/bootstrap/validate-generated-ts.d.ts +6 -0
- package/dist/bootstrap/validate-generated-ts.d.ts.map +1 -0
- package/dist/bootstrap/validate-generated-ts.js +26 -0
- package/dist/bootstrap/validate-generated-ts.js.map +1 -0
- package/dist/build/generate-manifest.d.ts +10 -0
- package/dist/build/generate-manifest.d.ts.map +1 -0
- package/dist/build/generate-manifest.js +138 -0
- package/dist/build/generate-manifest.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +421 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/build.d.ts +21 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +399 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/db/create.d.ts +17 -0
- package/dist/commands/db/create.d.ts.map +1 -0
- package/dist/commands/db/create.js +94 -0
- package/dist/commands/db/create.js.map +1 -0
- package/dist/commands/db/diff.d.ts +39 -0
- package/dist/commands/db/diff.d.ts.map +1 -0
- package/dist/commands/db/diff.js +81 -0
- package/dist/commands/db/diff.js.map +1 -0
- package/dist/commands/db/generate.d.ts +58 -0
- package/dist/commands/db/generate.d.ts.map +1 -0
- package/dist/commands/db/generate.js +138 -0
- package/dist/commands/db/generate.js.map +1 -0
- package/dist/commands/db/migrate.d.ts +29 -0
- package/dist/commands/db/migrate.d.ts.map +1 -0
- package/dist/commands/db/migrate.js +118 -0
- package/dist/commands/db/migrate.js.map +1 -0
- package/dist/commands/db/pg-deps.d.ts +30 -0
- package/dist/commands/db/pg-deps.d.ts.map +1 -0
- package/dist/commands/db/pg-deps.js +178 -0
- package/dist/commands/db/pg-deps.js.map +1 -0
- package/dist/commands/db/rollback.d.ts +21 -0
- package/dist/commands/db/rollback.d.ts.map +1 -0
- package/dist/commands/db/rollback.js +85 -0
- package/dist/commands/db/rollback.js.map +1 -0
- package/dist/commands/db/types.d.ts +113 -0
- package/dist/commands/db/types.d.ts.map +1 -0
- package/dist/commands/db/types.js +4 -0
- package/dist/commands/db/types.js.map +1 -0
- package/dist/commands/dev.d.ts +12 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +79 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/exec.d.ts +21 -0
- package/dist/commands/exec.d.ts.map +1 -0
- package/dist/commands/exec.js +148 -0
- package/dist/commands/exec.js.map +1 -0
- package/dist/commands/generate.d.ts +11 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +19 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +476 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/start.d.ts +15 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +121 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/user.d.ts +19 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +125 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/config/load-config.d.ts +23 -0
- package/dist/config/load-config.d.ts.map +1 -0
- package/dist/config/load-config.js +105 -0
- package/dist/config/load-config.js.map +1 -0
- package/dist/config/load-env.d.ts +11 -0
- package/dist/config/load-env.d.ts.map +1 -0
- package/dist/config/load-env.js +61 -0
- package/dist/config/load-env.js.map +1 -0
- package/dist/config/resolve-adapters.d.ts +23 -0
- package/dist/config/resolve-adapters.d.ts.map +1 -0
- package/dist/config/resolve-adapters.js +96 -0
- package/dist/config/resolve-adapters.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/jiti.d.ts +2 -0
- package/dist/jiti.d.ts.map +1 -0
- package/dist/jiti.js +2 -0
- package/dist/jiti.js.map +1 -0
- package/dist/openapi/generate-spec.d.ts +56 -0
- package/dist/openapi/generate-spec.d.ts.map +1 -0
- package/dist/openapi/generate-spec.js +491 -0
- package/dist/openapi/generate-spec.js.map +1 -0
- package/dist/openapi/index.d.ts +4 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +3 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/swagger-html.d.ts +2 -0
- package/dist/openapi/swagger-html.d.ts.map +1 -0
- package/dist/openapi/swagger-html.js +29 -0
- package/dist/openapi/swagger-html.js.map +1 -0
- package/dist/plugins/merge-resources.d.ts +18 -0
- package/dist/plugins/merge-resources.d.ts.map +1 -0
- package/dist/plugins/merge-resources.js +76 -0
- package/dist/plugins/merge-resources.js.map +1 -0
- package/dist/plugins/resolve-plugins.d.ts +14 -0
- package/dist/plugins/resolve-plugins.d.ts.map +1 -0
- package/dist/plugins/resolve-plugins.js +73 -0
- package/dist/plugins/resolve-plugins.js.map +1 -0
- package/dist/resource-loader.d.ts +151 -0
- package/dist/resource-loader.d.ts.map +1 -0
- package/dist/resource-loader.js +456 -0
- package/dist/resource-loader.js.map +1 -0
- package/dist/route-discovery.d.ts +33 -0
- package/dist/route-discovery.d.ts.map +1 -0
- package/dist/route-discovery.js +69 -0
- package/dist/route-discovery.js.map +1 -0
- package/dist/server-bootstrap.d.ts +38 -0
- package/dist/server-bootstrap.d.ts.map +1 -0
- package/dist/server-bootstrap.js +21 -0
- package/dist/server-bootstrap.js.map +1 -0
- package/dist/spa/generate-spa.d.ts +15 -0
- package/dist/spa/generate-spa.d.ts.map +1 -0
- package/dist/spa/generate-spa.js +357 -0
- package/dist/spa/generate-spa.js.map +1 -0
- package/dist/templates/agent/nextjs.md +129 -0
- package/dist/templates/agent/nuxt.md +98 -0
- package/dist/templates/agent/standalone.md +498 -0
- package/dist/types.d.ts +145 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/colors.d.ts +7 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/colors.js +8 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/prompts.d.ts +6 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +28 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/spinner.d.ts +7 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +20 -0
- package/dist/utils/spinner.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DiscoveredSpa } from '../resource-loader';
|
|
2
|
+
export interface SpaGenerateOptions {
|
|
3
|
+
cwd: string;
|
|
4
|
+
spa: DiscoveredSpa;
|
|
5
|
+
dashboard?: string;
|
|
6
|
+
preset?: string;
|
|
7
|
+
/** Backend server port (from PORT env or default 3000) */
|
|
8
|
+
port?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Generate all build artifacts for a SPA.
|
|
12
|
+
* Returns the path to the generated vite.config.ts.
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateSpaArtifacts(options: SpaGenerateOptions): string;
|
|
15
|
+
//# sourceMappingURL=generate-spa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-spa.d.ts","sourceRoot":"","sources":["../../src/spa/generate-spa.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,aAAa,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAmBxE"}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
// SPA entry point generator — generates .manta/spa/{name}/ with:
|
|
2
|
+
// - index.html (auto-generated)
|
|
3
|
+
// - entry.tsx (imports dashboard shell + routes)
|
|
4
|
+
// - routes.ts (filesystem-derived routing)
|
|
5
|
+
// - vite.config.ts (Vite build config)
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
8
|
+
/**
|
|
9
|
+
* Generate all build artifacts for a SPA.
|
|
10
|
+
* Returns the path to the generated vite.config.ts.
|
|
11
|
+
*/
|
|
12
|
+
export function generateSpaArtifacts(options) {
|
|
13
|
+
const { cwd, spa, dashboard, preset, port = 3000 } = options;
|
|
14
|
+
const outDir = resolve(cwd, '.manta', 'spa', spa.name);
|
|
15
|
+
mkdirSync(outDir, { recursive: true });
|
|
16
|
+
// Generate routes.ts
|
|
17
|
+
writeFileSync(join(outDir, 'routes.ts'), generateRoutes(spa, cwd));
|
|
18
|
+
// Generate entry.tsx
|
|
19
|
+
writeFileSync(join(outDir, 'entry.tsx'), generateEntry(spa, cwd, outDir, dashboard, preset));
|
|
20
|
+
// Generate index.html
|
|
21
|
+
writeFileSync(join(outDir, 'index.html'), generateHtml(spa));
|
|
22
|
+
// Generate vite.config.ts
|
|
23
|
+
const viteConfigPath = join(outDir, 'vite.config.ts');
|
|
24
|
+
writeFileSync(viteConfigPath, generateViteConfig(spa, cwd, outDir, dashboard, preset, port));
|
|
25
|
+
return viteConfigPath;
|
|
26
|
+
}
|
|
27
|
+
function generateRoutes(spa, cwd) {
|
|
28
|
+
const lines = [
|
|
29
|
+
'// Auto-generated — do not edit',
|
|
30
|
+
`// Pages discovered from src/spa/${spa.name}/`,
|
|
31
|
+
'',
|
|
32
|
+
"import { lazy } from 'react'",
|
|
33
|
+
'',
|
|
34
|
+
];
|
|
35
|
+
// Config import (defineSpa)
|
|
36
|
+
if (spa.configPath) {
|
|
37
|
+
const relPath = relative(resolve(cwd, '.manta', 'spa', spa.name), spa.configPath).replace(/\.ts$/, '');
|
|
38
|
+
lines.push(`import spaConfig from '${relPath}'`);
|
|
39
|
+
lines.push('');
|
|
40
|
+
}
|
|
41
|
+
const imports = [];
|
|
42
|
+
const routeDefs = [];
|
|
43
|
+
const specImports = [];
|
|
44
|
+
const specDefs = [];
|
|
45
|
+
for (const page of spa.pages) {
|
|
46
|
+
const varName = routeToVarName(page.route);
|
|
47
|
+
const relPath = relative(resolve(cwd, '.manta', 'spa', spa.name), page.path).replace(/\.tsx?$/, '');
|
|
48
|
+
const isSpec = page.path.endsWith('.ts') && !page.path.endsWith('.tsx');
|
|
49
|
+
if (isSpec) {
|
|
50
|
+
// Spec page (definePage/defineForm) — static import
|
|
51
|
+
specImports.push(`import ${varName}Spec from '${relPath}'`);
|
|
52
|
+
specDefs.push(` { route: '${page.route}', spec: ${varName}Spec },`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// React page — lazy import
|
|
56
|
+
imports.push(`const ${varName} = lazy(() => import('${relPath}'))`);
|
|
57
|
+
routeDefs.push(` { path: '${page.route}', component: ${varName} },`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Block imports
|
|
61
|
+
const blockImports = [];
|
|
62
|
+
const blockDefs = [];
|
|
63
|
+
for (const block of spa.blocks) {
|
|
64
|
+
const relPath = relative(resolve(cwd, '.manta', 'spa', spa.name), block.path).replace(/\.tsx?$/, '');
|
|
65
|
+
blockImports.push(`import ${block.type} from '${relPath}'`);
|
|
66
|
+
blockDefs.push(` '${block.type}': ${block.type},`);
|
|
67
|
+
}
|
|
68
|
+
lines.push(...specImports);
|
|
69
|
+
lines.push(...imports);
|
|
70
|
+
if (blockImports.length > 0) {
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push(...blockImports);
|
|
73
|
+
}
|
|
74
|
+
lines.push('');
|
|
75
|
+
// Export React routes (legacy)
|
|
76
|
+
lines.push('export const routes = [');
|
|
77
|
+
lines.push(...routeDefs);
|
|
78
|
+
lines.push(']');
|
|
79
|
+
lines.push('');
|
|
80
|
+
// Export spec pages (definePage/defineForm)
|
|
81
|
+
lines.push('export const pageSpecs = [');
|
|
82
|
+
lines.push(...specDefs);
|
|
83
|
+
lines.push(']');
|
|
84
|
+
lines.push('');
|
|
85
|
+
// Export custom blocks
|
|
86
|
+
if (blockDefs.length > 0) {
|
|
87
|
+
lines.push('export const customBlocks = {');
|
|
88
|
+
lines.push(...blockDefs);
|
|
89
|
+
lines.push('}');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
lines.push('export const customBlocks = {}');
|
|
93
|
+
}
|
|
94
|
+
lines.push('');
|
|
95
|
+
// Export SPA config
|
|
96
|
+
if (spa.configPath) {
|
|
97
|
+
lines.push('export { spaConfig }');
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
lines.push('export const spaConfig = null');
|
|
101
|
+
}
|
|
102
|
+
lines.push('');
|
|
103
|
+
// Export command schemas (for form validation)
|
|
104
|
+
const schemasPath = relative(resolve(cwd, '.manta', 'spa', spa.name), resolve(cwd, '.manta', 'command-schemas')).replace(/\\/g, '/');
|
|
105
|
+
lines.push(`export { commandSchemas } from '${schemasPath}'`);
|
|
106
|
+
lines.push('');
|
|
107
|
+
return lines.join('\n');
|
|
108
|
+
}
|
|
109
|
+
function generateEntry(spa, cwd, _outDir, dashboard, preset) {
|
|
110
|
+
// When @mantajs/dashboard is the dashboard shell, generate an entry that uses MantaDashboard
|
|
111
|
+
// which provides the full admin shell (sidebar, auth, registry, etc.)
|
|
112
|
+
if (dashboard === '@mantajs/dashboard') {
|
|
113
|
+
// Resolve the CSS path relative to the generated entry file
|
|
114
|
+
let cssImport = '// @mantajs/dashboard CSS not found';
|
|
115
|
+
try {
|
|
116
|
+
const pkgDir = dirname(require.resolve('@mantajs/dashboard/package.json', { paths: [cwd] }));
|
|
117
|
+
const distCss = join(pkgDir, 'dist', 'index.css');
|
|
118
|
+
const cssPath = (existsSync(distCss) ? distCss : join(pkgDir, 'src', 'index.css')).replace(/\\/g, '/');
|
|
119
|
+
cssImport = `import '${cssPath}'`;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
/* not found */
|
|
123
|
+
}
|
|
124
|
+
const lines = [
|
|
125
|
+
'// Auto-generated — do not edit',
|
|
126
|
+
"import { Suspense } from 'react'",
|
|
127
|
+
"import { createRoot } from 'react-dom/client'",
|
|
128
|
+
"import { MantaDashboard } from '@mantajs/dashboard'",
|
|
129
|
+
"import { routes, pageSpecs, customBlocks, spaConfig, commandSchemas } from './routes'",
|
|
130
|
+
cssImport,
|
|
131
|
+
'',
|
|
132
|
+
'const apiUrl = window.location.origin',
|
|
133
|
+
'',
|
|
134
|
+
'// Convert filesystem routes to React Router route objects (wrapped in Suspense for lazy loading)',
|
|
135
|
+
'const customRoutes = routes.map((r) => ({',
|
|
136
|
+
" path: r.path === '/' ? undefined : r.path.replace(/^\\//, ''),",
|
|
137
|
+
' element: <Suspense fallback={null}><r.component /></Suspense>,',
|
|
138
|
+
'}))',
|
|
139
|
+
'',
|
|
140
|
+
"createRoot(document.getElementById('root')!).render(",
|
|
141
|
+
` <MantaDashboard apiUrl={apiUrl} basename="/${spa.name}" customRoutes={customRoutes} pageSpecs={pageSpecs} customBlocks={customBlocks} spaConfig={spaConfig} commandSchemas={commandSchemas} />,`,
|
|
142
|
+
')',
|
|
143
|
+
'',
|
|
144
|
+
];
|
|
145
|
+
return lines.join('\n');
|
|
146
|
+
}
|
|
147
|
+
// Fallback: bare BrowserRouter for custom SPAs without a dashboard shell
|
|
148
|
+
const lines = [
|
|
149
|
+
'// Auto-generated — do not edit',
|
|
150
|
+
"import React, { Suspense } from 'react'",
|
|
151
|
+
"import { createRoot } from 'react-dom/client'",
|
|
152
|
+
"import { BrowserRouter, Routes, Route } from 'react-router-dom'",
|
|
153
|
+
"import { routes } from './routes'",
|
|
154
|
+
];
|
|
155
|
+
if (preset && preset !== '@mantajs/ui') {
|
|
156
|
+
lines.push(`import '${preset}/styles.css'`);
|
|
157
|
+
}
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push('function App() {');
|
|
160
|
+
lines.push(` return (
|
|
161
|
+
<BrowserRouter basename="/${spa.name}">
|
|
162
|
+
<Suspense fallback={<div>Loading...</div>}>
|
|
163
|
+
<Routes>
|
|
164
|
+
{routes.map((r) => (
|
|
165
|
+
<Route key={r.path} path={r.path} element={<r.component />} />
|
|
166
|
+
))}
|
|
167
|
+
</Routes>
|
|
168
|
+
</Suspense>
|
|
169
|
+
</BrowserRouter>
|
|
170
|
+
)`);
|
|
171
|
+
lines.push('}');
|
|
172
|
+
lines.push('');
|
|
173
|
+
lines.push("createRoot(document.getElementById('root')!).render(<App />)");
|
|
174
|
+
lines.push('');
|
|
175
|
+
return lines.join('\n');
|
|
176
|
+
}
|
|
177
|
+
function generateHtml(spa) {
|
|
178
|
+
return `<!DOCTYPE html>
|
|
179
|
+
<html lang="en">
|
|
180
|
+
<head>
|
|
181
|
+
<meta charset="UTF-8" />
|
|
182
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
183
|
+
<title>${spa.name.charAt(0).toUpperCase() + spa.name.slice(1)}</title>
|
|
184
|
+
</head>
|
|
185
|
+
<body>
|
|
186
|
+
<div id="root"></div>
|
|
187
|
+
<script type="module" src="./entry.tsx"></script>
|
|
188
|
+
</body>
|
|
189
|
+
</html>
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
function generateViteConfig(spa, cwd, outDir, dashboard, _preset, port = 3000) {
|
|
193
|
+
const lines = [
|
|
194
|
+
`import { defineConfig } from 'vite'`,
|
|
195
|
+
`import react from '@vitejs/plugin-react'`,
|
|
196
|
+
`import tailwindcss from '@tailwindcss/vite'`,
|
|
197
|
+
'',
|
|
198
|
+
`export default defineConfig({`,
|
|
199
|
+
` root: '${outDir.replace(/\\/g, '/')}',`,
|
|
200
|
+
` base: '/${spa.name}/',`,
|
|
201
|
+
` appType: 'spa',`,
|
|
202
|
+
` plugins: [`,
|
|
203
|
+
` react(),`,
|
|
204
|
+
` tailwindcss(),`,
|
|
205
|
+
` {`,
|
|
206
|
+
` name: 'manta-trailing-slash',`,
|
|
207
|
+
` configureServer(server) {`,
|
|
208
|
+
` server.middlewares.use((req, _res, next) => {`,
|
|
209
|
+
` if (req.url === '/${spa.name}') req.url = '/${spa.name}/'`,
|
|
210
|
+
` next()`,
|
|
211
|
+
` })`,
|
|
212
|
+
` },`,
|
|
213
|
+
` },`,
|
|
214
|
+
` ],`,
|
|
215
|
+
` server: {`,
|
|
216
|
+
` hmr: true,`,
|
|
217
|
+
` strictPort: true,`,
|
|
218
|
+
` proxy: {`,
|
|
219
|
+
` '/api': {`,
|
|
220
|
+
` target: 'http://localhost:${port}',`,
|
|
221
|
+
` changeOrigin: true,`,
|
|
222
|
+
` },`,
|
|
223
|
+
` },`,
|
|
224
|
+
` },`,
|
|
225
|
+
` build: {`,
|
|
226
|
+
` outDir: '${resolve(cwd, 'public', spa.name).replace(/\\/g, '/')}',`,
|
|
227
|
+
` emptyOutDir: true,`,
|
|
228
|
+
` },`,
|
|
229
|
+
` resolve: {`,
|
|
230
|
+
` preserveSymlinks: true,`,
|
|
231
|
+
` alias: {`,
|
|
232
|
+
` '~spa': '${spa.path.replace(/\\/g, '/')}',`,
|
|
233
|
+
];
|
|
234
|
+
// Deduplicate React — monorepo packages may resolve different copies
|
|
235
|
+
// Point to the package directory so sub-path imports (react/jsx-runtime) still work
|
|
236
|
+
for (const reactPkg of ['react', 'react-dom']) {
|
|
237
|
+
try {
|
|
238
|
+
const pkgDir = dirname(require.resolve(`${reactPkg}/package.json`, { paths: [cwd] })).replace(/\\/g, '/');
|
|
239
|
+
lines.push(` '${reactPkg}': '${pkgDir}',`);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
/* not found */
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// App pages often import peer UI deps directly. In a pnpm workspace those
|
|
246
|
+
// deps may live under a Manta package node_modules rather than the app root.
|
|
247
|
+
const depResolvePaths = [cwd];
|
|
248
|
+
const addDepResolvePath = (path) => {
|
|
249
|
+
if (!depResolvePaths.includes(path))
|
|
250
|
+
depResolvePaths.push(path);
|
|
251
|
+
};
|
|
252
|
+
try {
|
|
253
|
+
addDepResolvePath(dirname(require.resolve('@mantajs/dashboard/package.json', { paths: [cwd] })));
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
/* not found */
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
const uiDir = dirname(require.resolve('@mantajs/ui/package.json', { paths: [cwd] }));
|
|
260
|
+
addDepResolvePath(uiDir);
|
|
261
|
+
addDepResolvePath(resolve(dirname(require.resolve('radix-ui', { paths: [uiDir] })), '..'));
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
/* not found */
|
|
265
|
+
}
|
|
266
|
+
const directPeerDeps = [
|
|
267
|
+
'@ai-sdk/react',
|
|
268
|
+
'@date-fns/tz',
|
|
269
|
+
'@hookform/resolvers',
|
|
270
|
+
'@tanstack/react-query',
|
|
271
|
+
'@tanstack/react-table',
|
|
272
|
+
'lucide-react',
|
|
273
|
+
'zod',
|
|
274
|
+
'react-router-dom',
|
|
275
|
+
'recharts',
|
|
276
|
+
'react-hook-form',
|
|
277
|
+
'react-helmet-async',
|
|
278
|
+
'motion',
|
|
279
|
+
'motion/react',
|
|
280
|
+
'radix-ui',
|
|
281
|
+
'react-day-picker',
|
|
282
|
+
'date-fns',
|
|
283
|
+
'cmdk',
|
|
284
|
+
'class-variance-authority',
|
|
285
|
+
'clsx',
|
|
286
|
+
'tailwind-merge',
|
|
287
|
+
'sonner',
|
|
288
|
+
'@radix-ui/react-slot',
|
|
289
|
+
'@radix-ui/react-checkbox',
|
|
290
|
+
'@radix-ui/react-dialog',
|
|
291
|
+
'@radix-ui/react-popover',
|
|
292
|
+
'@radix-ui/react-progress',
|
|
293
|
+
'@radix-ui/react-radio-group',
|
|
294
|
+
'@radix-ui/react-scroll-area',
|
|
295
|
+
'@radix-ui/react-select',
|
|
296
|
+
'@radix-ui/react-switch',
|
|
297
|
+
'@radix-ui/react-tabs',
|
|
298
|
+
];
|
|
299
|
+
for (const depPkg of directPeerDeps) {
|
|
300
|
+
try {
|
|
301
|
+
let resolved = '';
|
|
302
|
+
let packageDir = '';
|
|
303
|
+
try {
|
|
304
|
+
packageDir = dirname(require.resolve(`${depPkg}/package.json`, { paths: depResolvePaths }));
|
|
305
|
+
resolved = packageDir;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
resolved = require.resolve(depPkg, { paths: depResolvePaths });
|
|
309
|
+
packageDir = dirname(resolved);
|
|
310
|
+
}
|
|
311
|
+
addDepResolvePath(packageDir);
|
|
312
|
+
lines.push(` '${depPkg}': '${resolved.replace(/\\/g, '/')}',`);
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
/* not found */
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Resolve Manta packages for Vite alias
|
|
319
|
+
const pkgsToResolve = ['@mantajs/sdk', '@mantajs/ui'];
|
|
320
|
+
if (dashboard)
|
|
321
|
+
pkgsToResolve.push(dashboard);
|
|
322
|
+
for (const pkg of pkgsToResolve) {
|
|
323
|
+
try {
|
|
324
|
+
const pkgDir = dirname(require.resolve(`${pkg}/package.json`, { paths: [cwd] }));
|
|
325
|
+
const distDir = join(pkgDir, 'dist');
|
|
326
|
+
const sourceDir = existsSync(distDir) ? distDir : join(pkgDir, 'src');
|
|
327
|
+
const hasDist = sourceDir === distDir;
|
|
328
|
+
const hasTsx = existsSync(join(pkgDir, 'src', 'index.tsx'));
|
|
329
|
+
const entryFile = hasDist ? 'dist/index.js' : hasTsx ? 'src/index.tsx' : 'src/index.ts';
|
|
330
|
+
// Exact import → entry file, sub-path imports (e.g. /index.css) → package source/build directory
|
|
331
|
+
lines.push(` '${pkg}': '${join(pkgDir, entryFile).replace(/\\/g, '/')}',`);
|
|
332
|
+
lines.push(` '${pkg}/': '${sourceDir.replace(/\\/g, '/')}/',`);
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Not resolved — let Vite handle it
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
lines.push(` },`);
|
|
339
|
+
lines.push(` },`);
|
|
340
|
+
lines.push(`})`);
|
|
341
|
+
return lines.join('\n');
|
|
342
|
+
}
|
|
343
|
+
function routeToVarName(route) {
|
|
344
|
+
if (route === '/')
|
|
345
|
+
return 'PageHome';
|
|
346
|
+
return ('Page' +
|
|
347
|
+
route
|
|
348
|
+
.split('/')
|
|
349
|
+
.filter(Boolean)
|
|
350
|
+
.map((s) => s
|
|
351
|
+
.replace(/^:/, '')
|
|
352
|
+
.split('-')
|
|
353
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
354
|
+
.join(''))
|
|
355
|
+
.join(''));
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=generate-spa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-spa.js","sourceRoot":"","sources":["../../src/spa/generate-spa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Manta + Next.js — AI Agent Instructions
|
|
2
|
+
|
|
3
|
+
You are working in a **Next.js App Router project with Manta mounted inline**. The frontend is Next.js (React 19, App Router, TypeScript). The backend is Manta — a filesystem-first framework with integrated database, CQRS, auth, and admin dashboard. **They run in the same process**: Next owns the HTTP server; Manta lives inside a catch-all route handler.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
- **Runtime**: Next.js 15 App Router
|
|
8
|
+
- **Backend**: Manta (auto-discovered from `src/modules/`, `src/commands/`, `src/queries/`, …)
|
|
9
|
+
- **Database**: PostgreSQL (managed by Manta through its adapters)
|
|
10
|
+
- **API**: Auto-generated from Manta commands, queries, auth, and the query graph
|
|
11
|
+
- **Admin**: `@mantajs/dashboard` mounted as a Next client component (no separate Vite server)
|
|
12
|
+
|
|
13
|
+
## How they are wired together
|
|
14
|
+
|
|
15
|
+
The entire integration is 3 files in the Next project:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// next.config.ts
|
|
19
|
+
import { withManta } from '@mantajs/adapter-nextjs'
|
|
20
|
+
export default withManta({})
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// app/api/[...manta]/route.ts
|
|
25
|
+
export { GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD } from '@mantajs/adapter-nextjs/handler'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// app/admin/[[...slug]]/page.tsx
|
|
30
|
+
export { default } from '@mantajs/adapter-nextjs/admin'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- The API catch-all forwards every `/api/*` request to Manta's internal HTTP pipeline. All Manta-generated routes (commands, queries, graph, auth, openapi) are reachable this way.
|
|
34
|
+
- The admin catch-all mounts the Manta dashboard as a client component. Next bundles `@mantajs/dashboard` itself via `transpilePackages` (configured by `withManta`). `react-router-dom` inside the dashboard handles sub-routes.
|
|
35
|
+
- `withManta()` sets `transpilePackages` + `serverExternalPackages` so the raw-TS `@mantajs/*` workspace packages and native deps (postgres, pino, drizzle-orm) play nice with Next.
|
|
36
|
+
|
|
37
|
+
## Project layout
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
my-app/
|
|
41
|
+
├── app/ Next.js App Router (frontend + API mount points)
|
|
42
|
+
│ ├── layout.tsx
|
|
43
|
+
│ ├── page.tsx your public home
|
|
44
|
+
│ ├── api/[...manta]/route.ts 1 line: re-export from @mantajs/adapter-nextjs/handler
|
|
45
|
+
│ ├── admin/[[...slug]]/page.tsx 1 line: re-export from @mantajs/adapter-nextjs/admin
|
|
46
|
+
│ └── (your other Next pages)
|
|
47
|
+
│
|
|
48
|
+
├── lib/ shared client-side code (hooks, utilities, types)
|
|
49
|
+
│
|
|
50
|
+
├── src/ Manta backend (filesystem-first, auto-discovered)
|
|
51
|
+
│ ├── modules/{mod}/entities/{entity}/{model,service}.ts
|
|
52
|
+
│ ├── commands/{context}/{name}.ts
|
|
53
|
+
│ ├── queries/{context}/{name,graph}.ts
|
|
54
|
+
│ ├── subscribers/{name}.ts
|
|
55
|
+
│ ├── jobs/{name}.ts
|
|
56
|
+
│ ├── links/{name}.ts
|
|
57
|
+
│ ├── agents/{name}.ts
|
|
58
|
+
│ └── middleware/{context}.ts
|
|
59
|
+
│
|
|
60
|
+
├── manta.config.ts defineConfig — database, ports, presets
|
|
61
|
+
├── next.config.ts withManta({})
|
|
62
|
+
├── tsconfig.json
|
|
63
|
+
└── AGENT.md this file
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Development workflow
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pnpm dev # runs next dev — that's it. No separate Manta process.
|
|
70
|
+
pnpm generate # regenerate .manta/generated.d.ts (types for defineModel, field, etc.)
|
|
71
|
+
pnpm db:generate # create SQL migration from model changes
|
|
72
|
+
pnpm db:migrate # apply migrations to the database
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Manta boots lazily inside the Next.js server on the first API request (singleton pattern in `@mantajs/adapter-nextjs/bootstrap`). Subsequent requests reuse the cached app. Hot reload works normally — Next reloads on file changes, and Manta re-boots on module edits.
|
|
76
|
+
|
|
77
|
+
## Consuming Manta from Next
|
|
78
|
+
|
|
79
|
+
### From client components (most common)
|
|
80
|
+
|
|
81
|
+
Use `@mantajs/sdk` hooks — they call the relative `/api/*` endpoints via `fetch`:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
'use client'
|
|
85
|
+
import { useQuery, useCommand, useGraphQuery } from '@mantajs/sdk'
|
|
86
|
+
|
|
87
|
+
const { data } = useQuery('list-products', { status: 'active' })
|
|
88
|
+
const createProduct = useCommand('create-product')
|
|
89
|
+
const { data: products } = useGraphQuery({ entity: 'product', relations: ['inventory_item'] })
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### From React Server Components
|
|
93
|
+
|
|
94
|
+
Two options:
|
|
95
|
+
|
|
96
|
+
1. **HTTP round-trip** (simplest): `fetch('/api/public/my-query', ...)` from the RSC. Works everywhere, no singleton coupling.
|
|
97
|
+
2. **Direct app access** (zero-latency): import `getMantaApp` from `@mantajs/adapter-nextjs` and call `app.queryService.graph(...)` / `app.commandRegistry.execute(...)` directly. Bypasses HTTP entirely. Use when you need sub-millisecond latency for SSR.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// app/products/page.tsx — RSC
|
|
101
|
+
import { getMantaApp } from '@mantajs/adapter-nextjs'
|
|
102
|
+
|
|
103
|
+
export default async function ProductsPage() {
|
|
104
|
+
const app = await getMantaApp()
|
|
105
|
+
const products = await app.queryService.graph({ entity: 'product', pagination: { take: 20 } })
|
|
106
|
+
return <ProductList products={products} />
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### From Next API routes (for frontend-specific endpoints)
|
|
111
|
+
|
|
112
|
+
Don't. If you need a new endpoint, create a `defineCommand` or `defineQuery` in `src/`. The only Next API route you should own is the `[...manta]` catch-all. This keeps auth, validation, and auto-docs uniform.
|
|
113
|
+
|
|
114
|
+
## Critical rules
|
|
115
|
+
|
|
116
|
+
1. **No Next API routes beyond the catch-all** — Commands and queries ARE the API. Every endpoint goes through `src/commands/` or `src/queries/`. The `/api/[...manta]` catch-all covers everything.
|
|
117
|
+
2. **`app/` is for pages only** (including RSC and client components). Backend logic lives in `src/`.
|
|
118
|
+
3. **`src/spa/admin/pages/` is NOT used in the Next preset** — unlike the Nitro preset, where it feeds a Vite-built SPA. Custom admin pages in Next are inserted via `<MantaDashboard pageSpecs={...} customBlocks={...}>` props if you need them. For most projects the auto-generated dashboard is enough.
|
|
119
|
+
4. **Always use `@mantajs/sdk` hooks in client components** — never hand-roll `fetch('/api/...')`. The SDK handles auth tokens, error normalisation, and React Query integration.
|
|
120
|
+
5. **RSC → `getMantaApp()` path is optional** — prefer it for SSR data fetching, but `fetch('/api/...')` also works and is simpler for static rendering.
|
|
121
|
+
6. **Manta rules still apply** — the 14 primitives below (`defineModel`, `defineCommand`, `defineQuery`, `defineWorkflow`, …) govern the backend exactly as in a standalone Manta project. Entity names PascalCase, 1 entity = 1 service, compensation automatic, etc.
|
|
122
|
+
|
|
123
|
+
## Deployment
|
|
124
|
+
|
|
125
|
+
Manta-on-Next is a normal Next app. Deploy to Vercel, Node servers, or any runtime that supports Next 15 + server functions. Make sure `DATABASE_URL` is set in the environment. Manta's cold-start overhead is ~100-200ms on first request (singleton bootstrap).
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
_The sections below are the canonical Manta primitives reference. Everything after this line is identical to the standalone Manta AGENT.md and applies to the `src/` backend in this project._
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Manta + Nuxt — AI Agent Instructions
|
|
2
|
+
|
|
3
|
+
You are working in a **Nuxt project with Manta backend**. The frontend is Nuxt (Vue, auto-imports). The backend is Manta — a tool-first runtime for AI agents with an integrated database.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
|
|
7
|
+
- **Frontend**: Nuxt 3 (Vue 3, auto-imports, Nitro server)
|
|
8
|
+
- **Backend**: Manta (CQRS commands, DML models, compensable workflows)
|
|
9
|
+
- **Database**: PostgreSQL (managed by Manta)
|
|
10
|
+
- **API**: Auto-generated from Manta commands and contexts
|
|
11
|
+
|
|
12
|
+
## How they connect
|
|
13
|
+
|
|
14
|
+
Nuxt calls Manta's auto-generated API endpoints via `$fetch` or `useFetch`:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// In a Nuxt page or composable:
|
|
18
|
+
const { data: posts } = await useFetch('http://localhost:9000/api/store/query/blog', {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
body: { filters: { status: 'published' }, limit: 10 },
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// Execute a command:
|
|
24
|
+
const result = await $fetch('http://localhost:9000/api/admin/command/create-post', {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
27
|
+
body: { title: 'Hello World', slug: 'hello-world', content: '...' },
|
|
28
|
+
})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Manta backend structure
|
|
32
|
+
|
|
33
|
+
The Manta backend lives alongside Nuxt:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
my-app/
|
|
37
|
+
├── pages/ # Nuxt pages (frontend)
|
|
38
|
+
├── components/ # Nuxt components
|
|
39
|
+
├── composables/ # Nuxt composables
|
|
40
|
+
├── server/ # Nuxt server routes (if needed)
|
|
41
|
+
├── src/ # Manta backend
|
|
42
|
+
│ ├── modules/
|
|
43
|
+
│ │ └── blog/
|
|
44
|
+
│ │ ├── entities/
|
|
45
|
+
│ │ │ └── post/
|
|
46
|
+
│ │ │ ├── model.ts
|
|
47
|
+
│ │ │ └── service.ts
|
|
48
|
+
│ │ └── index.ts
|
|
49
|
+
│ ├── commands/
|
|
50
|
+
│ ├── subscribers/
|
|
51
|
+
│ ├── jobs/
|
|
52
|
+
│ ├── links/
|
|
53
|
+
│ └── contexts/
|
|
54
|
+
├── manta.config.ts # Manta configuration
|
|
55
|
+
├── nuxt.config.ts # Nuxt configuration
|
|
56
|
+
└── AGENT.md # This file
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Manta backend rules
|
|
60
|
+
|
|
61
|
+
Same rules as standalone Manta. See documentation links below.
|
|
62
|
+
|
|
63
|
+
### The 8 primitives
|
|
64
|
+
|
|
65
|
+
| Function | Purpose | Location |
|
|
66
|
+
|----------|---------|----------|
|
|
67
|
+
| `defineModel()` | Data entity schema | `src/modules/{mod}/entities/{entity}/model.ts` |
|
|
68
|
+
| `defineService()` | Mutations with compensation | `src/modules/{mod}/entities/{entity}/service.ts` |
|
|
69
|
+
| `defineCommand()` | Workflow entry point | `src/commands/{name}.ts` |
|
|
70
|
+
| `defineSubscriber()` | Event reaction | `src/subscribers/{name}.ts` |
|
|
71
|
+
| `defineJob()` | Cron task | `src/jobs/{name}.ts` |
|
|
72
|
+
| `defineLink()` | Cross-module relation | `src/links/{name}.ts` |
|
|
73
|
+
| `defineContext()` | API surface | `src/contexts/{name}.ts` |
|
|
74
|
+
| `defineConfig()` | Configuration | `manta.config.ts` |
|
|
75
|
+
|
|
76
|
+
### Critical rules
|
|
77
|
+
|
|
78
|
+
1. **No API routes in Manta** — Commands are the API. Use Nuxt `server/` routes only for frontend-specific needs.
|
|
79
|
+
2. **1 entity = 1 service** — `model.ts` + `service.ts` per entity.
|
|
80
|
+
3. **Compensation is mandatory** in `service.method()`.
|
|
81
|
+
4. **Use `step.service.*` in commands**.
|
|
82
|
+
5. **Entity names are PascalCase**.
|
|
83
|
+
|
|
84
|
+
## Running both
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Terminal 1: Manta backend
|
|
88
|
+
manta dev
|
|
89
|
+
|
|
90
|
+
# Terminal 2: Nuxt frontend
|
|
91
|
+
nuxt dev
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
|
|
96
|
+
Complete Manta documentation in `node_modules/@mantajs/core/docs/` — see [00-overview.md](node_modules/@mantajs/core/docs/00-overview.md) to start.
|
|
97
|
+
|
|
98
|
+
**Read the relevant doc BEFORE writing Manta backend code.**
|