@polymorphism-tech/morph-spec 9.6.0 → 9.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/morph-spec.js +12 -5
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents.json +3 -3
- package/framework/docs/CLI.md +35 -7
- package/framework/evals/review-checklist.md +2 -2
- package/framework/hooks/claude-code/__pycache__/statusline.cpython-313.pyc +0 -0
- package/framework/hooks/claude-code/core/README.md +4 -0
- package/framework/hooks/claude-code/core/test-budget.js +89 -0
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/heavy-command.js +60 -1
- package/framework/hooks/shared/host-services.js +433 -0
- package/framework/schemas/config.schema.json +53 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-machine/SKILL.md +1 -1
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +2 -2
- package/framework/skills/core/morph-review/SKILL.md +3 -2
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +2 -1
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +14 -1
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +47 -24
- package/src/commands/observability/cost.js +12 -0
- package/src/commands/project/worktree.js +7 -3
- package/src/commands/state/advance.js +3 -0
- package/src/commands/state/create.js +3 -3
- package/src/commands/state/delete.js +1 -1
- package/src/commands/state/finish.js +3 -1
- package/src/commands/validation/plan-check.js +1 -0
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/e2e/stack-teardown.js +19 -4
- package/src/lib/review-reports.js +21 -10
- package/src/lib/tasks/test-runner.js +3 -0
- package/src/lib/telemetry/metrics.js +47 -3
- package/src/lib/validators/packages/package-validator.js +2 -2
- package/src/utils/agents-installer.js +4 -1
- package/src/utils/file-copier.js +26 -4
- package/src/utils/hooks-installer.js +4 -4
- package/framework/templates/.idea/morph-templates.xml +0 -92
- package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
-- TEMPLATE: pgvector-embeddings-migration.sql
|
|
2
|
-
-- PURPOSE: Creates the kb_embeddings table for custom RAG — chunk storage with pgvector.
|
|
3
|
-
-- READS STANDARD: ai-agents-rag-custom-pgvector
|
|
4
|
-
-- PLACEHOLDERS:
|
|
5
|
-
-- {{SCHEMA}} — target schema (default: public)
|
|
6
|
-
-- LAST-VERIFIED: 2026-05-19
|
|
7
|
-
--
|
|
8
|
-
-- PREREQUISITES:
|
|
9
|
-
-- - pgvector extension enabled in Neon (see infrastructure-neon-pgvector).
|
|
10
|
-
-- - NpgsqlDataSourceBuilder.UseVector() called in the project's DB setup.
|
|
11
|
-
--
|
|
12
|
-
-- DIMENSION NOTE:
|
|
13
|
-
-- embedding vector(1536) matches text-embedding-3-small (default 1536 dimensions).
|
|
14
|
-
-- If the project uses a different embedding model, adjust the dimension to match.
|
|
15
|
-
-- NEVER mix embedding models on a single column — vectors live in different spaces.
|
|
16
|
-
|
|
17
|
-
-- ============================================================
|
|
18
|
-
-- 1. EXTENSION
|
|
19
|
-
-- ============================================================
|
|
20
|
-
|
|
21
|
-
CREATE EXTENSION IF NOT EXISTS vector;
|
|
22
|
-
|
|
23
|
-
-- ============================================================
|
|
24
|
-
-- 2. TABLE
|
|
25
|
-
-- ============================================================
|
|
26
|
-
|
|
27
|
-
CREATE TABLE {{SCHEMA}}.kb_embeddings (
|
|
28
|
-
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
29
|
-
tenant_id uuid NOT NULL,
|
|
30
|
-
source text NOT NULL, -- document identifier or source URL
|
|
31
|
-
chunk_index int NOT NULL, -- position of this chunk within the source document
|
|
32
|
-
content text NOT NULL, -- chunk text returned to the agent as context
|
|
33
|
-
embedding vector(1536) NOT NULL, -- vector dimension must match embedding model
|
|
34
|
-
metadata jsonb NOT NULL DEFAULT '{}',
|
|
35
|
-
created_at timestamptz NOT NULL DEFAULT now()
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
COMMENT ON TABLE {{SCHEMA}}.kb_embeddings IS 'RAG knowledge base — chunk text and pgvector embeddings for semantic search.';
|
|
39
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.tenant_id IS 'Tenant partition. Every query MUST filter on this column. Never query across tenants.';
|
|
40
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.source IS 'Document identifier or URL. Used for citation and re-indexing detection.';
|
|
41
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.chunk_index IS 'Zero-based position of this chunk within the source document.';
|
|
42
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.content IS 'Chunk text returned to the agent. Plain text, no markup.';
|
|
43
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.embedding IS 'Float vector. Dimension MUST match the embedding model declared in model-registry.json.';
|
|
44
|
-
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.metadata IS 'Arbitrary JSON metadata (section headers, page numbers, doc type, etc.). Used for filtering.';
|
|
45
|
-
|
|
46
|
-
-- ============================================================
|
|
47
|
-
-- 3. INDEXES
|
|
48
|
-
-- ============================================================
|
|
49
|
-
|
|
50
|
-
-- HNSW index for cosine similarity — production-grade recall, no training data required.
|
|
51
|
-
-- vector_cosine_ops: use <=> operator (cosine distance, ascending = most similar first).
|
|
52
|
-
-- m=16, ef_construction=64 are pgvector defaults. Tune per infrastructure-neon-pgvector §HNSW Parameters.
|
|
53
|
-
CREATE INDEX ix_kb_embeddings_hnsw
|
|
54
|
-
ON {{SCHEMA}}.kb_embeddings
|
|
55
|
-
USING hnsw (embedding vector_cosine_ops)
|
|
56
|
-
WITH (m = 16, ef_construction = 64);
|
|
57
|
-
|
|
58
|
-
-- Index for the mandatory tenant_id filter (applied in every search query).
|
|
59
|
-
CREATE INDEX ix_kb_embeddings_tenant
|
|
60
|
-
ON {{SCHEMA}}.kb_embeddings (tenant_id);
|
|
61
|
-
|
|
62
|
-
-- Composite index for source-level operations (re-indexing, deletion by document).
|
|
63
|
-
CREATE INDEX ix_kb_embeddings_source
|
|
64
|
-
ON {{SCHEMA}}.kb_embeddings (tenant_id, source);
|
|
65
|
-
|
|
66
|
-
-- ============================================================
|
|
67
|
-
-- 4. ROW-LEVEL SECURITY (multi-tenant)
|
|
68
|
-
-- ============================================================
|
|
69
|
-
|
|
70
|
-
-- RLS enforces tenant isolation at the database level as a second line of defence.
|
|
71
|
-
-- The application already filters on tenant_id in every query; RLS is the backstop.
|
|
72
|
-
--
|
|
73
|
-
-- See templates/code/sql/postgresql-rls-policy.sql for the policy pattern that
|
|
74
|
-
-- binds app.current_tenant_id (a session-level setting) to the RLS policy.
|
|
75
|
-
--
|
|
76
|
-
-- Uncomment and adapt once RLS is wired in the project:
|
|
77
|
-
--
|
|
78
|
-
-- ALTER TABLE {{SCHEMA}}.kb_embeddings ENABLE ROW LEVEL SECURITY;
|
|
79
|
-
--
|
|
80
|
-
-- CREATE POLICY kb_embeddings_tenant_isolation
|
|
81
|
-
-- ON {{SCHEMA}}.kb_embeddings
|
|
82
|
-
-- USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
|
|
83
|
-
|
|
84
|
-
-- ============================================================
|
|
85
|
-
-- ROLLBACK
|
|
86
|
-
-- ============================================================
|
|
87
|
-
|
|
88
|
-
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_hnsw;
|
|
89
|
-
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_tenant;
|
|
90
|
-
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_source;
|
|
91
|
-
-- DROP TABLE IF EXISTS {{SCHEMA}}.kb_embeddings CASCADE;
|
|
1
|
+
-- TEMPLATE: pgvector-embeddings-migration.sql
|
|
2
|
+
-- PURPOSE: Creates the kb_embeddings table for custom RAG — chunk storage with pgvector.
|
|
3
|
+
-- READS STANDARD: ai-agents-rag-custom-pgvector
|
|
4
|
+
-- PLACEHOLDERS:
|
|
5
|
+
-- {{SCHEMA}} — target schema (default: public)
|
|
6
|
+
-- LAST-VERIFIED: 2026-05-19
|
|
7
|
+
--
|
|
8
|
+
-- PREREQUISITES:
|
|
9
|
+
-- - pgvector extension enabled in Neon (see infrastructure-neon-pgvector).
|
|
10
|
+
-- - NpgsqlDataSourceBuilder.UseVector() called in the project's DB setup.
|
|
11
|
+
--
|
|
12
|
+
-- DIMENSION NOTE:
|
|
13
|
+
-- embedding vector(1536) matches text-embedding-3-small (default 1536 dimensions).
|
|
14
|
+
-- If the project uses a different embedding model, adjust the dimension to match.
|
|
15
|
+
-- NEVER mix embedding models on a single column — vectors live in different spaces.
|
|
16
|
+
|
|
17
|
+
-- ============================================================
|
|
18
|
+
-- 1. EXTENSION
|
|
19
|
+
-- ============================================================
|
|
20
|
+
|
|
21
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
22
|
+
|
|
23
|
+
-- ============================================================
|
|
24
|
+
-- 2. TABLE
|
|
25
|
+
-- ============================================================
|
|
26
|
+
|
|
27
|
+
CREATE TABLE {{SCHEMA}}.kb_embeddings (
|
|
28
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
29
|
+
tenant_id uuid NOT NULL,
|
|
30
|
+
source text NOT NULL, -- document identifier or source URL
|
|
31
|
+
chunk_index int NOT NULL, -- position of this chunk within the source document
|
|
32
|
+
content text NOT NULL, -- chunk text returned to the agent as context
|
|
33
|
+
embedding vector(1536) NOT NULL, -- vector dimension must match embedding model
|
|
34
|
+
metadata jsonb NOT NULL DEFAULT '{}',
|
|
35
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
COMMENT ON TABLE {{SCHEMA}}.kb_embeddings IS 'RAG knowledge base — chunk text and pgvector embeddings for semantic search.';
|
|
39
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.tenant_id IS 'Tenant partition. Every query MUST filter on this column. Never query across tenants.';
|
|
40
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.source IS 'Document identifier or URL. Used for citation and re-indexing detection.';
|
|
41
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.chunk_index IS 'Zero-based position of this chunk within the source document.';
|
|
42
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.content IS 'Chunk text returned to the agent. Plain text, no markup.';
|
|
43
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.embedding IS 'Float vector. Dimension MUST match the embedding model declared in model-registry.json.';
|
|
44
|
+
COMMENT ON COLUMN {{SCHEMA}}.kb_embeddings.metadata IS 'Arbitrary JSON metadata (section headers, page numbers, doc type, etc.). Used for filtering.';
|
|
45
|
+
|
|
46
|
+
-- ============================================================
|
|
47
|
+
-- 3. INDEXES
|
|
48
|
+
-- ============================================================
|
|
49
|
+
|
|
50
|
+
-- HNSW index for cosine similarity — production-grade recall, no training data required.
|
|
51
|
+
-- vector_cosine_ops: use <=> operator (cosine distance, ascending = most similar first).
|
|
52
|
+
-- m=16, ef_construction=64 are pgvector defaults. Tune per infrastructure-neon-pgvector §HNSW Parameters.
|
|
53
|
+
CREATE INDEX ix_kb_embeddings_hnsw
|
|
54
|
+
ON {{SCHEMA}}.kb_embeddings
|
|
55
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
56
|
+
WITH (m = 16, ef_construction = 64);
|
|
57
|
+
|
|
58
|
+
-- Index for the mandatory tenant_id filter (applied in every search query).
|
|
59
|
+
CREATE INDEX ix_kb_embeddings_tenant
|
|
60
|
+
ON {{SCHEMA}}.kb_embeddings (tenant_id);
|
|
61
|
+
|
|
62
|
+
-- Composite index for source-level operations (re-indexing, deletion by document).
|
|
63
|
+
CREATE INDEX ix_kb_embeddings_source
|
|
64
|
+
ON {{SCHEMA}}.kb_embeddings (tenant_id, source);
|
|
65
|
+
|
|
66
|
+
-- ============================================================
|
|
67
|
+
-- 4. ROW-LEVEL SECURITY (multi-tenant)
|
|
68
|
+
-- ============================================================
|
|
69
|
+
|
|
70
|
+
-- RLS enforces tenant isolation at the database level as a second line of defence.
|
|
71
|
+
-- The application already filters on tenant_id in every query; RLS is the backstop.
|
|
72
|
+
--
|
|
73
|
+
-- See templates/code/sql/postgresql-rls-policy.sql for the policy pattern that
|
|
74
|
+
-- binds app.current_tenant_id (a session-level setting) to the RLS policy.
|
|
75
|
+
--
|
|
76
|
+
-- Uncomment and adapt once RLS is wired in the project:
|
|
77
|
+
--
|
|
78
|
+
-- ALTER TABLE {{SCHEMA}}.kb_embeddings ENABLE ROW LEVEL SECURITY;
|
|
79
|
+
--
|
|
80
|
+
-- CREATE POLICY kb_embeddings_tenant_isolation
|
|
81
|
+
-- ON {{SCHEMA}}.kb_embeddings
|
|
82
|
+
-- USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
|
|
83
|
+
|
|
84
|
+
-- ============================================================
|
|
85
|
+
-- ROLLBACK
|
|
86
|
+
-- ============================================================
|
|
87
|
+
|
|
88
|
+
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_hnsw;
|
|
89
|
+
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_tenant;
|
|
90
|
+
-- DROP INDEX IF EXISTS {{SCHEMA}}.ix_kb_embeddings_source;
|
|
91
|
+
-- DROP TABLE IF EXISTS {{SCHEMA}}.kb_embeddings CASCADE;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
// features/{{kebabCase featureName}}/components/{{kebabCase featureName}}-list.tsx
|
|
2
|
-
'use client';
|
|
3
|
-
|
|
4
|
-
import { use{{pascalCase featureName}}s } from '@/features/{{kebabCase featureName}}/hooks/use-{{kebabCase featureName}}s';
|
|
5
|
-
import { DataTable } from '@/components/data-table';
|
|
6
|
-
import type { {{pascalCase featureName}} } from '@/features/{{kebabCase featureName}}/types/{{kebabCase featureName}}.types';
|
|
7
|
-
import type { ColumnDef } from '@tanstack/react-table';
|
|
8
|
-
|
|
9
|
-
const columns: ColumnDef<{{pascalCase featureName}}>[] = [
|
|
10
|
-
{ accessorKey: 'id', header: 'ID' },
|
|
11
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
12
|
-
];
|
|
13
|
-
|
|
14
|
-
interface {{pascalCase featureName}}ListProps {
|
|
15
|
-
initialData?: {{pascalCase featureName}}[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function {{pascalCase featureName}}List({ initialData }: {{pascalCase featureName}}ListProps) {
|
|
19
|
-
const { data = initialData ?? [], isLoading } = use{{pascalCase featureName}}s();
|
|
20
|
-
|
|
21
|
-
if (isLoading) {
|
|
22
|
-
return <div className="flex items-center justify-center h-32">Loading...</div>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return <DataTable columns={columns} data={data} />;
|
|
26
|
-
}
|
|
1
|
+
// features/{{kebabCase featureName}}/components/{{kebabCase featureName}}-list.tsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import { use{{pascalCase featureName}}s } from '@/features/{{kebabCase featureName}}/hooks/use-{{kebabCase featureName}}s';
|
|
5
|
+
import { DataTable } from '@/components/data-table';
|
|
6
|
+
import type { {{pascalCase featureName}} } from '@/features/{{kebabCase featureName}}/types/{{kebabCase featureName}}.types';
|
|
7
|
+
import type { ColumnDef } from '@tanstack/react-table';
|
|
8
|
+
|
|
9
|
+
const columns: ColumnDef<{{pascalCase featureName}}>[] = [
|
|
10
|
+
{ accessorKey: 'id', header: 'ID' },
|
|
11
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
interface {{pascalCase featureName}}ListProps {
|
|
15
|
+
initialData?: {{pascalCase featureName}}[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function {{pascalCase featureName}}List({ initialData }: {{pascalCase featureName}}ListProps) {
|
|
19
|
+
const { data = initialData ?? [], isLoading } = use{{pascalCase featureName}}s();
|
|
20
|
+
|
|
21
|
+
if (isLoading) {
|
|
22
|
+
return <div className="flex items-center justify-center h-32">Loading...</div>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return <DataTable columns={columns} data={data} />;
|
|
26
|
+
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
-
"allowJs": false,
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noUncheckedIndexedAccess": true,
|
|
9
|
-
"noImplicitOverride": true,
|
|
10
|
-
"forceConsistentCasingInFileNames": true,
|
|
11
|
-
"noEmit": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"module": "esnext",
|
|
14
|
-
"moduleResolution": "bundler",
|
|
15
|
-
"resolveJsonModule": true,
|
|
16
|
-
"isolatedModules": true,
|
|
17
|
-
"jsx": "preserve",
|
|
18
|
-
"incremental": true,
|
|
19
|
-
"plugins": [{ "name": "next" }],
|
|
20
|
-
"paths": {
|
|
21
|
-
"@/*": ["./src/*"]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
25
|
-
"exclude": ["node_modules"]
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": false,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noUncheckedIndexedAccess": true,
|
|
9
|
+
"noImplicitOverride": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"module": "esnext",
|
|
14
|
+
"moduleResolution": "bundler",
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"jsx": "preserve",
|
|
18
|
+
"incremental": true,
|
|
19
|
+
"plugins": [{ "name": "next" }],
|
|
20
|
+
"paths": {
|
|
21
|
+
"@/*": ["./src/*"]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
25
|
+
"exclude": ["node_modules"]
|
|
26
|
+
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
# Multi-stage Dockerfile for Next.js Production Build
|
|
2
|
-
# Optimized for Next.js 15 with App Router
|
|
3
|
-
|
|
4
|
-
FROM node:20-alpine AS base
|
|
5
|
-
|
|
6
|
-
# Install dependencies only when needed
|
|
7
|
-
FROM base AS deps
|
|
8
|
-
RUN apk add --no-cache libc6-compat
|
|
9
|
-
WORKDIR /app
|
|
10
|
-
|
|
11
|
-
# Copy package files
|
|
12
|
-
COPY package.json package-lock.json* ./
|
|
13
|
-
RUN npm ci
|
|
14
|
-
|
|
15
|
-
# Rebuild the source code only when needed
|
|
16
|
-
FROM base AS builder
|
|
17
|
-
WORKDIR /app
|
|
18
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
19
|
-
COPY . .
|
|
20
|
-
|
|
21
|
-
# Set build-time environment variables
|
|
22
|
-
ENV NEXT_TELEMETRY_DISABLED 1
|
|
23
|
-
|
|
24
|
-
# Build Next.js application
|
|
25
|
-
RUN npm run build
|
|
26
|
-
|
|
27
|
-
# Production image, copy all the files and run next
|
|
28
|
-
FROM base AS runner
|
|
29
|
-
WORKDIR /app
|
|
30
|
-
|
|
31
|
-
ENV NODE_ENV production
|
|
32
|
-
ENV NEXT_TELEMETRY_DISABLED 1
|
|
33
|
-
|
|
34
|
-
# Create nextjs user
|
|
35
|
-
RUN addgroup --system --gid 1001 nodejs
|
|
36
|
-
RUN adduser --system --uid 1001 nextjs
|
|
37
|
-
|
|
38
|
-
# Copy built application
|
|
39
|
-
COPY --from=builder /app/public ./public
|
|
40
|
-
|
|
41
|
-
# Set the correct permission for prerender cache
|
|
42
|
-
RUN mkdir .next
|
|
43
|
-
RUN chown nextjs:nodejs .next
|
|
44
|
-
|
|
45
|
-
# Automatically leverage output traces to reduce image size
|
|
46
|
-
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
|
47
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
48
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
49
|
-
|
|
50
|
-
USER nextjs
|
|
51
|
-
|
|
52
|
-
EXPOSE 3000
|
|
53
|
-
|
|
54
|
-
ENV PORT 3000
|
|
55
|
-
ENV HOSTNAME "0.0.0.0"
|
|
56
|
-
|
|
57
|
-
# Run Next.js server
|
|
58
|
-
CMD ["node", "server.js"]
|
|
1
|
+
# Multi-stage Dockerfile for Next.js Production Build
|
|
2
|
+
# Optimized for Next.js 15 with App Router
|
|
3
|
+
|
|
4
|
+
FROM node:20-alpine AS base
|
|
5
|
+
|
|
6
|
+
# Install dependencies only when needed
|
|
7
|
+
FROM base AS deps
|
|
8
|
+
RUN apk add --no-cache libc6-compat
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
|
|
11
|
+
# Copy package files
|
|
12
|
+
COPY package.json package-lock.json* ./
|
|
13
|
+
RUN npm ci
|
|
14
|
+
|
|
15
|
+
# Rebuild the source code only when needed
|
|
16
|
+
FROM base AS builder
|
|
17
|
+
WORKDIR /app
|
|
18
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
19
|
+
COPY . .
|
|
20
|
+
|
|
21
|
+
# Set build-time environment variables
|
|
22
|
+
ENV NEXT_TELEMETRY_DISABLED 1
|
|
23
|
+
|
|
24
|
+
# Build Next.js application
|
|
25
|
+
RUN npm run build
|
|
26
|
+
|
|
27
|
+
# Production image, copy all the files and run next
|
|
28
|
+
FROM base AS runner
|
|
29
|
+
WORKDIR /app
|
|
30
|
+
|
|
31
|
+
ENV NODE_ENV production
|
|
32
|
+
ENV NEXT_TELEMETRY_DISABLED 1
|
|
33
|
+
|
|
34
|
+
# Create nextjs user
|
|
35
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
36
|
+
RUN adduser --system --uid 1001 nextjs
|
|
37
|
+
|
|
38
|
+
# Copy built application
|
|
39
|
+
COPY --from=builder /app/public ./public
|
|
40
|
+
|
|
41
|
+
# Set the correct permission for prerender cache
|
|
42
|
+
RUN mkdir .next
|
|
43
|
+
RUN chown nextjs:nodejs .next
|
|
44
|
+
|
|
45
|
+
# Automatically leverage output traces to reduce image size
|
|
46
|
+
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
|
47
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
48
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
49
|
+
|
|
50
|
+
USER nextjs
|
|
51
|
+
|
|
52
|
+
EXPOSE 3000
|
|
53
|
+
|
|
54
|
+
ENV PORT 3000
|
|
55
|
+
ENV HOSTNAME "0.0.0.0"
|
|
56
|
+
|
|
57
|
+
# Run Next.js server
|
|
58
|
+
CMD ["node", "server.js"]
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
# ============================================================
|
|
2
|
-
# Dockerfile: .NET 10 API ({{titleCase FEATURE_NAME}})
|
|
3
|
-
# Stack: Next.js + Neon + .NET API
|
|
4
|
-
# Generated by MORPH Framework
|
|
5
|
-
# ============================================================
|
|
6
|
-
|
|
7
|
-
# Stage 1: Build
|
|
8
|
-
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
|
9
|
-
WORKDIR /src
|
|
10
|
-
|
|
11
|
-
# Copy project file and restore dependencies
|
|
12
|
-
COPY *.csproj .
|
|
13
|
-
RUN dotnet restore
|
|
14
|
-
|
|
15
|
-
# Copy source code and publish
|
|
16
|
-
COPY . .
|
|
17
|
-
RUN dotnet publish -c Release -o /app/publish --no-restore
|
|
18
|
-
|
|
19
|
-
# Stage 2: Runtime
|
|
20
|
-
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
|
21
|
-
WORKDIR /app
|
|
22
|
-
|
|
23
|
-
# Copy published output
|
|
24
|
-
COPY --from=build /app/publish .
|
|
25
|
-
|
|
26
|
-
# Configuration
|
|
27
|
-
ENV ASPNETCORE_URLS=http://+:8080
|
|
28
|
-
ENV ASPNETCORE_ENVIRONMENT=Production
|
|
29
|
-
|
|
30
|
-
# Expose port
|
|
31
|
-
EXPOSE 8080
|
|
32
|
-
|
|
33
|
-
# Health check
|
|
34
|
-
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
35
|
-
CMD curl -f http://localhost:8080/health || exit 1
|
|
36
|
-
|
|
37
|
-
# Entrypoint
|
|
38
|
-
ENTRYPOINT ["dotnet", "Api.dll"]
|
|
1
|
+
# ============================================================
|
|
2
|
+
# Dockerfile: .NET 10 API ({{titleCase FEATURE_NAME}})
|
|
3
|
+
# Stack: Next.js + Neon + .NET API
|
|
4
|
+
# Generated by MORPH Framework
|
|
5
|
+
# ============================================================
|
|
6
|
+
|
|
7
|
+
# Stage 1: Build
|
|
8
|
+
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
|
9
|
+
WORKDIR /src
|
|
10
|
+
|
|
11
|
+
# Copy project file and restore dependencies
|
|
12
|
+
COPY *.csproj .
|
|
13
|
+
RUN dotnet restore
|
|
14
|
+
|
|
15
|
+
# Copy source code and publish
|
|
16
|
+
COPY . .
|
|
17
|
+
RUN dotnet publish -c Release -o /app/publish --no-restore
|
|
18
|
+
|
|
19
|
+
# Stage 2: Runtime
|
|
20
|
+
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
|
21
|
+
WORKDIR /app
|
|
22
|
+
|
|
23
|
+
# Copy published output
|
|
24
|
+
COPY --from=build /app/publish .
|
|
25
|
+
|
|
26
|
+
# Configuration
|
|
27
|
+
ENV ASPNETCORE_URLS=http://+:8080
|
|
28
|
+
ENV ASPNETCORE_ENVIRONMENT=Production
|
|
29
|
+
|
|
30
|
+
# Expose port
|
|
31
|
+
EXPOSE 8080
|
|
32
|
+
|
|
33
|
+
# Health check
|
|
34
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
35
|
+
CMD curl -f http://localhost:8080/health || exit 1
|
|
36
|
+
|
|
37
|
+
# Entrypoint
|
|
38
|
+
ENTRYPOINT ["dotnet", "Api.dll"]
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
# ============================================================
|
|
2
|
-
# Dockerfile: Next.js Frontend ({{titleCase FEATURE_NAME}})
|
|
3
|
-
# Stack: Next.js + Neon
|
|
4
|
-
# Generated by MORPH Framework
|
|
5
|
-
# Requires: output: "standalone" in next.config.ts
|
|
6
|
-
# ============================================================
|
|
7
|
-
|
|
8
|
-
# Stage 1: Install dependencies
|
|
9
|
-
FROM node:22-alpine AS deps
|
|
10
|
-
WORKDIR /app
|
|
11
|
-
COPY package.json package-lock.json ./
|
|
12
|
-
RUN npm ci --omit=dev
|
|
13
|
-
|
|
14
|
-
# Stage 2: Build application
|
|
15
|
-
FROM node:22-alpine AS builder
|
|
16
|
-
WORKDIR /app
|
|
17
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
18
|
-
COPY . .
|
|
19
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
20
|
-
RUN npm run build
|
|
21
|
-
|
|
22
|
-
# Stage 3: Production runtime
|
|
23
|
-
FROM node:22-alpine AS runner
|
|
24
|
-
WORKDIR /app
|
|
25
|
-
|
|
26
|
-
ENV NODE_ENV=production
|
|
27
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
28
|
-
|
|
29
|
-
# Create non-root user
|
|
30
|
-
RUN addgroup --system --gid 1001 nodejs && \
|
|
31
|
-
adduser --system --uid 1001 nextjs
|
|
32
|
-
|
|
33
|
-
# Copy build output
|
|
34
|
-
COPY --from=builder /app/public ./public
|
|
35
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
36
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
37
|
-
|
|
38
|
-
# Switch to non-root user
|
|
39
|
-
USER nextjs
|
|
40
|
-
|
|
41
|
-
# Expose port
|
|
42
|
-
EXPOSE 3000
|
|
43
|
-
|
|
44
|
-
ENV PORT=3000
|
|
45
|
-
ENV HOSTNAME="0.0.0.0"
|
|
46
|
-
|
|
47
|
-
# Start server
|
|
48
|
-
CMD ["node", "server.js"]
|
|
1
|
+
# ============================================================
|
|
2
|
+
# Dockerfile: Next.js Frontend ({{titleCase FEATURE_NAME}})
|
|
3
|
+
# Stack: Next.js + Neon
|
|
4
|
+
# Generated by MORPH Framework
|
|
5
|
+
# Requires: output: "standalone" in next.config.ts
|
|
6
|
+
# ============================================================
|
|
7
|
+
|
|
8
|
+
# Stage 1: Install dependencies
|
|
9
|
+
FROM node:22-alpine AS deps
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
COPY package.json package-lock.json ./
|
|
12
|
+
RUN npm ci --omit=dev
|
|
13
|
+
|
|
14
|
+
# Stage 2: Build application
|
|
15
|
+
FROM node:22-alpine AS builder
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
18
|
+
COPY . .
|
|
19
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
20
|
+
RUN npm run build
|
|
21
|
+
|
|
22
|
+
# Stage 3: Production runtime
|
|
23
|
+
FROM node:22-alpine AS runner
|
|
24
|
+
WORKDIR /app
|
|
25
|
+
|
|
26
|
+
ENV NODE_ENV=production
|
|
27
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
28
|
+
|
|
29
|
+
# Create non-root user
|
|
30
|
+
RUN addgroup --system --gid 1001 nodejs && \
|
|
31
|
+
adduser --system --uid 1001 nextjs
|
|
32
|
+
|
|
33
|
+
# Copy build output
|
|
34
|
+
COPY --from=builder /app/public ./public
|
|
35
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
36
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
37
|
+
|
|
38
|
+
# Switch to non-root user
|
|
39
|
+
USER nextjs
|
|
40
|
+
|
|
41
|
+
# Expose port
|
|
42
|
+
EXPOSE 3000
|
|
43
|
+
|
|
44
|
+
ENV PORT=3000
|
|
45
|
+
ENV HOSTNAME="0.0.0.0"
|
|
46
|
+
|
|
47
|
+
# Start server
|
|
48
|
+
CMD ["node", "server.js"]
|