@jskit-ai/create-app 0.1.133 → 0.1.136
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/package.json +2 -2
- package/src/server/index.js +3 -4
- package/templates/ai-seed/AGENTS.md +0 -1
- package/templates/base-shell/.jskit/lock.json +7 -1
- package/templates/base-shell/package.json +0 -1
- package/templates/base-shell/playwright.config.mjs +4 -0
- package/templates/base-shell/tests/e2e/base-shell.spec.ts +2 -55
- package/templates/base-shell/tests/server/minimalShell.validator.test.js +0 -1
- package/templates/minimal-shell/package.json +0 -1
- package/templates/minimal-shell/playwright.config.mjs +4 -0
- package/templates/minimal-shell/tests/e2e/base-shell.spec.ts +2 -55
- package/templates/minimal-shell/tests/server/minimalShell.validator.test.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/create-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.136",
|
|
4
4
|
"description": "Scaffold JSKIT app shells.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"./client": "./src/client/index.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@jskit-ai/jskit-cli": "0.2.
|
|
23
|
+
"@jskit-ai/jskit-cli": "0.2.139"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": "^22.12.0 || ^24.0.0 || ^26.0.0"
|
package/src/server/index.js
CHANGED
|
@@ -16,7 +16,6 @@ const DEFAULT_INITIAL_BUNDLES = "none";
|
|
|
16
16
|
const DEFAULT_PLAYWRIGHT_VERSION = "1.61.1";
|
|
17
17
|
const INITIAL_BUNDLE_PRESETS = new Set(["none", "auth"]);
|
|
18
18
|
const TENANCY_MODES = new Set(["none", "personal", "workspaces"]);
|
|
19
|
-
const EXACT_SEMVER_PATTERN = /^\d+\.\d+\.\d+$/u;
|
|
20
19
|
const ALLOWED_EXISTING_TARGET_ENTRIES = new Set([".git"]);
|
|
21
20
|
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
22
21
|
const TEMPLATES_ROOT = path.join(PACKAGE_ROOT, "templates");
|
|
@@ -57,12 +56,12 @@ function normalizeTenancyMode(value, { showUsage = true } = {}) {
|
|
|
57
56
|
|
|
58
57
|
function normalizePlaywrightVersion(value, { showUsage = true } = {}) {
|
|
59
58
|
const normalized = String(value || "").trim();
|
|
60
|
-
if (
|
|
59
|
+
if (normalized === DEFAULT_PLAYWRIGHT_VERSION) {
|
|
61
60
|
return normalized;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
throw createCliError(
|
|
65
|
-
`Invalid --playwright-version value "${value}".
|
|
64
|
+
`Invalid --playwright-version value "${value}". JSKIT requires ${DEFAULT_PLAYWRIGHT_VERSION}.`,
|
|
66
65
|
{ showUsage }
|
|
67
66
|
);
|
|
68
67
|
}
|
|
@@ -262,7 +261,7 @@ function printUsage(stream = process.stderr) {
|
|
|
262
261
|
stream.write(" --title <text> App title used for template replacements\n");
|
|
263
262
|
stream.write(" --target <path> Target directory (default: ./<app-name>)\n");
|
|
264
263
|
stream.write(" --initial-bundles <preset> Optional initial setup preset: none | auth (default: none)\n");
|
|
265
|
-
stream.write(` --playwright-version <
|
|
264
|
+
stream.write(` --playwright-version <version> Supported Playwright test version (${DEFAULT_PLAYWRIGHT_VERSION})\n`);
|
|
266
265
|
stream.write(" --tenancy-mode <mode> Optional config seed: none | personal | workspaces\n");
|
|
267
266
|
stream.write(" --force Allow writing into a non-empty target directory\n");
|
|
268
267
|
stream.write(" --dry-run Print planned writes without changing the filesystem\n");
|
|
@@ -7,6 +7,5 @@ Keep this stage minimal:
|
|
|
7
7
|
- Decide the app name and tenancy mode.
|
|
8
8
|
- Promote the directory into a real scaffold with `npx @jskit-ai/create-app <app-name> --target . --force --tenancy-mode <mode>`.
|
|
9
9
|
- Run `npm install`.
|
|
10
|
-
- If local JSKIT checkout links are used, run `npm run devlinks` immediately afterward.
|
|
11
10
|
|
|
12
11
|
After the real scaffold exists, follow the generated app `AGENTS.md` and JSKIT agent docs. Do not continue from this seed file as a workflow source of truth.
|
|
@@ -48,7 +48,13 @@
|
|
|
48
48
|
"value": "0.x"
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
|
-
"devDependencies": {
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@playwright/test": {
|
|
53
|
+
"hadPrevious": true,
|
|
54
|
+
"previousValue": "__PLAYWRIGHT_VERSION__",
|
|
55
|
+
"value": "__PLAYWRIGHT_VERSION__"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
52
58
|
"scripts": {}
|
|
53
59
|
},
|
|
54
60
|
"text": {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"server:all": "node ./bin/server.js",
|
|
13
13
|
"server:home": "SERVER_SURFACE=home node ./bin/server.js",
|
|
14
14
|
"start": "node ./bin/server.js",
|
|
15
|
-
"devlinks": "jskit app link-local-packages",
|
|
16
15
|
"dev": "vite",
|
|
17
16
|
"dev:all": "vite",
|
|
18
17
|
"dev:home": "VITE_SURFACE=home vite",
|
|
@@ -1,57 +1,4 @@
|
|
|
1
1
|
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { runGeneratedAppSmoke } from "@jskit-ai/jskit-cli/test/playwright";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const SMOKE_PATH = String(process.env.JSKIT_PLAYWRIGHT_SMOKE_PATH || "/home");
|
|
5
|
-
|
|
6
|
-
const viewports = [
|
|
7
|
-
{ name: "compact", width: 390, height: 844 },
|
|
8
|
-
{ name: "medium", width: 768, height: 1024 },
|
|
9
|
-
{ name: "expanded", width: 1280, height: 900 }
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
async function expectNoHorizontalOverflow(page) {
|
|
13
|
-
const metrics = await page.evaluate(() => ({
|
|
14
|
-
clientWidth: document.documentElement.clientWidth,
|
|
15
|
-
scrollWidth: document.documentElement.scrollWidth
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
expect(metrics.scrollWidth).toBeLessThanOrEqual(metrics.clientWidth + 1);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function expectGeneratedScreenContract(page) {
|
|
22
|
-
const screen = page.locator(".generated-ui-screen").first();
|
|
23
|
-
|
|
24
|
-
await expect(screen).toBeVisible();
|
|
25
|
-
await expect(screen).toHaveClass(/generated-ui-screen--app/u);
|
|
26
|
-
await expect(screen.locator("h1").first()).toBeVisible();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function expectVisibleTapTargets(page) {
|
|
30
|
-
const targetHeights = await page.locator("a[href], button, [role='button'], .v-btn, .v-list-item").evaluateAll(
|
|
31
|
-
(elements) => elements
|
|
32
|
-
.filter((element) => {
|
|
33
|
-
const rect = element.getBoundingClientRect();
|
|
34
|
-
const style = window.getComputedStyle(element);
|
|
35
|
-
return style.display !== "none" && style.visibility !== "hidden" && rect.width > 0 && rect.height > 0;
|
|
36
|
-
})
|
|
37
|
-
.map((element) => element.getBoundingClientRect().height)
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
for (const height of targetHeights) {
|
|
41
|
-
expect(height).toBeGreaterThanOrEqual(48);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
test.describe("generated base app responsive smoke", () => {
|
|
46
|
-
for (const viewport of viewports) {
|
|
47
|
-
test(`${viewport.name} home route renders without horizontal overflow`, async ({ page }) => {
|
|
48
|
-
await page.setViewportSize({ width: viewport.width, height: viewport.height });
|
|
49
|
-
await page.goto(`${BASE_URL}${SMOKE_PATH}`);
|
|
50
|
-
await expect(page.locator("body")).toBeVisible();
|
|
51
|
-
await expect(page.getByText("Ready")).toBeVisible();
|
|
52
|
-
await expectGeneratedScreenContract(page);
|
|
53
|
-
await expectVisibleTapTargets(page);
|
|
54
|
-
await expectNoHorizontalOverflow(page);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
});
|
|
4
|
+
runGeneratedAppSmoke({ test, expect, expectedText: "Ready" });
|
|
@@ -9,7 +9,6 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const APP_ROOT = path.resolve(__dirname, "../..");
|
|
10
10
|
|
|
11
11
|
const EXPECTED_MANAGED_SCRIPTS = Object.freeze({
|
|
12
|
-
devlinks: "jskit app link-local-packages",
|
|
13
12
|
verify: "jskit app verify && npm run --if-present verify:app",
|
|
14
13
|
release: "jskit app release",
|
|
15
14
|
"jskit:update": "jskit app update-packages"
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"server:all": "node ./bin/server.js",
|
|
13
13
|
"server:home": "SERVER_SURFACE=home node ./bin/server.js",
|
|
14
14
|
"start": "node ./bin/server.js",
|
|
15
|
-
"devlinks": "jskit app link-local-packages",
|
|
16
15
|
"dev": "vite",
|
|
17
16
|
"dev:all": "vite",
|
|
18
17
|
"dev:home": "VITE_SURFACE=home vite",
|
|
@@ -1,57 +1,4 @@
|
|
|
1
1
|
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { runGeneratedAppSmoke } from "@jskit-ai/jskit-cli/test/playwright";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const SMOKE_PATH = String(process.env.JSKIT_PLAYWRIGHT_SMOKE_PATH || "/home");
|
|
5
|
-
|
|
6
|
-
const viewports = [
|
|
7
|
-
{ name: "compact", width: 390, height: 844 },
|
|
8
|
-
{ name: "medium", width: 768, height: 1024 },
|
|
9
|
-
{ name: "expanded", width: 1280, height: 900 }
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
async function expectNoHorizontalOverflow(page) {
|
|
13
|
-
const metrics = await page.evaluate(() => ({
|
|
14
|
-
clientWidth: document.documentElement.clientWidth,
|
|
15
|
-
scrollWidth: document.documentElement.scrollWidth
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
expect(metrics.scrollWidth).toBeLessThanOrEqual(metrics.clientWidth + 1);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function expectGeneratedScreenContract(page) {
|
|
22
|
-
const screen = page.locator(".generated-ui-screen").first();
|
|
23
|
-
|
|
24
|
-
await expect(screen).toBeVisible();
|
|
25
|
-
await expect(screen).toHaveClass(/generated-ui-screen--app/u);
|
|
26
|
-
await expect(screen.locator("h1").first()).toBeVisible();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function expectVisibleTapTargets(page) {
|
|
30
|
-
const targetHeights = await page.locator("a[href], button, [role='button'], .v-btn, .v-list-item").evaluateAll(
|
|
31
|
-
(elements) => elements
|
|
32
|
-
.filter((element) => {
|
|
33
|
-
const rect = element.getBoundingClientRect();
|
|
34
|
-
const style = window.getComputedStyle(element);
|
|
35
|
-
return style.display !== "none" && style.visibility !== "hidden" && rect.width > 0 && rect.height > 0;
|
|
36
|
-
})
|
|
37
|
-
.map((element) => element.getBoundingClientRect().height)
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
for (const height of targetHeights) {
|
|
41
|
-
expect(height).toBeGreaterThanOrEqual(48);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
test.describe("generated base app responsive smoke", () => {
|
|
46
|
-
for (const viewport of viewports) {
|
|
47
|
-
test(`${viewport.name} home route renders without horizontal overflow`, async ({ page }) => {
|
|
48
|
-
await page.setViewportSize({ width: viewport.width, height: viewport.height });
|
|
49
|
-
await page.goto(`${BASE_URL}${SMOKE_PATH}`);
|
|
50
|
-
await expect(page.locator("body")).toBeVisible();
|
|
51
|
-
await expect(page.getByText("Home base")).toBeVisible();
|
|
52
|
-
await expectGeneratedScreenContract(page);
|
|
53
|
-
await expectVisibleTapTargets(page);
|
|
54
|
-
await expectNoHorizontalOverflow(page);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
});
|
|
4
|
+
runGeneratedAppSmoke({ test, expect, expectedText: "Home base" });
|
|
@@ -9,7 +9,6 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const APP_ROOT = path.resolve(__dirname, "../..");
|
|
10
10
|
|
|
11
11
|
const EXPECTED_MANAGED_SCRIPTS = Object.freeze({
|
|
12
|
-
devlinks: "jskit app link-local-packages",
|
|
13
12
|
verify: "jskit app verify && npm run --if-present verify:app",
|
|
14
13
|
release: "jskit app release",
|
|
15
14
|
"jskit:update": "jskit app update-packages"
|