makersclaw 0.6.0 → 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.
Files changed (141) hide show
  1. package/README.md +48 -8
  2. package/package.json +1 -1
  3. package/r/annotate.json +4 -4
  4. package/r/approval-request.json +3 -3
  5. package/r/audio-player.json +3 -3
  6. package/r/auth-form.json +2 -2
  7. package/r/board.json +4 -4
  8. package/r/calendar-view.json +4 -4
  9. package/r/cart.json +3 -3
  10. package/r/chart.json +3 -3
  11. package/r/chat.json +3 -3
  12. package/r/code-editor.json +4 -4
  13. package/r/comment-box.json +4 -4
  14. package/r/contact-section.json +3 -3
  15. package/r/core.json +3 -3
  16. package/r/csv-import.json +4 -4
  17. package/r/data-table.json +3 -3
  18. package/r/diagram.json +3 -3
  19. package/r/doc-editor.json +4 -4
  20. package/r/doc-page.json +4 -4
  21. package/r/email-render.json +2 -2
  22. package/r/faq.json +2 -2
  23. package/r/file-upload.json +3 -3
  24. package/r/flow-canvas.json +4 -4
  25. package/r/footer.json +3 -3
  26. package/r/gantt.json +4 -4
  27. package/r/job-panel.json +3 -3
  28. package/r/json-editor.json +4 -4
  29. package/r/map.json +5 -5
  30. package/r/menubar.json +2 -2
  31. package/r/mind-map.json +4 -4
  32. package/r/navigation-menu.json +2 -2
  33. package/r/order-detail.json +2 -2
  34. package/r/org-chart.json +4 -4
  35. package/r/page-builder.json +6 -6
  36. package/r/payment-methods.json +2 -2
  37. package/r/pdf-document.json +2 -2
  38. package/r/pdf-viewer.json +6 -6
  39. package/r/product-detail.json +3 -3
  40. package/r/product-grid.json +4 -4
  41. package/r/record-form.json +3 -3
  42. package/r/record-notes.json +5 -5
  43. package/r/registry.json +121 -121
  44. package/r/search-dialog.json +3 -3
  45. package/r/settings-list.json +3 -3
  46. package/r/setup-checklist.json +3 -3
  47. package/r/share-dialog.json +3 -3
  48. package/r/sidebar.json +2 -2
  49. package/r/signature-pad.json +3 -3
  50. package/r/sketch-canvas.json +5 -5
  51. package/r/spreadsheet.json +3 -3
  52. package/r/stat-cards.json +4 -4
  53. package/r/task-list.json +4 -4
  54. package/r/task-model.json +3 -3
  55. package/r/testimonials.json +2 -2
  56. package/r/transaction-list.json +3 -3
  57. package/r/whiteboard.json +4 -4
  58. package/registry/blocks/annotate/README.md +14 -5
  59. package/registry/blocks/approval-request/README.md +15 -8
  60. package/registry/blocks/audio-player/README.md +17 -10
  61. package/registry/blocks/board/README.md +13 -9
  62. package/registry/blocks/board/board.jsx +1 -1
  63. package/registry/blocks/calendar-view/README.md +28 -4
  64. package/registry/blocks/cart/README.md +14 -10
  65. package/registry/blocks/chart/README.md +14 -7
  66. package/registry/blocks/chat/README.md +43 -13
  67. package/registry/blocks/code-editor/README.md +4 -0
  68. package/registry/blocks/code-editor/code-editor.jsx +1 -1
  69. package/registry/blocks/comment-box/README.md +20 -13
  70. package/registry/blocks/contact-section/README.md +7 -6
  71. package/registry/blocks/csv-import/README.md +34 -12
  72. package/registry/blocks/data-table/README.md +41 -8
  73. package/registry/blocks/diagram/diagram.jsx +1 -1
  74. package/registry/blocks/doc-editor/README.md +18 -6
  75. package/registry/blocks/doc-editor/doc-editor.jsx +1 -1
  76. package/registry/blocks/doc-page/README.md +16 -6
  77. package/registry/blocks/file-upload/README.md +7 -1
  78. package/registry/blocks/flow-canvas/README.md +16 -5
  79. package/registry/blocks/flow-canvas/flow-canvas.jsx +1 -1
  80. package/registry/blocks/footer/README.md +4 -2
  81. package/registry/blocks/gantt/README.md +18 -12
  82. package/registry/blocks/job-panel/README.md +1 -1
  83. package/registry/blocks/json-editor/README.md +16 -4
  84. package/registry/blocks/map/README.md +19 -3
  85. package/registry/blocks/map/map-view.jsx +1 -1
  86. package/registry/blocks/map/maplibre.js +1 -1
  87. package/registry/blocks/mind-map/README.md +16 -5
  88. package/registry/blocks/org-chart/README.md +10 -7
  89. package/registry/blocks/page-builder/README.md +13 -6
  90. package/registry/blocks/page-builder/page-builder.jsx +1 -1
  91. package/registry/blocks/page-builder/page-view.jsx +1 -1
  92. package/registry/blocks/page-builder/page.js +1 -1
  93. package/registry/blocks/pdf-viewer/README.md +22 -20
  94. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1 -1
  95. package/registry/blocks/pdf-viewer/pdfjs.js +1 -1
  96. package/registry/blocks/pdf-viewer/ssr-shim.js +1 -1
  97. package/registry/blocks/product-detail/README.md +13 -7
  98. package/registry/blocks/product-detail/demo.jsx +1 -1
  99. package/registry/blocks/product-grid/README.md +12 -10
  100. package/registry/blocks/record-form/README.md +26 -9
  101. package/registry/blocks/record-notes/README.md +42 -30
  102. package/registry/blocks/search-dialog/README.md +38 -7
  103. package/registry/blocks/settings-list/README.md +29 -17
  104. package/registry/blocks/setup-checklist/README.md +12 -14
  105. package/registry/blocks/share-dialog/README.md +1 -1
  106. package/registry/blocks/signature-pad/README.md +15 -4
  107. package/registry/blocks/sketch-canvas/README.md +13 -4
  108. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1 -1
  109. package/registry/blocks/sketch-canvas/ssr-shim.js +3 -3
  110. package/registry/blocks/spreadsheet/README.md +17 -8
  111. package/registry/blocks/stat-cards/README.md +17 -8
  112. package/registry/blocks/task-list/README.md +14 -11
  113. package/registry/blocks/task-model/README.md +3 -3
  114. package/registry/blocks/transaction-list/README.md +15 -7
  115. package/registry/blocks/whiteboard/README.md +19 -13
  116. package/src/cli.mjs +31 -4
  117. package/src/install.mjs +263 -21
  118. package/src/registry.mjs +78 -1
  119. package/templates/next/browser/app/auto-refresh.jsx +67 -0
  120. package/templates/next/browser/app/layout.jsx +94 -0
  121. package/templates/next/browser/app/page.jsx +60 -0
  122. package/templates/next/browser/app/s/[key]/page.jsx +95 -0
  123. package/templates/next/browser/lib/actions.js +16 -0
  124. package/templates/next/browser/lib/data.js +43 -0
  125. package/templates/next/files/README.md +810 -79
  126. package/templates/next/files/app/frame.js +128 -4
  127. package/templates/next/files/check/run.mjs +1438 -41
  128. package/templates/next/files/components/ui/item.jsx +2 -2
  129. package/templates/next/files/components/ui/notice.jsx +1 -1
  130. package/templates/next/files/components/ui/separator.jsx +1 -1
  131. package/templates/next/files/lib/actions.js +170 -51
  132. package/templates/next/files/lib/brain-server.js +96 -0
  133. package/templates/next/files/lib/brain.js +413 -0
  134. package/templates/next/files/lib/claw.js +11 -0
  135. package/templates/next/files/lib/data.js +119 -29
  136. package/templates/next/files/lib/db.js +97 -17
  137. package/templates/next/files/lib/door.js +680 -0
  138. package/templates/next/files/next.config.mjs +36 -2
  139. package/templates/next/files/surfaces.js +3 -2
  140. package/templates/next/template.json +9 -3
  141. package/templates/next/files/schema.sql +0 -22
