@fasl-work/caos-app-shell 0.6.13 → 0.7.1

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/gate/serve.mjs ADDED
@@ -0,0 +1,97 @@
1
+ // A static server that answers the way GitHub Pages does, so a local gate run sees what the deployed site will:
2
+ // an existing file is 200; a directory without a trailing slash is a 301 to the slash; a directory with one serves its
3
+ // index.html; `/name` falls back to `name.html`; anything else is 404 with the site's 404.html. There is no SPA
4
+ // fallback, which is the point: a route that was not materialised, or an artifact missing from the build, fails here
5
+ // exactly as it would on Pages (failure classes 2 and 22: deep links that 404, artifacts answered with HTML).
6
+
7
+ import { createServer } from 'node:http';
8
+ import { existsSync, readFileSync, statSync } from 'node:fs';
9
+ import { extname, join, normalize, resolve, sep } from 'node:path';
10
+
11
+ const MIME = {
12
+ '.html': 'text/html; charset=utf-8',
13
+ '.js': 'text/javascript; charset=utf-8',
14
+ '.mjs': 'text/javascript; charset=utf-8',
15
+ '.css': 'text/css; charset=utf-8',
16
+ '.json': 'application/json; charset=utf-8',
17
+ '.geojson': 'application/geo+json',
18
+ '.svg': 'image/svg+xml',
19
+ '.png': 'image/png',
20
+ '.jpg': 'image/jpeg',
21
+ '.jpeg': 'image/jpeg',
22
+ '.webp': 'image/webp',
23
+ '.gif': 'image/gif',
24
+ '.ico': 'image/x-icon',
25
+ '.woff': 'font/woff',
26
+ '.woff2': 'font/woff2',
27
+ '.ttf': 'font/ttf',
28
+ '.txt': 'text/plain; charset=utf-8',
29
+ '.csv': 'text/csv; charset=utf-8',
30
+ '.map': 'application/json',
31
+ '.wasm': 'application/wasm',
32
+ '.webmanifest': 'application/manifest+json',
33
+ '.xml': 'application/xml',
34
+ };
35
+
36
+ /**
37
+ * @param {string} dir the built site
38
+ * @param {string} basePath the site's base path ('/' for a custom domain, '/Repo/' for a project page)
39
+ * @param {number} port 0 for any free port (the gate), or a fixed one (a product's preview)
40
+ * @returns {Promise<{ url: string, close: () => Promise<void> }>}
41
+ */
42
+ export function servePages(dir, basePath = '/', port = 0) {
43
+ const root = resolve(dir);
44
+ const base = basePath.endsWith('/') ? basePath : `${basePath}/`;
45
+ const notFound = join(root, '404.html');
46
+ const server = createServer((req, res) => {
47
+ const send = (status, file, headers = {}) => {
48
+ res.writeHead(status, { 'Content-Type': MIME[extname(file).toLowerCase()] ?? 'application/octet-stream', 'Cache-Control': 'no-store', ...headers });
49
+ res.end(req.method === 'HEAD' ? undefined : readFileSync(file));
50
+ };
51
+ const missing = () => {
52
+ if (existsSync(notFound)) send(404, notFound);
53
+ else {
54
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
55
+ res.end('404');
56
+ }
57
+ };
58
+ let path;
59
+ try {
60
+ path = decodeURIComponent(new URL(req.url ?? '/', 'http://x').pathname);
61
+ } catch {
62
+ return missing();
63
+ }
64
+ if (`${path}/` === base) {
65
+ res.writeHead(301, { Location: base });
66
+ return res.end();
67
+ }
68
+ if (!path.startsWith(base)) return missing();
69
+ const rel = path.slice(base.length);
70
+ const file = normalize(join(root, rel));
71
+ if (file !== root && !file.startsWith(root + sep)) return missing();
72
+ if (existsSync(file)) {
73
+ const st = statSync(file);
74
+ if (st.isFile()) return send(200, file);
75
+ if (st.isDirectory()) {
76
+ const index = join(file, 'index.html');
77
+ if (!existsSync(index)) return missing();
78
+ if (!path.endsWith('/')) {
79
+ res.writeHead(301, { Location: `${path}/` });
80
+ return res.end();
81
+ }
82
+ return send(200, index);
83
+ }
84
+ }
85
+ if (!path.endsWith('/') && existsSync(`${file}.html`)) return send(200, `${file}.html`);
86
+ return missing();
87
+ });
88
+ return new Promise((ok) => {
89
+ server.listen(port, '127.0.0.1', () => {
90
+ const { port } = server.address();
91
+ ok({
92
+ url: `http://127.0.0.1:${port}${base}`,
93
+ close: () => new Promise((done) => server.close(() => done())),
94
+ });
95
+ });
96
+ });
97
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fasl-work/caos-app-shell",
3
- "version": "0.6.13",
4
- "description": "Shared web-app shell + content primitives + design system for the CAOS / Faena public apps (ADR-0016).",
3
+ "version": "0.7.1",
4
+ "description": "Shared web-app shell, workbench primitives, content primitives, design system and measured gate for the CAOS / Faena public apps (ADR-0016, ADR-0017, ADR-0071).",
5
5
  "license": "MIT",
6
6
  "author": "Felipe Santibáñez-Leal",
7
7
  "repository": {
@@ -20,18 +20,37 @@
20
20
  "types": "./dist/index.d.ts",
21
21
  "import": "./dist/index.js"
22
22
  },
23
- "./styles.css": "./styles.css"
23
+ "./chart": {
24
+ "types": "./dist/chart.d.ts",
25
+ "import": "./dist/chart.js"
26
+ },
27
+ "./keys": {
28
+ "types": "./dist/keys.d.ts",
29
+ "import": "./dist/keys.js"
30
+ },
31
+ "./styles.css": "./styles.css",
32
+ "./chart.css": "./chart.css",
33
+ "./reserved-classes.json": "./reserved-classes.json",
34
+ "./serve": "./gate/serve.mjs",
35
+ "./gate": "./gate/run.mjs",
36
+ "./package.json": "./package.json"
24
37
  },
