makersclaw 0.5.2 → 0.7.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 +73 -7
- package/package.json +3 -2
- package/r/annotate.json +4 -4
- package/r/approval-request.json +3 -3
- package/r/audio-player.json +3 -3
- package/r/auth-form.json +2 -2
- package/r/board.json +4 -4
- package/r/calendar-view.json +4 -4
- package/r/cart.json +3 -3
- package/r/chart.json +3 -3
- package/r/chat.json +3 -3
- package/r/code-editor.json +4 -4
- package/r/comment-box.json +4 -4
- package/r/contact-section.json +3 -3
- package/r/core.json +3 -3
- package/r/csv-import.json +4 -4
- package/r/data-table.json +3 -3
- package/r/diagram.json +3 -3
- package/r/doc-editor.json +4 -4
- package/r/doc-page.json +4 -4
- package/r/email-render.json +2 -2
- package/r/faq.json +2 -2
- package/r/file-upload.json +3 -3
- package/r/flow-canvas.json +4 -4
- package/r/footer.json +3 -3
- package/r/gantt.json +4 -4
- package/r/job-panel.json +3 -3
- package/r/json-editor.json +4 -4
- package/r/map.json +5 -5
- package/r/menubar.json +2 -2
- package/r/mind-map.json +4 -4
- package/r/navigation-menu.json +2 -2
- package/r/order-detail.json +2 -2
- package/r/org-chart.json +4 -4
- package/r/page-builder.json +6 -6
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +6 -6
- package/r/product-detail.json +3 -3
- package/r/product-grid.json +4 -4
- package/r/record-form.json +3 -3
- package/r/record-notes.json +5 -5
- package/r/registry.json +121 -121
- package/r/search-dialog.json +3 -3
- package/r/settings-list.json +3 -3
- package/r/setup-checklist.json +3 -3
- package/r/share-dialog.json +3 -3
- package/r/sidebar.json +2 -2
- package/r/signature-pad.json +3 -3
- package/r/sketch-canvas.json +5 -5
- package/r/spreadsheet.json +3 -3
- package/r/stat-cards.json +4 -4
- package/r/task-list.json +4 -4
- package/r/task-model.json +3 -3
- package/r/testimonials.json +2 -2
- package/r/transaction-list.json +3 -3
- package/r/whiteboard.json +4 -4
- package/registry/blocks/annotate/README.md +14 -5
- package/registry/blocks/approval-request/README.md +15 -8
- package/registry/blocks/audio-player/README.md +17 -10
- package/registry/blocks/board/README.md +13 -9
- package/registry/blocks/board/board.jsx +1 -1
- package/registry/blocks/calendar-view/README.md +28 -4
- package/registry/blocks/cart/README.md +14 -10
- package/registry/blocks/chart/README.md +14 -7
- package/registry/blocks/chat/README.md +43 -13
- package/registry/blocks/code-editor/README.md +4 -0
- package/registry/blocks/code-editor/code-editor.jsx +1 -1
- package/registry/blocks/comment-box/README.md +20 -13
- package/registry/blocks/contact-section/README.md +7 -6
- package/registry/blocks/csv-import/README.md +34 -12
- package/registry/blocks/data-table/README.md +41 -8
- package/registry/blocks/diagram/diagram.jsx +1 -1
- package/registry/blocks/doc-editor/README.md +18 -6
- package/registry/blocks/doc-editor/doc-editor.jsx +1 -1
- package/registry/blocks/doc-page/README.md +16 -6
- package/registry/blocks/file-upload/README.md +7 -1
- package/registry/blocks/flow-canvas/README.md +16 -5
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1 -1
- package/registry/blocks/footer/README.md +4 -2
- package/registry/blocks/gantt/README.md +18 -12
- package/registry/blocks/job-panel/README.md +1 -1
- package/registry/blocks/json-editor/README.md +16 -4
- package/registry/blocks/map/README.md +19 -3
- package/registry/blocks/map/map-view.jsx +1 -1
- package/registry/blocks/map/maplibre.js +1 -1
- package/registry/blocks/mind-map/README.md +16 -5
- package/registry/blocks/org-chart/README.md +10 -7
- package/registry/blocks/page-builder/README.md +13 -6
- package/registry/blocks/page-builder/page-builder.jsx +1 -1
- package/registry/blocks/page-builder/page-view.jsx +1 -1
- package/registry/blocks/page-builder/page.js +1 -1
- package/registry/blocks/pdf-viewer/README.md +22 -20
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1 -1
- package/registry/blocks/pdf-viewer/pdfjs.js +1 -1
- package/registry/blocks/pdf-viewer/ssr-shim.js +1 -1
- package/registry/blocks/product-detail/README.md +13 -7
- package/registry/blocks/product-detail/demo.jsx +1 -1
- package/registry/blocks/product-grid/README.md +12 -10
- package/registry/blocks/record-form/README.md +26 -9
- package/registry/blocks/record-notes/README.md +42 -30
- package/registry/blocks/search-dialog/README.md +38 -7
- package/registry/blocks/settings-list/README.md +29 -17
- package/registry/blocks/setup-checklist/README.md +12 -14
- package/registry/blocks/share-dialog/README.md +1 -1
- package/registry/blocks/signature-pad/README.md +15 -4
- package/registry/blocks/sketch-canvas/README.md +13 -4
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1 -1
- package/registry/blocks/sketch-canvas/ssr-shim.js +3 -3
- package/registry/blocks/spreadsheet/README.md +17 -8
- package/registry/blocks/stat-cards/README.md +17 -8
- package/registry/blocks/task-list/README.md +14 -11
- package/registry/blocks/task-model/README.md +3 -3
- package/registry/blocks/transaction-list/README.md +15 -7
- package/registry/blocks/whiteboard/README.md +19 -13
- package/src/cli.mjs +65 -9
- package/src/install.mjs +360 -21
- package/src/lockfile.mjs +468 -0
- package/src/pm.mjs +473 -0
- package/src/registry.mjs +125 -1
- package/templates/next/browser/app/auto-refresh.jsx +67 -0
- package/templates/next/browser/app/layout.jsx +94 -0
- package/templates/next/browser/app/page.jsx +60 -0
- package/templates/next/browser/app/s/[key]/page.jsx +95 -0
- package/templates/next/browser/lib/actions.js +16 -0
- package/templates/next/browser/lib/data.js +43 -0
- package/templates/next/files/README.md +818 -82
- package/templates/next/files/app/claw-alive/route.js +2 -2
- package/templates/next/files/app/frame.js +134 -9
- package/templates/next/files/app/layout.jsx +2 -2
- package/templates/next/files/check/run.mjs +1491 -53
- package/templates/next/files/components/ui/item.jsx +2 -2
- package/templates/next/files/components/ui/notice.jsx +1 -1
- package/templates/next/files/components/ui/separator.jsx +1 -1
- package/templates/next/files/lib/actions.js +171 -52
- package/templates/next/files/lib/brain-server.js +96 -0
- package/templates/next/files/lib/brain.js +413 -0
- package/templates/next/files/lib/claw.js +11 -0
- package/templates/next/files/lib/data.js +120 -30
- package/templates/next/files/lib/db.js +97 -17
- package/templates/next/files/lib/door.js +680 -0
- package/templates/next/files/next.config.mjs +85 -9
- package/templates/next/files/package.json +3 -3
- package/templates/next/files/{middleware.js → proxy.js} +13 -6
- package/templates/next/files/surfaces.js +3 -2
- package/templates/next/pnpm-lock.yaml +5870 -0
- package/templates/next/template.json +13 -6
- package/templates/next/files/schema.sql +0 -22
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// before every refresh: only a 2xx from here means the refresh will get
|
|
5
5
|
// its payload and not reload the frame (app/frame.js, answering, has the
|
|
6
6
|
// story). It renders nothing and reads nothing, so the question costs the
|
|
7
|
-
// app almost nothing;
|
|
8
|
-
//
|
|
7
|
+
// app almost nothing; proxy.js's token check still runs first, as on
|
|
8
|
+
// every request.
|
|
9
9
|
//
|
|
10
10
|
// A 204 and not the 404 of a path nobody serves: the browser logs every
|
|
11
11
|
// 404 fetch as a console error, and an app that logs one every 5 s reads
|
|
@@ -63,7 +63,8 @@ export const PRESENCE_EVENTS = ["pointerdown", "pointermove", "keydown", "wheel"
|
|
|
63
63
|
* and no probe, while any element on the page carries it. For a surface
|
|
64
64
|
* whose rows only its own writes change, or one too big to send every
|
|
65
65
|
* few seconds (a base of 4,812 records was about 2 MB a refresh). Its
|
|
66
|
-
* writes still re-render it (lib/actions.js revalidates
|
|
66
|
+
* writes still re-render it (a server app's lib/actions.js revalidates;
|
|
67
|
+
* a browser app's writes call lib/door.js dataChanged()), and so does
|
|
67
68
|
* every navigation. */
|
|
68
69
|
export const REFRESH_OFF = '[data-claw-refresh="off"]';
|
|
69
70
|
|
|
@@ -142,9 +143,9 @@ export function nextRefreshIn(lastCostMs = 0) {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
/** What to ask before a refresh: app/claw-alive/route.js, a fixed route
|
|
145
|
-
* that answers 204 with no body — no render, no database.
|
|
146
|
-
* checks the proxy's token first, as on every request, so a 204
|
|
147
|
-
* page's own request would be answered too.
|
|
146
|
+
* that answers 204 with no body — no render, no database. proxy.js
|
|
147
|
+
* checks the product proxy's token first, as on every request, so a 204
|
|
148
|
+
* says the page's own request would be answered too.
|
|
148
149
|
*
|
|
149
150
|
* Not a path the app merely 404s. The first draft of 0.3.3 asked for a
|
|
150
151
|
* file under _next/static/ that no build writes and read the 404 as
|
|
@@ -172,8 +173,9 @@ export function probeUrl(doc) {
|
|
|
172
173
|
*
|
|
173
174
|
* Why ask first: router.refresh() treats any answer that is not its own
|
|
174
175
|
* payload as "this is not my app any more" and loads the whole page
|
|
175
|
-
* again (
|
|
176
|
-
*
|
|
176
|
+
* again (fetch-server-response.js: a non-OK or non-RSC response becomes
|
|
177
|
+
* a browser navigation; Next 16's refresh reaches it through
|
|
178
|
+
* ppr-navigations.js and still does). In the frame that reload wipes a
|
|
177
179
|
* half-typed field, and one 502 was enough (landing-page-reviewer,
|
|
178
180
|
* okr-tracker, 2026-09-24). So the probe says yes exactly where the
|
|
179
181
|
* refresh would not turn into a reload. Asking first leaves only the
|
|
@@ -194,6 +196,123 @@ export async function answering(url, fetchImpl = globalThis.fetch, timeoutMs = P
|
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
// Auto-refresh in a browser app
|
|
201
|
+
|
|
202
|
+
// A browser app (makersclaw.json "mode": "browser") has no server to ask
|
|
203
|
+
// and nothing to re-render from: its pages are files, prerendered once,
|
|
204
|
+
// and its rows come from the platform's data door through lib/door.js's
|
|
205
|
+
// hooks. So its refresh is not router.refresh(): under an export that
|
|
206
|
+
// fetches the same prebuilt payload and shows nothing new. It is the
|
|
207
|
+
// hooks reading again (lib/door.js dataChanged(), then whenLanded()),
|
|
208
|
+
// and only when something changed: a question the door answers in one
|
|
209
|
+
// small request, where the server app's refresh re-rendered every
|
|
210
|
+
// surface every 5 s whether anything had changed or not (claw's
|
|
211
|
+
// STATIC-SPEC §3, a browser app's auto-refresh).
|
|
212
|
+
//
|
|
213
|
+
// The question is the door's change feed, GET _claw/data/changes (claw's
|
|
214
|
+
// CONTRACTS §8), which answers two things:
|
|
215
|
+
// - `changes`: the company brain's changes in the app's kinds and the
|
|
216
|
+
// member's areas since the cursor, and `next`, the cursor after them;
|
|
217
|
+
// - `tables`: a stamp of the app's own tables (Postgres's counters:
|
|
218
|
+
// rows written, then rows live). It moves with any write to them, the
|
|
219
|
+
// agent's, a job's, another member's. The platform's counters lag:
|
|
220
|
+
// a write shows in the stamp within about 11 s, two or three ticks.
|
|
221
|
+
// The first answer only sets the cursor and the stamp: the hooks read
|
|
222
|
+
// the rows on their own as the page opened. After it, "something
|
|
223
|
+
// changed" is a brain change, a cursor that moved (a brain that
|
|
224
|
+
// appeared, or an app whose grant went away), or a different stamp, up
|
|
225
|
+
// or down. A stamp that moved for nothing (autovacuum re-counting, a
|
|
226
|
+
// rolled-back write, a restart that zeroed the counters) costs one read
|
|
227
|
+
// too many, never one too few; so does the page's own write, which
|
|
228
|
+
// reads again at once and then shows in the stamp too.
|
|
229
|
+
|
|
230
|
+
/** The feed's path under _claw/: the changes after `since`, the last
|
|
231
|
+
* answer's `next`. None yet: the door answers where the feed is now. */
|
|
232
|
+
export function changesPath(since) {
|
|
233
|
+
return since === undefined || since === null || since === "" ? "data/changes" : `data/changes?since=${encodeURIComponent(String(since))}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** An abort signal that fires at the deadline or on `stop`, whichever is
|
|
237
|
+
* first. A browser without AbortSignal.any keeps the deadline: a held
|
|
238
|
+
* request must not stall every tick after it. */
|
|
239
|
+
function askSignal(timeoutMs, stop) {
|
|
240
|
+
const timeout = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
241
|
+
if (!timeout || !stop) return timeout ?? stop;
|
|
242
|
+
return typeof AbortSignal.any === "function" ? AbortSignal.any([timeout, stop]) : timeout;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* The browser app's probe: has anything changed since the last refresh?
|
|
247
|
+
* `ask(path, signal)` sends GET _claw/<path> and resolves to lib/claw.js
|
|
248
|
+
* claw()'s answer ({ ok, status, data, unavailable }); it may throw, and
|
|
249
|
+
* a throw is no answer. → { probe, covered, stop }
|
|
250
|
+
*
|
|
251
|
+
* - probe() resolves true when a change was seen that no refresh has
|
|
252
|
+
* covered yet. It asks the door every time (one ask at a time: a
|
|
253
|
+
* second probe while one is out shares its answer), within
|
|
254
|
+
* PROBE_TIMEOUT_MS.
|
|
255
|
+
* - covered(): a refresh has started, so what was seen is on its way.
|
|
256
|
+
* A change stays owed until then: a tick that saw one and found the
|
|
257
|
+
* founder typing refreshes on a later tick, not never.
|
|
258
|
+
* - A failed answer changes nothing: the cursor and the stamp stay, and
|
|
259
|
+
* the next tick asks again. A 5xx, a 401 (a grant gone stale), no
|
|
260
|
+
* network, no answer in time. A refresh would read nothing new.
|
|
261
|
+
* - A 404 that names no code is no door at all (a Makersclaw from
|
|
262
|
+
* before it, a `next dev` with nothing in front of it): the feed
|
|
263
|
+
* stops asking for the page's life, so the console does not log a
|
|
264
|
+
* failed request every five seconds.
|
|
265
|
+
* - stop() aborts an ask in flight; every probe after it is false.
|
|
266
|
+
*/
|
|
267
|
+
export function changeFeed(ask, { timeoutMs = PROBE_TIMEOUT_MS } = {}) {
|
|
268
|
+
let first = true; // no answer yet: the next one only sets where we are
|
|
269
|
+
let cursor = null; // the feed's `next`: where the next ask starts
|
|
270
|
+
let stamp = null; // the own tables' stamp, as last answered
|
|
271
|
+
let owed = false; // a change seen and not yet covered by a refresh
|
|
272
|
+
let gone = false; // no door answers here
|
|
273
|
+
let stopped = false;
|
|
274
|
+
let asking = null; // the ask in flight
|
|
275
|
+
const halt = typeof AbortController === "function" ? new AbortController() : null;
|
|
276
|
+
|
|
277
|
+
async function askOnce() {
|
|
278
|
+
let answer;
|
|
279
|
+
try {
|
|
280
|
+
answer = await ask(changesPath(cursor), askSignal(timeoutMs, halt?.signal));
|
|
281
|
+
} catch {
|
|
282
|
+
return; // no answer
|
|
283
|
+
}
|
|
284
|
+
if (stopped || !answer) return;
|
|
285
|
+
if (!answer.ok) {
|
|
286
|
+
if (answer.status === 404 && answer.unavailable) gone = true;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const data = answer.data;
|
|
290
|
+
if (!data || typeof data !== "object" || Array.isArray(data) || data.ok === false) return;
|
|
291
|
+
const next = data.next === undefined || data.next === null ? null : String(data.next);
|
|
292
|
+
const tables = data.tables === undefined || data.tables === null ? null : String(data.tables);
|
|
293
|
+
const changed = (Array.isArray(data.changes) && data.changes.length > 0) || next !== cursor || tables !== stamp;
|
|
294
|
+
if (!first && changed) owed = true;
|
|
295
|
+
first = false;
|
|
296
|
+
cursor = next;
|
|
297
|
+
stamp = tables;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
probe() {
|
|
302
|
+
if (stopped || gone) return Promise.resolve(false);
|
|
303
|
+
if (!asking) asking = askOnce().finally(() => (asking = null));
|
|
304
|
+
return asking.then(() => owed && !stopped);
|
|
305
|
+
},
|
|
306
|
+
covered() {
|
|
307
|
+
owed = false;
|
|
308
|
+
},
|
|
309
|
+
stop() {
|
|
310
|
+
stopped = true;
|
|
311
|
+
halt?.abort();
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
197
316
|
/** `promise`, or undefined once `ms` have passed, whichever comes first. */
|
|
198
317
|
function within(promise, ms, timers) {
|
|
199
318
|
let timer = null;
|
|
@@ -204,8 +323,14 @@ function within(promise, ms, timers) {
|
|
|
204
323
|
/**
|
|
205
324
|
* The refresh loop app/auto-refresh.jsx runs, as plain code over a
|
|
206
325
|
* document so `npm test` can drive it. `refresh()` starts one refresh and
|
|
207
|
-
* resolves when it has landed (
|
|
208
|
-
*
|
|
326
|
+
* resolves when it has landed; `probe()` is asked first, and a tick
|
|
327
|
+
* refreshes only on its yes. → { stop() }
|
|
328
|
+
*
|
|
329
|
+
* The two modes differ only in those two. A server app's refresh is
|
|
330
|
+
* router.refresh() in a transition, landed when the transition settles,
|
|
331
|
+
* and its probe is `answering` (the default here): will the app answer?
|
|
332
|
+
* A browser app's refresh is lib/door.js dataChanged() then whenLanded(),
|
|
333
|
+
* and its probe is a changeFeed's: has anything changed?
|
|
209
334
|
*
|
|
210
335
|
* Until 0.5.0 a timer fired every REFRESH_MS whatever was in flight: the
|
|
211
336
|
* probe was guarded, the refresh was not, so a render slower than the
|
|
@@ -222,7 +347,7 @@ function within(promise, ms, timers) {
|
|
|
222
347
|
* (PRESENCE_EVENTS, in the frame): the next sign refreshes at once
|
|
223
348
|
* and the loop goes on. Coming back from hidden is such a sign;
|
|
224
349
|
* - a tick refreshes only when shouldRefresh says so, with the probe's
|
|
225
|
-
*
|
|
350
|
+
* yes, and never while a surface has opted out (REFRESH_OFF).
|
|
226
351
|
*
|
|
227
352
|
* The rules are asked again after the probe: typing may have started, or
|
|
228
353
|
* the tab changed, while it was on its way.
|
|
@@ -20,8 +20,8 @@ export const metadata = { title: process.env.CLAW_PRODUCT || "Artifact" };
|
|
|
20
20
|
// lib/claw.js, the product name, and data-theme. The theme follows the
|
|
21
21
|
// desk: the OS window opens the app with ?theme=light|dark and the
|
|
22
22
|
// product proxy repeats it as the x-claw-theme header on every request
|
|
23
|
-
// (
|
|
24
|
-
// the proxy. Dark when neither says — the desk is dark.
|
|
23
|
+
// (proxy.js explains); the claw_theme cookie covers a run without
|
|
24
|
+
// the product proxy. Dark when neither says — the desk is dark.
|
|
25
25
|
//
|
|
26
26
|
// The palette follows the WORKSPACE: <head> links `_claw/theme.css`, the
|
|
27
27
|
// preset picked in System Settings → Appearance, served by the product
|