@@ -1,3 +1,4 @@
1
+ import { headers } from "next/headers";
1
2
  import { Pool, types } from "pg";
2
3
 
3
4
  // A `date` column is a day on a wall calendar, not an instant, so it is
@@ -26,18 +27,84 @@ globalThis._pgPool = pool;
26
27
 
27
28
  export const query = (text, params) => pool.query(text, params);
28
29
 
30
+ /**
31
+ * Who is asking: the member the platform's proxy named on this request
32
+ * (`x-claw-user-id`, `x-claw-user-email`; the proxy drops a browser's own
33
+ * copies first, so they are only ever its word). `''` for each one it did
34
+ * not name: a local run, a render outside a request, a job.
35
+ * → { id, email }
36
+ */
37
+ export async function requestMember() {
38
+ try {
39
+ const asked = await headers();
40
+ return { id: asked.get("x-claw-user-id") || "", email: asked.get("x-claw-user-email") || "" };
41
+ } catch {
42
+ return { id: "", email: "" };
43
+ }
44
+ }
45
+
46
+ // The member, told to the database inside the write's own transaction. The
47
+ // third argument, true, makes each setting local: the COMMIT ends it, so the
48
+ // next statement on this pooled connection never runs as this member. Never
49
+ // false (the platform's rule since the Neon probe; test/data.test.mjs greps
50
+ // the template for it). Values are bound, never written into the text.
51
+ const MEMBER_SETTINGS =
52
+ "SELECT set_config('claw.member_id', $1, true), set_config('claw.member_email', $2, true)";
53
+
54
+ /**
55
+ * Run `work(query)` in one transaction on one connection, after telling
56
+ * the database who is asking. A default, a trigger or an action function
57
+ * reads it the same way in a server app and a browser one (where the
58
+ * platform's data door sets the same two):
59
+ *
60
+ * nullif(current_setting('claw.member_email', true), '')
61
+ *
62
+ * It is a label, not a permission: nothing in the platform trusts it, and
63
+ * a column the page must not choose (`created_by`) is set by a trigger
64
+ * that reads it. Every lib/actions.js write runs here. `work` gets a
65
+ * `query(text, params)` bound to the transaction's connection; use only
66
+ * that inside it. → whatever `work` returns. A failure rolls back and
67
+ * throws on.
68
+ */
69
+ export async function transaction(work) {
70
+ const member = await requestMember();
71
+ const client = await pool.connect();
72
+ let broken;
73
+ try {
74
+ await client.query("BEGIN");
75
+ await client.query(MEMBER_SETTINGS, [member.id, member.email]);
76
+ const result = await work((text, params) => client.query(text, params));
77
+ await client.query("COMMIT");
78
+ return result;
79
+ } catch (error) {
80
+ try {
81
+ await client.query("ROLLBACK");
82
+ } catch (lost) {
83
+ // The connection itself failed: the pool must not lend it again.
84
+ broken = lost;
85
+ }
86
+ throw error;
87
+ } finally {
88
+ client.release(broken);
89
+ }
90
+ }
91
+
29
92
  /** The artifact this app belongs to. product_run sets it from the folder
30
- * the app runs in; every activity row keys on it, and so does the
31
- * Activity tab the OS draws on the app window. */
93
+ * the app runs in; app/layout.jsx reads it to turn examples off, and an
94
+ * app may use it to name itself. The activity lines no longer need it:
95
+ * claw_app.activity fills in the app itself (logActivity, below). */
32
96
  export function artifactId() {
33
97
  return process.env.CLAW_ARTIFACT_ID || null;
34
98
  }
