@aipt/cli 0.1.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.
Files changed (69) hide show
  1. package/README.md +116 -0
  2. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/package.json +4 -0
  3. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/pnpm-workspace.yaml +1 -0
  4. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/src/index.test.ts +8 -0
  5. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/src/index.ts +3 -0
  6. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/tsconfig.build.json +12 -0
  7. package/dist/catalog/foundation.standalone-npm-package/1.0.0/assets/tsconfig.json +14 -0
  8. package/dist/catalog/foundation.standalone-npm-package/1.0.0/release.json +29 -0
  9. package/dist/catalog/foundation.typescript-quality/1.0.0/assets/package.json +21 -0
  10. package/dist/catalog/foundation.typescript-quality/1.0.0/assets/pnpm-workspace.yaml +1 -0
  11. package/dist/catalog/foundation.typescript-quality/1.0.0/assets/src/index.test.ts +8 -0
  12. package/dist/catalog/foundation.typescript-quality/1.0.0/assets/src/index.ts +3 -0
  13. package/dist/catalog/foundation.typescript-quality/1.0.0/assets/tsconfig.json +14 -0
  14. package/dist/catalog/foundation.typescript-quality/1.0.0/release.json +57 -0
  15. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/package.json +4 -0
  16. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/src/app.test.ts +21 -0
  17. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/src/app.ts +14 -0
  18. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/src/index.test.ts +14 -0
  19. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/src/index.ts +53 -0
  20. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/tsconfig.build.json +12 -0
  21. package/dist/catalog/foundation.workspace-node-application/1.0.0/assets/tsconfig.json +7 -0
  22. package/dist/catalog/foundation.workspace-node-application/1.0.0/release.json +19 -0
  23. package/dist/catalog/foundation.workspace-npm-package/1.0.0/assets/package.json +4 -0
  24. package/dist/catalog/foundation.workspace-npm-package/1.0.0/assets/src/index.test.ts +8 -0
  25. package/dist/catalog/foundation.workspace-npm-package/1.0.0/assets/src/index.ts +3 -0
  26. package/dist/catalog/foundation.workspace-npm-package/1.0.0/assets/tsconfig.build.json +12 -0
  27. package/dist/catalog/foundation.workspace-npm-package/1.0.0/assets/tsconfig.json +7 -0
  28. package/dist/catalog/foundation.workspace-npm-package/1.0.0/release.json +17 -0
  29. package/dist/catalog/foundation.workspace-root/1.0.0/assets/package.json +16 -0
  30. package/dist/catalog/foundation.workspace-root/1.0.0/assets/packages/README.md +3 -0
  31. package/dist/catalog/foundation.workspace-root/1.0.0/assets/pnpm-workspace.yaml +3 -0
  32. package/dist/catalog/foundation.workspace-root/1.0.0/assets/tsconfig.base.json +12 -0
  33. package/dist/catalog/foundation.workspace-root/1.0.0/release.json +16 -0
  34. package/dist/catalog/foundation.workspace-root/1.1.0/assets/apps/README.md +3 -0
  35. package/dist/catalog/foundation.workspace-root/1.1.0/assets/package.json +16 -0
  36. package/dist/catalog/foundation.workspace-root/1.1.0/assets/packages/README.md +3 -0
  37. package/dist/catalog/foundation.workspace-root/1.1.0/assets/pnpm-workspace.yaml +3 -0
  38. package/dist/catalog/foundation.workspace-root/1.1.0/assets/tsconfig.base.json +12 -0
  39. package/dist/catalog/foundation.workspace-root/1.1.0/release.json +17 -0
  40. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/index.html +14 -0
  41. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/package.json +4 -0
  42. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/App.css +26 -0
  43. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/App.test.tsx +21 -0
  44. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/App.tsx +51 -0
  45. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/index.css +6 -0
  46. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/main.tsx +13 -0
  47. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/src/test/setup.ts +1 -0
  48. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/tsconfig.app.json +17 -0
  49. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/tsconfig.json +7 -0
  50. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/tsconfig.node.json +16 -0
  51. package/dist/catalog/foundation.workspace-web-application/1.0.0/assets/vite.config.ts +11 -0
  52. package/dist/catalog/foundation.workspace-web-application/1.0.0/release.json +24 -0
  53. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/index.html +14 -0
  54. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/package.json +4 -0
  55. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/App.css +26 -0
  56. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/App.test.tsx +21 -0
  57. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/App.tsx +51 -0
  58. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/index.css +6 -0
  59. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/main.tsx +16 -0
  60. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/runtime-error-reporter.test.ts +13 -0
  61. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/runtime-error-reporter.ts +30 -0
  62. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/src/test/setup.ts +1 -0
  63. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/tsconfig.app.json +17 -0
  64. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/tsconfig.json +7 -0
  65. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/tsconfig.node.json +16 -0
  66. package/dist/catalog/foundation.workspace-web-application/1.1.0/assets/vite.config.ts +11 -0
  67. package/dist/catalog/foundation.workspace-web-application/1.1.0/release.json +131 -0
  68. package/dist/cli.js +12027 -0
  69. package/package.json +25 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "capabilityId": "foundation.workspace-root",
