@jskit-ai/create-app 0.1.74 → 0.1.76
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
CHANGED
|
@@ -34,5 +34,6 @@ What to do now:
|
|
|
34
34
|
`npx @jskit-ai/create-app <app-name> --target . --force --tenancy-mode <mode>`
|
|
35
35
|
Use the current directory name as `<app-name>` unless the developer explicitly wants a different app name.
|
|
36
36
|
9. After that, run `npm install`.
|
|
37
|
-
10.
|
|
38
|
-
11.
|
|
37
|
+
10. If this app is being tested against a local JSKIT checkout with linked packages, run `npm run devlinks` immediately after `npm install`.
|
|
38
|
+
11. Then stop, re-read the overwritten `AGENTS.md`, and continue with the normal JSKIT app workflow from that file. Do not rely on memory from the seed stage.
|
|
39
|
+
12. Do not install JSKIT runtime packages until the new app `AGENTS.md` has been re-read.
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"lint": "eslint .",
|
|
24
24
|
"test": "node --test",
|
|
25
25
|
"test:client": "vitest run tests/client",
|
|
26
|
+
"test:e2e": "playwright test tests/e2e",
|
|
26
27
|
"verify": "jskit app verify && npm run --if-present verify:app",
|
|
27
28
|
"release": "jskit app release",
|
|
28
29
|
"jskit:update": "jskit app update-packages"
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"@local/main": "file:packages/main",
|
|
32
33
|
"@fastify/static": "^9.1.1",
|
|
33
34
|
"@jskit-ai/kernel": "0.x",
|
|
35
|
+
"@tanstack/vue-query": "^5.90.5",
|
|
34
36
|
"fastify": "^5.7.4",
|
|
35
37
|
"json-rest-schema": "^1.0.13",
|
|
36
38
|
"pinia": "^3.0.4",
|
|
@@ -43,6 +45,7 @@
|
|
|
43
45
|
"@jskit-ai/agent-docs": "0.x",
|
|
44
46
|
"@jskit-ai/config-eslint": "0.x",
|
|
45
47
|
"@jskit-ai/jskit-cli": "0.x",
|
|
48
|
+
"@playwright/test": "^1.57.0",
|
|
46
49
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
47
50
|
"eslint": "^9.39.1",
|
|
48
51
|
"vite": "^6.1.0",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createApp } from "vue";
|
|
2
2
|
import { createPinia } from "pinia";
|
|
3
|
+
import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
|
|
3
4
|
import { createRouter, createWebHistory } from "vue-router/auto";
|
|
4
5
|
import { routes } from "vue-router/auto-routes";
|
|
5
6
|
import "vuetify/styles";
|
|
@@ -11,6 +12,10 @@ import App from "./App.vue";
|
|
|
11
12
|
import NotFoundView from "./views/NotFound.vue";
|
|
12
13
|
import { bootInstalledClientModules } from "virtual:jskit-client-bootstrap";
|
|
13
14
|
import { createSurfaceRuntime } from "@jskit-ai/kernel/shared/surface/runtime";
|
|
15
|
+
import {
|
|
16
|
+
shouldRetryTransientQueryFailure,
|
|
17
|
+
transientQueryRetryDelay
|
|
18
|
+
} from "@jskit-ai/kernel/shared/support";
|
|
14
19
|
import {
|
|
15
20
|
bootstrapClientShellApp,
|
|
16
21
|
createShellRouter
|
|
@@ -51,13 +56,28 @@ const vuetify = createVuetify({
|
|
|
51
56
|
}
|
|
52
57
|
});
|
|
53
58
|
const pinia = createPinia();
|
|
59
|
+
const queryClient = new QueryClient({
|
|
60
|
+
defaultOptions: {
|
|
61
|
+
queries: {
|
|
62
|
+
refetchOnWindowFocus: false,
|
|
63
|
+
refetchOnReconnect: true,
|
|
64
|
+
retry: shouldRetryTransientQueryFailure,
|
|
65
|
+
retryDelay: transientQueryRetryDelay
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
54
69
|
|
|
55
70
|
void bootstrapClientShellApp({
|
|
56
71
|
createApp,
|
|
57
72
|
rootComponent: App,
|
|
58
73
|
appConfig: config,
|
|
59
|
-
appPlugins: [
|
|
74
|
+
appPlugins: [
|
|
75
|
+
pinia,
|
|
76
|
+
[VueQueryPlugin, { queryClient }],
|
|
77
|
+
vuetify
|
|
78
|
+
],
|
|
60
79
|
pinia,
|
|
80
|
+
queryClient,
|
|
61
81
|
router,
|
|
62
82
|
bootClientModules: bootInstalledClientModules,
|
|
63
83
|
surfaceRuntime,
|
|
@@ -1,12 +1,42 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<section class="generated-ui-screen generated-ui-screen--app home-start-screen d-flex flex-column ga-4">
|
|
3
|
+
<header>
|
|
4
|
+
<p class="text-overline text-medium-emphasis mb-1">Home</p>
|
|
5
|
+
<h1 class="home-start-screen__title">Home base</h1>
|
|
6
|
+
<p class="text-body-2 text-medium-emphasis mb-0">
|
|
7
|
+
The app runtime is online and ready for the first real workflow.
|
|
8
|
+
</p>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<v-sheet rounded="lg" border class="home-start-screen__panel">
|
|
12
|
+
<h2 class="text-h6 mb-2">No activity yet</h2>
|
|
13
|
+
<p class="text-body-2 text-medium-emphasis mb-0">
|
|
14
|
+
Recent work, saved records, and next actions will appear here once this app has data.
|
|
15
|
+
</p>
|
|
16
|
+
</v-sheet>
|
|
17
|
+
</section>
|
|
12
18
|
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped>
|
|
21
|
+
.generated-ui-screen {
|
|
22
|
+
--generated-ui-screen-title-size: clamp(1.5rem, 3vw, 2.5rem);
|
|
23
|
+
--generated-ui-screen-panel-padding: 1rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.home-start-screen {
|
|
27
|
+
margin-inline: auto;
|
|
28
|
+
max-width: 48rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.home-start-screen__title {
|
|
32
|
+
font-size: var(--generated-ui-screen-title-size);
|
|
33
|
+
font-weight: 700;
|
|
34
|
+
letter-spacing: -0.03em;
|
|
35
|
+
line-height: 1.08;
|
|
36
|
+
margin: 0 0 0.45rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.home-start-screen__panel {
|
|
40
|
+
padding: var(--generated-ui-screen-panel-padding);
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
const BASE_URL = String(process.env.PLAYWRIGHT_BASE_URL || "http://127.0.0.1:5173").replace(/\/+$/u, "");
|
|
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
|
+
});
|