35
99
 
36
100
  const IDENT = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
37
101
 
38
- /** Quote a table or column name for SQL: "investors" → "investors",
39
- * "public.investors" → "public"."investors". Anything else throws, so a
40
- * typo in a surface config can never reach the database as SQL. */
102
+ /** Quote a table or column name for SQL: "investors" → "investors".
103
+ * An app names its tables bare: its own schema is first on its role's
104
+ * search_path. Two parts still pass ("public.investors" →
105
+ * "public"."investors"), for an app from before 0.7.0 whose tables are
106
+ * in public and whose code says so. Anything else throws, so a typo in a
107
+ * surface config can never reach the database as SQL. */
41
108
  export function ident(name) {
42
109
  const parts = String(name ?? "").split(".");
43
110
  if (!parts.length || parts.length > 2 || !parts.every((p) => IDENT.test(p))) {
@@ -46,13 +113,26 @@ export function ident(name) {
46
113
  return parts.map((p) => `"${p}"`).join(".");
47
114
  }
48
115
 
116
+ // Postgres's "relation does not exist": no claw_app.activity to write to.
117
+ const NO_SUCH_RELATION = "42P01";
118
+
49
119
  /**
50
120
  * Record what happened, for the Activity tab the OS draws on the app
51
- * window (and any surface that reads the table with loadActivity). Every
52
- * lib/actions.js write calls this; the artifact's agent writes the same
53
- * table with the sql verb.
121
+ * window (and any surface that reads the lines with loadActivity). Every
122
+ * lib/actions.js write calls this; the app's agent writes the same lines
123
+ * with the sql verb.
54
124
  * Never throws — an activity line must not fail the write it describes.
55
125
  *
126
+ * The line goes into claw_app.activity: the platform's view of the
127
+ * workspace's activity table, holding only this app's lines. The view
128
+ * fills in `artifact_id` (the app whose role the connection runs as) and
129
+ * `id`, so this names neither: the app needs no CLAW_ARTIFACT_ID, and it
130
+ * cannot write a line as another app. Up to 0.6.x it inserted into
131
+ * public.artifact_activity with CLAW_ARTIFACT_ID; an app on its own schema
132
+ * can reach nothing in public. Outside Makersclaw, or on a platform from
133
+ * before the view, there is no claw_app.activity: the line is not
134
+ * recorded, and this returns false, as on any other failure.
135
+ *
56
136
  * action found, drafted, sent, replied, skipped, edited, moved, added…
57
137
  * surface the surface key the row belongs to (the OS tab shows its
58
138
  * label; a link into the app is /s/<surface>?row=<row_ref>)
@@ -62,17 +142,11 @@ export function ident(name) {
62
142
  * by 'agent' | 'user:<email>' | 'run:<id>'
63
143
  */
64
144
  export async function logActivity({ action, surface, row_ref, detail, data, by }) {
65
- const id = artifactId();
66
- if (!id) {
67
- console.warn(`[activity] not recorded (no CLAW_ARTIFACT_ID): ${action} ${detail ?? ""}`);
68
- return false;
69
- }
70
145
  try {
71
146
  await query(
72
- `INSERT INTO public.artifact_activity (artifact_id, action, surface, row_ref, detail, data, by)
73
- VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7)`,
147
+ `INSERT INTO claw_app.activity (action, surface, row_ref, detail, data, by)
148
+ VALUES ($1, $2, $3, $4, $5::jsonb, $6)`,
74
149
  [
75
- id,
76
150
  String(action || "edited"),
77
151
  surface ?? null,
78
152
  row_ref == null ? null : String(row_ref),
@@ -83,7 +157,13 @@ export async function logActivity({ action, surface, row_ref, detail, data, by }
83
157
  );
84
158
  return true;
85
159
  } catch (error) {
86
- console.error(`[activity] not recorded: ${String(error)}`);
160
+ // No view is where the app runs, not a fault in it: a warning, as the
161
+ // missing CLAW_ARTIFACT_ID was up to 0.6.x. Anything else is an error.
162
+ if (error?.code === NO_SUCH_RELATION) {
163
+ console.warn(`[activity] not recorded (no claw_app.activity here): ${action} ${detail ?? ""}`);
164
+ } else {
165
+ console.error(`[activity] not recorded: ${String(error)}`);
166
+ }
87
167
  return false;
88
168
  }
89
169
  }