statikapi 0.4.0 → 0.5.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.
- package/README.md +5 -7
- package/package.json +1 -1
- package/src/commands/dev.js +8 -17
package/README.md
CHANGED
|
@@ -122,10 +122,6 @@ You can override via flags: `--srcDir <dir>`, `--outDir <dir>`.
|
|
|
122
122
|
- Rebuilds on changes, updates the preview UI via SSE.
|
|
123
123
|
- `--previewHost`, `--previewPort` — where to notify the preview server.
|
|
124
124
|
- `--srcDir`, `--outDir` — override config paths.
|
|
125
|
-
|
|
126
|
-
`preview`
|
|
127
|
-
|
|
128
|
-
- Serves `api-out/` and the UI at `/\_ui`.
|
|
129
125
|
- `--host` (default 127.0.0.1)
|
|
130
126
|
- `--port` (default 8788)
|
|
131
127
|
- `--open` — try to open the browser
|
|
@@ -142,15 +138,17 @@ There are two example projects in this repo under `example/`:
|
|
|
142
138
|
# from repo root
|
|
143
139
|
|
|
144
140
|
pnpm -C example/basic dev
|
|
145
|
-
pnpm -C example/basic
|
|
141
|
+
pnpm -C example/basic build
|
|
146
142
|
|
|
147
143
|
pnpm -C example/dynamic dev
|
|
148
|
-
pnpm -C example/dynamic
|
|
144
|
+
pnpm -C example/dynamic build
|
|
145
|
+
|
|
146
|
+
pnpm -C example/showcase dev
|
|
147
|
+
pnpm -C example/showcase build
|
|
149
148
|
```
|
|
150
149
|
|
|
151
150
|
## Troubleshooting
|
|
152
151
|
|
|
153
|
-
- UI doesn’t load: ensure `preview` is running; if you’re developing the UI separately, start Vite on port 5173 or pass `--uiDir` to serve a built UI.
|
|
154
152
|
- Dynamic routes not emitted: make sure the file exports a valid `paths()` function returning strings (or arrays of strings for catch-all).
|
|
155
153
|
|
|
156
154
|
License
|
package/package.json
CHANGED
package/src/commands/dev.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import chokidar from 'chokidar';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
|
-
import fss from 'node:fs';
|
|
4
|
+
import fss from 'node:fs';
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
|
-
import http from 'node:http';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import http from 'node:http';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
8
|
|
|
9
9
|
import { loadConfig } from '../config/loadConfig.js';
|
|
10
10
|
import { loadModuleValue } from '../loader/loadModuleValue.js';
|
|
@@ -72,13 +72,11 @@ export default async function devCmd(argv) {
|
|
|
72
72
|
const { config } = await loadConfig({ flags });
|
|
73
73
|
|
|
74
74
|
// Where to notify preview
|
|
75
|
-
// NEW: dev server + UI defaults
|
|
76
75
|
const host = String(flags.host ?? '127.0.0.1');
|
|
77
76
|
const port = Number.isFinite(flags.port) ? Number(flags.port) : 8788;
|
|
78
77
|
const noUi = !!(flags['no-ui'] || flags.noUi);
|
|
79
78
|
const noOpen = !!(flags['no-open'] || flags.noOpen);
|
|
80
79
|
|
|
81
|
-
// NEW: live SSE clients
|
|
82
80
|
const sseClients = new Set(); // each entry: { id, res }
|
|
83
81
|
function sseBroadcast(msg) {
|
|
84
82
|
const line = `data: ${msg}\n\n`;
|
|
@@ -274,7 +272,6 @@ export default async function devCmd(argv) {
|
|
|
274
272
|
await writeManifest();
|
|
275
273
|
console.log(`[statikapi] ready. Watching ${path.relative(process.cwd(), config.paths.srcAbs)}/`);
|
|
276
274
|
|
|
277
|
-
// NEW: start HTTP server (UI + JSON helpers + SSE)
|
|
278
275
|
const server = http.createServer(async (req, res) => {
|
|
279
276
|
try {
|
|
280
277
|
let url;
|
|
@@ -286,7 +283,6 @@ export default async function devCmd(argv) {
|
|
|
286
283
|
}
|
|
287
284
|
const pathname = url.pathname;
|
|
288
285
|
|
|
289
|
-
// 1) SSE: /_ui/events
|
|
290
286
|
if (pathname === '/_ui/events') {
|
|
291
287
|
res.writeHead(200, {
|
|
292
288
|
'Content-Type': 'text/event-stream',
|
|
@@ -301,7 +297,6 @@ export default async function devCmd(argv) {
|
|
|
301
297
|
return;
|
|
302
298
|
}
|
|
303
299
|
|
|
304
|
-
// 2) Manifest JSON for UI: /ui/index
|
|
305
300
|
if (pathname === '/ui/index' && req.method === 'GET') {
|
|
306
301
|
const list = Array.from(manifestByRoute.values()).sort((a, b) =>
|
|
307
302
|
a.route.localeCompare(b.route)
|
|
@@ -312,7 +307,6 @@ export default async function devCmd(argv) {
|
|
|
312
307
|
return;
|
|
313
308
|
}
|
|
314
309
|
|
|
315
|
-
// 3) Serve built file content: /_ui/file?route=/path
|
|
316
310
|
if (pathname === '/_ui/file' && req.method === 'GET') {
|
|
317
311
|
const route = url.searchParams.get('route') || '';
|
|
318
312
|
const outFile = routeToOutPath({ outAbs: config.paths.outAbs, route });
|
|
@@ -332,7 +326,6 @@ export default async function devCmd(argv) {
|
|
|
332
326
|
return;
|
|
333
327
|
}
|
|
334
328
|
|
|
335
|
-
// 4) Static React UI at /_ui/* (unless --no-ui)
|
|
336
329
|
if (!noUi && pathname.startsWith('/_ui/')) {
|
|
337
330
|
const uiRoot = resolveUiDist();
|
|
338
331
|
const rel = pathname.replace(/^\/_ui\//, '') || 'index.html';
|
|
@@ -360,14 +353,13 @@ export default async function devCmd(argv) {
|
|
|
360
353
|
return;
|
|
361
354
|
}
|
|
362
355
|
|
|
363
|
-
// 5) Root → redirect to UI (unless --no-ui)
|
|
364
356
|
if (!noUi && pathname === '/') {
|
|
365
357
|
res.writeHead(302, { Location: '/_ui/' });
|
|
366
358
|
res.end();
|
|
367
359
|
return;
|
|
368
360
|
}
|
|
369
361
|
|
|
370
|
-
//
|
|
362
|
+
// Serve built JSON directly from api-out
|
|
371
363
|
{
|
|
372
364
|
const outRoot = config.paths.outAbs;
|
|
373
365
|
// strip leading slash and normalize
|
|
@@ -439,7 +431,6 @@ export default async function devCmd(argv) {
|
|
|
439
431
|
return 0;
|
|
440
432
|
}
|
|
441
433
|
|
|
442
|
-
// NEW: helpers (static file & UI dist resolver & opener)
|
|
443
434
|
function streamFile(file, res) {
|
|
444
435
|
const ext = path.extname(file).toLowerCase();
|
|
445
436
|
const ctype =
|
|
@@ -461,19 +452,19 @@ function streamFile(file, res) {
|
|
|
461
452
|
}
|
|
462
453
|
|
|
463
454
|
function resolveUiDist() {
|
|
464
|
-
//
|
|
455
|
+
// Optional override for power users
|
|
465
456
|
const fromEnv = process.env.STATIKAPI_UI_DIR;
|
|
466
457
|
if (fromEnv && hasIndex(fromEnv)) return fromEnv;
|
|
467
458
|
|
|
468
|
-
//
|
|
459
|
+
// Bundled with the CLI: packages/cli/ui/
|
|
469
460
|
const bundled = path.resolve(__dirname, '..', '..', 'ui');
|
|
470
461
|
if (hasIndex(bundled)) return bundled;
|
|
471
462
|
|
|
472
|
-
//
|
|
463
|
+
// Monorepo dev fallback: packages/ui/dist
|
|
473
464
|
const monorepoDist = path.resolve(__dirname, '..', '..', '..', 'ui', 'dist');
|
|
474
465
|
if (hasIndex(monorepoDist)) return monorepoDist;
|
|
475
466
|
|
|
476
|
-
//
|
|
467
|
+
// Last resort: throw with a helpful hint
|
|
477
468
|
throw new Error(
|
|
478
469
|
'StatikAPI UI build not found. ' +
|
|
479
470
|
'Either keep a built UI at packages/cli/ui/ (index.html present), ' +
|