@dashai/cli 0.3.0 → 0.3.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/dist/bin.js +242 -20
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -381,12 +381,7 @@ function manifestJson(opts) {
|
|
|
381
381
|
},
|
|
382
382
|
module_kind: kind,
|
|
383
383
|
owns: {
|
|
384
|
-
tables: [
|
|
385
|
-
{
|
|
386
|
-
slug: "items",
|
|
387
|
-
fields: [{ slug: "title", type: "text", required: true }]
|
|
388
|
-
}
|
|
389
|
-
]
|
|
384
|
+
tables: []
|
|
390
385
|
}
|
|
391
386
|
};
|
|
392
387
|
if (kind === "custom") {
|
|
@@ -505,41 +500,42 @@ function gitignore() {
|
|
|
505
500
|
""
|
|
506
501
|
].join("\n");
|
|
507
502
|
}
|
|
508
|
-
function envLocalExample() {
|
|
503
|
+
function envLocalExample(apiUrl = SCAFFOLD_DEFAULT_API_URL) {
|
|
509
504
|
return [
|
|
510
505
|
"# Copy to .env.local + fill in real values.",
|
|
511
506
|
"# These vars are auto-injected by `dashwise dev` (the unified dev loop)",
|
|
512
507
|
"# from ~/.config/dashwise/auth.json \u2014 you only need to edit this file if",
|
|
513
508
|
"# you want to point at a non-default backend or run `next dev` standalone.",
|
|
514
|
-
|
|
509
|
+
`DASHWISE_API_URL=${apiUrl}`,
|
|
515
510
|
"# Client-side mirror \u2014 Next.js inlines NEXT_PUBLIC_* into the browser",
|
|
516
511
|
"# bundle so the SDK's <AuthProvider> can hit `/api/auth/sessions/me`",
|
|
517
512
|
"# on the right origin. Should match DASHWISE_API_URL above.",
|
|
518
|
-
|
|
513
|
+
`NEXT_PUBLIC_DASHWISE_API_URL=${apiUrl}`,
|
|
519
514
|
"DASHWISE_API_TOKEN=",
|
|
520
515
|
"DASHWISE_INSTALLATION_ID=local",
|
|
521
516
|
""
|
|
522
517
|
].join("\n");
|
|
523
518
|
}
|
|
524
|
-
function envLocal() {
|
|
519
|
+
function envLocal(apiUrl = SCAFFOLD_DEFAULT_API_URL) {
|
|
525
520
|
return [
|
|
526
521
|
"# Local dev config \u2014 auto-generated by `dashwise module init`.",
|
|
527
|
-
|
|
528
|
-
"#
|
|
522
|
+
`# Backend URL pinned to your logged-in CLI config (${apiUrl}). Gitignored;`,
|
|
523
|
+
"# safe to edit. `dashwise dev` (the unified loop) auto-injects",
|
|
524
|
+
"# DASHWISE_API_TOKEN from ~/.config/dashwise/auth.json AND",
|
|
529
525
|
"# DASHWISE_DEV_SESSION_ID from the dev session it registers \u2014 so",
|
|
530
526
|
"# you typically don't need to set either here. Change DASHWISE_API_URL",
|
|
531
|
-
"# (and NEXT_PUBLIC_DASHWISE_API_URL to match) to point at a
|
|
532
|
-
"# backend
|
|
527
|
+
"# (and NEXT_PUBLIC_DASHWISE_API_URL to match) to point at a different",
|
|
528
|
+
"# backend.",
|
|
533
529
|
"#",
|
|
534
530
|
"# DASHWISE_INSTALLATION_ID is only needed AFTER you publish + install",
|
|
535
531
|
"# the module in a workspace; until then dev mode (DASHWISE_DEV_SESSION_ID,",
|
|
536
532
|
"# auto-set by `dashwise dev`) is the auth path.",
|
|
537
|
-
|
|
533
|
+
`DASHWISE_API_URL=${apiUrl}`,
|
|
538
534
|
"# Client-side mirror (must match DASHWISE_API_URL). Next.js inlines",
|
|
539
535
|
"# NEXT_PUBLIC_* into the browser bundle so the SDK's AuthProvider can",
|
|
540
536
|
"# call /api/auth/sessions/me on the right origin instead of bouncing",
|
|
541
537
|
"# off the local module server with a 404.",
|
|
542
|
-
|
|
538
|
+
`NEXT_PUBLIC_DASHWISE_API_URL=${apiUrl}`,
|
|
543
539
|
"DASHWISE_API_TOKEN=",
|
|
544
540
|
"DASHWISE_INSTALLATION_ID=",
|
|
545
541
|
""
|
|
@@ -1513,8 +1509,227 @@ function escapeHtml(s) {
|
|
|
1513
1509
|
function isValidSlug(slug) {
|
|
1514
1510
|
return /^[a-z][a-z0-9_-]*$/.test(slug);
|
|
1515
1511
|
}
|
|
1512
|
+
function claudeMd(opts) {
|
|
1513
|
+
const isCustom = (opts.kind ?? "hand_authored") === "custom";
|
|
1514
|
+
return `# CLAUDE.md \u2014 ${opts.name}
|
|
1515
|
+
|
|
1516
|
+
Instructions for AI coding agents (Claude Code, Cursor, etc.) working
|
|
1517
|
+
in this DashWise module. Read this before making changes.
|
|
1518
|
+
|
|
1519
|
+
## What this module is
|
|
1520
|
+
|
|
1521
|
+
A DashWise ${isCustom ? "**custom Next.js** module (full app runtime, machine-class)" : "**hand-authored simple** module (isolate runtime)"} authored against \`@dashai/sdk\`.
|
|
1522
|
+
Module slug: \`${opts.slug}\`.
|
|
1523
|
+
|
|
1524
|
+
DashWise calls apps "modules". A module is a Next.js app + a
|
|
1525
|
+
manifest (\`module.json\`) declaring the tables it owns, modules it
|
|
1526
|
+
depends on, and actions it exposes. The DashWise backend hosts the
|
|
1527
|
+
data plane + auth; this module ships UI + business logic.
|
|
1528
|
+
|
|
1529
|
+
## Spec-first, log-every-change
|
|
1530
|
+
|
|
1531
|
+
This scaffold mirrors the dashwise-backend convention:
|
|
1532
|
+
|
|
1533
|
+
- **\`spec.md\`** is the source of truth for what this module does \u2014
|
|
1534
|
+
tables, fields, API contracts, business rules, error cases. Update
|
|
1535
|
+
it BEFORE writing code that changes behavior. If a behavior isn't
|
|
1536
|
+
in \`spec.md\`, it isn't real yet.
|
|
1537
|
+
- **\`agent-log.md\`** is an append-only log of every meaningful
|
|
1538
|
+
change. Every commit that touches \`module.json\`, \`spec.md\`, a
|
|
1539
|
+
schema mutation, or a public surface MUST add an entry. Format:
|
|
1540
|
+
|
|
1541
|
+
\`\`\`
|
|
1542
|
+
## YYYY-MM-DD HH:MM \u2014 <author or agent name>
|
|
1543
|
+
|
|
1544
|
+
**Change:** one-line summary
|
|
1545
|
+
**Files:** comma-separated list of files
|
|
1546
|
+
**Reason:** why this change was necessary
|
|
1547
|
+
**Spec impact:** none | updated spec.md \xA7<section>
|
|
1548
|
+
\`\`\`
|
|
1549
|
+
|
|
1550
|
+
Reverse chronological (newest first).
|
|
1551
|
+
|
|
1552
|
+
## Schema changes go through the CLI, not by hand
|
|
1553
|
+
|
|
1554
|
+
\`module.json\` is the manifest. The backend has its own copy that
|
|
1555
|
+
the runtime data plane uses. To keep them in sync, mutate via the
|
|
1556
|
+
CLI \u2014 \`dashwise table create\`, \`dashwise field add\`, etc. \u2014
|
|
1557
|
+
which calls the schema endpoints and rewrites the local
|
|
1558
|
+
\`module.json\` from the backend's response. Hand-edits to
|
|
1559
|
+
\`module.json\` won't sync until the next CLI mutation picks them up.
|
|
1560
|
+
|
|
1561
|
+
Common commands:
|
|
1562
|
+
|
|
1563
|
+
\`\`\`
|
|
1564
|
+
dashwise table create <slug> --field <slug:type[:required]>
|
|
1565
|
+
dashwise table delete <slug>
|
|
1566
|
+
dashwise field add <table> <slug:type[:required]>
|
|
1567
|
+
dashwise field remove <table> <slug>
|
|
1568
|
+
dashwise field set-type <table> <slug> <type>
|
|
1569
|
+
\`\`\`
|
|
1570
|
+
|
|
1571
|
+
Allowed field types: \`text\`, \`long_text\`, \`number\`, \`boolean\`,
|
|
1572
|
+
\`date\`, \`datetime\`, \`single_select\`, \`multi_select\`,
|
|
1573
|
+
\`link_row\`, \`file\`, \`multi_file\`, \`email\`, \`url\`,
|
|
1574
|
+
\`phone\`, \`formula\`, \`ai\`.
|
|
1575
|
+
|
|
1576
|
+
## Read + write data via the generated SDK
|
|
1577
|
+
|
|
1578
|
+
The CLI's watcher regenerates typed clients into
|
|
1579
|
+
\`node_modules/@dashai/generated/\` every time \`module.json\` changes.
|
|
1580
|
+
Import from there:
|
|
1581
|
+
|
|
1582
|
+
\`\`\`ts
|
|
1583
|
+
import { db, qb } from '@dashai/generated';
|
|
1584
|
+
|
|
1585
|
+
// Simple CRUD
|
|
1586
|
+
const rows = await db.<table>.list();
|
|
1587
|
+
await db.<table>.create({ /* fields */ });
|
|
1588
|
+
|
|
1589
|
+
// Query builder (joins, aggregates)
|
|
1590
|
+
const stats = await qb.from('<table>').where({ /* ... */ }).execute();
|
|
1591
|
+
\`\`\`
|
|
1592
|
+
|
|
1593
|
+
The data plane authenticates via the per-module runtime token cached
|
|
1594
|
+
in \`~/.config/dashwise/auth.json#modules[${opts.slug}]\` after
|
|
1595
|
+
\`dashwise init\` provisions the dev install. \`dashwise dev\` injects
|
|
1596
|
+
this token into the Next.js child env automatically.
|
|
1597
|
+
|
|
1598
|
+
## Auth in dev mode
|
|
1599
|
+
|
|
1600
|
+
\`dashwise dev\` registers a dev-mode SSO session with the backend
|
|
1601
|
+
and injects \`DASHWISE_DEV_SESSION_ID\` so workspace members can sign
|
|
1602
|
+
into the locally-running module via DashWise SSO \u2014 no installed
|
|
1603
|
+
\`installation_id\` required.
|
|
1604
|
+
|
|
1605
|
+
In Server Components: \`await getServerSession()\` (from
|
|
1606
|
+
\`@dashai/sdk/auth/server\`).
|
|
1607
|
+
In Client Components: \`useSession()\` (from
|
|
1608
|
+
\`@dashai/sdk/auth/client\`), wrapped in \`<AuthProvider>\` (already
|
|
1609
|
+
in \`app/layout.tsx\`).
|
|
1610
|
+
|
|
1611
|
+
## Local dev lifecycle
|
|
1612
|
+
|
|
1613
|
+
\`\`\`
|
|
1614
|
+
dashwise login # one-time, opens browser
|
|
1615
|
+
dashwise init [slug] # scaffold + provision dev install
|
|
1616
|
+
dashwise dev # watcher + next dev, auth env auto-injected
|
|
1617
|
+
dashwise module destroy-dev-install # tear down when done (cleans backend + auth.json)
|
|
1618
|
+
\`\`\`
|
|
1619
|
+
|
|
1620
|
+
## Engineering bar
|
|
1621
|
+
|
|
1622
|
+
- **No hacks, shortcuts, or temporary "quick fixes" as final
|
|
1623
|
+
implementations.** If something needs work, leave it as a stub and
|
|
1624
|
+
open an issue / TODO with a clear name \u2014 don't bury a workaround.
|
|
1625
|
+
- **No silent error swallowing.** Catch what you can handle; surface
|
|
1626
|
+
what you can't. Tests should assert error codes, not just status.
|
|
1627
|
+
- **No untyped \`any\`.** The generated SDK gives you types \u2014 use
|
|
1628
|
+
them. If you need an escape hatch, add a \`@ts-expect-error\` with
|
|
1629
|
+
a comment explaining why.
|
|
1630
|
+
- **No secrets in code or env files.** Use \`runtime.secrets[]\` in
|
|
1631
|
+
\`module.json\`; values are encrypted at rest and resolved at
|
|
1632
|
+
runtime.
|
|
1633
|
+
|
|
1634
|
+
## Pointers
|
|
1635
|
+
|
|
1636
|
+
- Full walkthrough \u2014 \`@dashai/cli\`'s [building-modules.md](https://github.com/Intuize/dashwise-cli/blob/main/docs/building-modules.md).
|
|
1637
|
+
- Manifest schema \u2014 \`@dashai/sdk/dist/manifest/schema.d.ts\` (generated from the backend Zod source of truth).
|
|
1638
|
+
- Query plane reference \u2014 same docs, \`Query AST v1 wire format\` section.
|
|
1639
|
+
`;
|
|
1640
|
+
}
|
|
1641
|
+
function specMd(opts) {
|
|
1642
|
+
return `# ${opts.name} \u2014 Spec
|
|
1643
|
+
|
|
1644
|
+
> Living document. Source of truth for what this module does. Update
|
|
1645
|
+
> this BEFORE changing code that changes behavior \u2014 see CLAUDE.md.
|
|
1646
|
+
|
|
1647
|
+
## Notion
|
|
1648
|
+
|
|
1649
|
+
(link to ticket / design doc here, or remove this section)
|
|
1650
|
+
|
|
1651
|
+
## Overview
|
|
1652
|
+
|
|
1653
|
+
One-sentence description of what this module does, who uses it, and
|
|
1654
|
+
what tables it owns.
|
|
1655
|
+
|
|
1656
|
+
## Database schema
|
|
1657
|
+
|
|
1658
|
+
| Table | Columns | Notes |
|
|
1659
|
+
|---|---|---|
|
|
1660
|
+
| (none yet) | run \`dashwise table create <slug> --field <slug:type>\` to add one | |
|
|
1661
|
+
|
|
1662
|
+
## API / contract
|
|
1663
|
+
|
|
1664
|
+
| Method | Path | Auth | Purpose |
|
|
1665
|
+
|---|---|---|---|
|
|
1666
|
+
| (none yet) | | | |
|
|
1667
|
+
|
|
1668
|
+
## Business rules
|
|
1669
|
+
|
|
1670
|
+
- (RBAC, validation, domain logic.)
|
|
1671
|
+
|
|
1672
|
+
## Dependencies
|
|
1673
|
+
|
|
1674
|
+
Modules this module reads from + which tables/actions:
|
|
1675
|
+
|
|
1676
|
+
- (none yet \u2014 declare in \`module.json#dependencies[]\`)
|
|
1677
|
+
|
|
1678
|
+
## Exposed tables + actions
|
|
1679
|
+
|
|
1680
|
+
Tables or server-actions this module makes available to other
|
|
1681
|
+
modules:
|
|
1682
|
+
|
|
1683
|
+
- (none yet)
|
|
1684
|
+
|
|
1685
|
+
## Error cases
|
|
1686
|
+
|
|
1687
|
+
- (what can go wrong + how it's handled)
|
|
1688
|
+
|
|
1689
|
+
## Decisions
|
|
1690
|
+
|
|
1691
|
+
- (architectural choices + the trade-offs that drove them)
|
|
1692
|
+
|
|
1693
|
+
## Open questions
|
|
1694
|
+
|
|
1695
|
+
- (anything blocking implementation)
|
|
1696
|
+
`;
|
|
1697
|
+
}
|
|
1698
|
+
function agentLogMd(opts) {
|
|
1699
|
+
return `# Agent Log \u2014 ${opts.name}
|
|
1700
|
+
|
|
1701
|
+
Append-only log of meaningful changes to this module. Every commit
|
|
1702
|
+
that touches \`module.json\`, \`spec.md\`, a schema, or a public
|
|
1703
|
+
surface MUST add an entry here in the same change.
|
|
1704
|
+
|
|
1705
|
+
Format (reverse chronological, newest first):
|
|
1706
|
+
|
|
1707
|
+
\`\`\`
|
|
1708
|
+
## YYYY-MM-DD HH:MM \u2014 <author or agent name>
|
|
1709
|
+
|
|
1710
|
+
**Change:** one-line summary
|
|
1711
|
+
**Files:** comma-separated list of files
|
|
1712
|
+
**Reason:** why this change was necessary
|
|
1713
|
+
**Spec impact:** none | updated spec.md \xA7<section>
|
|
1714
|
+
|
|
1715
|
+
(optional: longer context, verification steps, decisions deferred)
|
|
1716
|
+
\`\`\`
|
|
1717
|
+
|
|
1718
|
+
---
|
|
1719
|
+
|
|
1720
|
+
## ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)} \u2014 dashwise module init
|
|
1721
|
+
|
|
1722
|
+
**Change:** Scaffolded module \`${opts.slug}\` via \`dashwise module init\`.
|
|
1723
|
+
**Files:** entire scaffold (\`module.json\`, \`app/\`, \`components/\`, ...).
|
|
1724
|
+
**Reason:** initial scaffold.
|
|
1725
|
+
**Spec impact:** seeded \`spec.md\` template \u2014 fill in before first
|
|
1726
|
+
schema mutation.
|
|
1727
|
+
`;
|
|
1728
|
+
}
|
|
1729
|
+
var SCAFFOLD_DEFAULT_API_URL;
|
|
1516
1730
|
var init_scaffold = __esm({
|
|
1517
1731
|
"src/lib/scaffold.ts"() {
|
|
1732
|
+
SCAFFOLD_DEFAULT_API_URL = "http://localhost:3000";
|
|
1518
1733
|
}
|
|
1519
1734
|
});
|
|
1520
1735
|
async function selectWorkspace(opts) {
|
|
@@ -1622,15 +1837,22 @@ async function moduleInitCommand(slugArg, options) {
|
|
|
1622
1837
|
kind,
|
|
1623
1838
|
...options.git !== void 0 ? { repositoryUrl: options.git } : {}
|
|
1624
1839
|
};
|
|
1840
|
+
const scaffoldApiUrl = resolveApiUrl();
|
|
1625
1841
|
const files = [
|
|
1626
1842
|
["module.json", manifestJson(scaffoldOpts)],
|
|
1627
1843
|
["tsconfig.json", tsconfigJson()],
|
|
1628
1844
|
["next.config.mjs", nextConfig()],
|
|
1629
1845
|
["next-env.d.ts", nextEnvDts()],
|
|
1630
1846
|
[".gitignore", gitignore()],
|
|
1631
|
-
[".env.local.example", envLocalExample()],
|
|
1632
|
-
[".env.local", envLocal()],
|
|
1633
|
-
["README.md", readme(scaffoldOpts)]
|
|
1847
|
+
[".env.local.example", envLocalExample(scaffoldApiUrl)],
|
|
1848
|
+
[".env.local", envLocal(scaffoldApiUrl)],
|
|
1849
|
+
["README.md", readme(scaffoldOpts)],
|
|
1850
|
+
// HH-CC-FUP-5: agent-facing docs ship with every scaffold so AI
|
|
1851
|
+
// coding agents (Claude Code, Cursor, etc.) have the spec + log
|
|
1852
|
+
// discipline + SDK pointers loaded into context from byte one.
|
|
1853
|
+
["CLAUDE.md", claudeMd(scaffoldOpts)],
|
|
1854
|
+
["spec.md", specMd(scaffoldOpts)],
|
|
1855
|
+
["agent-log.md", agentLogMd(scaffoldOpts)]
|
|
1634
1856
|
];
|
|
1635
1857
|
if (kind === "custom") {
|
|
1636
1858
|
files.push(
|
|
@@ -5722,7 +5944,7 @@ fieldCmd.command("set-type <table-slug> <field-slug> <new-type>").description(
|
|
|
5722
5944
|
}
|
|
5723
5945
|
})();
|
|
5724
5946
|
function getVersion() {
|
|
5725
|
-
return "0.3.
|
|
5947
|
+
return "0.3.1";
|
|
5726
5948
|
}
|
|
5727
5949
|
function parseIntOption(value) {
|
|
5728
5950
|
const n = Number.parseInt(value, 10);
|