forked from c-fu/arah2
feat(03-01): stand up web/ npm workspace with Wave-0 hand-rolled test runner (D-01, D-02, D-11, D-14)
- web/ workspace: TS + Vite shell (maplibre-gl 6.15.0, vite 8.3.5, TS 5.9.3; no UI framework, no Telegram SDK script tag) - tsconfig mirrors bot/ strictness byte-for-byte except the three authorized keys (DOM lib, vite/client types, resolveJsonModule) - test/runner.mjs + harness.mjs copied verbatim from bot/test/ (body-identical past header) - root package.json: web workspace + web:* delegate scripts - web/src/main.ts entry module created (tsc include:['src'] needs ≥1 input; 03-02/03-03 mount here)
This commit is contained in:
+8
-2
@@ -4,7 +4,8 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"theme",
|
"theme",
|
||||||
"bot"
|
"bot",
|
||||||
|
"web"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run build --workspace theme",
|
"build": "npm run build --workspace theme",
|
||||||
@@ -16,6 +17,11 @@
|
|||||||
"bot:typecheck": "npm run typecheck -w bot",
|
"bot:typecheck": "npm run typecheck -w bot",
|
||||||
"bot:dev": "npm run dev -w bot",
|
"bot:dev": "npm run dev -w bot",
|
||||||
"bot:deploy": "npm run deploy -w bot",
|
"bot:deploy": "npm run deploy -w bot",
|
||||||
"bot:commands": "npm run commands -w bot"
|
"bot:commands": "npm run commands -w bot",
|
||||||
|
"web:test": "npm test -w web",
|
||||||
|
"web:typecheck": "npm run typecheck -w web",
|
||||||
|
"web:dev": "npm run dev -w web",
|
||||||
|
"web:build": "npm run build -w web",
|
||||||
|
"web:capture": "npm run capture -w web"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||||
|
<title>araharah</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "@araharah/web",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/runner.mjs",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"capture": "node scripts/capture.mjs"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"maplibre-gl": "^6.15.0",
|
||||||
|
"@araharah/theme": "*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite": "^8.3.5",
|
||||||
|
"typescript": "^5.9.3",
|
||||||
|
"playwright": "^1.50.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* main.ts — the Mini App entry module (D-01, D-02, D-11).
|
||||||
|
* --------------------------------------------------------
|
||||||
|
* The one-and-only DOM entry: web/index.html loads it as `type="module"`
|
||||||
|
* into `<div id="app">`. This plan (03-01) scaffolds the workspace; the
|
||||||
|
* Telegram WebApp binding behind the narrow TelegramWebAppLike interface
|
||||||
|
* and the map shell mount here in plans 03-02 and 03-03. Kept
|
||||||
|
* dependency-free until those plans introduce their modules.
|
||||||
|
*/
|
||||||
|
export {};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* harness.mjs — zero-dependency test registry (D-12).
|
||||||
|
* Suites import { test } and register async cases; runner.mjs drains the registry.
|
||||||
|
* Same hand-rolled shape as theme/scripts/audit.test.mjs (Phase 1 precedent).
|
||||||
|
*/
|
||||||
|
const tests = [];
|
||||||
|
export function test(name, fn) {
|
||||||
|
tests.push({ name, fn });
|
||||||
|
}
|
||||||
|
export const registry = tests;
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/*
|
||||||
|
* runner.mjs — hand-rolled zero-dependency test runner (D-02, D-11).
|
||||||
|
*
|
||||||
|
* Auto-discovers *.test.mjs in this directory (sorted), dynamic-imports
|
||||||
|
* them, and drains the harness registry. A suite that fails to LOAD is
|
||||||
|
* recorded as one failing case — the run never crashes mid-way.
|
||||||
|
* Same hand-rolled shape as theme/scripts/audit.test.mjs (Phase 1)
|
||||||
|
* and bot/test/ (Phase 2) — copied verbatim, workspace-agnostic.
|
||||||
|
*/
|
||||||
|
import { readdirSync } from "node:fs";
|
||||||
|
import { registry } from "./harness.mjs";
|
||||||
|
|
||||||
|
const dir = import.meta.dirname;
|
||||||
|
const suites = readdirSync(dir)
|
||||||
|
.filter((f) => f.endsWith(".test.mjs"))
|
||||||
|
.sort();
|
||||||
|
|
||||||
|
for (const file of suites) {
|
||||||
|
try {
|
||||||
|
await import(`./${file}`);
|
||||||
|
} catch (loadErr) {
|
||||||
|
registry.push({
|
||||||
|
name: `suite load failed: ${file}`,
|
||||||
|
fn: () => {
|
||||||
|
throw loadErr;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let passedCount = 0;
|
||||||
|
let failedCount = 0;
|
||||||
|
for (const { name, fn } of registry) {
|
||||||
|
try {
|
||||||
|
await fn();
|
||||||
|
passedCount++;
|
||||||
|
console.log(`PASS ${name}`);
|
||||||
|
} catch (err) {
|
||||||
|
failedCount++;
|
||||||
|
console.log(`FAIL ${name}`);
|
||||||
|
console.error(` ${err && err.stack ? err.stack : String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[runner] ${passedCount} passed, ${failedCount} failed`);
|
||||||
|
process.exitCode = failedCount > 0 ? 1 : 0;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2023",
|
||||||
|
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"types": ["vite/client"],
|
||||||
|
"strict": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
base: "/",
|
||||||
|
build: {
|
||||||
|
outDir: "dist",
|
||||||
|
emptyOutDir: true,
|
||||||
|
target: "es2022",
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
strictPort: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user