25
38
  "files": [
26
39
  "dist",
27
- "styles.css"
40
+ "styles.css",
41
+ "chart.css",
42
+ "bin",
43
+ "gate",
44
+ "reserved-classes.json"
28
45
  ],
29
46
  "scripts": {
30
47
  "build": "tsup",
31
48
  "test": "node --import tsx --test \"test/**/*.test.ts\" \"test/**/*.test.tsx\"",
32
49
  "test:browser": "node --import tsx --test \"e2e/**/*.test.ts\"",
33
50
  "prepare": "npm run build",
34
- "prepublishOnly": "npm run build"
51
+ "prepublishOnly": "npm run build",
52
+ "prebuild": "node scripts/reserved-classes.mjs",
53
+ "test:gate": "node --test test/gate-selftest.mjs"
35
54
  },
36
55
  "peerDependencies": {
37
56
  "katex": "^0.16.0",
@@ -39,7 +58,9 @@
39
58
  "react": "^18 || ^19",
40
59
  "react-dom": "^18 || ^19",
41
60
  "react-router": "^6 || ^7 || ^8",
42
- "zustand": "^4 || ^5"
61
+ "zustand": "^4 || ^5",
62
+ "playwright": ">=1.40",
63
+ "uplot": "^1.6.30"
43
64
  },
44
65
  "devDependencies": {
45
66
  "@playwright/test": "1.63.0",
@@ -55,9 +76,21 @@
55
76
  "tsup": "^8.3.5",
56
77
  "tsx": "^4.23.0",
57
78
  "typescript": "^5.7.3",
58
- "zustand": "^5.0.2"
79
+ "zustand": "^5.0.2",
80
+ "uplot": "1.6.32"
59
81
  },
60
82
  "overrides": {
61
83
  "esbuild": "0.28.1"
84
+ },
85
+ "bin": {
86
+ "caos-shell-gate": "bin/caos-shell-gate.mjs"
87
+ },
88
+ "peerDependenciesMeta": {
89
+ "playwright": {
90
+ "optional": true
91
+ },
92
+ "uplot": {
93
+ "optional": true
94
+ }
62
95
  }
63
96
  }
