@jskit-ai/create-app 0.1.2 → 0.1.6
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/jskit-create-app.js +2 -2
- package/package.json +7 -5
- package/src/client/index.js +1 -0
- package/src/index.js +1 -0
- package/src/{shared → server}/index.js +56 -61
- package/templates/base-shell/.jskit/lock.json +31 -0
- package/templates/base-shell/README.md +24 -20
- package/templates/base-shell/app.scripts.config.mjs +1 -1
- package/templates/base-shell/config/public.js +30 -0
- package/templates/base-shell/config/server.js +1 -0
- package/templates/base-shell/config/surfaceAccessPolicies.js +12 -0
- package/templates/base-shell/eslint.config.mjs +1 -1
- package/templates/base-shell/gitignore +2 -0
- package/templates/base-shell/index.html +1 -1
- package/templates/base-shell/jsconfig.json +8 -0
- package/templates/base-shell/package.json +43 -18
- package/templates/base-shell/packages/main/package.descriptor.mjs +55 -0
- package/templates/base-shell/packages/main/package.json +12 -0
- package/templates/base-shell/packages/main/src/client/index.js +13 -0
- package/templates/base-shell/packages/main/src/client/providers/MainClientProvider.js +33 -0
- package/templates/base-shell/packages/main/src/server/controllers/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/index.js +1 -0
- package/templates/base-shell/packages/main/src/server/providers/MainServiceProvider.js +22 -0
- package/templates/base-shell/packages/main/src/server/routes/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/services/index.js +9 -0
- package/templates/base-shell/packages/main/src/server/support/loadAppConfig.js +55 -0
- package/templates/base-shell/packages/main/src/shared/index.js +8 -0
- package/templates/base-shell/packages/main/src/shared/schemas/index.js +20 -0
- package/templates/base-shell/scripts/dev-bootstrap-jskit.sh +110 -0
- package/templates/base-shell/scripts/just_run_verde +37 -0
- package/templates/base-shell/scripts/link-local-jskit-packages.sh +90 -0
- package/templates/base-shell/scripts/update-jskit-packages.sh +73 -0
- package/templates/base-shell/scripts/verdaccio/config.yaml +26 -0
- package/templates/base-shell/scripts/verdaccio-reset-and-publish-packages.sh +314 -0
- package/templates/base-shell/server/lib/runtimeEnv.js +29 -0
- package/templates/base-shell/server/lib/surfaceRuntime.js +10 -0
- package/templates/base-shell/server.js +39 -68
- package/templates/base-shell/src/App.vue +11 -22
- package/templates/base-shell/src/main.js +87 -1
- package/templates/base-shell/src/pages/console/index.vue +12 -0
- package/templates/base-shell/src/pages/console.vue +13 -0
- package/templates/base-shell/src/pages/home/index.vue +12 -0
- package/templates/base-shell/src/pages/home.vue +13 -0
- package/templates/base-shell/src/views/NotFound.vue +13 -0
- package/templates/base-shell/tests/server/{minimalShell.contract.test.js → minimalShell.validator.test.js} +44 -6
- package/templates/base-shell/tests/server/smoke.test.js +3 -6
- package/templates/base-shell/vite.config.mjs +24 -3
- package/templates/base-shell/vite.shared.mjs +51 -1
- package/README.md +0 -24
- package/templates/base-shell/package.json.ACTUAL_CORRECT +0 -38
- /package/src/{shared → server}/cliEntrypoint.js +0 -0
|
@@ -9,17 +9,22 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const APP_ROOT = path.resolve(__dirname, "../..");
|
|
10
10
|
|
|
11
11
|
const EXPECTED_RUNTIME_DEPENDENCIES = Object.freeze([
|
|
12
|
-
"@
|
|
13
|
-
"@jskit-ai/
|
|
12
|
+
"@fastify/type-provider-typebox",
|
|
13
|
+
"@jskit-ai/http-runtime",
|
|
14
|
+
"@jskit-ai/kernel",
|
|
15
|
+
"@local/main",
|
|
14
16
|
"fastify",
|
|
15
|
-
"vue"
|
|
17
|
+
"vue",
|
|
18
|
+
"vue-router",
|
|
19
|
+
"vuetify"
|
|
16
20
|
]);
|
|
17
21
|
|
|
18
22
|
const EXPECTED_DEV_DEPENDENCIES = Object.freeze([
|
|
19
23
|
"@jskit-ai/config-eslint",
|
|
20
|
-
"@jskit-ai/jskit",
|
|
24
|
+
"@jskit-ai/jskit-cli",
|
|
21
25
|
"@vitejs/plugin-vue",
|
|
22
26
|
"eslint",
|
|
27
|
+
"unplugin-vue-router",
|
|
23
28
|
"vite",
|
|
24
29
|
"vitest"
|
|
25
30
|
]);
|
|
@@ -29,13 +34,15 @@ const EXPECTED_TOP_LEVEL_ENTRIES = Object.freeze([
|
|
|
29
34
|
"README.md",
|
|
30
35
|
"app.scripts.config.mjs",
|
|
31
36
|
"bin",
|
|
37
|
+
"config",
|
|
32
38
|
"eslint.config.mjs",
|
|
33
39
|
"favicon.svg",
|
|
34
|
-
"gitignore",
|
|
35
40
|
"index.html",
|
|
41
|
+
"jsconfig.json",
|
|
36
42
|
"package.json",
|
|
37
|
-
"
|
|
43
|
+
"packages",
|
|
38
44
|
"server.js",
|
|
45
|
+
"scripts",
|
|
39
46
|
"server",
|
|
40
47
|
"src",
|
|
41
48
|
"tests",
|
|
@@ -74,6 +81,20 @@ async function readTopLevelEntries() {
|
|
|
74
81
|
.filter((name) => !ignored.has(name));
|
|
75
82
|
}
|
|
76
83
|
|
|
84
|
+
async function listFilesRecursive(directory) {
|
|
85
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
86
|
+
const files = [];
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
const absolutePath = path.join(directory, entry.name);
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
files.push(...(await listFilesRecursive(absolutePath)));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
files.push(absolutePath);
|
|
94
|
+
}
|
|
95
|
+
return files;
|
|
96
|
+
}
|
|
97
|
+
|
|
77
98
|
test("minimal shell keeps strict dependency allowlist", async () => {
|
|
78
99
|
const packageJson = await readPackageJson();
|
|
79
100
|
assert.deepEqual(
|
|
@@ -94,3 +115,20 @@ test("starter shell keeps a strict top-level footprint", async () => {
|
|
|
94
115
|
test("legacy app.manifest scaffold is removed from starter shell", async () => {
|
|
95
116
|
await assert.rejects(access(path.join(APP_ROOT, "framework/app.manifest.mjs")), /ENOENT/);
|
|
96
117
|
});
|
|
118
|
+
|
|
119
|
+
test("local package source avoids brittle deep relative imports", async () => {
|
|
120
|
+
const packageSourceFiles = await listFilesRecursive(path.join(APP_ROOT, "packages"));
|
|
121
|
+
const brittleImportPattern = /\bfrom\s+["'](?:\.\.\/){5,}[^"']+["']/;
|
|
122
|
+
|
|
123
|
+
for (const filePath of packageSourceFiles) {
|
|
124
|
+
if (!filePath.endsWith(".js") && !filePath.endsWith(".mjs")) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const source = await readFile(filePath, "utf8");
|
|
128
|
+
assert.equal(
|
|
129
|
+
brittleImportPattern.test(source),
|
|
130
|
+
false,
|
|
131
|
+
`Found brittle deep relative import in ${path.relative(APP_ROOT, filePath)}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
@@ -2,18 +2,15 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { createServer } from "../../server.js";
|
|
4
4
|
|
|
5
|
-
test("GET /api/
|
|
5
|
+
test("GET /api/health returns built-in health response", async () => {
|
|
6
6
|
const app = await createServer();
|
|
7
7
|
const response = await app.inject({
|
|
8
8
|
method: "GET",
|
|
9
|
-
url: "/api/
|
|
9
|
+
url: "/api/health"
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
assert.equal(response.statusCode, 200);
|
|
13
|
-
assert.
|
|
14
|
-
ok: true,
|
|
15
|
-
app: "__APP_NAME__"
|
|
16
|
-
});
|
|
13
|
+
assert.equal(response.json().ok, true);
|
|
17
14
|
|
|
18
15
|
await app.close();
|
|
19
16
|
});
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from "node:url";
|
|
1
2
|
import { defineConfig } from "vite";
|
|
2
3
|
import vue from "@vitejs/plugin-vue";
|
|
3
|
-
import
|
|
4
|
+
import VueRouter from "unplugin-vue-router/vite";
|
|
5
|
+
import { createJskitClientBootstrapPlugin } from "@jskit-ai/kernel/client/vite";
|
|
6
|
+
import { loadViteDevProxyEntries, toPositiveInt } from "./vite.shared.mjs";
|
|
4
7
|
|
|
5
8
|
const devPort = toPositiveInt(process.env.VITE_DEV_PORT, 5173);
|
|
6
9
|
const apiProxyTarget = String(process.env.VITE_API_PROXY_TARGET || "").trim() || "http://localhost:3000";
|
|
10
|
+
const viteModuleProxyEntries = loadViteDevProxyEntries({
|
|
11
|
+
appRootUrl: import.meta.url,
|
|
12
|
+
fallbackTarget: apiProxyTarget
|
|
13
|
+
});
|
|
7
14
|
const clientEntry = (() => {
|
|
8
15
|
const normalized = String(process.env.VITE_CLIENT_ENTRY || "").trim();
|
|
9
16
|
if (!normalized) {
|
|
@@ -19,12 +26,25 @@ const clientEntry = (() => {
|
|
|
19
26
|
})();
|
|
20
27
|
|
|
21
28
|
export default defineConfig({
|
|
29
|
+
resolve: {
|
|
30
|
+
preserveSymlinks: true,
|
|
31
|
+
alias: {
|
|
32
|
+
"@": fileURLToPath(new URL("./src", import.meta.url))
|
|
33
|
+
}
|
|
34
|
+
},
|
|
22
35
|
plugins: [
|
|
36
|
+
createJskitClientBootstrapPlugin(),
|
|
37
|
+
VueRouter({
|
|
38
|
+
routesFolder: "src/pages",
|
|
39
|
+
dts: "src/typed-router.d.ts"
|
|
40
|
+
}),
|
|
23
41
|
vue(),
|
|
24
42
|
{
|
|
25
43
|
name: "jskit-client-entry",
|
|
26
44
|
transformIndexHtml(source) {
|
|
27
|
-
return String(source || "")
|
|
45
|
+
return String(source || "")
|
|
46
|
+
.replace(/\/src\/%VITE_CLIENT_ENTRY%/g, clientEntry)
|
|
47
|
+
.replace(/\/src\/main\.js/g, clientEntry);
|
|
28
48
|
}
|
|
29
49
|
}
|
|
30
50
|
],
|
|
@@ -37,7 +57,8 @@ export default defineConfig({
|
|
|
37
57
|
"/api": {
|
|
38
58
|
target: apiProxyTarget,
|
|
39
59
|
changeOrigin: true
|
|
40
|
-
}
|
|
60
|
+
},
|
|
61
|
+
...viteModuleProxyEntries
|
|
41
62
|
}
|
|
42
63
|
}
|
|
43
64
|
});
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const VITE_DEV_PROXY_CONFIG_RELATIVE_PATH = ".jskit/vite.dev.proxy.json";
|
|
6
|
+
|
|
1
7
|
function toPositiveInt(value, fallback) {
|
|
2
8
|
const parsed = Number.parseInt(String(value || "").trim(), 10);
|
|
3
9
|
if (Number.isInteger(parsed) && parsed > 0) {
|
|
@@ -6,4 +12,48 @@ function toPositiveInt(value, fallback) {
|
|
|
6
12
|
return fallback;
|
|
7
13
|
}
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
function loadViteDevProxyEntries({ appRootUrl = import.meta.url, fallbackTarget = "" } = {}) {
|
|
16
|
+
const appRootPath = fileURLToPath(new URL(".", appRootUrl));
|
|
17
|
+
const absoluteConfigPath = path.join(appRootPath, VITE_DEV_PROXY_CONFIG_RELATIVE_PATH);
|
|
18
|
+
if (!existsSync(absoluteConfigPath)) {
|
|
19
|
+
return Object.freeze({});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let source = {};
|
|
23
|
+
try {
|
|
24
|
+
source = JSON.parse(readFileSync(absoluteConfigPath, "utf8"));
|
|
25
|
+
} catch {
|
|
26
|
+
return Object.freeze({});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const entries = Array.isArray(source?.entries) ? source.entries : [];
|
|
30
|
+
const proxy = {};
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const record = entry && typeof entry === "object" && !Array.isArray(entry) ? entry : {};
|
|
33
|
+
const routePath = String(record.path || "").trim();
|
|
34
|
+
if (!routePath || !routePath.startsWith("/")) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const target = String(record.target || "").trim() || String(fallbackTarget || "").trim();
|
|
39
|
+
if (!target) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const proxyConfig = {
|
|
44
|
+
target
|
|
45
|
+
};
|
|
46
|
+
if (Object.hasOwn(record, "changeOrigin")) {
|
|
47
|
+
proxyConfig.changeOrigin = record.changeOrigin === true;
|
|
48
|
+
}
|
|
49
|
+
if (Object.hasOwn(record, "ws")) {
|
|
50
|
+
proxyConfig.ws = record.ws === true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
proxy[routePath] = proxyConfig;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Object.freeze(proxy);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { toPositiveInt, loadViteDevProxyEntries };
|
package/README.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# @jskit-ai/create-app
|
|
2
|
-
|
|
3
|
-
Scaffold a minimal JSKIT app shell from in-repo templates.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
jskit-create-app my-app
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
jskit-create-app --interactive
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Options
|
|
16
|
-
|
|
17
|
-
- `--template <name>` template name under `templates/` (default `base-shell`)
|
|
18
|
-
- `--title <text>` override the generated app title placeholder
|
|
19
|
-
- `--target <path>` output directory (default `./<app-name>`)
|
|
20
|
-
- `--initial-bundles <preset>` optional framework preset: `none`, `db`, or `db-auth`
|
|
21
|
-
- `--db-provider <provider>` provider for `db` presets: `mysql` or `postgres`
|
|
22
|
-
- `--force` allow writes into non-empty target directories
|
|
23
|
-
- `--dry-run` preview writes only
|
|
24
|
-
- `--interactive` prompt for app values
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "__APP_NAME__",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"description": "Minimal JSKIT base app (Fastify + Vue)",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": "20.x"
|
|
9
|
-
},
|
|
10
|
-
"bin": {
|
|
11
|
-
"jskit": "node_modules/@jskit-ai/jskit/packages/tooling/jskit/bin/jskit.js"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"server": "jskit-app-scripts server",
|
|
15
|
-
"start": "jskit-app-scripts start",
|
|
16
|
-
"dev": "jskit-app-scripts dev",
|
|
17
|
-
"build": "jskit-app-scripts build",
|
|
18
|
-
"preview": "jskit-app-scripts preview",
|
|
19
|
-
"lint": "jskit-app-scripts lint",
|
|
20
|
-
"lint:process-env": "jskit-app-scripts lint:process-env",
|
|
21
|
-
"test": "jskit-app-scripts test",
|
|
22
|
-
"test:client": "jskit-app-scripts test:client"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@jskit-ai/app-scripts": "0.1.0",
|
|
26
|
-
"@jskit-ai/server-runtime-core": "file:node_modules/@jskit-ai/jskit/packages/runtime/server-runtime-core",
|
|
27
|
-
"fastify": "^5.7.4",
|
|
28
|
-
"vue": "^3.5.13"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@jskit-ai/config-eslint": "0.1.0",
|
|
32
|
-
"@jskit-ai/jskit": "github:mobily-enterprises/jskit-ai",
|
|
33
|
-
"@vitejs/plugin-vue": "^5.2.1",
|
|
34
|
-
"eslint": "^9.39.1",
|
|
35
|
-
"vite": "^6.1.0",
|
|
36
|
-
"vitest": "^4.0.18"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
File without changes
|