@tdk-landscape/tdk-cli-core 1.3.87 → 1.3.89
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 +4 -4
- package/cli/dist/backend-frameworks/elysia.js +39 -0
- package/cli/dist/backend-frameworks/express.js +50 -0
- package/cli/dist/backend-frameworks/fastify.js +44 -0
- package/cli/dist/backend-frameworks/registry.js +45 -0
- package/cli/dist/backend-frameworks/types.js +2 -0
- package/cli/dist/backend-languages/go.js +98 -0
- package/cli/dist/backend-languages/registry.js +2 -0
- package/cli/dist/commands/resource.js +35 -8
- package/cli/dist/frontend-frameworks/lit.js +65 -0
- package/cli/dist/frontend-frameworks/preact.js +63 -0
- package/cli/dist/frontend-frameworks/qwik.js +62 -0
- package/cli/dist/frontend-frameworks/registry.js +16 -3
- package/cli/dist/frontend-frameworks/solid.js +63 -0
- package/cli/dist/frontend-frameworks/svelte.js +68 -0
- package/cli/dist/frontend-frameworks/vanilla.js +60 -0
- package/cli/dist/utils/service-manifest.js +1 -0
- package/cli/package.json +2 -2
- package/engine/schemas/service-schema.json +30 -7
- package/engine/topologies/platform/docker/compose/compose.star +9 -1
- package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +34 -3
- package/engine/topologies/platform/docker/index.star +2 -0
- package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +10 -1
- package/engine/topologies/tilt/generators/validators.star +4 -3
- package/engine/topologies/tilt/generators/vite/frameworks/lit.star +90 -0
- package/engine/topologies/tilt/generators/vite/frameworks/preact.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/qwik.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/solid.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/svelte.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/vanilla.star +90 -0
- package/engine/topologies/tilt/generators/vite/frontend.star +30 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +7 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +2 -2
- package/package.json +2 -2
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { TdkError } from "../utils/errors.js";
|
|
2
|
+
import { litFrontendProvider } from "./lit.js";
|
|
3
|
+
import { preactFrontendProvider } from "./preact.js";
|
|
4
|
+
import { qwikFrontendProvider } from "./qwik.js";
|
|
2
5
|
import { reactFrontendProvider } from "./react.js";
|
|
6
|
+
import { solidFrontendProvider } from "./solid.js";
|
|
7
|
+
import { svelteFrontendProvider } from "./svelte.js";
|
|
8
|
+
import { vanillaFrontendProvider } from "./vanilla.js";
|
|
3
9
|
import { vueFrontendProvider } from "./vue.js";
|
|
4
10
|
export const DEFAULT_FRONTEND_FRAMEWORK = "react";
|
|
5
11
|
export const FRONTEND_FRAMEWORKS = {
|
|
6
12
|
react: reactFrontendProvider,
|
|
7
13
|
vue: vueFrontendProvider,
|
|
14
|
+
svelte: svelteFrontendProvider,
|
|
15
|
+
preact: preactFrontendProvider,
|
|
16
|
+
lit: litFrontendProvider,
|
|
17
|
+
solid: solidFrontendProvider,
|
|
18
|
+
qwik: qwikFrontendProvider,
|
|
19
|
+
vanilla: vanillaFrontendProvider,
|
|
8
20
|
};
|
|
9
21
|
export function getFrontendFramework(frameworkId) {
|
|
10
22
|
const id = (frameworkId ?? DEFAULT_FRONTEND_FRAMEWORK).trim().toLowerCase();
|
|
@@ -17,9 +29,10 @@ export function getFrontendFramework(frameworkId) {
|
|
|
17
29
|
}
|
|
18
30
|
export function resolveFrontendFramework(resourceType, frameworkId) {
|
|
19
31
|
if (resourceType !== "frontend") {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
// Backends take their own framework ids (see backend-frameworks/registry.ts).
|
|
33
|
+
if (frameworkId !== undefined && resourceType !== "backend") {
|
|
34
|
+
throw new TdkError("--framework can only be used with --type frontend or --type backend.", [
|
|
35
|
+
"Add --type frontend or --type backend, or drop --framework for this resource type",
|
|
23
36
|
]);
|
|
24
37
|
}
|
|
25
38
|
return undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const solidFrontendProvider = {
|
|
2
|
+
id: "solid",
|
|
3
|
+
label: "Solid + Vite",
|
|
4
|
+
dependencies: {
|
|
5
|
+
"solid-js": "^1.9.0",
|
|
6
|
+
},
|
|
7
|
+
devDependencies: {
|
|
8
|
+
"vite-plugin-solid": "^2.11.0",
|
|
9
|
+
},
|
|
10
|
+
compilerOptions: {
|
|
11
|
+
jsx: "preserve",
|
|
12
|
+
jsxImportSource: "solid-js",
|
|
13
|
+
},
|
|
14
|
+
createFiles(name) {
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
filename: "index.html",
|
|
18
|
+
content: `<!DOCTYPE html>
|
|
19
|
+
<html lang="en">
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="UTF-8" />
|
|
22
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
23
|
+
<title>${name}</title>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div id="app"></div>
|
|
27
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
`,
|
|
31
|
+
description: "Generating HTML template",
|
|
32
|
+
emoji: "💻",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
filename: "src/main.tsx",
|
|
36
|
+
content: `import { render } from 'solid-js/web';
|
|
37
|
+
import App from './App';
|
|
38
|
+
|
|
39
|
+
render(() => <App />, document.getElementById('app')!);
|
|
40
|
+
`,
|
|
41
|
+
description: "Generating Solid entry",
|
|
42
|
+
emoji: "💻",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
filename: "src/App.tsx",
|
|
46
|
+
content: `function App() {
|
|
47
|
+
return (
|
|
48
|
+
<div style={{ padding: '2rem', 'font-family': 'system-ui' }}>
|
|
49
|
+
<h1>${name}</h1>
|
|
50
|
+
<p>Frontend resource created with TDK</p>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default App;
|
|
56
|
+
`,
|
|
57
|
+
description: "Generating Solid app",
|
|
58
|
+
emoji: "💻",
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=solid.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export const svelteFrontendProvider = {
|
|
2
|
+
id: "svelte",
|
|
3
|
+
label: "Svelte + Vite",
|
|
4
|
+
dependencies: {
|
|
5
|
+
svelte: "^5.0.0",
|
|
6
|
+
},
|
|
7
|
+
devDependencies: {
|
|
8
|
+
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
|
9
|
+
},
|
|
10
|
+
compilerOptions: {},
|
|
11
|
+
createFiles(name) {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
filename: "index.html",
|
|
15
|
+
content: `<!DOCTYPE html>
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<head>
|
|
18
|
+
<meta charset="UTF-8" />
|
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
20
|
+
<title>${name}</title>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div id="app"></div>
|
|
24
|
+
<script type="module" src="/src/main.ts"></script>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
27
|
+
`,
|
|
28
|
+
description: "Generating HTML template",
|
|
29
|
+
emoji: "💻",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
filename: "src/main.ts",
|
|
33
|
+
content: `import { mount } from 'svelte';
|
|
34
|
+
import App from './App.svelte';
|
|
35
|
+
|
|
36
|
+
const app = mount(App, { target: document.getElementById('app')! });
|
|
37
|
+
|
|
38
|
+
export default app;
|
|
39
|
+
`,
|
|
40
|
+
description: "Generating Svelte entry",
|
|
41
|
+
emoji: "💻",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
filename: "src/App.svelte",
|
|
45
|
+
content: `<script lang="ts">
|
|
46
|
+
const message: string = 'Frontend resource created with TDK';
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<main style="padding: 2rem; font-family: system-ui">
|
|
50
|
+
<h1>${name}</h1>
|
|
51
|
+
<p>{message}</p>
|
|
52
|
+
</main>
|
|
53
|
+
`,
|
|
54
|
+
description: "Generating Svelte app",
|
|
55
|
+
emoji: "💻",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
filename: "src/vite-env.d.ts",
|
|
59
|
+
content: `/// <reference types="svelte" />
|
|
60
|
+
/// <reference types="vite/client" />
|
|
61
|
+
`,
|
|
62
|
+
description: "Generating Svelte module types",
|
|
63
|
+
emoji: "⚙️",
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=svelte.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const vanillaFrontendProvider = {
|
|
2
|
+
id: "vanilla",
|
|
3
|
+
label: "Vanilla TypeScript + Vite",
|
|
4
|
+
dependencies: {},
|
|
5
|
+
devDependencies: {},
|
|
6
|
+
compilerOptions: {},
|
|
7
|
+
createFiles(name) {
|
|
8
|
+
return [
|
|
9
|
+
{
|
|
10
|
+
filename: "index.html",
|
|
11
|
+
content: `<!DOCTYPE html>
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="UTF-8" />
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
16
|
+
<title>${name}</title>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<div id="app"></div>
|
|
20
|
+
<script type="module" src="/src/main.ts"></script>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
23
|
+
`,
|
|
24
|
+
description: "Generating HTML template",
|
|
25
|
+
emoji: "💻",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
filename: "src/main.ts",
|
|
29
|
+
content: `import { renderApp } from './app';
|
|
30
|
+
|
|
31
|
+
const root = document.getElementById('app');
|
|
32
|
+
if (root) {
|
|
33
|
+
renderApp(root);
|
|
34
|
+
}
|
|
35
|
+
`,
|
|
36
|
+
description: "Generating vanilla entry",
|
|
37
|
+
emoji: "💻",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
filename: "src/app.ts",
|
|
41
|
+
content: `export function renderApp(root: HTMLElement): void {
|
|
42
|
+
root.style.padding = '2rem';
|
|
43
|
+
root.style.fontFamily = 'system-ui';
|
|
44
|
+
|
|
45
|
+
const title = document.createElement('h1');
|
|
46
|
+
title.textContent = '${name}';
|
|
47
|
+
|
|
48
|
+
const note = document.createElement('p');
|
|
49
|
+
note.textContent = 'Frontend resource created with TDK';
|
|
50
|
+
|
|
51
|
+
root.replaceChildren(title, note);
|
|
52
|
+
}
|
|
53
|
+
`,
|
|
54
|
+
description: "Generating vanilla app",
|
|
55
|
+
emoji: "💻",
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=vanilla.js.map
|
package/cli/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tdk-cli-internal",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.89",
|
|
5
5
|
"description": "TDK CLI — start services on your laptop.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tdk",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"prepack": "../scripts/stage-npm-engine.sh && npm run build"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"chalk": "^
|
|
56
|
+
"chalk": "^6.0.1",
|
|
57
57
|
"commander": "^15.0.0",
|
|
58
58
|
"handlebars": "^4.7.8",
|
|
59
59
|
"ink": "^7.1.1",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"type": "string"
|
|
108
108
|
},
|
|
109
109
|
"appType": {
|
|
110
|
-
"description": "Resource type determining build strategy:\n• backend - Hono/Express API server\n• frontend - Vite single-page application (React or
|
|
110
|
+
"description": "Resource type determining build strategy:\n• backend - Hono/Express API server\n• frontend - Vite single-page application (React, Vue, Svelte, Preact, Lit, Solid, Qwik or Vanilla TypeScript, see framework)\n• sdk - Shared library package\n• worker - Background job processor\n• migrator - Database migration runner\n• library - Shared code library\n• bring-your-own - Wrap an existing service. No app scaffold. Needs Dockerfile or --image.",
|
|
111
111
|
"enum": [
|
|
112
112
|
"backend",
|
|
113
113
|
"frontend",
|
|
@@ -153,6 +153,16 @@
|
|
|
153
153
|
"description": "Whether this bring-your-own resource receives a Traefik route. Defaults to true.",
|
|
154
154
|
"type": "boolean"
|
|
155
155
|
},
|
|
156
|
+
"restart": {
|
|
157
|
+
"description": "Docker Compose restart policy for this bring-your-own resource. Use \"no\" or \"on-failure\" for one-shot jobs such as database migrations, so a finished job is not restarted. Defaults to unless-stopped.",
|
|
158
|
+
"enum": [
|
|
159
|
+
"no",
|
|
160
|
+
"on-failure",
|
|
161
|
+
"unless-stopped",
|
|
162
|
+
"always"
|
|
163
|
+
],
|
|
164
|
+
"type": "string"
|
|
165
|
+
},
|
|
156
166
|
"image": {
|
|
157
167
|
"description": "Docker image name instead of building from Dockerfile. Optional for bring-your-own type.",
|
|
158
168
|
"type": "string"
|
|
@@ -215,19 +225,32 @@
|
|
|
215
225
|
"uniqueItems": true
|
|
216
226
|
},
|
|
217
227
|
"framework": {
|
|
218
|
-
"description": "
|
|
219
|
-
"
|
|
228
|
+
"description": "Framework provider id. For frontend resources it selects the Vite and TypeScript config (omitted means react, legacy manifests). For backend resources it selects the HTTP framework on the Bun runtime (omitted means hono; not used with a language that owns its runtime, such as python). Valid ids come from the CLI provider registries, which reject unknown ids before writing a resource.",
|
|
229
|
+
"examples": [
|
|
220
230
|
"react",
|
|
221
|
-
"vue"
|
|
231
|
+
"vue",
|
|
232
|
+
"svelte",
|
|
233
|
+
"preact",
|
|
234
|
+
"lit",
|
|
235
|
+
"solid",
|
|
236
|
+
"qwik",
|
|
237
|
+
"vanilla",
|
|
238
|
+
"hono",
|
|
239
|
+
"express",
|
|
240
|
+
"elysia",
|
|
241
|
+
"fastify"
|
|
222
242
|
],
|
|
243
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
223
244
|
"type": "string"
|
|
224
245
|
},
|
|
225
246
|
"language": {
|
|
226
|
-
"description": "Backend language provider used to scaffold and run the service. Only meaningful for backend resources; omitted means bun (legacy manifests).",
|
|
227
|
-
"
|
|
247
|
+
"description": "Backend language provider id used to scaffold and run the service. Only meaningful for backend resources; omitted means bun (legacy manifests). Valid ids come from the CLI provider registry.",
|
|
248
|
+
"examples": [
|
|
228
249
|
"bun",
|
|
229
|
-
"python"
|
|
250
|
+
"python",
|
|
251
|
+
"go"
|
|
230
252
|
],
|
|
253
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
231
254
|
"type": "string"
|
|
232
255
|
},
|
|
233
256
|
"healthCheckPath": {
|
|
@@ -267,6 +267,13 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
267
267
|
is_byo and not manifest.get('exposeViaProxy', True)
|
|
268
268
|
) if manifest else False
|
|
269
269
|
|
|
270
|
+
# One-shot jobs (migrations, seeders) must not be restarted after they exit 0, so a
|
|
271
|
+
# bring-your-own resource can choose its Compose restart policy. Default is unchanged.
|
|
272
|
+
restart_policy = 'unless-stopped'
|
|
273
|
+
if is_byo and manifest.get('restart') in ['no', 'on-failure', 'unless-stopped', 'always']:
|
|
274
|
+
restart_policy = manifest.get('restart')
|
|
275
|
+
restart_policy = '"no"' if restart_policy == 'no' else restart_policy
|
|
276
|
+
|
|
270
277
|
if is_worker or is_proxy_disabled_byo:
|
|
271
278
|
traefik_labels = ' - "traefik.enable=false"'
|
|
272
279
|
healthcheck_section = "" if is_worker or is_byo else """ healthcheck:
|
|
@@ -299,7 +306,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
299
306
|
{resource_entry_name}:
|
|
300
307
|
image: {image_name}
|
|
301
308
|
init: true
|
|
302
|
-
restart:
|
|
309
|
+
restart: {restart_policy}
|
|
303
310
|
{build_config}
|
|
304
311
|
{ports_section}
|
|
305
312
|
env_file:
|
|
@@ -350,6 +357,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
350
357
|
stack=stack,
|
|
351
358
|
internal_port=internal_port,
|
|
352
359
|
port_anchor=internal_port,
|
|
360
|
+
restart_policy=restart_policy,
|
|
353
361
|
dev_port=dev_port,
|
|
354
362
|
db_name=db_name,
|
|
355
363
|
db_url_for_tilt=db_url_for_tilt,
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
BASE_PORT_BACKEND = 4000
|
|
9
9
|
|
|
10
10
|
# Languages whose runtime files are owned by the provider (no Vite/tsconfig/Bun config).
|
|
11
|
-
PROVIDER_OWNED_LANGUAGES = ["python"]
|
|
11
|
+
PROVIDER_OWNED_LANGUAGES = ["python", "go"]
|
|
12
|
+
|
|
13
|
+
# Files a provider-owned language must scaffold; checked before generating anything.
|
|
14
|
+
LANGUAGE_REQUIRED_FILES = {
|
|
15
|
+
"python": ["pyproject.toml", "src/main.py"],
|
|
16
|
+
"go": ["go.mod", "main.go"],
|
|
17
|
+
}
|
|
12
18
|
|
|
13
19
|
_CURL = """RUN apt-get update && apt-get install -y --no-install-recommends curl \\
|
|
14
20
|
&& rm -rf /var/lib/apt/lists/*
|
|
@@ -42,9 +48,34 @@ EXPOSE {port}
|
|
|
42
48
|
CMD ["sh", "-c", "uvicorn main:app --app-dir src --host 0.0.0.0 --port ${{PORT:-{port}}} --reload --reload-dir src"]
|
|
43
49
|
"""
|
|
44
50
|
|
|
51
|
+
_GO = """# Generated by TDK for a Go backend. Do not edit; change service.json instead.
|
|
52
|
+
FROM golang:1.23-bookworm AS build
|
|
53
|
+
|
|
54
|
+
WORKDIR /app/{res_path}
|
|
55
|
+
|
|
56
|
+
COPY {res_path}/go.* ./
|
|
57
|
+
RUN go mod download
|
|
58
|
+
|
|
59
|
+
COPY {res_path}/ ./
|
|
60
|
+
RUN CGO_ENABLED=0 go build -o /out/app .
|
|
61
|
+
|
|
62
|
+
FROM build AS test
|
|
63
|
+
RUN go test ./...
|
|
64
|
+
|
|
65
|
+
FROM debian:bookworm-slim AS production
|
|
66
|
+
|
|
67
|
+
{curl}
|
|
68
|
+
COPY --from=build /out/app /usr/local/bin/app
|
|
69
|
+
|
|
70
|
+
{healthcheck}
|
|
71
|
+
EXPOSE {port}
|
|
72
|
+
|
|
73
|
+
CMD ["app"]
|
|
74
|
+
"""
|
|
75
|
+
|
|
45
76
|
def generate_language_dockerfile(res_path, language, port = BASE_PORT_BACKEND):
|
|
46
77
|
"""Dockerfile text for a provider-owned backend language, or fail for an unknown one."""
|
|
47
|
-
template = {"python": _PYTHON}.get(language)
|
|
78
|
+
template = {"python": _PYTHON, "go": _GO}.get(language)
|
|
48
79
|
if template == None:
|
|
49
80
|
fail("No Dockerfile generator for backend language '{}'".format(language))
|
|
50
81
|
return template.format(
|
|
@@ -56,7 +87,7 @@ def generate_language_dockerfile(res_path, language, port = BASE_PORT_BACKEND):
|
|
|
56
87
|
|
|
57
88
|
|
|
58
89
|
def is_provider_owned_language(manifest):
|
|
59
|
-
"""True when the manifest selects
|
|
90
|
+
"""True when the manifest selects a provider-owned language (a missing language means Bun)."""
|
|
60
91
|
if not manifest:
|
|
61
92
|
return False
|
|
62
93
|
return manifest.get("appType", "backend") == "backend" and manifest.get("language", "bun") in PROVIDER_OWNED_LANGUAGES
|
|
@@ -8,6 +8,7 @@ load(
|
|
|
8
8
|
"./dockerfile/language_dockerfile.star",
|
|
9
9
|
"generate_language_dockerfile",
|
|
10
10
|
"is_provider_owned_language",
|
|
11
|
+
"LANGUAGE_REQUIRED_FILES",
|
|
11
12
|
)
|
|
12
13
|
load("./config/dockerignore.star", "generate_dockerignore")
|
|
13
14
|
load(
|
|
@@ -25,6 +26,7 @@ Docker = struct(
|
|
|
25
26
|
migrator = generate_migrator_dockerfile,
|
|
26
27
|
backend_language = generate_language_dockerfile,
|
|
27
28
|
is_provider_owned_language = is_provider_owned_language,
|
|
29
|
+
language_required_files = LANGUAGE_REQUIRED_FILES,
|
|
28
30
|
generate_dockerignore = generate_dockerignore,
|
|
29
31
|
frontend_compose = generate_frontend_compose,
|
|
30
32
|
backend_compose = generate_backend_compose_entry,
|
|
@@ -77,7 +77,7 @@ def generate_frontend_tsconfig(resource_path, write_fn, internal_deps=None, is_d
|
|
|
77
77
|
resource_path
|
|
78
78
|
))
|
|
79
79
|
print(" Docker build will resolve @{npm_scope}/* from node_modules")
|
|
80
|
-
if framework not in ['react', 'vue']:
|
|
80
|
+
if framework not in ['react', 'vue', 'svelte', 'preact', 'lit', 'solid', 'qwik', 'vanilla']:
|
|
81
81
|
fail("Unknown frontend framework for TypeScript generation: " + str(framework))
|
|
82
82
|
|
|
83
83
|
compiler_options = {
|
|
@@ -99,6 +99,15 @@ def generate_frontend_tsconfig(resource_path, write_fn, internal_deps=None, is_d
|
|
|
99
99
|
}
|
|
100
100
|
if framework == 'react':
|
|
101
101
|
compiler_options['jsx'] = 'react-jsx'
|
|
102
|
+
elif framework == 'preact':
|
|
103
|
+
compiler_options['jsx'] = 'react-jsx'
|
|
104
|
+
compiler_options['jsxImportSource'] = 'preact'
|
|
105
|
+
elif framework == 'qwik':
|
|
106
|
+
compiler_options['jsx'] = 'react-jsx'
|
|
107
|
+
compiler_options['jsxImportSource'] = '@builder.io/qwik'
|
|
108
|
+
elif framework == 'solid':
|
|
109
|
+
compiler_options['jsx'] = 'preserve'
|
|
110
|
+
compiler_options['jsxImportSource'] = 'solid-js'
|
|
102
111
|
|
|
103
112
|
content = {
|
|
104
113
|
"compilerOptions": compiler_options,
|
|
@@ -555,9 +555,10 @@ def generate_resource_health_check(resource_name, resource_path, manifest, check
|
|
|
555
555
|
health_checks = []
|
|
556
556
|
|
|
557
557
|
# Check 1: Required files exist
|
|
558
|
-
frontend_entry = "src/main.ts" if manifest.get("framework", "react")
|
|
558
|
+
frontend_entry = "src/main.ts" if manifest.get("framework", "react") in ["vue", "svelte", "lit", "vanilla"] else "src/main.tsx"
|
|
559
559
|
backend_files = {
|
|
560
560
|
"python": ["pyproject.toml", "src/main.py"],
|
|
561
|
+
"go": ["go.mod", "main.go"],
|
|
561
562
|
}.get(manifest.get("language", "bun"), ["package.json", "prisma/schema.prisma"])
|
|
562
563
|
required_files = {
|
|
563
564
|
"backend": backend_files,
|
|
@@ -573,8 +574,8 @@ if [ ! -f "{}" ]; then
|
|
|
573
574
|
fi
|
|
574
575
|
'''.format(req_file, req_file))
|
|
575
576
|
|
|
576
|
-
# Check 2: Package.json is valid JSON (Python backends have no package.json)
|
|
577
|
-
if manifest.get("language", "bun")
|
|
577
|
+
# Check 2: Package.json is valid JSON (Python and Go backends have no package.json)
|
|
578
|
+
if manifest.get("language", "bun") not in ["python", "go"]:
|
|
578
579
|
health_checks.append('''
|
|
579
580
|
if ! cat package.json | head -1 > /dev/null 2>&1; then
|
|
580
581
|
echo "❌ package.json is not valid"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Lit-specific Vite templates for frontend resources.
|
|
2
|
+
|
|
3
|
+
LIT_VITE_FRONTEND = """{header}
|
|
4
|
+
import {{ resolve }} from 'node:path';
|
|
5
|
+
import {{ defineConfig }} from 'vite';
|
|
6
|
+
|
|
7
|
+
export default defineConfig({{
|
|
8
|
+
base: '{base_path}',
|
|
9
|
+
build: {{
|
|
10
|
+
cssCodeSplit: false,
|
|
11
|
+
minify: false,
|
|
12
|
+
modulePreload: false,
|
|
13
|
+
rollupOptions: {{
|
|
14
|
+
output: {{
|
|
15
|
+
entryFileNames: '[name].js',
|
|
16
|
+
format: 'esm',
|
|
17
|
+
}},
|
|
18
|
+
}},
|
|
19
|
+
target: 'esnext',
|
|
20
|
+
}},
|
|
21
|
+
define: {{
|
|
22
|
+
global: 'globalThis',
|
|
23
|
+
}},
|
|
24
|
+
optimizeDeps: {{
|
|
25
|
+
include: [{optimize_deps_include}],
|
|
26
|
+
}},
|
|
27
|
+
plugins: [],
|
|
28
|
+
preview: {{
|
|
29
|
+
host: '0.0.0.0',
|
|
30
|
+
port: {port},
|
|
31
|
+
}},
|
|
32
|
+
resolve: {{
|
|
33
|
+
alias: {{
|
|
34
|
+
'@/autogenerated': resolve(__dirname),
|
|
35
|
+
'@': resolve(__dirname, '../src'),
|
|
36
|
+
'set-cookie-parser': resolve(__dirname, '../src/utils/empty-module.js'),
|
|
37
|
+
{internal_aliases}
|
|
38
|
+
}},
|
|
39
|
+
}},
|
|
40
|
+
server: {{
|
|
41
|
+
host: '0.0.0.0',
|
|
42
|
+
port: {port},
|
|
43
|
+
hmr: {{
|
|
44
|
+
port: {hmr_port},
|
|
45
|
+
}},
|
|
46
|
+
{proxy_config}
|
|
47
|
+
}},
|
|
48
|
+
}});
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
LIT_VITE_FRONTEND_BUILD = """{header}
|
|
52
|
+
import {{ resolve }} from 'node:path';
|
|
53
|
+
import {{ defineConfig }} from 'vite';
|
|
54
|
+
|
|
55
|
+
export default defineConfig({{
|
|
56
|
+
mode: 'production',
|
|
57
|
+
base: '{base_path}',
|
|
58
|
+
build: {{
|
|
59
|
+
cssCodeSplit: false,
|
|
60
|
+
minify: true,
|
|
61
|
+
modulePreload: false,
|
|
62
|
+
rollupOptions: {{
|
|
63
|
+
output: {{
|
|
64
|
+
entryFileNames: '[name].js',
|
|
65
|
+
format: 'esm',
|
|
66
|
+
manualChunks: undefined,
|
|
67
|
+
}},
|
|
68
|
+
}},
|
|
69
|
+
target: 'esnext',
|
|
70
|
+
}},
|
|
71
|
+
define: {{
|
|
72
|
+
global: 'globalThis',
|
|
73
|
+
__DEV__: 'false',
|
|
74
|
+
'process.env.NODE_ENV': '"production"',
|
|
75
|
+
}},
|
|
76
|
+
optimizeDeps: {{
|
|
77
|
+
include: [{optimize_deps_include}],
|
|
78
|
+
}},
|
|
79
|
+
plugins: [],
|
|
80
|
+
resolve: {{
|
|
81
|
+
alias: {{
|
|
82
|
+
'@/autogenerated': resolve(__dirname),
|
|
83
|
+
'@': resolve(__dirname, '../src'),
|
|
84
|
+
'set-cookie-parser': resolve(__dirname, '../src/utils/empty-module.js'),
|
|
85
|
+
}},
|
|
86
|
+
conditions: ['browser', 'import', 'module', 'es2020', 'default'],
|
|
87
|
+
mainFields: ['browser', 'module', 'jsnext:main', 'jsnext', 'main'],
|
|
88
|
+
}},
|
|
89
|
+
}});
|
|
90
|
+
"""
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Preact-specific Vite templates for frontend resources.
|
|
2
|
+
|
|
3
|
+
PREACT_VITE_FRONTEND = """{header}
|
|
4
|
+
import {{ resolve }} from 'node:path';
|
|
5
|
+
import preact from '@preact/preset-vite';
|
|
6
|
+
import {{ defineConfig }} from 'vite';
|
|
7
|
+
|
|
8
|
+
export default defineConfig({{
|
|
9
|
+
base: '{base_path}',
|
|
10
|
+
build: {{
|
|
11
|
+
cssCodeSplit: false,
|
|
12
|
+
minify: false,
|
|
13
|
+
modulePreload: false,
|
|
14
|
+
rollupOptions: {{
|
|
15
|
+
output: {{
|
|
16
|
+
entryFileNames: '[name].js',
|
|
17
|
+
format: 'esm',
|
|
18
|
+
}},
|
|
19
|
+
}},
|
|
20
|
+
target: 'esnext',
|
|
21
|
+
}},
|
|
22
|
+
define: {{
|
|
23
|
+
global: 'globalThis',
|
|
24
|
+
}},
|
|
25
|
+
optimizeDeps: {{
|
|
26
|
+
include: [{optimize_deps_include}],
|
|
27
|
+
}},
|
|
28
|
+
plugins: [preact()],
|
|
29
|
+
preview: {{
|
|
30
|
+
host: '0.0.0.0',
|
|
31
|
+
port: {port},
|
|
32
|
+
}},
|
|
33
|
+
resolve: {{
|
|
34
|
+
alias: {{
|
|
35
|
+
'@/autogenerated': resolve(__dirname),
|
|
36
|
+
'@': resolve(__dirname, '../src'),
|
|
37
|
+
'set-cookie-parser': resolve(__dirname, '../src/utils/empty-module.js'),
|
|
38
|
+
{internal_aliases}
|
|
39
|
+
}},
|
|
40
|
+
}},
|
|
41
|
+
server: {{
|
|
42
|
+
host: '0.0.0.0',
|
|
43
|
+
port: {port},
|
|
44
|
+
hmr: {{
|
|
45
|
+
port: {hmr_port},
|
|
46
|
+
}},
|
|
47
|
+
{proxy_config}
|
|
48
|
+
}},
|
|
49
|
+
}});
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
PREACT_VITE_FRONTEND_BUILD = """{header}
|
|
53
|
+
import {{ resolve }} from 'node:path';
|
|
54
|
+
import preact from '@preact/preset-vite';
|
|
55
|
+
import {{ defineConfig }} from 'vite';
|
|
56
|
+
|
|
57
|
+
export default defineConfig({{
|
|
58
|
+
mode: 'production',
|
|
59
|
+
base: '{base_path}',
|
|
60
|
+
build: {{
|
|
61
|
+
cssCodeSplit: false,
|
|
62
|
+
minify: true,
|
|
63
|
+
modulePreload: false,
|
|
64
|
+
rollupOptions: {{
|
|
65
|
+
output: {{
|
|
66
|
+
entryFileNames: '[name].js',
|
|
67
|
+
format: 'esm',
|
|
68
|
+
manualChunks: undefined,
|
|
69
|
+
}},
|
|
70
|
+
}},
|
|
71
|
+
target: 'esnext',
|
|
72
|
+
}},
|
|
73
|
+
define: {{
|
|
74
|
+
global: 'globalThis',
|
|
75
|
+
__DEV__: 'false',
|
|
76
|
+
'process.env.NODE_ENV': '"production"',
|
|
77
|
+
}},
|
|
78
|
+
optimizeDeps: {{
|
|
79
|
+
include: [{optimize_deps_include}],
|
|
80
|
+
}},
|
|
81
|
+
plugins: [preact()],
|
|
82
|
+
resolve: {{
|
|
83
|
+
alias: {{
|
|
84
|
+
'@/autogenerated': resolve(__dirname),
|
|
85
|
+
'@': resolve(__dirname, '../src'),
|
|
86
|
+
'set-cookie-parser': resolve(__dirname, '../src/utils/empty-module.js'),
|
|
87
|
+
}},
|
|
88
|
+
conditions: ['browser', 'import', 'module', 'es2020', 'default'],
|
|
89
|
+
mainFields: ['browser', 'module', 'jsnext:main', 'jsnext', 'main'],
|
|
90
|
+
}},
|
|
91
|
+
}});
|
|
92
|
+
"""
|