@@ -0,0 +1,224 @@
1
+ {
2
+ "generated_from": [
3
+ "styles.css",
4
+ "chart.css"
5
+ ],
6
+ "classes": [
7
+ "accent",
8
+ "active",
9
+ "app-shell",
10
+ "assume",
11
+ "assume-title",
12
+ "badge",
13
+ "banner",
14
+ "brand",
15
+ "brand-mark",
16
+ "btn",
17
+ "callout",
18
+ "callout-body",
19
+ "callout-honest",
20
+ "callout-note",
21
+ "callout-strong",
22
+ "callout-title",
23
+ "caos-arch-toggle",
24
+ "caos-architecture-diagram",
25
+ "caos-badges",
26
+ "caos-chart",
27
+ "caos-chart-key",
28
+ "caos-chart-legend",
29
+ "caos-chart-plot",
30
+ "caos-chart-readout",
31
+ "caos-chart-swatch",
32
+ "caos-chip-row",
33
+ "caos-chipgroup",
34
+ "caos-chipgroup-label",
35
+ "caos-col-text",
36
+ "caos-cw",
37
+ "caos-cw-context",
38
+ "caos-cw-panel",
39
+ "caos-cw-panel-head",
40
+ "caos-doc-section",
41
+ "caos-field",
42
+ "caos-focus-actions",
43
+ "caos-focus-hud",
44
+ "caos-focus-instrument",
45
+ "caos-focus-label",
46
+ "caos-focus-rail",
47
+ "caos-focus-shell",
48
+ "caos-focus-stage",
49
+ "caos-gauge-legend",
50
+ "caos-gauge-needle",
51
+ "caos-gauge-scale",
52
+ "caos-gauge-title",
53
+ "caos-gauge-track",
54
+ "caos-gauge-value",
55
+ "caos-gauge-zone",
56
+ "caos-knob",
57
+ "caos-knob-head",
58
+ "caos-knob-value",
59
+ "caos-lane-live",
60
+ "caos-lane-offline",
61
+ "caos-lane-replay",
62
+ "caos-panel-error",
63
+ "caos-pending",
64
+ "caos-plot",
65
+ "caos-plot-actions",
66
+ "caos-plot-body",
67
+ "caos-plot-head",
68
+ "caos-plot-note",
69
+ "caos-plot-title",
70
+ "caos-prov-published",
71
+ "caos-prov-real",
72
+ "caos-prov-synthetic",
73
+ "caos-readout",
74
+ "caos-readout-head",
75
+ "caos-readout-row",
76
+ "caos-readout-title",
77
+ "caos-readout-unit",
78
+ "caos-readout-value",
79
+ "caos-stage",
80
+ "caos-stale",
81
+ "caos-stale-note",
82
+ "caos-stale-overlay",
83
+ "caos-table",
84
+ "caos-variant-bar",
85
+ "caos-variant-head",
86
+ "caos-variant-note",
87
+ "caos-variant-title",
88
+ "caos-verdict",
89
+ "caos-verdict-text",
90
+ "caos-verdict-title",
91
+ "caos-views-row",
92
+ "caos-wb",
93
+ "caos-wb-main",
94
+ "caos-wb-rail",
95
+ "caos-wb-rail-head",
96
+ "caos-wb-rail-panel",
97
+ "caos-wb-rail-sections",
98
+ "caos-workbench-content",
99
+ "caos-workbench-header",
100
+ "caos-workbench-main",
101
+ "caos-workbench-shell",
102
+ "caos-workbench-sidebar",
103
+ "card",
104
+ "chip",
105
+ "cite-inline",
106
+ "compact",
107
+ "contain",
108
+ "container",
109
+ "cross-list",
110
+ "cs",
111
+ "cs-chip",
112
+ "cs-chip-id",
113
+ "cs-chip-name",
114
+ "cs-chips",
115
+ "cs-group",
116
+ "cs-group-label",
117
+ "cs-kind",
118
+ "cs-kind-real",
119
+ "cs-kind-uploaded",
120
+ "cs-locked",
121
+ "cs-modified",
122
+ "cs-reset",
123
+ "cs-select",
124
+ "cs-source",
125
+ "cs-source-label",
126
+ "cs-source-tabs",
127
+ "css",
128
+ "def",
129
+ "def-grid",
130
+ "dg-arrowhead",
131
+ "dg-asymptote",
132
+ "dg-axis",
133
+ "dg-axis-label",
134
+ "dg-bar",
135
+ "dg-bar-2",
136
+ "dg-bar-label",
137
+ "dg-box",
138
+ "dg-box-sub",
139
+ "dg-box-title",
140
+ "dg-curve",
141
+ "dg-curve-2",
142
+ "dg-curve-faint",
143
+ "dg-edge",
144
+ "dg-edge-label",
145
+ "dg-fill-accent",
146
+ "dg-fill-warn",
147
+ "dg-grid",
148
+ "dg-marker",
149
+ "dg-marker-label",
150
+ "dg-node",
151
+ "dg-node-label",
152
+ "dg-note",
153
+ "dg-tick",
154
+ "dot",
155
+ "equation",
156
+ "equation-caption",
157
+ "error",
158
+ "faint",
159
+ "fig-cap",
160
+ "fig-row",
161
+ "fig-svg",
162
+ "figure",
163
+ "figure-caption",
164
+ "fill",
165
+ "fixed",
166
+ "footer-build",
167
+ "footer-inner",
168
+ "footer-meta",
169
+ "good",
170
+ "header-actions",
171
+ "header-inner",
172
+ "header-sep",
173
+ "hint",
174
+ "icon-btn",
175
+ "katex",
176
+ "l-en",
177
+ "l-es",
178
+ "lang-code",
179
+ "lede",
180
+ "live",
181
+ "main-nav",
182
+ "measure",
183
+ "mono",
184
+ "muted",
185
+ "nav-link",
186
+ "on",
187
+ "page",
188
+ "page-body",
189
+ "page-head",
190
+ "precomputed",
191
+ "primary",
192
+ "prose",
193
+ "range",
194
+ "reference-list",
195
+ "references",
196
+ "rev",
197
+ "select",
198
+ "site-footer",
199
+ "site-header",
200
+ "small",
201
+ "sr-only",
202
+ "subtab",
203
+ "subtablist",
204
+ "subtabpanel",
205
+ "subtabpanels",
206
+ "subtabs",
207
+ "subtabs-vertical",
208
+ "tab",
209
+ "tablist",
210
+ "tabpanel",
211
+ "tabs",
212
+ "th-refs",
213
+ "th-refs-label",
214
+ "tick-list",
215
+ "tone-accent",
216
+ "tone-bad",
217
+ "tone-good",
218
+ "tone-neutral",
219
+ "tone-warn",
220
+ "two-col",
221
+ "warn",
222
+ "wide"
223
+ ]
224
+ }