makersclaw 0.5.1 → 0.6.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 +29 -3
- package/package.json +3 -2
- package/r/annotate.json +3 -3
- package/r/approval-request.json +2 -2
- package/r/audio-player.json +2 -2
- package/r/auth-form.json +2 -2
- package/r/board.json +2 -2
- package/r/calendar-view.json +3 -3
- package/r/cart.json +2 -2
- package/r/chart.json +2 -2
- package/r/chat.json +2 -2
- package/r/code-editor.json +2 -2
- package/r/comment-box.json +3 -3
- package/r/contact-section.json +2 -2
- package/r/csv-import.json +3 -3
- package/r/data-table.json +2 -2
- package/r/diagram.json +2 -2
- package/r/doc-editor.json +2 -2
- package/r/doc-page.json +3 -3
- package/r/email-render.json +2 -2
- package/r/faq.json +2 -2
- package/r/file-upload.json +2 -2
- package/r/flow-canvas.json +2 -2
- package/r/footer.json +2 -2
- package/r/gantt.json +3 -3
- package/r/job-panel.json +2 -2
- package/r/json-editor.json +3 -3
- package/r/map.json +2 -2
- package/r/menubar.json +2 -2
- package/r/mind-map.json +3 -3
- package/r/navigation-menu.json +2 -2
- package/r/order-detail.json +2 -2
- package/r/org-chart.json +3 -3
- package/r/page-builder.json +2 -2
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +2 -2
- package/r/product-detail.json +2 -2
- package/r/product-grid.json +3 -3
- package/r/record-form.json +2 -2
- package/r/record-notes.json +4 -4
- package/r/registry.json +121 -121
- package/r/search-dialog.json +2 -2
- package/r/settings-list.json +2 -2
- package/r/setup-checklist.json +2 -2
- package/r/share-dialog.json +2 -2
- package/r/sidebar.json +2 -2
- package/r/signature-pad.json +2 -2
- package/r/sketch-canvas.json +2 -2
- package/r/spreadsheet.json +2 -2
- package/r/stat-cards.json +3 -3
- package/r/task-list.json +3 -3
- package/r/task-model.json +2 -2
- package/r/testimonials.json +2 -2
- package/r/transaction-list.json +2 -2
- package/r/whiteboard.json +3 -3
- package/src/cli.mjs +35 -6
- package/src/install.mjs +101 -4
- package/src/lockfile.mjs +468 -0
- package/src/pm.mjs +473 -0
- package/src/registry.mjs +48 -1
- package/templates/next/files/README.md +20 -15
- package/templates/next/files/app/claw-alive/route.js +2 -2
- package/templates/next/files/app/frame.js +6 -5
- package/templates/next/files/app/layout.jsx +2 -2
- package/templates/next/files/check/run.mjs +125 -15
- package/templates/next/files/lib/actions.js +1 -1
- package/templates/next/files/lib/data.js +1 -1
- package/templates/next/files/next.config.mjs +50 -8
- package/templates/next/files/package.json +3 -3
- package/templates/next/files/{middleware.js → proxy.js} +13 -6
- package/templates/next/pnpm-lock.yaml +5870 -0
- package/templates/next/template.json +5 -4
package/r/search-dialog.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "SearchDialog",
|
|
6
6
|
"description": "One ⌘K search over every kind of record — chats, documents, images, projects, people. Before typing it shows your sections (Last opened, Recent); while typing, ranked matches with the typed text marked, a date, image thumbnails, and kind chips (All, Chats, Images…) to narrow them. Searches your list in the browser, or your server through an async onSearch. Built on the kit's Command; SearchPanel is the same box inline.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"docs": "Installed to components/makersclaw/blocks/search-dialog. Import: import { SearchDialog, SearchPanel } from \"@/components/makersclaw/blocks/search-dialog\". Props and an example: components/makersclaw/blocks/search-dialog/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
45
45
|
"meta": {
|
|
46
46
|
"makersclaw": {
|
|
47
|
-
"version": "0.
|
|
47
|
+
"version": "0.6.0",
|
|
48
48
|
"useWhen": "An app has more than one kind of record and wants one global search box or ⌘K palette to find any of them, or a search page with type filters."
|
|
49
49
|
}
|
|
50
50
|
}
|
package/r/settings-list.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "SettingsList",
|
|
6
6
|
"description": "A card of settings, one row each — icon, label, description, meta lines, a badge, and its control: a Switch, a Select, a Button, a remove button or a menu of actions, with optional details that open under the row. Every change saves on its own through an async callback; the row shows the new value at once, a spinner while it saves, and on failure the old value back with the reason and Try again. variant=\"matrix\" is the notification grid: events by group down the side, channels (email, push, SMS) across, a switch per cell, stacked on a phone.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"docs": "Installed to components/makersclaw/blocks/settings-list. Import: import { SettingsList } from \"@/components/makersclaw/blocks/settings-list\". Props and an example: components/makersclaw/blocks/settings-list/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
60
60
|
"meta": {
|
|
61
61
|
"makersclaw": {
|
|
62
|
-
"version": "0.
|
|
62
|
+
"version": "0.6.0",
|
|
63
63
|
"useWhen": "An account or workspace settings screen where each setting applies the moment it is changed: preferences, two-step sign-in methods, signed-in devices, connected integrations, billing profiles, notification preferences per channel. Not for a form of fields saved together with one button (record-form)."
|
|
64
64
|
}
|
|
65
65
|
}
|
package/r/setup-checklist.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "SetupChecklist",
|
|
6
6
|
"description": "The steps to get set up: which are done, how far along the whole is (a ring, a bar, or \"Step 2 of 4\"), and the button for the next one, sent out through an async onAction that can fail on the step. Four shapes: folding rows in a card with a dismiss menu, numbered step cards, a plain step list with a help panel, and bordered accordion rows that can be locked until the step before is done.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"docs": "Installed to components/makersclaw/blocks/setup-checklist. Import: import { SetupChecklist } from \"@/components/makersclaw/blocks/setup-checklist\". Props and an example: components/makersclaw/blocks/setup-checklist/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
45
45
|
"meta": {
|
|
46
46
|
"makersclaw": {
|
|
47
|
-
"version": "0.
|
|
47
|
+
"version": "0.6.0",
|
|
48
48
|
"useWhen": "A new account, workspace or shop has a few things to do before it is useful (complete the profile, invite the team, connect a tool, launch) and the founder should see what is left. Not for a running job's stages (kit Steps or job-panel), and not for a multi-page form wizard."
|
|
49
49
|
}
|
|
50
50
|
}
|
package/r/share-dialog.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "ShareDialog",
|
|
6
6
|
"description": "Who can see a record and how to let more people in: invite by email (comma separated, with an access level), each person with their access in a menu (can view, can edit, remove), sharing switches, and a link with a copy button that turns to a check. A dialog, or the same body inline (SharePanel). Every change is an async callback; a failure shows and the old value comes back.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"docs": "Installed to components/makersclaw/blocks/share-dialog. Import: import { ShareDialog, SharePanel } from \"@/components/makersclaw/blocks/share-dialog\". Props and an example: components/makersclaw/blocks/share-dialog/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
46
46
|
"meta": {
|
|
47
47
|
"makersclaw": {
|
|
48
|
-
"version": "0.
|
|
48
|
+
"version": "0.6.0",
|
|
49
49
|
"useWhen": "A record, project, document or workspace can be shared: an \"Invite\" or \"Share\" button, a members list with roles, a public link to copy."
|
|
50
50
|
}
|
|
51
51
|
}
|
package/r/sidebar.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Sidebar",
|
|
6
6
|
"description": "An app's navigation down the left edge: app name or workspace switcher, groups of items with icons, counts and nested items, the signed-in person with their menu; collapses to icons (remembered) and becomes a Sheet behind a trigger on a phone. Optional: inset or floating look, a ⌘K search over every item, folding groups with colour dots, a second column (a mail list, or a parent's children to drill into), a \"New\" button and a \"…\" menu per item (a chat history).",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"docs": "Installed to components/makersclaw/blocks/sidebar. Import: import { Sidebar, SidebarLayout, SidebarTrigger, useSidebar } from \"@/components/makersclaw/blocks/sidebar\". Props and an example: components/makersclaw/blocks/sidebar/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
63
63
|
"meta": {
|
|
64
64
|
"makersclaw": {
|
|
65
|
-
"version": "0.
|
|
65
|
+
"version": "0.6.0",
|
|
66
66
|
"useWhen": "An app with more than a handful of places to go (inbox, deals, contacts, reports, settings, projects) that wants a real app shell: compose it in app/shell.jsx around the surfaces. Not for in-page tabs (Tabs) or a short strip of links."
|
|
67
67
|
}
|
|
68
68
|
}
|
package/r/signature-pad.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "SignaturePad",
|
|
6
6
|
"description": "A signature field (signature_pad) in the workspace theme: a full-name field, then draw on a paper box (smooth pen strokes, undo the last stroke, clear with Undo) or type the name set as a signature. Sign returns a record: a cropped transparent PNG in dark ink, the typed name, the mode and the time; the signed view shows it with Sign again. Works as a form field too, through a handle (toPNG, getSignature).",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [
|
|
11
11
|
"signature_pad@5.1.4"
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"docs": "Installed to components/makersclaw/blocks/signature-pad. Import: import { SignaturePad, useSignaturePad, signatureRecord, formatSignedAt } from \"@/components/makersclaw/blocks/signature-pad\". Props and an example: components/makersclaw/blocks/signature-pad/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
66
66
|
"meta": {
|
|
67
67
|
"makersclaw": {
|
|
68
|
-
"version": "0.
|
|
68
|
+
"version": "0.6.0",
|
|
69
69
|
"useWhen": "A screen needs someone to sign: accepting a proposal or a quote, a delivery or work-done sign-off, a waiver, a consent form, an approval on a record. The proposal-accept block is built on it. It records an acceptance with a picture of the signature — it is not a certified legal e-signature (no identity check, no audit trail beyond what you store)."
|
|
70
70
|
}
|
|
71
71
|
}
|
package/r/sketch-canvas.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "SketchCanvas",
|
|
6
6
|
"description": "A freeform drawing canvas (Excalidraw) in the workspace theme: a Miro-style tool rail (select, pan, draw, shapes, arrows, text, image, eraser, frames), a floating toolbar over the selection with colours from the theme's tokens, zoom and undo controls, a friendly empty state, and stamp tools that place ready-made drawings (UI wireframe pieces built in). Optional locked background image for annotating a screenshot. The sketch is plain JSON; helpers read its words for an agent, and the handle exports a PNG.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [
|
|
11
11
|
"@excalidraw/excalidraw@0.18.1"
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"docs": "Installed to components/makersclaw/blocks/sketch-canvas. Import: import { SketchCanvas, useSketchCanvas, SKETCH_TOOLS, WIREFRAME_STAMPS, STROKES, FILLS, emptySketch, isSketchEmpty, sketchToText, sketchItems, toSketch } from \"@/components/makersclaw/blocks/sketch-canvas\". Props and an example: components/makersclaw/blocks/sketch-canvas/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
93
93
|
"meta": {
|
|
94
94
|
"makersclaw": {
|
|
95
|
-
"version": "0.
|
|
95
|
+
"version": "0.6.0",
|
|
96
96
|
"useWhen": "A screen needs freehand drawing: a whiteboard, marking up a screenshot, sketching a UI wireframe, a diagram drawn by hand. The whiteboard, annotate and sketch-to-app blocks are built on it. Not for structured boards of cards and connectors (flow-canvas), charts (chart) or a kanban (board)."
|
|
97
97
|
}
|
|
98
98
|
}
|
package/r/spreadsheet.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Spreadsheet",
|
|
6
6
|
"description": "A table you edit like Google Sheets or Airtable, virtualised for 10,000+ rows: typed columns (text, number, currency, date, single and multiple select, person, checkbox, link, rating) each with its own in-cell editor, a cell cursor and range selection with the mouse and arrow keys, typing to edit, copy and paste ranges as TSV (to and from Sheets and Excel), drag-to-fill and ⌘D fill down, undo/redo, column resize, drag to reorder, hide, freeze, rename, change type and add fields, row insert and delete with Undo, sort and filter panels, search, a sum/average of the selection, validation marks, and a phone layout. Edits go out as async callbacks answering { ok }, applied at once and rolled back on failure. A column-type registry and an imperative handle for blocks built on it.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [
|
|
11
11
|
"@tanstack/react-virtual@3.14.13"
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"docs": "Installed to components/makersclaw/blocks/spreadsheet. Import: import { Spreadsheet, CellValue, CellPanel, OptionBadge, editorFor, TYPE_ORDER, sortWords, COLUMN_TYPES, typeOf, parseCell, convertValue, guessType, parseNumberText, parseDateText, optionValue, isBlank, emptyView, normalizeView, orderedColumns, visibleColumns, processRows, passesFilters, parseTSV, toTSV, pasteChanges, fillChanges, clearChanges, applyChanges, invertChanges } from \"@/components/makersclaw/blocks/spreadsheet\". Props and an example: components/makersclaw/blocks/spreadsheet/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
84
84
|
"meta": {
|
|
85
85
|
"makersclaw": {
|
|
86
|
-
"version": "0.
|
|
86
|
+
"version": "0.6.0",
|
|
87
87
|
"useWhen": "People need to enter or clean up many records in a grid, fast, with the keyboard: a lead list, an inventory, a budget, a content calendar, a table view over any collection, the grid under an Airtable-like base. Not for a read-mostly list to scan and act on row by row (data-table), records moving through stages (board), or a single record (record-form)."
|
|
88
88
|
}
|
|
89
89
|
}
|
package/r/stat-cards.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"title": "Stat cards",
|
|
6
6
|
"description": "A row of key numbers, each with its name and its change: one bordered strip, or a card each with a change in the corner or after the value, a \"from\" value, a status dot and a goal meter, a sparkline, a \"View more\" footer; or a usage tile per amount against its limit (a bar or a ring, a split by kind with what is free, a warning line near the cap, an action and a limit the founder can change); or a plain list of values with their change. Loading, empty and error states.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
9
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json",
|
|
9
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/chart.json"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": [],
|
|
12
12
|
"files": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"docs": "Installed to components/makersclaw/blocks/stat-cards. Import: import { StatCards } from \"@/components/makersclaw/blocks/stat-cards\". Props and an example: components/makersclaw/blocks/stat-cards/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
60
60
|
"meta": {
|
|
61
61
|
"makersclaw": {
|
|
62
|
-
"version": "0.
|
|
62
|
+
"version": "0.6.0",
|
|
63
63
|
"useWhen": "The few numbers at the top of a dashboard or a report: revenue, users, conversion, spend against budget, seats and storage against a plan. Not for a trend worth reading on its own (a chart), many rows of records (a table), or one subject scored against thresholds (a scorecard)."
|
|
64
64
|
}
|
|
65
65
|
}
|
package/r/task-list.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"title": "Task list",
|
|
6
6
|
"description": "The List view of work, like ClickUp's or Linear's: tasks under headings that fold (group by status, assignee, priority, project, due date or any field), a round check to complete each, the title edited in place, subtasks indented under their parent with their own fold, the fields you choose (assignees, due date, priority, tags, project, estimate) as inline pickers, a quick-add row at the end of every group, drag to reorder and to move between groups (saving the new status, assignee or due date), multi-select with a bulk bar (status, assign, due, priority, delete with undo), a toolbar with search, filter chips, group by, sort and fields, and friendly empty states with starter templates. One async onChange saves every change; failures roll back with a notice.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
9
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json",
|
|
9
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/task-model.json"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": [],
|
|
12
12
|
"files": [
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"docs": "Installed to components/makersclaw/blocks/task-list. Import: import { TaskList } from \"@/components/makersclaw/blocks/task-list\". Props and an example: components/makersclaw/blocks/task-list/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
57
57
|
"meta": {
|
|
58
58
|
"makersclaw": {
|
|
59
|
-
"version": "0.
|
|
59
|
+
"version": "0.6.0",
|
|
60
60
|
"useWhen": "A screen that lists work to get done and moves it along: a team's tasks, a launch checklist, a sprint, a personal to-do list, onboarding steps, content to publish. Not for records that are not work (data-table), for stage columns side by side (board), or for dates on a grid (calendar)."
|
|
61
61
|
}
|
|
62
62
|
}
|
package/r/task-model.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Task model",
|
|
6
6
|
"description": "The shared work-item model every task view reads: one task shape (status, assignees, start/due, estimate, progress, priority, parent, dependencies, location, tags, project, extra fields) with statuses, people and projects; pure helpers to search, filter, group by any field, sort, nest subtasks, do date math (week and month grids, working days, overlaps, time scales), sum capacity per person, follow dependencies and the critical path, and apply, undo and persist changes; the shared parts (StatusPill, AssigneeStack, DueLabel, PriorityFlag, TaskChip, CompleteToggle), the ViewToolbar (search, filter chips, group by, sort, show fields), drag primitives on @dnd-kit, a hook for optimistic saves with rollback and undo, and adapters that drive the Board and DataTable blocks from tasks.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [
|
|
11
11
|
"@dnd-kit/core@6.3.1",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"docs": "Installed to components/makersclaw/blocks/task-model. Import: import { NONE, PRIORITIES, DEFAULT_STATUSES, TASK_FIELDS, DEFAULT_VIEW, normalizeTask, normalizeTasks, createTaskContext, fieldOf, isDone, doneStatusId, openStatusId, toggleDoneChange, newTaskId, draftTask, valuesOf, optionsOf, labelOf, searchText, searchTasks, filterTasks, orderOf, sortTasks, sortOptions, groupTasks, groupOptions, movePatch, applyView, activeFilterCount, rankBetween, placeChange, childrenMap, buildTree, flattenTree, descendantIds, ancestorIds, subtaskCounts, rollup, progressOf, dependencyEdges, blockersOf, wouldCycle, dateConflicts, criticalPath, hoursPerDay, workload, sumOf, applyChange, invertChange, changeWrites, changedIds, deleteChange, toBoard, toTableRows, taskFacets, StatusPill, CompleteToggle, AssigneeStack, PersonLabel, DueLabel, PriorityFlag, TagList, SubtaskCount, ProgressLine, TaskChip, GroupLabel, taskColumns, TONE_TEXT, HUE_EDGE, HUE_BG, TaskDragProvider, SortableGroup, useSortableTask, useDraggableTask, useDropTarget, DragHandle, DropLine, LIFTED, useReducedMotion, arrayMove, isDay, dayNumber, fromDayNumber, dayOf, minutesOf, withTime, todayDay, addDays, diffDays, weekdayOf, startOfWeek, endOfWeek, weekDays, startOfMonth, endOfMonth, addMonths, daysBetween, monthGrid, WEEKEND, isWeekend, isWorkingDay, workingDaysBetween, addWorkingDays, spanOf, spansOverlap, tasksInRange, tasksOnDay, shiftDates, spanPatch, dueBucket, DUE_BUCKETS, dayForBucket, formatDay, formatTime, formatDate, timeScale, rangeOfTasks, isNewId } from \"@/components/makersclaw/blocks/task-model\". Props and an example: components/makersclaw/blocks/task-model/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
92
92
|
"meta": {
|
|
93
93
|
"makersclaw": {
|
|
94
|
-
"version": "0.
|
|
94
|
+
"version": "0.6.0",
|
|
95
95
|
"useWhen": "You are building a view of work items — a list, calendar, gantt, workload, roadmap or a switcher between them — or driving Board / DataTable from tasks. Views import it; a surface rarely renders it alone. Not for records that are not work (use data-table or board directly)."
|
|
96
96
|
}
|
|
97
97
|
}
|
package/r/testimonials.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Testimonials",
|
|
6
6
|
"description": "A marketing section of customer quotes: name, role, company, face or logo, the quote, an optional star rating, a verified mark and a \"view on X\" source, and optional headline numbers (stats). Layouts: a grid of cards (plain, card or raised; hover can light one and dim the rest; a \"write a review\" tile), one large quote, a switcher of faces, and a carousel, optionally over a picture.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"docs": "Installed to components/makersclaw/blocks/testimonials. Import: import { Testimonials } from \"@/components/makersclaw/blocks/testimonials\". Props and an example: components/makersclaw/blocks/testimonials/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
46
46
|
"meta": {
|
|
47
47
|
"makersclaw": {
|
|
48
|
-
"version": "0.
|
|
48
|
+
"version": "0.6.0",
|
|
49
49
|
"useWhen": "Social proof on a public page: a landing page, a pricing page, a product page, a case-study teaser. Not for reviews a signed-in user writes and manages (a record list or form), or an app's own activity feed."
|
|
50
50
|
}
|
|
51
51
|
}
|
package/r/transaction-list.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "TransactionList",
|
|
6
6
|
"description": "Money records as a plain list, in two variants: history (payments in and out, grouped by month, a received / paid / pending / failed mark and a signed amount) and invoices (number, date, a Paid / Due in N days / N days overdue badge, amount, download). Optional date-range filter, Export and per-row download. Empty, loading and error states built in.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": [],
|
|
11
11
|
"files": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"docs": "Installed to components/makersclaw/blocks/transaction-list. Import: import { TransactionList } from \"@/components/makersclaw/blocks/transaction-list\". Props and an example: components/makersclaw/blocks/transaction-list/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
47
47
|
"meta": {
|
|
48
48
|
"makersclaw": {
|
|
49
|
-
"version": "0.
|
|
49
|
+
"version": "0.6.0",
|
|
50
50
|
"useWhen": "A billing page's invoices, an account's payment history, a wallet's recent activity: records read top to bottom, newest first. Not for records the founder sorts, filters by column or totals (data-table), or for one order (order-detail)."
|
|
51
51
|
}
|
|
52
52
|
}
|
package/r/whiteboard.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"title": "Whiteboard",
|
|
6
6
|
"description": "A full-page freeform whiteboard on sketch-canvas: a top bar with the board's title (click to rename), the save state (Saving…, Saved, or the error with Retry), a Board / Text view switch, Export PNG and an optional Share button; under it the Miro-style canvas (tool rail, floating toolbar, zoom, undo). An empty board offers starter templates — blank, a grid of titled areas, a 2×2 matrix — and the Text view lists every word on the board for a screen reader or an agent. With onCreateTask, a selected note or text becomes a task from the top bar (\"Create task\", editable title; several notes make one task each), and a small badge marks it on the board from then on. The sketch is plain JSON; saves are async callbacks answering { ok }.",
|
|
7
7
|
"registryDependencies": [
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
9
|
-
"https://cdn.jsdelivr.net/npm/makersclaw@0.
|
|
8
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/core.json",
|
|
9
|
+
"https://cdn.jsdelivr.net/npm/makersclaw@0.6.0/r/sketch-canvas.json"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": [],
|
|
12
12
|
"files": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"docs": "Installed to components/makersclaw/blocks/whiteboard. Import: import { Whiteboard, WHITEBOARD_TEMPLATES, gridSketch, matrixSketch } from \"@/components/makersclaw/blocks/whiteboard\". Props and an example: components/makersclaw/blocks/whiteboard/README.md. Makersclaw builds whole apps from these blocks: https://makersclaw.com",
|
|
60
60
|
"meta": {
|
|
61
61
|
"makersclaw": {
|
|
62
|
-
"version": "0.
|
|
62
|
+
"version": "0.6.0",
|
|
63
63
|
"useWhen": "A screen is one board to think on: a team whiteboard, a planning or prioritisation board, a place to sketch an idea and keep it with a record. Not for marking up a screenshot (annotate), sketching a UI to build (sketch-to-app), a structured board of cards and connectors (flow-canvas), or a kanban (board)."
|
|
64
64
|
}
|
|
65
65
|
}
|
package/src/cli.mjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// --json is the same result as one object, for the platform.
|
|
5
5
|
|
|
6
6
|
import { delimiter, resolve } from "node:path";
|
|
7
|
-
import { CliError, add, diff, init, remove, update } from "./install.mjs";
|
|
7
|
+
import { CliError, add, diff, init, install, remove, update } from "./install.mjs";
|
|
8
8
|
import { loadItems, loadTemplate, packageInfo, readmeOf, searchItems, suggest, templateNames, useExtraBlockRoots } from "./registry.mjs";
|
|
9
9
|
|
|
10
10
|
const COMMANDS = {
|
|
@@ -21,6 +21,8 @@ const COMMANDS = {
|
|
|
21
21
|
diff: "diff",
|
|
22
22
|
update: "update",
|
|
23
23
|
upgrade: "update",
|
|
24
|
+
install: "install",
|
|
25
|
+
i: "install",
|
|
24
26
|
help: "help",
|
|
25
27
|
};
|
|
26
28
|
|
|
@@ -82,9 +84,11 @@ function helpText() {
|
|
|
82
84
|
npx makersclaw diff what update would change in this app
|
|
83
85
|
npx makersclaw update [--major] lay this version's fixed files and blocks
|
|
84
86
|
[--adopt] …or take on an app laid before makersclaw (kit era)
|
|
87
|
+
npx makersclaw install the app's packages: pnpm, from pnpm-lock.yaml
|
|
85
88
|
|
|
86
89
|
--cwd <dir> the app (default: this folder) --json one JSON object
|
|
87
90
|
--force init over an app that exists (your own files stay)
|
|
91
|
+
install: MAKERSCLAW_PNPM names a pnpm, MAKERSCLAW_PNPM_STORE its store
|
|
88
92
|
templates: ${templateNames().join(", ")}`;
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -100,6 +104,13 @@ function packageLines(changes) {
|
|
|
100
104
|
return [` package.json: ${changes.map((c) => `${c.name} ${c.from ?? "(new)"} → ${c.to}`).join(" · ")}`];
|
|
101
105
|
}
|
|
102
106
|
|
|
107
|
+
/** The lock's line, when it was written. What it left out is a note. */
|
|
108
|
+
function lockLine(lock, written) {
|
|
109
|
+
if (!lock || !written) return [];
|
|
110
|
+
const kept = lock.carried.length ? ` · kept from yours: ${lock.carried.join(", ")}` : "";
|
|
111
|
+
return [` pnpm-lock.yaml: cut from this release's lock, ${plural(lock.covered, "dependency", "dependencies")}${kept}`];
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
function layText(r, verb) {
|
|
104
115
|
const head =
|
|
105
116
|
verb === "update"
|
|
@@ -115,10 +126,11 @@ function layText(r, verb) {
|
|
|
115
126
|
if (r.removed.length) lines.push(` removed (no longer shipped): ${listLine(r.removed)}`);
|
|
116
127
|
if (r.blocks.length) lines.push(` blocks: ${r.blocks.join(", ")}`);
|
|
117
128
|
lines.push(...packageLines(r.package));
|
|
129
|
+
lines.push(...lockLine(r.lock, r.written.includes("pnpm-lock.yaml")));
|
|
118
130
|
lines.push(` ${plural(r.pinned, "fixed file")} pinned in check/pins.json · makersclaw.json records ${r.version}`);
|
|
119
131
|
for (const n of r.notes) lines.push(` note: ${n}`);
|
|
120
132
|
const next = [];
|
|
121
|
-
if (r.install) next.push("
|
|
133
|
+
if (r.install) next.push("npx makersclaw install");
|
|
122
134
|
if (verb === "init" && !r.from) next.push("design app/shell.jsx and the surfaces", "find blocks: npx makersclaw search <what the surface needs>");
|
|
123
135
|
else next.push("npm run check");
|
|
124
136
|
lines.push(`next: ${next.join(" · ")}`);
|
|
@@ -134,7 +146,9 @@ function addText(r) {
|
|
|
134
146
|
lines.push(` ${a.import}`);
|
|
135
147
|
}
|
|
136
148
|
lines.push(...packageLines(r.package));
|
|
137
|
-
|
|
149
|
+
lines.push(...lockLine(r.lock, r.lock?.written));
|
|
150
|
+
for (const n of r.notes) lines.push(` note: ${n}`);
|
|
151
|
+
if (r.install) lines.push("next: npx makersclaw install");
|
|
138
152
|
for (const u of r.usage) if (u.readme) lines.push("", u.readme.trimEnd());
|
|
139
153
|
return lines.join("\n");
|
|
140
154
|
}
|
|
@@ -198,6 +212,16 @@ function diffText(r) {
|
|
|
198
212
|
return lines.join("\n");
|
|
199
213
|
}
|
|
200
214
|
|
|
215
|
+
function installText(r) {
|
|
216
|
+
const how = r.manager === "pnpm" ? `pnpm ${r.version} (${r.via})` : `npm ${r.version ?? ""}`.trim();
|
|
217
|
+
const lock = r.manager !== "pnpm" ? "pnpm-lock.yaml not read" : r.frozen ? "frozen: pnpm-lock.yaml as laid" : `pnpm-lock.yaml updated — ${r.why}`;
|
|
218
|
+
const lines = [`installed with ${how} · ${lock}`];
|
|
219
|
+
if (r.manager === "pnpm") lines.push(` node_modules hoisted, hard-linked from ${r.store ?? "pnpm's default store"}`);
|
|
220
|
+
for (const n of r.notes) lines.push(` note: ${n}`);
|
|
221
|
+
lines.push("next: npm run check");
|
|
222
|
+
return lines.join("\n");
|
|
223
|
+
}
|
|
224
|
+
|
|
201
225
|
function templateFor(opts, fallback = "next") {
|
|
202
226
|
const name = opts.template ?? fallback;
|
|
203
227
|
const tpl = loadTemplate(name);
|
|
@@ -205,8 +229,9 @@ function templateFor(opts, fallback = "next") {
|
|
|
205
229
|
return tpl;
|
|
206
230
|
}
|
|
207
231
|
|
|
208
|
-
/** Run one command. Returns { result, text } or throws a CliError.
|
|
209
|
-
|
|
232
|
+
/** Run one command. Returns { result, text } or throws a CliError.
|
|
233
|
+
* `stderr` hears what must not wait for the end (install's fallback). */
|
|
234
|
+
export function run(opts, { stderr = process.stderr, env = process.env } = {}) {
|
|
210
235
|
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
211
236
|
switch (opts.command) {
|
|
212
237
|
case "help":
|
|
@@ -233,6 +258,10 @@ export function run(opts) {
|
|
|
233
258
|
text: `removed ${opts.args.join(", ")} — ${plural(result.removed.length, "file")}; installed now: ${result.blocks.join(", ") || "no blocks"}`,
|
|
234
259
|
};
|
|
235
260
|
}
|
|
261
|
+
case "install": {
|
|
262
|
+
const result = install(cwd, { env, onNote: (line) => stderr.write(`makersclaw: ${line}\n`) });
|
|
263
|
+
return { result: { dir: cwd, ...result }, text: installText(result) };
|
|
264
|
+
}
|
|
236
265
|
case "diff": {
|
|
237
266
|
const result = diff(cwd);
|
|
238
267
|
return { result: { dir: cwd, ...result }, text: diffText(result) };
|
|
@@ -299,7 +328,7 @@ export function main(argv, { stdout = process.stdout, stderr = process.stderr, e
|
|
|
299
328
|
try {
|
|
300
329
|
opts = parseArgs(argv);
|
|
301
330
|
if (opts.help && opts.command !== "help") opts = { ...opts, command: "help" };
|
|
302
|
-
const { result, text } = run(opts);
|
|
331
|
+
const { result, text } = run(opts, { stderr, env });
|
|
303
332
|
stdout.write(opts.json ? `${JSON.stringify({ ok: true, command: opts.command, ...result }, null, 2)}\n` : `${text}\n`);
|
|
304
333
|
return 0;
|
|
305
334
|
} catch (error) {
|
package/src/install.mjs
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
// block with the version it came from
|
|
7
7
|
// check/pins.json sha256 of every fixed file, the template's and the
|
|
8
8
|
// blocks' — `npm run check` refuses one that differs
|
|
9
|
+
// and a third says which package versions it installs:
|
|
10
|
+
// pnpm-lock.yaml cut from the release lock for this package.json
|
|
11
|
+
// (src/lockfile.mjs) by init, add and update; the
|
|
12
|
+
// install writes in what the release does not lock
|
|
9
13
|
//
|
|
10
14
|
// Everything this CLI writes is FIXED (ours: pinned, replaced by update),
|
|
11
15
|
// DOCS (ours, not pinned), a STARTER (laid when missing, the app's from
|
|
@@ -15,6 +19,8 @@
|
|
|
15
19
|
import { existsSync, readFileSync } from "node:fs";
|
|
16
20
|
import { join } from "node:path";
|
|
17
21
|
import { hashFile, readJson, removeFile, sha256, walk, writeFile, writeJson } from "./fsutil.mjs";
|
|
22
|
+
import { LOCKFILE, LockError, deriveLock, parseLock } from "./lockfile.mjs";
|
|
23
|
+
import { NPM_LOCKFILE, PNPM_VERSION, installDeps } from "./pm.mjs";
|
|
18
24
|
import { BLOCK_DIR, loadBlocks, loadItems, loadTemplate, packageInfo, readmeOf, suggest, templateNames } from "./registry.mjs";
|
|
19
25
|
|
|
20
26
|
export const MANIFEST = "makersclaw.json";
|
|
@@ -97,11 +103,60 @@ function mergePackage(app, tpl) {
|
|
|
97
103
|
return { out, changes };
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
const releaseLocks = new Map();
|
|
107
|
+
function releaseLock(tpl) {
|
|
108
|
+
if (!releaseLocks.has(tpl.lock)) releaseLocks.set(tpl.lock, parseLock(readFileSync(tpl.lock, "utf8")));
|
|
109
|
+
return releaseLocks.get(tpl.lock);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The app's pnpm-lock.yaml for `pkg`, cut from the template's release
|
|
114
|
+
* lock: { text, before, covered, carried, left, notes }, or null when the
|
|
115
|
+
* template ships no lock. The app's current lock lends what the release
|
|
116
|
+
* does not lock (src/lockfile.mjs says when); one this reader cannot take
|
|
117
|
+
* lends nothing, and the install resolves those packages again.
|
|
118
|
+
*/
|
|
119
|
+
function cutLock(dir, tpl, pkg) {
|
|
120
|
+
if (!tpl.lock || !pkg) return null;
|
|
121
|
+
const path = join(dir, LOCKFILE);
|
|
122
|
+
const before = existsSync(path) ? readFileSync(path, "utf8") : null;
|
|
123
|
+
const notes = [];
|
|
124
|
+
let current = null;
|
|
125
|
+
if (before !== null) {
|
|
126
|
+
try {
|
|
127
|
+
current = parseLock(before);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (!(error instanceof LockError)) throw error;
|
|
130
|
+
notes.push(`${LOCKFILE} could not be read (${error.message}) — cut again from the release lock`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const cut = deriveLock(releaseLock(tpl), pkg, current);
|
|
134
|
+
// The install resolves what is left; where npm installed the app before,
|
|
135
|
+
// at package-lock.json's versions when they still fit (src/pm.mjs).
|
|
136
|
+
const one = cut.left.length === 1;
|
|
137
|
+
const npmPinned = existsSync(join(dir, NPM_LOCKFILE)) ? `, keeping ${NPM_LOCKFILE}'s version${one ? "" : "s"} where ${one ? "it fits" : "they fit"}` : "";
|
|
138
|
+
if (cut.left.length) notes.push(`${LOCKFILE}: ${cut.left.join(", ")} not in makersclaw ${version()}'s lock — the install resolves ${one ? "it" : "them"}${npmPinned}`);
|
|
139
|
+
return { ...cut, before, notes };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Write the cut when it differs; say so in `written`. */
|
|
143
|
+
function writeLock(dir, cut, written) {
|
|
144
|
+
if (!cut || cut.text === cut.before) return false;
|
|
145
|
+
writeFile(join(dir, LOCKFILE), cut.text);
|
|
146
|
+
written.push(LOCKFILE);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const lockSummary = (cut) => (cut ? { covered: cut.covered.length, carried: cut.carried, left: cut.left } : null);
|
|
151
|
+
|
|
100
152
|
/** Paths a template may remove when a newer version stops shipping them:
|
|
101
|
-
* its fixed files
|
|
102
|
-
*
|
|
153
|
+
* its fixed files, the ones it names as retired (middleware.js since
|
|
154
|
+
* 0.6.0: Next 16 fails a build that has it beside proxy.js), and the kit,
|
|
155
|
+
* parts and block folders. Anything else a pins.json names is left alone
|
|
156
|
+
* — it is not ours to delete. */
|
|
103
157
|
function ownedPath(path, tpl) {
|
|
104
158
|
if (/^components\/(?:ui|parts|blocks)\//.test(path) || /^lib\/[^/]+\.js$/.test(path)) return true;
|
|
159
|
+
if ((tpl.retired ?? []).includes(path)) return true;
|
|
105
160
|
return tpl.files.some((f) => f.class === "fixed" && f.path === path);
|
|
106
161
|
}
|
|
107
162
|
|
|
@@ -187,6 +242,11 @@ function lay(dir, tpl, before) {
|
|
|
187
242
|
}
|
|
188
243
|
}
|
|
189
244
|
|
|
245
|
+
// The lock last: package.json is final now.
|
|
246
|
+
const cut = cutLock(dir, tpl, readJson(join(dir, "package.json")));
|
|
247
|
+
const lockWritten = writeLock(dir, cut, written);
|
|
248
|
+
if (cut) notes.push(...cut.notes);
|
|
249
|
+
|
|
190
250
|
for (const p of Object.keys(before.pins)) {
|
|
191
251
|
if (p in pins) continue;
|
|
192
252
|
if (p.startsWith(`${BLOCK_DIR}/`) && !(p.split("/")[2] in blocks)) continue;
|
|
@@ -210,7 +270,8 @@ function lay(dir, tpl, before) {
|
|
|
210
270
|
kept,
|
|
211
271
|
removed,
|
|
212
272
|
package: pkg,
|
|
213
|
-
|
|
273
|
+
lock: lockSummary(cut),
|
|
274
|
+
install: fresh || lockWritten || pkg.some((c) => c.key !== "scripts"),
|
|
214
275
|
pinned: Object.keys(pins).length,
|
|
215
276
|
blocks: Object.keys(blocks),
|
|
216
277
|
notes,
|
|
@@ -355,13 +416,19 @@ export function add(dir, names) {
|
|
|
355
416
|
if (changes.length) writeJson(path, out);
|
|
356
417
|
pkg = changes;
|
|
357
418
|
}
|
|
419
|
+
// A block's packages come with their lock entries: the release resolved
|
|
420
|
+
// them with everything else, so the next install is frozen.
|
|
421
|
+
const cut = cutLock(dir, tpl, readJson(join(dir, "package.json")));
|
|
422
|
+
const lockWritten = writeLock(dir, cut, []);
|
|
358
423
|
writeJson(join(dir, PINS), sortKeys(pins));
|
|
359
424
|
writeJson(join(dir, MANIFEST), { ...manifest, blocks: sortKeys(manifest.blocks) });
|
|
360
425
|
return {
|
|
361
426
|
version: v,
|
|
362
427
|
added,
|
|
363
428
|
package: pkg,
|
|
364
|
-
|
|
429
|
+
lock: cut ? { ...lockSummary(cut), written: lockWritten } : null,
|
|
430
|
+
notes: cut?.notes ?? [],
|
|
431
|
+
install: pkg.length > 0 || lockWritten,
|
|
365
432
|
usage: order.filter((i) => i.type === "block" && names.includes(i.name)).map((i) => ({ name: i.name, readme: readmeOf(i) })),
|
|
366
433
|
};
|
|
367
434
|
}
|
|
@@ -464,6 +531,12 @@ export function diff(dir) {
|
|
|
464
531
|
// …and the installed blocks' npm packages, which update lays with them.
|
|
465
532
|
const blockDeps = Object.assign({}, ...Object.keys(manifest.blocks ?? {}).map((n) => known.find((b) => b.name === n)?.dependencies ?? {}));
|
|
466
533
|
if (existsSync(pkgPath) && Object.keys(blockDeps).length) pkg.push(...mergePackage(readJson(pkgPath), { dependencies: blockDeps }).changes);
|
|
534
|
+
// …and the lock update would cut for the package.json it would leave.
|
|
535
|
+
if (existsSync(pkgPath) && tplPkg) {
|
|
536
|
+
const after = mergePackage(mergePackage(readJson(pkgPath), readJson(tplPkg.from)).out, { dependencies: blockDeps }).out;
|
|
537
|
+
const cut = cutLock(dir, tpl, after);
|
|
538
|
+
if (cut && cut.text !== cut.before) entries.push({ item: "template", path: LOCKFILE, status: cut.before === null ? "new" : "changed" });
|
|
539
|
+
}
|
|
467
540
|
return {
|
|
468
541
|
from: manifest.version,
|
|
469
542
|
to: v,
|
|
@@ -473,3 +546,27 @@ export function diff(dir) {
|
|
|
473
546
|
blocks: manifest.blocks ?? {},
|
|
474
547
|
};
|
|
475
548
|
}
|
|
549
|
+
|
|
550
|
+
/** `install` — the app's packages: pnpm from its lock, frozen when the
|
|
551
|
+
* lock names exactly package.json's dependencies (src/pm.mjs); npm when
|
|
552
|
+
* no pnpm runs, said in `notes` — but not when the registry did not
|
|
553
|
+
* answer, since npm would need it too. */
|
|
554
|
+
export function install(dir, { env = process.env, onNote } = {}) {
|
|
555
|
+
if (!existsSync(join(dir, "package.json"))) {
|
|
556
|
+
throw new CliError(`${dir} has no package.json — there is no app here`, "makersclaw init lays the template here");
|
|
557
|
+
}
|
|
558
|
+
const r = installDeps(dir, { env, onNote });
|
|
559
|
+
if (r.unreachable) {
|
|
560
|
+
throw new CliError(
|
|
561
|
+
`no pnpm on this machine, and npm could not fetch pnpm ${PNPM_VERSION}: the registry did not answer (${r.unreachable}). An npm install would need the same registry, so nothing was installed\n${r.log}`,
|
|
562
|
+
`name a pnpm ${PNPM_VERSION.split(".")[0]} in MAKERSCLAW_PNPM or put one on PATH, or install again once the registry answers`,
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
if (!r.ok) {
|
|
566
|
+
throw new CliError(
|
|
567
|
+
`${r.manager} install failed (exit ${r.code})${r.notes.length ? ` — ${r.notes.join("; ")}` : ""}${r.log ? `\n${r.log}` : ""}`,
|
|
568
|
+
r.manager === "pnpm" && r.frozen ? "a frozen install needs every package in the store or the registry" : null,
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
return r;
|
|
572
|
+
}
|