4
+ "version": "1.1.0",
5
+ "integrity": "sha256:0764015bb9ef22e05569d3735c2e1f685955be577130cb03ee838172643521ad",
6
+ "consumerProfile": "workspace-root",
7
+ "compatibility": { "node": ">=24.18.0 <25", "pnpm": "11.21.0", "typescript": "6.0.3" },
8
+ "assets": [
9
+ { "path": "apps/README.md", "ownership": "owned-file", "digest": "sha256:f15e8f25a62a5757bb40e52d322a68493d8828df13970b90119aa6a28e36567c", "mode": 420 },
10
+ { "path": "package.json", "ownership": "owned-file", "digest": "sha256:59420801655582958906c77d0b893498ccfc447462f693d2147ac74c24c4f4b1", "mode": 420 },
11
+ { "path": "packages/README.md", "ownership": "owned-file", "digest": "sha256:89ef48abb0e71878e4f8c267cf449e0356aeb467429a9897a4d51f22f94fc2fb", "mode": 420 },
12
+ { "path": "pnpm-workspace.yaml", "ownership": "owned-file", "digest": "sha256:316f2a0038d464f103abd64d7338dacefc35d0d09e57c8296defa0d5ddb898fe", "mode": 420 },
13
+ { "path": "tsconfig.base.json", "ownership": "owned-file", "digest": "sha256:075bf5c84e6dd6e0215084de39a4ce2ef96f083a1b19deb0e0f6586d98c8ac87", "mode": 420 }
14
+ ],
15
+ "verifiers": [{ "id": "workspace.structure" }],
16
+ "exit": { "ownedAssets": ["apps/README.md", "package.json", "packages/README.md", "pnpm-workspace.yaml", "tsconfig.base.json"] }
17
+ }
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="theme-color" content="#0d1b1e" />
7
+ <meta name="description" content="一个具备完整工程基线的工作区 Web 应用。" />
8
+ <title>工作区 Web 应用</title>
9
+ </head>
10
+ <body data-application-shell>
11
+ <div id="root"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "renderer": "web-application-package-json-v1"
4
+ }
@@ -0,0 +1,26 @@
1
+ main { min-height: 100vh; overflow: hidden; }
2
+ nav { height: 82px; padding: 0 clamp(24px, 5vw, 76px); display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid rgba(16,36,39,.16); }
3
+ .brand { display: flex; align-items: center; gap: 12px; color: inherit; text-decoration: none; font: 700 12px/1 "Manrope", sans-serif; letter-spacing: .12em; }
4
+ .brand-mark { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; color: #f3f0e8; background: #102427; font-size: 14px; }
5
+ .status { display: flex; align-items: center; gap: 10px; font-size: 13px; color: #3e5557; }
6
+ .status > span { width: 8px; height: 8px; border-radius: 50%; background: #2f886c; box-shadow: 0 0 0 5px rgba(47,136,108,.12); }
7
+ .hero { min-height: calc(100vh - 82px); padding: clamp(72px, 11vh, 128px) clamp(24px, 8vw, 128px) 80px; position: relative; }
8
+ .hero::after { content: ""; position: absolute; width: min(42vw, 560px); aspect-ratio: 1; right: -8%; top: 8%; border: 1px solid rgba(16,36,39,.13); border-radius: 50%; box-shadow: 0 0 0 72px rgba(16,36,39,.025), 0 0 0 144px rgba(16,36,39,.018); pointer-events: none; }
9
+ .eyebrow { margin: 0 0 26px; font: 600 11px/1 "Manrope", sans-serif; letter-spacing: .18em; color: #4d686a; }
10
+ h1, h2 { margin: 0; font-family: "Manrope", sans-serif; letter-spacing: -.055em; font-weight: 600; }
11
+ h1 { max-width: 900px; font-size: clamp(64px, 10vw, 144px); line-height: .88; }
12
+ .intro { max-width: 520px; margin: 40px 0 34px; font-size: clamp(17px, 1.5vw, 21px); line-height: 1.58; color: #425a5c; }
13
+ .actions { display: flex; flex-wrap: wrap; align-items: center; gap: 28px; }
14
+ .actions button { border: 0; border-radius: 999px; padding: 15px 20px 15px 24px; color: #f8f5ee; background: #102427; cursor: pointer; display: flex; align-items: center; gap: 18px; }
15
+ .actions button span { min-width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%; background: #d66a3c; }
16
+ .actions a { color: #102427; text-underline-offset: 5px; }
17
+ .foundation { padding: clamp(80px, 10vw, 144px) clamp(24px, 8vw, 128px); color: #eef2e9; background: #102427; display: grid; grid-template-columns: minmax(250px, .8fr) minmax(420px, 1.2fr); gap: 10vw; }
18
+ .foundation .eyebrow { color: #88a1a0; }
19
+ h2 { font-size: clamp(42px, 5vw, 72px); line-height: 1; }
20
+ .capability-list { border-top: 1px solid rgba(238,242,233,.22); }
21
+ article { display: grid; grid-template-columns: 56px 1fr; gap: 20px; padding: 28px 0; border-bottom: 1px solid rgba(238,242,233,.22); }
22
+ article > span { color: #d66a3c; font: 600 12px/1.4 "Manrope", sans-serif; }
23
+ article h3 { margin: 0 0 8px; font: 600 22px/1.2 "Manrope", sans-serif; }
24
+ article p { margin: 0; max-width: 450px; color: #aebdbc; line-height: 1.55; }
25
+ @media (max-width: 760px) { nav { height: 70px; } .status { font-size: 0; } .hero { min-height: calc(100vh - 70px); padding-top: 80px; } .hero::after { top: 22%; opacity: .6; } .foundation { grid-template-columns: 1fr; gap: 64px; } }
26
+ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
@@ -0,0 +1,21 @@
1
+ import { cleanup, fireEvent, render, screen } from "@testing-library/react";
2
+ import { afterEach, describe, expect, it } from "vitest";
3
+ import { App } from "./App.js";
4
+
5
+ afterEach(cleanup);
6
+
7
+ describe("workspace web application", () => {
8
+ it("presents the production foundation", () => {
9
+ render(<App />);
10
+ expect(screen.getByRole("heading", { level: 1, name: /从清晰的起点.*开始创造/ })).toBeVisible();
11
+ expect(screen.getByText("准备就绪")).toBeVisible();
12
+ expect(screen.getAllByRole("article")).toHaveLength(3);
13
+ });
14
+
15
+ it("supports an observable interaction", () => {
16
+ render(<App />);
17
+ const button = screen.getByRole("button", { name: /测试交互 0/ });
18
+ fireEvent.click(button);
19
+ expect(screen.getByRole("button", { name: /测试交互 1/ })).toBeVisible();
20
+ });
21
+ });
@@ -0,0 +1,51 @@
1
+ import { useState } from "react";
2
+ import "./App.css";
3
+
4
+ const capabilities = [
5
+ { number: "01", title: "开发", detail: "通过专注且快速的 Vite 开发服务器获得即时反馈。" },
6
+ { number: "02", title: "验证", detail: "类型、组件、生产构建与预览检查已经就绪。" },
7
+ { number: "03", title: "交付", detail: "优化后的静态产物让部署边界保持清晰。" },
8
+ ];
9
+
10
+ export function App() {
11
+ const [count, setCount] = useState(0);
12
+
13
+ return (
14
+ <main>
15
+ <nav aria-label="应用导航">
16
+ <a className="brand" href="#top" aria-label="工作区 Web 应用首页">
17
+ <span aria-hidden="true" className="brand-mark">D</span>
18
+ <span>工作区 / WEB</span>
19
+ </a>
20
+ <span className="status"><span aria-hidden="true" />准备就绪</span>
21
+ </nav>
22
+
23
+ <section className="hero" id="top">
24
+ <p className="eyebrow">React 19 · Vite 8 · TypeScript 6</p>
25
+ <h1>从清晰的起点<br />开始创造。</h1>
26
+ <p className="intro">这个应用刻意从小处开始:一个明确归属的界面、一条经过验证的生产链路,以及留给产品决策的充足空间。</p>
27
+ <div className="actions">
28
+ <button type="button" onClick={() => setCount((value) => value + 1)}>
29
+ 测试交互 <span aria-live="polite">{count}</span>
30
+ </button>
31
+ <a href="#foundation">查看工程基线 <span aria-hidden="true">↓</span></a>
32
+ </div>
33
+ </section>
34
+
35
+ <section className="foundation" id="foundation" aria-labelledby="foundation-title">
36
+ <header>
37
+ <p className="eyebrow">工程基线</p>
38
+ <h2 id="foundation-title">界面保持轻盈,<br />契约足够坚实。</h2>
39
+ </header>
40
+ <div className="capability-list">
41
+ {capabilities.map((capability) => (
42
+ <article key={capability.number}>
43
+ <span>{capability.number}</span>
44
+ <div><h3>{capability.title}</h3><p>{capability.detail}</p></div>
45
+ </article>
46
+ ))}
47
+ </div>
48
+ </section>
49
+ </main>
50
+ );
51
+ }
@@ -0,0 +1,6 @@
1
+ :root { font-family: Inter, ui-sans-serif, system-ui, sans-serif; color: #102427; background: #f3f0e8; font-synthesis: none; text-rendering: optimizeLegibility; }
2
+ * { box-sizing: border-box; }
3
+ html { scroll-behavior: smooth; }
4
+ body { margin: 0; min-width: 320px; min-height: 100vh; }
5
+ button, a { font: inherit; }
6
+ button:focus-visible, a:focus-visible { outline: 3px solid #ffb648; outline-offset: 4px; }
@@ -0,0 +1,13 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { App } from "./App.js";
4
+ import "./index.css";
5
+
6
+ const root = document.getElementById("root");
7
+ if (root === null) throw new Error("Application root is unavailable");
8
+
9
+ createRoot(root).render(
10
+ <StrictMode>
11
+ <App />
12
+ </StrictMode>,
13
+ );
@@ -0,0 +1 @@
1
+ import "@testing-library/jest-dom/vitest";
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.cache/tsconfig.app.tsbuildinfo",
5
+ "target": "ES2023",
6
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "moduleResolution": "Bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"]
15
+ },
16
+ "include": ["src"]
17
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.cache/tsconfig.node.tsbuildinfo",
5
+ "target": "ES2023",
6
+ "lib": ["ES2023"],
7
+ "module": "ESNext",
8
+ "moduleResolution": "Bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "types": ["node"]
14
+ },
15
+ "include": ["vite.config.ts"]
16
+ }
@@ -0,0 +1,11 @@
1
+ import react from "@vitejs/plugin-react";
2
+ import { defineConfig } from "vitest/config";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ build: { sourcemap: true },
7
+ test: {
8
+ environment: "jsdom",
9
+ setupFiles: "./src/test/setup.ts",
10
+ },
11
+ });
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "capabilityId": "foundation.workspace-web-application",
4
+ "version": "1.0.0",
5
+ "integrity": "sha256:469f2e63e95023f6980c3d7eab54ab9092aed508558f38418cb2a3dc557ac18f",
6
+ "consumerProfile": "workspace-web-application",
7
+ "compatibility": { "node": ">=24.18.0 <25", "pnpm": "11.21.0", "typescript": "6.0.3" },
8
+ "assets": [
9
+ { "path": "index.html", "ownership": "owned-file", "digest": "sha256:d8a6db98333d1dfca2e4cde69e102205103f7b97bba005223b9fb0bc5ff61a13", "mode": 420 },
10
+ { "path": "package.json", "ownership": "owned-file", "digest": "sha256:989cd76c8c84d0608d72087cd6ecea6943f99739bd6aeaec6dff6e91eb4ff716", "mode": 420, "renderer": "web-application-package-json-v1" },
11
+ { "path": "src/App.css", "ownership": "owned-file", "digest": "sha256:653c3b8acf85c051ab28cbd62026555e61369deacb2c89673e69c26375d1ba2c", "mode": 420 },
12
+ { "path": "src/App.test.tsx", "ownership": "owned-file", "digest": "sha256:e0b402ab1c03cc54a77b98f98fe84f2ff838574d896db3d7e9b67a892c0cd94a", "mode": 420 },
13
+ { "path": "src/App.tsx", "ownership": "owned-file", "digest": "sha256:0a91406b782e6e9f2f9aaf4303d1bf12e68b642cefce898a7f903c2dcfbed845", "mode": 420 },
14
+ { "path": "src/index.css", "ownership": "owned-file", "digest": "sha256:052cf619027ea3611412e3e668c66c3ce3fe9b6d413bfcd13f9726d5c0285b96", "mode": 420 },
15
+ { "path": "src/main.tsx", "ownership": "owned-file", "digest": "sha256:16b797ba50a7c70470cc5887d14d81c60328984ad3d5a0de5852e6fc52cc5005", "mode": 420 },
16
+ { "path": "src/test/setup.ts", "ownership": "owned-file", "digest": "sha256:9b328c4843431fa76d8de00008fc159e95f99a840211085ff3b8f25e53d14409", "mode": 420 },
17
+ { "path": "tsconfig.app.json", "ownership": "owned-file", "digest": "sha256:e225b26679d9b79e148bad705190ee08eb9b2c44af48268cd68e6f8a4d5cbdfc", "mode": 420 },
18
+ { "path": "tsconfig.json", "ownership": "owned-file", "digest": "sha256:770b4140bbb581e2dfd9ea9946ffc9c75a1d86ba7d2db5f77c83e37cbdf9d808", "mode": 420 },
19
+ { "path": "tsconfig.node.json", "ownership": "owned-file", "digest": "sha256:283a0697a4f1102628f6b19285e6b3f2ffdcba9c6ef64dc3d0148243fcd14a52", "mode": 420 },
20
+ { "path": "vite.config.ts", "ownership": "owned-file", "digest": "sha256:c7f4054808eaf928355a57cf017c54cb84f95545b1f41ceb9918c90f9b48463d", "mode": 420 }
21
+ ],
22
+ "verifiers": [{ "id": "typescript.typecheck" }, { "id": "vitest.run" }, { "id": "web.application-build" }, { "id": "web.application-smoke" }],
23
+ "exit": { "ownedAssets": ["index.html", "package.json", "src/App.css", "src/App.test.tsx", "src/App.tsx", "src/index.css", "src/main.tsx", "src/test/setup.ts", "tsconfig.app.json", "tsconfig.json", "tsconfig.node.json", "vite.config.ts"] }
24
+ }
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="theme-color" content="#0d1b1e" />
7
+ <meta name="description" content="一个具备完整工程基线的工作区 Web 应用。" />
8
+ <title>工作区 Web 应用</title>
9
+ </head>
10
+ <body data-application-shell>
11
+ <div id="root"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "renderer": "web-application-package-json-v1"
4
+ }
@@ -0,0 +1,26 @@
1
+ main { min-height: 100vh; overflow: hidden; }
2
+ nav { height: 82px; padding: 0 clamp(24px, 5vw, 76px); display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid rgba(16,36,39,.16); }
3
+ .brand { display: flex; align-items: center; gap: 12px; color: inherit; text-decoration: none; font: 700 12px/1 "Manrope", sans-serif; letter-spacing: .12em; }
4
+ .brand-mark { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; color: #f3f0e8; background: #102427; font-size: 14px; }
5
+ .status { display: flex; align-items: center; gap: 10px; font-size: 13px; color: #3e5557; }
6
+ .status > span { width: 8px; height: 8px; border-radius: 50%; background: #2f886c; box-shadow: 0 0 0 5px rgba(47,136,108,.12); }
7
+ .hero { min-height: calc(100vh - 82px); padding: clamp(72px, 11vh, 128px) clamp(24px, 8vw, 128px) 80px; position: relative; }
8
+ .hero::after { content: ""; position: absolute; width: min(42vw, 560px); aspect-ratio: 1; right: -8%; top: 8%; border: 1px solid rgba(16,36,39,.13); border-radius: 50%; box-shadow: 0 0 0 72px rgba(16,36,39,.025), 0 0 0 144px rgba(16,36,39,.018); pointer-events: none; }
9
+ .eyebrow { margin: 0 0 26px; font: 600 11px/1 "Manrope", sans-serif; letter-spacing: .18em; color: #4d686a; }
10
+ h1, h2 { margin: 0; font-family: "Manrope", sans-serif; letter-spacing: -.055em; font-weight: 600; }
11
+ h1 { max-width: 900px; font-size: clamp(64px, 10vw, 144px); line-height: .88; }
12
+ .intro { max-width: 520px; margin: 40px 0 34px; font-size: clamp(17px, 1.5vw, 21px); line-height: 1.58; color: #425a5c; }
13
+ .actions { display: flex; flex-wrap: wrap; align-items: center; gap: 28px; }
14
+ .actions button { border: 0; border-radius: 999px; padding: 15px 20px 15px 24px; color: #f8f5ee; background: #102427; cursor: pointer; display: flex; align-items: center; gap: 18px; }
15
+ .actions button span { min-width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%; background: #d66a3c; }
16
+ .actions a { color: #102427; text-underline-offset: 5px; }
17
+ .foundation { padding: clamp(80px, 10vw, 144px) clamp(24px, 8vw, 128px); color: #eef2e9; background: #102427; display: grid; grid-template-columns: minmax(250px, .8fr) minmax(420px, 1.2fr); gap: 10vw; }
18
+ .foundation .eyebrow { color: #88a1a0; }
19
+ h2 { font-size: clamp(42px, 5vw, 72px); line-height: 1; }
20
+ .capability-list { border-top: 1px solid rgba(238,242,233,.22); }
21
+ article { display: grid; grid-template-columns: 56px 1fr; gap: 20px; padding: 28px 0; border-bottom: 1px solid rgba(238,242,233,.22); }
22
+ article > span { color: #d66a3c; font: 600 12px/1.4 "Manrope", sans-serif; }
23
+ article h3 { margin: 0 0 8px; font: 600 22px/1.2 "Manrope", sans-serif; }
24
+ article p { margin: 0; max-width: 450px; color: #aebdbc; line-height: 1.55; }
25
+ @media (max-width: 760px) { nav { height: 70px; } .status { font-size: 0; } .hero { min-height: calc(100vh - 70px); padding-top: 80px; } .hero::after { top: 22%; opacity: .6; } .foundation { grid-template-columns: 1fr; gap: 64px; } }
26
+ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
@@ -0,0 +1,21 @@
1
+ import { cleanup, fireEvent, render, screen } from "@testing-library/react";
2
+ import { afterEach, describe, expect, it } from "vitest";
3
+ import { App } from "./App.js";
4
+
5
+ afterEach(cleanup);
6
+
7
+ describe("workspace web application", () => {
8
+ it("presents the production foundation", () => {
9
+ render(<App />);
10
+ expect(screen.getByRole("heading", { level: 1, name: /从清晰的起点.*开始创造/ })).toBeVisible();
11
+ expect(screen.getByText("准备就绪")).toBeVisible();
12
+ expect(screen.getAllByRole("article")).toHaveLength(3);
13
+ });
14
+
15
+ it("supports an observable interaction", () => {
16
+ render(<App />);
17
+ const button = screen.getByRole("button", { name: /测试交互 0/ });
18
+ fireEvent.click(button);
19
+ expect(screen.getByRole("button", { name: /测试交互 1/ })).toBeVisible();
20
+ });
21
+ });
@@ -0,0 +1,51 @@
1
+ import { useState } from "react";
2
+ import "./App.css";
3
+
4
+ const capabilities = [
5
+ { number: "01", title: "开发", detail: "通过专注且快速的 Vite 开发服务器获得即时反馈。" },
6
+ { number: "02", title: "验证", detail: "类型、组件、生产构建与预览检查已经就绪。" },
7
+ { number: "03", title: "交付", detail: "优化后的静态产物让部署边界保持清晰。" },
8
+ ];
9
+
10
+ export function App() {
11
+ const [count, setCount] = useState(0);
12
+
13
+ return (
14
+ <main>
15
+ <nav aria-label="应用导航">
16
+ <a className="brand" href="#top" aria-label="工作区 Web 应用首页">
17
+ <span aria-hidden="true" className="brand-mark">D</span>
18
+ <span>工作区 / WEB</span>
19
+ </a>
20
+ <span className="status"><span aria-hidden="true" />准备就绪</span>
21
+ </nav>
22
+
23
+ <section className="hero" id="top">
24
+ <p className="eyebrow">React 19 · Vite 8 · TypeScript 6</p>
25
+ <h1>从清晰的起点<br />开始创造。</h1>
26
+ <p className="intro">这个应用刻意从小处开始:一个明确归属的界面、一条经过验证的生产链路,以及留给产品决策的充足空间。</p>
27
+ <div className="actions">
28
+ <button type="button" onClick={() => setCount((value) => value + 1)}>
29
+ 测试交互 <span aria-live="polite">{count}</span>
30
+ </button>
31
+ <a href="#foundation">查看工程基线 <span aria-hidden="true">↓</span></a>
32
+ </div>
33
+ </section>
34
+
35
+ <section className="foundation" id="foundation" aria-labelledby="foundation-title">
36
+ <header>
37
+ <p className="eyebrow">工程基线</p>
38
+ <h2 id="foundation-title">界面保持轻盈,<br />契约足够坚实。</h2>
39
+ </header>
40
+ <div className="capability-list">
41
+ {capabilities.map((capability) => (
42
+ <article key={capability.number}>
43
+ <span>{capability.number}</span>
44
+ <div><h3>{capability.title}</h3><p>{capability.detail}</p></div>
45
+ </article>
46
+ ))}
47
+ </div>
48
+ </section>
49
+ </main>
50
+ );
51
+ }
@@ -0,0 +1,6 @@
1
+ :root { font-family: Inter, ui-sans-serif, system-ui, sans-serif; color: #102427; background: #f3f0e8; font-synthesis: none; text-rendering: optimizeLegibility; }
2
+ * { box-sizing: border-box; }
3
+ html { scroll-behavior: smooth; }
4
+ body { margin: 0; min-width: 320px; min-height: 100vh; }
5
+ button, a { font: inherit; }
6
+ button:focus-visible, a:focus-visible { outline: 3px solid #ffb648; outline-offset: 4px; }
@@ -0,0 +1,16 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { App } from "./App.js";
4
+ import "./index.css";
5
+ import { installRuntimeErrorReporter } from "./runtime-error-reporter.js";
6
+
7
+ void installRuntimeErrorReporter();
8
+
9
+ const root = document.getElementById("root");
10
+ if (root === null) throw new Error("Application root is unavailable");
11
+
12
+ createRoot(root).render(
13
+ <StrictMode>
14
+ <App />
15
+ </StrictMode>,
16
+ );
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { createRuntimeErrorReporter } from "./runtime-error-reporter.js";
3
+
4
+ describe("runtime error reporter", () => {
5
+ it("sends a normalized event with stable release and deployment context", async () => {
6
+ const fetcher = vi.fn(async () => new Response(null, { status: 202 }));
7
+ const reporter = createRuntimeErrorReporter({ schemaVersion: 1, applicationId: "web", releaseId: `sha256:${"a".repeat(64)}`, deploymentId: `sha256:${"b".repeat(64)}`, collectorEndpoint: "http://127.0.0.1:4318" }, fetcher);
8
+ reporter.report({ kind: "reported-error", error: new Error("验收错误") });
9
+ await vi.waitFor(() => expect(fetcher).toHaveBeenCalledOnce());
10
+ const call = fetcher.mock.calls[0] as unknown as [string, RequestInit];
11
+ expect(JSON.parse(String(call[1].body))).toMatchObject({ applicationId: "web", kind: "reported-error", error: { message: "验收错误" }, page: { origin: "http://localhost:3000", path: "/" } });
12
+ });
13
+ });
@@ -0,0 +1,30 @@
1
+ export type RuntimeObservabilityConfig = { schemaVersion: 1; applicationId: string; releaseId: `sha256:${string}`; deploymentId: `sha256:${string}`; collectorEndpoint: string };
2
+ type ReportInput = { kind: "uncaught-error" | "unhandled-rejection" | "reported-error"; error: unknown };
3
+
4
+ function normalize(error: unknown) {
5
+ const value = error instanceof Error ? error : new Error(typeof error === "string" ? error : "未知运行时错误");
6
+ const frames = (value.stack ?? "").split("\n").slice(1, 21).flatMap((line) => { const match = line.match(/(?:at\s+(.*?)\s+\()?(.+?):(\d+):(\d+)\)?$/); return match ? [{ file: match[2]!, line: Number(match[3]), column: Number(match[4]), ...(match[1] ? { function: match[1] } : {}) }] : []; });
7
+ return { type: value.name.slice(0, 256), message: value.message.slice(0, 4096), frames };
8
+ }
9
+
10
+ export function createRuntimeErrorReporter(config: RuntimeObservabilityConfig, fetcher: typeof fetch = fetch) {
11
+ const pending: Array<{ body: string; attempt: number }> = []; let sending = false;
12
+ async function drain() {
13
+ if (sending) return; sending = true;
14
+ while (pending.length > 0) {
15
+ const item = pending[0]!;
16
+ try { const response = await fetcher(`${config.collectorEndpoint}/v1/runtime-errors`, { method: "POST", headers: { "content-type": "application/json" }, body: item.body, keepalive: true }); if (!response.ok) throw new Error("collector rejected event"); pending.shift(); }
17
+ catch { item.attempt += 1; if (item.attempt > 3) pending.shift(); else await new Promise((resolve) => setTimeout(resolve, 100 * 2 ** item.attempt)); }
18
+ }
19
+ sending = false;
20
+ }
21
+ function report(input: ReportInput) {
22
+ const body = JSON.stringify({ schemaVersion: 1, eventId: crypto.randomUUID(), occurredAt: new Date().toISOString(), applicationId: config.applicationId, releaseId: config.releaseId, deploymentId: config.deploymentId, kind: input.kind, error: normalize(input.error), page: { origin: location.origin, path: location.pathname } });
23
+ if (pending.length === 20) pending.shift(); pending.push({ body, attempt: 0 }); void drain();
24
+ }
25
+ return { report, install() { addEventListener("error", (event) => report({ kind: "uncaught-error", error: event.error ?? event.message })); addEventListener("unhandledrejection", (event) => report({ kind: "unhandled-rejection", error: event.reason })); } };
26
+ }
27
+
28
+ export async function installRuntimeErrorReporter(): Promise<ReturnType<typeof createRuntimeErrorReporter> | null> {
29
+ try { const response = await fetch("/dyyto-runtime-config.json", { cache: "no-store" }); if (!response.ok) return null; const config = await response.json() as RuntimeObservabilityConfig; if (config.schemaVersion !== 1) return null; const reporter = createRuntimeErrorReporter(config); reporter.install(); return reporter; } catch { return null; }
30
+ }
@@ -0,0 +1 @@
1
+ import "@testing-library/jest-dom/vitest";
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.cache/tsconfig.app.tsbuildinfo",
5
+ "target": "ES2023",
6
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "moduleResolution": "Bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"]
15
+ },
16
+ "include": ["src"]
17
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.cache/tsconfig.node.tsbuildinfo",
5
+ "target": "ES2023",
6
+ "lib": ["ES2023"],
7
+ "module": "ESNext",
8
+ "moduleResolution": "Bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "types": ["node"]
14
+ },
15
+ "include": ["vite.config.ts"]
16
+ }
@@ -0,0 +1,11 @@
1
+ import react from "@vitejs/plugin-react";
2
+ import { defineConfig } from "vitest/config";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ build: { sourcemap: "hidden" },
7
+ test: {
8
+ environment: "jsdom",
9
+ setupFiles: "./src/test/setup.ts",
10
+ },
11
+ });