@kardoe/quickback 0.5.12 → 0.5.14
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/commands/compile.d.ts +1 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +50 -5
- package/dist/commands/compile.js.map +1 -1
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +8 -3
- package/dist/docs/content.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/artifact-routing.d.ts +8 -0
- package/dist/lib/artifact-routing.d.ts.map +1 -0
- package/dist/lib/artifact-routing.js +34 -0
- package/dist/lib/artifact-routing.js.map +1 -0
- package/dist/lib/artifact-routing.test.d.ts +2 -0
- package/dist/lib/artifact-routing.test.d.ts.map +1 -0
- package/dist/lib/artifact-routing.test.js +37 -0
- package/dist/lib/artifact-routing.test.js.map +1 -0
- package/package.json +1 -1
- package/src/skill/SKILL.md +153 -127
- package/src/skill/agents/quickback-specialist/AGENT.md +58 -44
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* │ └── definitions/features/...
|
|
12
12
|
* ├── src/ ← compiled code written here
|
|
13
13
|
* ├── supabase/migrations/ ← for Supabase provider
|
|
14
|
-
* ├── drizzle/ ← for D1/SQLite providers
|
|
14
|
+
* ├── drizzle/ ← for D1/SQLite providers (when quickback/ folder is not used)
|
|
15
15
|
* └── package.json
|
|
16
16
|
*/
|
|
17
17
|
export declare function compile(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA2FH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA0O7C"}
|
package/dist/commands/compile.js
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
* │ └── definitions/features/...
|
|
12
12
|
* ├── src/ ← compiled code written here
|
|
13
13
|
* ├── supabase/migrations/ ← for Supabase provider
|
|
14
|
-
* ├── drizzle/ ← for D1/SQLite providers
|
|
14
|
+
* ├── drizzle/ ← for D1/SQLite providers (when quickback/ folder is not used)
|
|
15
15
|
* └── package.json
|
|
16
16
|
*/
|
|
17
|
-
import { join, dirname } from 'path';
|
|
17
|
+
import { join, dirname, resolve } from 'path';
|
|
18
18
|
import fs from 'fs/promises';
|
|
19
19
|
import pc from 'picocolors';
|
|
20
20
|
import ora from 'ora';
|
|
@@ -22,6 +22,7 @@ import { callCompiler, getApiUrl } from '../lib/api-client.js';
|
|
|
22
22
|
import { getStoredToken, getStoredUser } from '../lib/auth.js';
|
|
23
23
|
import { loadConfig, loadFeatures, findConfigPath, findFeaturesDir, findServicesDir, loadServices, loadDrizzleMeta } from '../lib/file-loader.js';
|
|
24
24
|
import { writeFilesWithMerge } from '../lib/file-writer.js';
|
|
25
|
+
import { isSecurityReportArtifactContent, partitionGeneratedFiles } from '../lib/artifact-routing.js';
|
|
25
26
|
import { runCommand } from '../lib/shell.js';
|
|
26
27
|
const DRIZZLE_META_RELATIVE_DIRS = [
|
|
27
28
|
'drizzle/auth/meta',
|
|
@@ -30,6 +31,15 @@ const DRIZZLE_META_RELATIVE_DIRS = [
|
|
|
30
31
|
'drizzle/webhooks/meta',
|
|
31
32
|
'drizzle/meta',
|
|
32
33
|
];
|
|
34
|
+
function areSamePath(a, b) {
|
|
35
|
+
return resolve(a) === resolve(b);
|
|
36
|
+
}
|
|
37
|
+
async function resolveQuickbackStateDir(projectRoot, outputDir) {
|
|
38
|
+
const quickbackDir = join(projectRoot, 'quickback');
|
|
39
|
+
if (areSamePath(quickbackDir, outputDir))
|
|
40
|
+
return undefined;
|
|
41
|
+
return await pathExists(quickbackDir) ? quickbackDir : undefined;
|
|
42
|
+
}
|
|
33
43
|
async function pathExists(path) {
|
|
34
44
|
try {
|
|
35
45
|
await fs.access(path);
|
|
@@ -41,7 +51,7 @@ async function pathExists(path) {
|
|
|
41
51
|
}
|
|
42
52
|
async function syncDrizzleMetaToQuickback(projectRoot, outputDir) {
|
|
43
53
|
const quickbackDir = join(projectRoot, 'quickback');
|
|
44
|
-
if (quickbackDir
|
|
54
|
+
if (areSamePath(quickbackDir, outputDir))
|
|
45
55
|
return 0;
|
|
46
56
|
if (!await pathExists(quickbackDir))
|
|
47
57
|
return 0;
|
|
@@ -63,6 +73,22 @@ async function syncDrizzleMetaToQuickback(projectRoot, outputDir) {
|
|
|
63
73
|
}
|
|
64
74
|
return synced;
|
|
65
75
|
}
|
|
76
|
+
async function syncSecurityReportsToQuickback(projectRoot, outputDir, generatedFiles) {
|
|
77
|
+
const quickbackDir = join(projectRoot, 'quickback');
|
|
78
|
+
if (areSamePath(quickbackDir, outputDir))
|
|
79
|
+
return 0;
|
|
80
|
+
if (!await pathExists(quickbackDir))
|
|
81
|
+
return 0;
|
|
82
|
+
const reportFiles = generatedFiles.filter((file) => file.path.endsWith('.json') && isSecurityReportArtifactContent(file.content));
|
|
83
|
+
let synced = 0;
|
|
84
|
+
for (const file of reportFiles) {
|
|
85
|
+
const targetPath = join(quickbackDir, file.path);
|
|
86
|
+
await fs.mkdir(dirname(targetPath), { recursive: true });
|
|
87
|
+
await fs.writeFile(targetPath, file.content, 'utf-8');
|
|
88
|
+
synced += 1;
|
|
89
|
+
}
|
|
90
|
+
return synced;
|
|
91
|
+
}
|
|
66
92
|
export async function compile() {
|
|
67
93
|
console.log(pc.bold('Quickback Compiler'));
|
|
68
94
|
// Show auth status
|
|
@@ -202,10 +228,23 @@ export async function compile() {
|
|
|
202
228
|
}
|
|
203
229
|
console.log();
|
|
204
230
|
}
|
|
231
|
+
const quickbackStateDir = await resolveQuickbackStateDir(projectRoot, outputDir);
|
|
232
|
+
const shouldRouteStateArtifactsToQuickback = Boolean(quickbackStateDir);
|
|
233
|
+
const { runtimeFiles, stateFiles } = partitionGeneratedFiles(result.files);
|
|
205
234
|
spinner.start('Writing output...');
|
|
206
235
|
// Use merge strategy - don't wipe existing files, just update generated ones
|
|
207
|
-
await writeFilesWithMerge(outputDir, result.files);
|
|
208
|
-
|
|
236
|
+
await writeFilesWithMerge(outputDir, shouldRouteStateArtifactsToQuickback ? runtimeFiles : result.files);
|
|
237
|
+
if (quickbackStateDir && stateFiles.length > 0) {
|
|
238
|
+
await writeFilesWithMerge(quickbackStateDir, stateFiles);
|
|
239
|
+
spinner.succeed(`Output written to ${pc.cyan(outputDir)} (state artifacts synced to ${pc.cyan(quickbackStateDir)})`);
|
|
240
|
+
const legacyDrizzlePath = join(outputDir, 'drizzle');
|
|
241
|
+
if (await pathExists(legacyDrizzlePath)) {
|
|
242
|
+
console.log(pc.yellow(' Legacy output/drizzle detected. New compiles write migration/state artifacts to quickback/drizzle.'));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
spinner.succeed(`Output written to ${pc.cyan(outputDir)}`);
|
|
247
|
+
}
|
|
209
248
|
// Run post-compile commands from providers
|
|
210
249
|
if (result.commands && result.commands.length > 0) {
|
|
211
250
|
console.log(pc.gray('\nRunning post-compile commands...\n'));
|
|
@@ -235,6 +274,12 @@ export async function compile() {
|
|
|
235
274
|
if (syncedMetaFiles > 0) {
|
|
236
275
|
console.log(pc.gray(` Synced ${syncedMetaFiles} Drizzle meta file(s) to quickback/drizzle`));
|
|
237
276
|
}
|
|
277
|
+
const syncedSecurityReportFiles = shouldRouteStateArtifactsToQuickback
|
|
278
|
+
? 0
|
|
279
|
+
: await syncSecurityReportsToQuickback(projectRoot, outputDir, result.files);
|
|
280
|
+
if (syncedSecurityReportFiles > 0) {
|
|
281
|
+
console.log(pc.gray(` Synced ${syncedSecurityReportFiles} security report file(s) to quickback/reports`));
|
|
282
|
+
}
|
|
238
283
|
// Print next steps
|
|
239
284
|
console.log(pc.green('\n✔ Compilation complete!'));
|
|
240
285
|
console.log(`\nGenerated files for: ${pc.cyan(result.meta.features.join(', ') || 'no features')}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA6ZzC,CAAC;AAEF,eAAO,MAAM,UAAU,UAwGtB,CAAC"}
|
package/dist/docs/content.js
CHANGED
|
@@ -89,9 +89,13 @@ export const DOCS = {
|
|
|
89
89
|
"title": "Inline Editing",
|
|
90
90
|
"content": "# Inline Editing\n\nThe CMS provides spreadsheet-style inline editing in Data Table mode, plus auto-generated create and edit forms in the record detail view. All editable fields are determined from your table's guard configuration.\n\n## Spreadsheet Editing\n\nIn Data Table mode, every editable cell becomes an inline editor. Select a cell, start typing, and the value is saved automatically when you move to another cell or press Enter.\n\n### Editable Fields\n\nThe CMS determines which fields are editable from the table's guards:\n\n- **`guards.updatable`** fields are editable in existing records\n- **`guards.createable`** fields are editable in new record forms\n- **`guards.immutable`** fields are locked after creation (shown as disabled in edit mode)\n- **`guards.protected`** fields can only be changed via actions (marked \"Updated via actions only\")\n\nIf a table has no explicit guard config, the CMS falls back to making all non-system columns editable (excluding `id`, audit fields, `organizationId`, and `deletedAt`).\n\n## Cell Types\n\nEach column type gets a specialized editor:\n\n### Text\n\nStandard text input. Type freely and press Enter or Tab to save.\n\n### Number\n\nNumeric input with step controls. Supports decimal values (step `0.01` for currency fields). The CMS detects money fields from column names containing `amount`, `total`, `price`, `cost`, `balance`, `rate`, etc.\n\n### Boolean\n\nA Yes/No dropdown. Click to toggle between the two values.\n\n### FK Typeahead\n\nForeign key columns (ending in `Id`) get a typeahead dropdown with server-side search:\n\n- **Debounced search** — Queries are debounced at 200ms to avoid flooding the API\n- **Server-side filtering** — Sends `?search=query&pageSize=20` to the FK target table's list endpoint\n- **Keyboard navigation** — Arrow keys to navigate options, Enter to select, Escape to close\n- **Auto-loads initial options** — Opens with the first 20 records sorted by display column\n- **Display labels** — Shows the target table's display column value (e.g., \"John Smith\" instead of `usr_abc123`)\n\nThe FK target table is derived by stripping the `Id` suffix from the column name. For example, `contactId` searches the `contact` table, and `accountCodeId` searches the `accountCode` table.\n\n### Enum / Select\n\nColumns with `validation.enum` render as a select dropdown with all allowed values.\n\n## Display Labels\n\nFK cells in the table view show human-readable names instead of raw IDs. The API enriches list responses with `_label` fields:\n\n```\ncontactId: \"cnt_abc123\" → displays \"Acme Corporation\"\nprojectId: \"prj_xyz789\" → displays \"Beach House Renovation\"\n```\n\nThe label comes from the referenced table's display column (auto-detected from `name`, `title`, `code`, etc.). This works in both Table mode and Data Table mode.\n\n## Keyboard Shortcuts\n\n| Shortcut | Action |\n|----------|--------|\n| Arrow keys | Navigate between cells |\n| Tab | Move to next editable cell |\n| Shift + Tab | Move to previous editable cell |\n| Enter | Start editing / confirm edit and move down |\n| Escape | Cancel current edit / deselect cell |\n| Type any character | Start editing the selected cell |\n\n### Navigation Flow\n\n1. **Select** a cell by clicking or using arrow keys\n2. **Edit** by pressing Enter, Tab, or just typing\n3. **Save** by pressing Enter (moves down), Tab (moves right to next editable), or clicking elsewhere\n4. **Cancel** by pressing Escape (reverts to previous value)\n\nWhen you press Tab, the cursor skips non-editable cells and jumps to the next editable cell in the row. At the end of a row, it wraps to the first editable cell of the next row.\n\n## Record Detail View\n\nClicking a row in Table mode navigates to the record detail view. Fields are automatically grouped by type:\n\n| Group | Fields Included |\n|-------|----------------|\n| Identity | `name`, `code`, `status`, `title`, `companyName`, fields ending in `Type` or `Status` |\n| Contact Info | `email`, `phone`, `mobile`, `website`, `address1`, `address2`, `city`, `state`, `zip`, `country` |\n| Financial | Money fields, fields with `Percent`, `Rate`, `Markup`, `Discount`, `Currency`, `exchange` |\n| References | All FK columns (ending in `Id`, excluding `id` and `organizationId`) |\n| Settings | Boolean fields |\n| Dates | Date/time fields |\n| Audit | `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy` |\n| Other | Remaining ungrouped fields |\n\nEach group is rendered as a card with the group label as a header. Fields display formatted values — dates are localized, money shows currency formatting, booleans render as Yes/No badges, enums use color-coded pills, and FK references are clickable links to the target record.\n\n## Auto-Generated Forms\n\nThe CMS generates create and edit forms from the table's guard configuration:\n\n### Create Form\n\nShows all fields listed in `guards.createable`. Required fields (notNull without a default) are marked with a red asterisk. Validation rules from the schema (min/max length, enum constraints, email format) are enforced client-side.\n\n### Edit Form\n\nShows all fields listed in `guards.updatable`. Additionally:\n\n- **Immutable fields** appear as disabled inputs with a lock icon\n- **Protected fields** appear as disabled inputs with the note \"Updated via actions only\"\n- **Validation** is applied on submit, with error messages shown per field\n\n### Field Input Types\n\nThe auto-form selects the appropriate input control based on column type and validation:\n\n| Detection | Input Type |\n|-----------|-----------|\n| `mode: \"boolean\"` | Checkbox |\n| `validation.enum` present | Select dropdown |\n| Column name matches date pattern | Date/time picker |\n| Column name matches money pattern | Number input (step 0.01) |\n| Column name matches URL pattern | URL input |\n| `validation.email: true` | Email input |\n| `type: \"integer\"` or `type: \"real\"` | Number input |\n| Long text (description, notes) | Textarea |\n| Default | Text input |\n\n## Next Steps\n\n- **[Table Views](/cms/table-views)** — Browse mode and view projections\n- **[Security](/cms/security)** — How guards control editability\n- **[Actions](/cms/actions)** — Trigger actions from the detail view"
|
|
91
91
|
},
|
|
92
|
+
"cms/record-layouts": {
|
|
93
|
+
"title": "Record Layouts",
|
|
94
|
+
"content": "# Record Layouts\n\nThe CMS record detail page groups fields into collapsible sections. By default, fields are auto-grouped by naming heuristics (Identity, Contact Info, Financial, etc.). With **record layouts**, you control the exact grouping.\n\nThere are two layers:\n\n1. **Code-defined layouts** — developers configure named layouts in `defineTable()`\n2. **User-created views** — end-users create and save custom views via the CMS UI\n\n## Code-Defined Layouts\n\nAdd a `layouts` property to your `defineTable()` config:\n\n```typescript\nexport default defineTable(contacts, {\n firewall: { organization: {} },\n crud: { /* ... */ },\n layouts: {\n default: {\n sections: [\n { label: \"Contact Info\", columns: 2, fields: [\"name\", \"email\", \"phone\", \"mobile\"] },\n { label: \"Address\", columns: 2, fields: [\"address1\", \"address2\", \"city\", \"state\", \"zip\"] },\n { label: \"Internal Notes\", collapsed: true, fields: [\"notes\", \"internalNotes\"] }\n ]\n },\n compact: {\n sections: [\n { label: \"Summary\", fields: [\"name\", \"status\", \"email\"] }\n ]\n }\n }\n});\n```\n\nEach layout has an ordered list of sections. Each section specifies:\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `label` | string | required | Section header text |\n| `fields` | string[] | required | Column names to display |\n| `columns` | `1 \\| 2` | `1` | Number of columns for field layout |\n| `collapsed` | boolean | `false` | Whether the section starts collapsed |\n\nFields not assigned to any section are collected into an \"Other Fields\" section at the bottom.\n\n### Layout Switcher\n\nWhen a table has multiple named layouts, a dropdown appears in the record detail header. Selections persist per table using `localStorage`.\n\nIf only one layout is defined, it's used automatically without showing a dropdown.\n\n## User-Created Custom Views\n\nEnd-users can create their own record layouts via the CMS UI. These are stored in the database and can be shared with other organization members.\n\n### Creating a View\n\n1. Open any record detail page\n2. Click the **+ View** button in the header\n3. In the view builder dialog:\n - Name your view\n - Add sections and assign fields from a dropdown\n - Set columns (1 or 2) and collapsed state per section\n - Optionally share with your organization\n4. Click **Create View**\n\nThe new view appears in the layout dropdown alongside code-defined layouts.\n\n### Editing and Deleting Views\n\n- Click the **gear icon** next to the dropdown to edit the current custom view\n- Click the **trash icon** to delete it (with confirmation)\n- Code-defined layouts cannot be edited or deleted from the CMS\n\n### Access Control\n\n| Operation | Who Can Do It |\n|-----------|---------------|\n| Create a view | Any member, admin, or owner |\n| Edit/delete own views | The creator |\n| Edit/delete any view | Admins and owners |\n| View shared views | All organization members |\n\n### Setting Up the Custom View Feature\n\nTo enable user-created views, add a `customView` table to your Quickback project:\n\n```typescript\n// quickback/features/cms/custom-view.ts\n\nexport const customView = sqliteTable(\"custom_view\", {\n id: text(\"id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n tableName: text(\"table_name\").notNull(),\n name: text(\"name\").notNull(),\n description: text(\"description\"),\n layoutConfig: text(\"layout_config\").notNull(),\n isShared: integer(\"is_shared\", { mode: \"boolean\" }).default(false),\n});\n\nexport default defineTable(customView, {\n displayColumn: \"name\",\n firewall: { organization: {} },\n crud: {\n list: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n get: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n create: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n update: {\n access: {\n or: [\n { roles: [\"owner\", \"admin\"] },\n { roles: [\"member\"], record: { createdBy: { equals: \"$userId\" } } }\n ]\n }\n },\n delete: {\n access: {\n or: [\n { roles: [\"owner\", \"admin\"] },\n { roles: [\"member\"], record: { createdBy: { equals: \"$userId\" } } }\n ]\n },\n mode: \"hard\"\n }\n },\n guards: {\n createable: [\"tableName\", \"name\", \"description\", \"layoutConfig\", \"isShared\"],\n updatable: [\"name\", \"description\", \"layoutConfig\", \"isShared\"]\n }\n});\n```\n\nCompile your project to generate the API endpoints. The CMS will automatically detect the `customView` table and enable the view builder UI.\n\n## Fallback Behavior\n\n| Scenario | Result |\n|----------|--------|\n| No `layouts` config, no custom views | Auto-grouping by naming heuristics |\n| `layouts` config defined | Uses \"default\" layout or first available |\n| Multiple layouts | Dropdown for switching, persisted per table |\n| Custom views created | Appear in dropdown below code-defined layouts |\n\n## Next Steps\n\n- **[Table Views](/cms/table-views)** — Column projections for list views\n- **[Schema Format](/cms/schema-format)** — Full TypeScript type reference\n- **[Database Schema](/compiler/definitions/database-schema)** — defineTable() configuration reference"
|
|
95
|
+
},
|
|
92
96
|
"cms/schema-format": {
|
|
93
97
|
"title": "Schema Format Reference",
|
|
94
|
-
"content": "# Schema Format Reference\n\nThe schema registry is a JSON file with a well-defined structure. Below are the complete TypeScript type definitions used by both the compiler (to generate) and the CMS (to consume).\n\n## SchemaRegistry\n\nThe top-level type:\n\n```typescript\ninterface SchemaRegistry {\n generatedAt: string;\n generatedBy: string;\n version: string;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `generatedAt` | ISO 8601 timestamp of when the registry was generated |\n| `generatedBy` | Always `\"quickback-compiler\"` |\n| `version` | Compiler version string |\n| `features` | Map of feature name to array of source file names |\n| `tables` | Map of camelCase table name to full table metadata |\n| `tablesByFeature` | Map of feature name to array of table names in that feature |\n\n## TableMeta\n\nFull metadata for a single table:\n\n```typescript\ninterface TableMeta {\n name: string;\n dbName: string;\n feature: string;\n columns: ColumnMeta[];\n firewall: Record<string, unknown>;\n crud: Record<string, CrudConfig>;\n guards: GuardsConfig;\n masking: Record<string, MaskingRule>;\n views: Record<string, ViewConfig>;\n validation: Record<string, ValidationRule>;\n actions: ActionMeta[];\n displayColumn?: string;\n inputHints?: Record<string, string>;\n internal?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase table name (e.g., `\"accountCode\"`) |\n| `dbName` | Snake_case SQL table name (e.g., `\"account_code\"`) |\n| `feature` | Parent feature name (e.g., `\"accounting\"`) |\n| `columns` | Ordered array of column metadata |\n| `firewall` | Tenant isolation config (organization, owner, softDelete, exception) |\n| `crud` | Per-operation (create, read, update, delete) access config |\n| `guards` | Field-level create/update/immutable/protected rules |\n| `masking` | Per-field masking rules keyed by column name |\n| `views` | Named column projections keyed by view name |\n| `validation` | Per-field validation rules keyed by column name |\n| `actions` | Array of action definitions for this table |\n| `displayColumn` | Column used as human-readable label (auto-detected or explicit) |\n| `inputHints` | Map of column name to preferred CMS input type (e.g., `\"select\"`, `\"textarea\"`, `\"checkbox\"`) |\n| `internal` | When `true`, table is hidden from CMS sidebar |\n\n## ColumnMeta\n\nMetadata for a single column:\n\n```typescript\ninterface ColumnMeta {\n name: string;\n dbName: string;\n type: \"text\" | \"integer\" | \"real\" | \"blob\";\n mode?: \"boolean\";\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase property name |\n| `dbName` | Snake_case SQL column name |\n| `type` | SQLite storage type |\n| `mode` | When `\"boolean\"`, an integer column represents true/false |\n| `primaryKey` | Whether this column is the primary key |\n| `notNull` | Whether the column has a NOT NULL constraint |\n| `defaultValue` | Static default value (strings, numbers, or booleans) |\n| `fkTarget` | Target table name for FK columns (e.g., `\"contact\"` for a `vendorId` column) |\n\n## CRUDConfig\n\nPer-operation access control:\n\n```typescript\ninterface CrudConfig {\n access?: AccessRule;\n mode?: string;\n}\n\ninterface AccessRule {\n roles?: string[];\n or?: Array<{\n roles?: string[];\n record?: Record<string, unknown>;\n }>;\n record?: Record<string, unknown>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `access.roles` | Array of roles allowed for this operation |\n| `access.or` | Alternative access conditions (any must match) |\n| `access.record` | Record-level conditions for access |\n| `mode` | Operation mode (e.g., `\"batch\"` for bulk create) |\n\n## GuardsConfig\n\nField-level control for create and update operations:\n\n```typescript\ninterface GuardsConfig {\n createable: string[];\n updatable: string[];\n immutable: string[];\n protected: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `createable` | Fields that can be set during record creation |\n| `updatable` | Fields that can be modified on existing records |\n| `immutable` | Fields that can be set on create but never changed |\n| `protected` | Fields only modifiable via named actions (field name to action names) |\n\n## ActionMeta\n\nMetadata for a custom action:\n\n```typescript\ninterface ActionMeta {\n name: string;\n description: string;\n inputFields: ActionInputField[];\n access?: {\n roles: string[];\n record?: Record<string, unknown>;\n };\n standalone?: boolean;\n path?: string;\n method?: string;\n responseType?: string;\n sideEffects?: string;\n cms?: CmsConfig;\n}\n\ninterface CmsConfig {\n label?: string;\n icon?: string;\n confirm?: string | boolean;\n destructive?: boolean;\n category?: string;\n hidden?: boolean;\n successMessage?: string;\n onSuccess?: 'refresh' | 'redirect:list' | 'close';\n order?: number;\n}\n\ninterface ActionInputField {\n name: string;\n type: string;\n required: boolean;\n default?: unknown;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | Action identifier (e.g., `\"approve\"`, `\"applyPayment\"`) |\n| `description` | Human-readable description shown in dialog |\n| `inputFields` | Array of input field definitions |\n| `access.roles` | Roles allowed to execute this action |\n| `access.record` | Record conditions (e.g., `{ status: { equals: \"pending\" } }`) |\n| `standalone` | When `true`, action is not tied to a specific record |\n| `path` | Custom API path (overrides default) |\n| `method` | HTTP method (defaults to POST) |\n| `responseType` | `\"file\"` for download responses |\n| `sideEffects` | `\"sync\"` for actions with synchronous side effects |\n| `cms` | Optional CMS rendering metadata (label, icon, confirm, destructive, category, hidden, successMessage, onSuccess, order) |\n\n### ActionInputField\n\n| Field | Description |\n|-------|-------------|\n| `name` | Field identifier |\n| `type` | Zod type string: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"array<string>\"` |\n| `required` | Whether the field must be provided |\n| `default` | Default value pre-filled in the form |\n\n## ViewConfig\n\nNamed column projection with access control:\n\n```typescript\ninterface ViewConfig {\n fields: string[];\n access: AccessRule;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `fields` | Array of column names to include in this view |\n| `access` | Role-based access rules (same shape as CrudConfig access) |\n\n## MaskingRule\n\nPer-field data masking:\n\n```typescript\ninterface MaskingRule {\n type: \"email\" | \"phone\" | \"ssn\" | \"redact\";\n show: {\n roles: string[];\n or?: string;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `type` | Masking pattern to apply |\n| `show.roles` | Roles that see the unmasked value |\n| `show.or` | Alternative condition for showing unmasked value |\n\n### Masking Patterns\n\n| Type | Input | Output |\n|------|-------|--------|\n| `email` | `john@acme.com` | `j***@acme.com` |\n| `phone` | `(555) 123-4567` | `***-***-4567` |\n| `ssn` | `123-45-6789` | `***-**-6789` |\n| `redact` | Any string | `------` |\n\n## ValidationRule\n\nPer-field validation constraints:\n\n```typescript\ninterface ValidationRule {\n minLength?: number;\n maxLength?: number;\n min?: number;\n max?: number;\n enum?: string[];\n email?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `minLength` | Minimum string length |\n| `maxLength` | Maximum string length |\n| `min` | Minimum numeric value |\n| `max` | Maximum numeric value |\n| `enum` | Array of allowed string values |\n| `email` | When `true`, validates email format |\n\n## Next Steps\n\n- **[Schema Registry](/cms/schema-registry)** — How the registry is generated and used\n- **[Components Reference](/cms/components)** — All CMS React components"
|
|
98
|
+
"content": "# Schema Format Reference\n\nThe schema registry is a JSON file with a well-defined structure. Below are the complete TypeScript type definitions used by both the compiler (to generate) and the CMS (to consume).\n\n## SchemaRegistry\n\nThe top-level type:\n\n```typescript\ninterface SchemaRegistry {\n generatedAt: string;\n generatedBy: string;\n version: string;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `generatedAt` | ISO 8601 timestamp of when the registry was generated |\n| `generatedBy` | Always `\"quickback-compiler\"` |\n| `version` | Compiler version string |\n| `features` | Map of feature name to array of source file names |\n| `tables` | Map of camelCase table name to full table metadata |\n| `tablesByFeature` | Map of feature name to array of table names in that feature |\n\n## TableMeta\n\nFull metadata for a single table:\n\n```typescript\ninterface TableMeta {\n name: string;\n dbName: string;\n feature: string;\n columns: ColumnMeta[];\n firewall: Record<string, unknown>;\n crud: Record<string, CrudConfig>;\n guards: GuardsConfig;\n masking: Record<string, MaskingRule>;\n views: Record<string, ViewConfig>;\n validation: Record<string, ValidationRule>;\n actions: ActionMeta[];\n displayColumn?: string;\n inputHints?: Record<string, string>;\n layouts?: Record<string, CmsLayout>;\n internal?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase table name (e.g., `\"accountCode\"`) |\n| `dbName` | Snake_case SQL table name (e.g., `\"account_code\"`) |\n| `feature` | Parent feature name (e.g., `\"accounting\"`) |\n| `columns` | Ordered array of column metadata |\n| `firewall` | Tenant isolation config (organization, owner, softDelete, exception) |\n| `crud` | Per-operation (create, read, update, delete) access config |\n| `guards` | Field-level create/update/immutable/protected rules |\n| `masking` | Per-field masking rules keyed by column name |\n| `views` | Named column projections keyed by view name |\n| `validation` | Per-field validation rules keyed by column name |\n| `actions` | Array of action definitions for this table |\n| `displayColumn` | Column used as human-readable label (auto-detected or explicit) |\n| `inputHints` | Map of column name to preferred CMS input type (e.g., `\"select\"`, `\"textarea\"`, `\"checkbox\"`) |\n| `layouts` | Named record page layouts keyed by layout name (see CmsLayout below) |\n| `internal` | When `true`, table is hidden from CMS sidebar |\n\n## ColumnMeta\n\nMetadata for a single column:\n\n```typescript\ninterface ColumnMeta {\n name: string;\n dbName: string;\n type: \"text\" | \"integer\" | \"real\" | \"blob\";\n mode?: \"boolean\";\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase property name |\n| `dbName` | Snake_case SQL column name |\n| `type` | SQLite storage type |\n| `mode` | When `\"boolean\"`, an integer column represents true/false |\n| `primaryKey` | Whether this column is the primary key |\n| `notNull` | Whether the column has a NOT NULL constraint |\n| `defaultValue` | Static default value (strings, numbers, or booleans) |\n| `fkTarget` | Target table name for FK columns (e.g., `\"contact\"` for a `vendorId` column) |\n\n## CRUDConfig\n\nPer-operation access control:\n\n```typescript\ninterface CrudConfig {\n access?: AccessRule;\n mode?: string;\n}\n\ninterface AccessRule {\n roles?: string[];\n or?: Array<{\n roles?: string[];\n record?: Record<string, unknown>;\n }>;\n record?: Record<string, unknown>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `access.roles` | Array of roles allowed for this operation |\n| `access.or` | Alternative access conditions (any must match) |\n| `access.record` | Record-level conditions for access |\n| `mode` | Operation mode (e.g., `\"batch\"` for bulk create) |\n\n## GuardsConfig\n\nField-level control for create and update operations:\n\n```typescript\ninterface GuardsConfig {\n createable: string[];\n updatable: string[];\n immutable: string[];\n protected: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `createable` | Fields that can be set during record creation |\n| `updatable` | Fields that can be modified on existing records |\n| `immutable` | Fields that can be set on create but never changed |\n| `protected` | Fields only modifiable via named actions (field name to action names) |\n\n## ActionMeta\n\nMetadata for a custom action:\n\n```typescript\ninterface ActionMeta {\n name: string;\n description: string;\n inputFields: ActionInputField[];\n access?: {\n roles: string[];\n record?: Record<string, unknown>;\n };\n standalone?: boolean;\n path?: string;\n method?: string;\n responseType?: string;\n sideEffects?: string;\n cms?: CmsConfig;\n}\n\ninterface CmsConfig {\n label?: string;\n icon?: string;\n confirm?: string | boolean;\n destructive?: boolean;\n category?: string;\n hidden?: boolean;\n successMessage?: string;\n onSuccess?: 'refresh' | 'redirect:list' | 'close';\n order?: number;\n}\n\ninterface ActionInputField {\n name: string;\n type: string;\n required: boolean;\n default?: unknown;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | Action identifier (e.g., `\"approve\"`, `\"applyPayment\"`) |\n| `description` | Human-readable description shown in dialog |\n| `inputFields` | Array of input field definitions |\n| `access.roles` | Roles allowed to execute this action |\n| `access.record` | Record conditions (e.g., `{ status: { equals: \"pending\" } }`) |\n| `standalone` | When `true`, action is not tied to a specific record |\n| `path` | Custom API path (overrides default) |\n| `method` | HTTP method (defaults to POST) |\n| `responseType` | `\"file\"` for download responses |\n| `sideEffects` | `\"sync\"` for actions with synchronous side effects |\n| `cms` | Optional CMS rendering metadata (label, icon, confirm, destructive, category, hidden, successMessage, onSuccess, order) |\n\n### ActionInputField\n\n| Field | Description |\n|-------|-------------|\n| `name` | Field identifier |\n| `type` | Zod type string: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"array<string>\"` |\n| `required` | Whether the field must be provided |\n| `default` | Default value pre-filled in the form |\n\n## ViewConfig\n\nNamed column projection with access control:\n\n```typescript\ninterface ViewConfig {\n fields: string[];\n access: AccessRule;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `fields` | Array of column names to include in this view |\n| `access` | Role-based access rules (same shape as CrudConfig access) |\n\n## CmsLayout\n\nNamed record page layout with ordered sections:\n\n```typescript\ninterface CmsLayout {\n sections: CmsLayoutSection[];\n}\n\ninterface CmsLayoutSection {\n label: string;\n fields: string[];\n columns?: 1 | 2;\n collapsed?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `sections` | Ordered array of field sections |\n\n### CmsLayoutSection\n\n| Field | Description |\n|-------|-------------|\n| `label` | Section header text |\n| `fields` | Array of column names to display in this section |\n| `columns` | `1` (default) or `2` for two-column field layout |\n| `collapsed` | When `true`, section starts collapsed with a toggle to expand |\n\nFields not assigned to any section in the active layout are collected into an \"Other Fields\" section.\n\n## MaskingRule\n\nPer-field data masking:\n\n```typescript\ninterface MaskingRule {\n type: \"email\" | \"phone\" | \"ssn\" | \"redact\";\n show: {\n roles: string[];\n or?: string;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `type` | Masking pattern to apply |\n| `show.roles` | Roles that see the unmasked value |\n| `show.or` | Alternative condition for showing unmasked value |\n\n### Masking Patterns\n\n| Type | Input | Output |\n|------|-------|--------|\n| `email` | `john@acme.com` | `j***@acme.com` |\n| `phone` | `(555) 123-4567` | `***-***-4567` |\n| `ssn` | `123-45-6789` | `***-**-6789` |\n| `redact` | Any string | `------` |\n\n## ValidationRule\n\nPer-field validation constraints:\n\n```typescript\ninterface ValidationRule {\n minLength?: number;\n maxLength?: number;\n min?: number;\n max?: number;\n enum?: string[];\n email?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `minLength` | Minimum string length |\n| `maxLength` | Maximum string length |\n| `min` | Minimum numeric value |\n| `max` | Maximum numeric value |\n| `enum` | Array of allowed string values |\n| `email` | When `true`, validates email format |\n\n## Next Steps\n\n- **[Schema Registry](/cms/schema-registry)** — How the registry is generated and used\n- **[Components Reference](/cms/components)** — All CMS React components"
|
|
95
99
|
},
|
|
96
100
|
"cms/schema-registry": {
|
|
97
101
|
"title": "Schema Registry",
|
|
@@ -119,7 +123,7 @@ export const DOCS = {
|
|
|
119
123
|
},
|
|
120
124
|
"compiler/cloud-compiler": {
|
|
121
125
|
"title": "Cloud Compiler",
|
|
122
|
-
"content": "Quickback offers a hosted compiler at `https://compiler.quickback.dev`. The CLI uses it to turn your definitions into a complete backend.\n\n## How It Works\n\n```\n┌──────────────┐ ┌──────────────────────┐\n│ quickback │ POST │ compiler.quickback │\n│ CLI │────────▶│ .dev/compile │\n│ │ │ │\n│ Sends: │ │ Returns: │\n│ - config │ │ - Hono routes │\n│ - features │◀────────│ - Drizzle migrations │\n│ - meta │ │ - TypeScript SDK │\n└──────────────┘ └──────────────────────┘\n```\n\n1. The CLI reads your `quickback.config.ts` and feature definitions.\n2. It sends them to the cloud compiler as a JSON payload.\n3. The compiler generates all backend files (routes, migrations, SDK, OpenAPI spec).\n4. The CLI writes the generated files to your project.\n\n## Quick Start\n\n```bash\n# 1. Install the CLI\nnpm install -g @kardoe/quickback\n\n# 2. Create a project\nquickback create cloudflare my-app\ncd my-app\n\n# 3. Log in\nquickback login\n\n# 4. Compile\nquickback compile\n```\n\n## Existing Databases\n\nWhen recompiling an existing project, the CLI automatically sends your Drizzle meta files so the compiler generates **incremental** migrations instead of fresh `CREATE TABLE` statements.\n\nMeta files are loaded from:\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\
|
|
126
|
+
"content": "Quickback offers a hosted compiler at `https://compiler.quickback.dev`. The CLI uses it to turn your definitions into a complete backend.\n\n## How It Works\n\n```\n┌──────────────┐ ┌──────────────────────┐\n│ quickback │ POST │ compiler.quickback │\n│ CLI │────────▶│ .dev/compile │\n│ │ │ │\n│ Sends: │ │ Returns: │\n│ - config │ │ - Hono routes │\n│ - features │◀────────│ - Drizzle migrations │\n│ - meta │ │ - TypeScript SDK │\n└──────────────┘ └──────────────────────┘\n```\n\n1. The CLI reads your `quickback.config.ts` and feature definitions.\n2. It sends them to the cloud compiler as a JSON payload.\n3. The compiler generates all backend files (routes, migrations, SDK, OpenAPI spec).\n4. The CLI writes the generated files to your project.\n\n## Quick Start\n\n```bash\n# 1. Install the CLI\nnpm install -g @kardoe/quickback\n\n# 2. Create a project\nquickback create cloudflare my-app\ncd my-app\n\n# 3. Log in\nquickback login\n\n# 4. Compile\nquickback compile\n```\n\n## Existing Databases\n\nWhen recompiling an existing project, the CLI automatically sends your Drizzle meta files so the compiler generates **incremental** migrations instead of fresh `CREATE TABLE` statements.\n\nMeta files are loaded from:\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nWhen a `quickback/` folder exists and compile output is project root, the CLI writes state artifacts directly into `quickback/`:\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\n\nThe CLI also syncs Drizzle meta JSON into `quickback/drizzle/...` as a compatibility fallback for tool-generated meta files.\n\nNo extra configuration needed — the CLI handles this automatically.\n\n## Next Steps\n\n- [CLI Reference](/compiler/cloud-compiler/cli) — All CLI commands\n- [Authentication](/compiler/cloud-compiler/authentication) — Login flow and API keys\n- [Endpoints](/compiler/cloud-compiler/endpoints) — Compiler API reference\n- [Troubleshooting](/compiler/cloud-compiler/troubleshooting) — Common issues\n- [Local Compiler](/compiler/cloud-compiler/local-compiler) — Run the compiler locally"
|
|
123
127
|
},
|
|
124
128
|
"compiler/cloud-compiler/local-compiler": {
|
|
125
129
|
"title": "Local Compiler",
|
|
@@ -135,7 +139,7 @@ export const DOCS = {
|
|
|
135
139
|
},
|
|
136
140
|
"compiler/config/output": {
|
|
137
141
|
"title": "Output Structure",
|
|
138
|
-
"content": "The compiler generates a complete project structure based on your definitions and provider configuration. The output varies depending on your runtime (Cloudflare vs Bun) and enabled features.\n\n**Warning:** Never edit files in `src/` directly. They are overwritten on every compile. Make changes in your `quickback/` definitions instead.\n\n## Cloudflare Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Workers export)\n├── env.d.ts # Cloudflare bindings TypeScript types\n├── db/\n│ ├── index.ts # Database connection factory\n│ ├── auth-schema.ts # Auth table schemas (dual mode)\n│ └── features-schema.ts # Feature table schemas (dual mode)\n├── auth/\n│ └── index.ts # Better Auth instance & config\n├── features/\n│ └── {feature}/\n│ ├── schema.ts # Drizzle table definition\n│ ├── routes.ts # CRUD + action endpoints\n│ └── actions.ts # Action handlers (if defined)\n├── lib/\n│ ├── access.ts # Access control helpers\n│ ├── types.ts # Runtime type definitions\n│ ├── masks.ts # Field masking utilities\n│ ├── services.ts # Service layer\n│ ├── audit-wrapper.ts # Auto-inject audit fields\n│ └── security-audit.ts # Unsafe cross-tenant audit logger (when needed)\n└── middleware/\n ├── auth.ts # Auth context middleware\n ├── db.ts # Database instance middleware\n └── services.ts # Service injection middleware\n\ndrizzle/\n├── auth/ # Auth migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n├── features/ # Feature migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n└── audit/ # Unsafe cross-tenant action audit migrations (when needed)\n ├── meta/\n └── 0000_initial.sql\n\n# Root config files\n├── package.json\n├── tsconfig.json\n├── wrangler.toml # Cloudflare Workers config\n├── drizzle.config.ts # Features DB drizzle config\n├── drizzle.auth.config.ts # Auth DB drizzle config (dual mode)\n└── drizzle.audit.config.ts # Audit DB drizzle config (when unsafe actions exist)\n```\n\n## Bun Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Bun server)\n├── db/\n│ ├── index.ts # SQLite connection (bun:sqlite)\n│ └── schema.ts # Combined schema (single DB)\n├── auth/\n│ └── index.ts # Better Auth instance\n├── features/\n│ └── {feature}/\n│ ├── schema.ts\n│ ├── routes.ts\n│ └── actions.ts\n├── lib/\n│ ├── access.ts\n│ ├── types.ts\n│ ├── masks.ts\n│ ├── services.ts\n│ └── audit-wrapper.ts\n└── middleware/\n ├── auth.ts\n ├── db.ts\n └── services.ts\n\ndrizzle/ # Single migration directory\n├── meta/\n│ ├── _journal.json\n│ └── 0000_snapshot.json\n└── 0000_initial.sql\n\ndata/ # SQLite database files\n└── app.db\n\n├── package.json\n├── tsconfig.json\n└── drizzle.config.ts\n```\n\n## Key Differences by Runtime\n\n| Aspect | Cloudflare | Bun |\n|--------|-----------|-----|\n| Entry point | Workers `export default` | `Bun.serve()` with port |\n| Database | D1 bindings (dual mode) | SQLite file (single DB) |\n| Types | `env.d.ts` for bindings | No extra types needed |\n| Config | `wrangler.toml` | `.env` file |\n| Migrations | `drizzle/auth/` + `drizzle/features/` | `drizzle/` |\n| Drizzle configs | 2 configs (auth + features) | 1 config |\n\n## Optional Output Files\n\nThese files are generated only when the corresponding features are configured:\n\n### Embeddings\n\nWhen any feature has `embeddings` configured:\n\n```\nsrc/\n├── lib/\n│ └── embeddings.ts # Embedding helpers\n├── routes/\n│ └── embeddings.ts # POST /api/v1/embeddings endpoint\n└── queue-consumer.ts # Queue handler for async embedding jobs\n```\n\n### File Storage (R2)\n\nWhen `fileStorage` is configured:\n\n```\nsrc/\n└── routes/\n └── storage.ts # File upload/download endpoints\ndrizzle/\n└── files/ # File metadata migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Webhooks\n\nWhen webhooks are enabled:\n\n```\nsrc/\n└── lib/\n └── webhooks/\n ├── index.ts # Webhook module entry\n ├── sign.ts # Webhook payload signing\n ├── handlers.ts # Handler registry\n ├── emit.ts # Queue emission helpers\n ├── routes.ts # Inbound/outbound endpoints\n └── providers/\n ├── index.ts\n └── stripe.ts # Stripe webhook handler\ndrizzle/\n└── webhooks/ # Webhook schema migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Security Audit Database (Unsafe Actions)\n\nWhen any action enables unsafe cross-tenant mode (`unsafe.crossTenant: true`):\n\n```\nsrc/\n├── db/\n│ └── audit-schema.ts # audit_events table\n└── lib/\n └── security-audit.ts # mandatory audit writer\n\ndrizzle/\n└── audit/\n ├── meta/\n └── 0000_*.sql\n\n# Root\n└── drizzle.audit.config.ts\n```\n\nCloudflare output also includes an `AUDIT_DB` D1 binding in `wrangler.toml` and migration scripts:\n\n- `db:migrate:audit:local`\n- `db:migrate:audit:remote`\n\n### Security Contract Report and Signature\n\nGenerated on every compile (unless disabled via `compiler.securityContracts.report.enabled: false`):\n\n```\nreports/\n├── security-contracts.report.json # Contract evaluation summary + violations\n└── security-contracts.report.sig.json # Signature / digest envelope for the report\n```\n\nThe signature file uses HMAC-SHA256 when a signing key is configured, otherwise it falls back to SHA-256 digest mode. \nSet `compiler.securityContracts.report.signature.required: true` to fail compilation when a signing key is missing.\n\n### Realtime\n\nWhen any feature has `realtime` configured:\n\n```\nsrc/\n└── lib/\n └── realtime.ts # Broadcast helpers\n\ncloudflare-workers/ # Separate Durable Objects worker\n└── broadcast/\n ├── Broadcaster.ts\n ├── index.ts\n └── wrangler.toml\n```\n\n### Device Authorization\n\nWhen the `deviceAuthorization` plugin is enabled:\n\n```\nsrc/\n└── routes/\n └── cli-auth.ts # Device auth flow endpoints\n```\n\n## Database Schemas\n\n### Dual Database Mode (Cloudflare Default)\n\nThe compiler separates schemas into two files:\n\n**`src/db/auth-schema.ts`** — Re-exports Better Auth table schemas:\n- `users`, `sessions`, `accounts`\n- `organizations`, `members`, `invitations` (if organizations enabled)\n- Plugin-specific tables (`apiKeys`, etc.)\n\n**`src/db/features-schema.ts`** — Re-exports your feature schemas:\n- All tables defined with `defineTable()`\n- Audit field columns added automatically\n\n### Single Database Mode (Bun Default)\n\n**`src/db/schema.ts`** — Combined re-export of all schemas (auth + features).\n\n## Generated Routes\n\nFor each feature, the compiler generates a routes file at `src/features/{name}/routes.ts` containing:\n\n| Route | Generated When |\n|-------|----------------|\n| `GET /` | `crud.list` configured |\n| `GET /:id` | `crud.get` configured |\n| `POST /` | `crud.create` configured |\n| `PATCH /:id` | `crud.update` configured |\n| `DELETE /:id` | `crud.delete` configured |\n| `PUT /:id` | `crud.put` configured |\n| `POST /batch` | `crud.create` exists (auto-enabled) |\n| `PATCH /batch` | `crud.update` exists (auto-enabled) |\n| `DELETE /batch` | `crud.delete` exists (auto-enabled) |\n| `PUT /batch` | `crud.put` exists (auto-enabled) |\n| `GET /views/{name}` | `views` configured |\n| `POST /:id/{action}` | Record-based actions defined |\n| `POST /{action}` | Standalone actions defined |\n\nAll routes are mounted under `/api/v1/{feature}` in the main app.\n\n## Migrations\n\nThe compiler runs `drizzle-kit generate` during compilation to produce SQL migration files. On subsequent compiles, it uses `existingFiles` (your current migration state) to generate only incremental changes.\n\nThe CLI loads migration meta JSON from:\n\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\
|
|
142
|
+
"content": "The compiler generates a complete project structure based on your definitions and provider configuration. The output varies depending on your runtime (Cloudflare vs Bun) and enabled features.\n\n**Warning:** Never edit files in `src/` directly. They are overwritten on every compile. Make changes in your `quickback/` definitions instead.\n\n## Cloudflare Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Workers export)\n├── env.d.ts # Cloudflare bindings TypeScript types\n├── db/\n│ ├── index.ts # Database connection factory\n│ ├── auth-schema.ts # Auth table schemas (dual mode)\n│ └── features-schema.ts # Feature table schemas (dual mode)\n├── auth/\n│ └── index.ts # Better Auth instance & config\n├── features/\n│ └── {feature}/\n│ ├── schema.ts # Drizzle table definition\n│ ├── routes.ts # CRUD + action endpoints\n│ └── actions.ts # Action handlers (if defined)\n├── lib/\n│ ├── access.ts # Access control helpers\n│ ├── types.ts # Runtime type definitions\n│ ├── masks.ts # Field masking utilities\n│ ├── services.ts # Service layer\n│ ├── audit-wrapper.ts # Auto-inject audit fields\n│ └── security-audit.ts # Unsafe cross-tenant audit logger (when needed)\n└── middleware/\n ├── auth.ts # Auth context middleware\n ├── db.ts # Database instance middleware\n └── services.ts # Service injection middleware\n\ndrizzle/\n├── auth/ # Auth migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n├── features/ # Feature migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n└── audit/ # Unsafe cross-tenant action audit migrations (when needed)\n ├── meta/\n └── 0000_initial.sql\n\n# Root config files\n├── package.json\n├── tsconfig.json\n├── wrangler.toml # Cloudflare Workers config\n├── drizzle.config.ts # Features DB drizzle config\n├── drizzle.auth.config.ts # Auth DB drizzle config (dual mode)\n└── drizzle.audit.config.ts # Audit DB drizzle config (when unsafe actions exist)\n```\n\n## Bun Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Bun server)\n├── db/\n│ ├── index.ts # SQLite connection (bun:sqlite)\n│ └── schema.ts # Combined schema (single DB)\n├── auth/\n│ └── index.ts # Better Auth instance\n├── features/\n│ └── {feature}/\n│ ├── schema.ts\n│ ├── routes.ts\n│ └── actions.ts\n├── lib/\n│ ├── access.ts\n│ ├── types.ts\n│ ├── masks.ts\n│ ├── services.ts\n│ └── audit-wrapper.ts\n└── middleware/\n ├── auth.ts\n ├── db.ts\n └── services.ts\n\ndrizzle/ # Single migration directory\n├── meta/\n│ ├── _journal.json\n│ └── 0000_snapshot.json\n└── 0000_initial.sql\n\ndata/ # SQLite database files\n└── app.db\n\n├── package.json\n├── tsconfig.json\n└── drizzle.config.ts\n```\n\n## Key Differences by Runtime\n\n| Aspect | Cloudflare | Bun |\n|--------|-----------|-----|\n| Entry point | Workers `export default` | `Bun.serve()` with port |\n| Database | D1 bindings (dual mode) | SQLite file (single DB) |\n| Types | `env.d.ts` for bindings | No extra types needed |\n| Config | `wrangler.toml` | `.env` file |\n| Migrations | `drizzle/auth/` + `drizzle/features/` | `drizzle/` |\n| Drizzle configs | 2 configs (auth + features) | 1 config |\n\n## Optional Output Files\n\nThese files are generated only when the corresponding features are configured:\n\n### Embeddings\n\nWhen any feature has `embeddings` configured:\n\n```\nsrc/\n├── lib/\n│ └── embeddings.ts # Embedding helpers\n├── routes/\n│ └── embeddings.ts # POST /api/v1/embeddings endpoint\n└── queue-consumer.ts # Queue handler for async embedding jobs\n```\n\n### File Storage (R2)\n\nWhen `fileStorage` is configured:\n\n```\nsrc/\n└── routes/\n └── storage.ts # File upload/download endpoints\ndrizzle/\n└── files/ # File metadata migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Webhooks\n\nWhen webhooks are enabled:\n\n```\nsrc/\n└── lib/\n └── webhooks/\n ├── index.ts # Webhook module entry\n ├── sign.ts # Webhook payload signing\n ├── handlers.ts # Handler registry\n ├── emit.ts # Queue emission helpers\n ├── routes.ts # Inbound/outbound endpoints\n └── providers/\n ├── index.ts\n └── stripe.ts # Stripe webhook handler\ndrizzle/\n└── webhooks/ # Webhook schema migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Security Audit Database (Unsafe Actions)\n\nWhen any action enables unsafe cross-tenant mode (`unsafe.crossTenant: true`):\n\n```\nsrc/\n├── db/\n│ └── audit-schema.ts # audit_events table\n└── lib/\n └── security-audit.ts # mandatory audit writer\n\ndrizzle/\n└── audit/\n ├── meta/\n └── 0000_*.sql\n\n# Root\n└── drizzle.audit.config.ts\n```\n\nCloudflare output also includes an `AUDIT_DB` D1 binding in `wrangler.toml` and migration scripts:\n\n- `db:migrate:audit:local`\n- `db:migrate:audit:remote`\n\n### Security Contract Report and Signature\n\nGenerated on every compile (unless disabled via `compiler.securityContracts.report.enabled: false`):\n\n```\nreports/\n├── security-contracts.report.json # Contract evaluation summary + violations\n└── security-contracts.report.sig.json # Signature / digest envelope for the report\n```\n\nThe signature file uses HMAC-SHA256 when a signing key is configured, otherwise it falls back to SHA-256 digest mode. \nSet `compiler.securityContracts.report.signature.required: true` to fail compilation when a signing key is missing.\n\n### Realtime\n\nWhen any feature has `realtime` configured:\n\n```\nsrc/\n└── lib/\n └── realtime.ts # Broadcast helpers\n\ncloudflare-workers/ # Separate Durable Objects worker\n└── broadcast/\n ├── Broadcaster.ts\n ├── index.ts\n └── wrangler.toml\n```\n\n### Device Authorization\n\nWhen the `deviceAuthorization` plugin is enabled:\n\n```\nsrc/\n└── routes/\n └── cli-auth.ts # Device auth flow endpoints\n```\n\n## Database Schemas\n\n### Dual Database Mode (Cloudflare Default)\n\nThe compiler separates schemas into two files:\n\n**`src/db/auth-schema.ts`** — Re-exports Better Auth table schemas:\n- `users`, `sessions`, `accounts`\n- `organizations`, `members`, `invitations` (if organizations enabled)\n- Plugin-specific tables (`apiKeys`, etc.)\n\n**`src/db/features-schema.ts`** — Re-exports your feature schemas:\n- All tables defined with `defineTable()`\n- Audit field columns added automatically\n\n### Single Database Mode (Bun Default)\n\n**`src/db/schema.ts`** — Combined re-export of all schemas (auth + features).\n\n## Generated Routes\n\nFor each feature, the compiler generates a routes file at `src/features/{name}/routes.ts` containing:\n\n| Route | Generated When |\n|-------|----------------|\n| `GET /` | `crud.list` configured |\n| `GET /:id` | `crud.get` configured |\n| `POST /` | `crud.create` configured |\n| `PATCH /:id` | `crud.update` configured |\n| `DELETE /:id` | `crud.delete` configured |\n| `PUT /:id` | `crud.put` configured |\n| `POST /batch` | `crud.create` exists (auto-enabled) |\n| `PATCH /batch` | `crud.update` exists (auto-enabled) |\n| `DELETE /batch` | `crud.delete` exists (auto-enabled) |\n| `PUT /batch` | `crud.put` exists (auto-enabled) |\n| `GET /views/{name}` | `views` configured |\n| `POST /:id/{action}` | Record-based actions defined |\n| `POST /{action}` | Standalone actions defined |\n\nAll routes are mounted under `/api/v1/{feature}` in the main app.\n\n## Migrations\n\nThe compiler runs `drizzle-kit generate` during compilation to produce SQL migration files. On subsequent compiles, it uses `existingFiles` (your current migration state) to generate only incremental changes.\n\nThe CLI loads migration meta JSON from:\n\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nWhen a `quickback/` folder exists and compile output goes to project root, the CLI writes state artifacts directly into `quickback/`:\n\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\n\nThe CLI also syncs Drizzle meta JSON from output into `quickback/drizzle/...` as a compatibility fallback for tool-generated meta files.\n\nFor non-interactive environments (cloud compile, CI), table/column renames must be declared with `compiler.migrations.renames` in `quickback.config.ts`. This avoids interactive rename prompts during migration generation.\n\nMigration files follow the Drizzle Kit naming convention:\n```\n0000_initial.sql\n0001_add_status_column.sql\n0002_create_orders_table.sql\n```\n\n## See Also\n\n- [Providers](/compiler/config/providers) — Configure runtime, database, and auth providers\n- [Environment variables](/compiler/config/variables) — Required variables by runtime"
|
|
139
143
|
},
|
|
140
144
|
"compiler/config/providers": {
|
|
141
145
|
"title": "Providers",
|
|
@@ -433,6 +437,7 @@ export const TOPIC_LIST = [
|
|
|
433
437
|
"cms/connecting",
|
|
434
438
|
"cms",
|
|
435
439
|
"cms/inline-editing",
|
|
440
|
+
"cms/record-layouts",
|
|
436
441
|
"cms/schema-format",
|
|
437
442
|
"cms/schema-registry",
|
|
438
443
|
"cms/security",
|
package/dist/docs/content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0DAA0D;AAO1D,MAAM,CAAC,MAAM,IAAI,GAA6B;IAC5C,0BAA0B,EAAE;QAC1B,OAAO,EAAE,eAAe;QACxB,SAAS,EAAE,8nRAA8nR;KAC1oR;IACD,kCAAkC,EAAE;QAClC,OAAO,EAAE,uBAAuB;QAChC,SAAS,EAAE,gpOAAgpO;KAC5pO;IACD,2BAA2B,EAAE;QAC3B,OAAO,EAAE,aAAa;QACtB,SAAS,EAAE,qjBAAqjB;KACjkB;IACD,8BAA8B,EAAE;QAC9B,OAAO,EAAE,oBAAoB;QAC7B,SAAS,EAAE,kgBAAkgB;KAC9gB;IACD,6BAA6B,EAAE;QAC7B,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,slBAAslB;KAClmB;IACD,mCAAmC,EAAE;QACnC,OAAO,EAAE,mBAAmB;QAC5B,SAAS,EAAE,irBAAirB;KAC7rB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,eAAe;QACxB,SAAS,EAAE,kjRAAkjR;KAC9jR;IACD,mCAAmC,EAAE;QACnC,OAAO,EAAE,eAAe;QACxB,SAAS,EAAE,60BAA60B;KACz1B;IACD,8BAA8B,EAAE;QAC9B,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,krDAAkrD;KAC9rD;IACD,kCAAkC,EAAE;QAClC,OAAO,EAAE,6BAA6B;QACtC,SAAS,EAAE,+uBAA+uB;KAC3vB;IACD,8BAA8B,EAAE;QAC9B,OAAO,EAAE,oBAAoB;QAC7B,SAAS,EAAE,0hBAA0hB;KACtiB;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,+jQAA+jQ;KAC3kQ;IACD,0BAA0B,EAAE;QAC1B,OAAO,EAAE,eAAe;QACxB,SAAS,EAAE,o7LAAo7L;KACh8L;IACD,uBAAuB,EAAE;QACvB,OAAO,EAAE,kBAAkB;QAC3B,SAAS,EAAE,mmIAAmmI;KAC/mI;IACD,2BAA2B,EAAE;QAC3B,OAAO,EAAE,gBAAgB;QACzB,SAAS,EAAE,kiLAAkiL;KAC9iL;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,43NAA43N;KACx4N;IACD,WAAW,EAAE;QACX,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,m6UAAm6U;KAC/6U;IACD,aAAa,EAAE;QACb,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,qnOAAqnO;KACjoO;IACD,gBAAgB,EAAE;QAChB,OAAO,EAAE,sBAAsB;QAC/B,SAAS,EAAE,kpTAAkpT;KAC9pT;IACD,gBAAgB,EAAE;QAChB,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,mxFAAmxF;KAC/xF;IACD,KAAK,EAAE;QACL,OAAO,EAAE,eAAe;QACxB,SAAS,EAAE,ovHAAovH;KAChwH;IACD,oBAAoB,EAAE;QACpB,OAAO,EAAE,gBAAgB;QACzB,SAAS,EAAE,6nMAA6nM;KACzoM;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,yBAAyB;QAClC,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GeneratedFile } from './file-writer.js';
|
|
2
|
+
export declare function isSecurityReportArtifactContent(content: string): boolean;
|
|
3
|
+
export declare function isStateArtifactFile(file: Pick<GeneratedFile, 'path' | 'content'>): boolean;
|
|
4
|
+
export declare function partitionGeneratedFiles(files: GeneratedFile[]): {
|
|
5
|
+
runtimeFiles: GeneratedFile[];
|
|
6
|
+
stateFiles: GeneratedFile[];
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=artifact-routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-routing.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOxE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAI1F;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EAAE,GACrB;IAAE,YAAY,EAAE,aAAa,EAAE,CAAC;IAAC,UAAU,EAAE,aAAa,EAAE,CAAA;CAAE,CAahE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const SECURITY_REPORT_KINDS = new Set([
|
|
2
|
+
'quickback-security-contract-report',
|
|
3
|
+
'quickback-security-contract-signature',
|
|
4
|
+
]);
|
|
5
|
+
export function isSecurityReportArtifactContent(content) {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = JSON.parse(content);
|
|
8
|
+
return SECURITY_REPORT_KINDS.has(parsed?.kind ?? '');
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function isStateArtifactFile(file) {
|
|
15
|
+
if (file.path.startsWith('drizzle/'))
|
|
16
|
+
return true;
|
|
17
|
+
if (!file.path.endsWith('.json'))
|
|
18
|
+
return false;
|
|
19
|
+
return isSecurityReportArtifactContent(file.content);
|
|
20
|
+
}
|
|
21
|
+
export function partitionGeneratedFiles(files) {
|
|
22
|
+
const runtimeFiles = [];
|
|
23
|
+
const stateFiles = [];
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
if (isStateArtifactFile(file)) {
|
|
26
|
+
stateFiles.push(file);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
runtimeFiles.push(file);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { runtimeFiles, stateFiles };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=artifact-routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-routing.js","sourceRoot":"","sources":["../../src/lib/artifact-routing.ts"],"names":[],"mappings":"AAEA,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,oCAAoC;IACpC,uCAAuC;CACxC,CAAC,CAAC;AAEH,MAAM,UAAU,+BAA+B,CAAC,OAAe;IAC7D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;QACxD,OAAO,qBAAqB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA6C;IAC/E,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAsB;IAEtB,MAAM,YAAY,GAAoB,EAAE,CAAC;IACzC,MAAM,UAAU,GAAoB,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-routing.test.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-routing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import { isStateArtifactFile, partitionGeneratedFiles } from './artifact-routing.js';
|
|
3
|
+
describe('artifact routing', () => {
|
|
4
|
+
// User story: As a developer keeping definitions in quickback/, I need drizzle migration state
|
|
5
|
+
// artifacts written to quickback so compile output does not keep recreating root drizzle folders.
|
|
6
|
+
it('classifies drizzle paths as state artifacts', () => {
|
|
7
|
+
expect(isStateArtifactFile({
|
|
8
|
+
path: 'drizzle/auth/meta/_journal.json',
|
|
9
|
+
content: '{"version":"1"}',
|
|
10
|
+
})).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
// User story: As a platform operator, I need security contract reports treated as state artifacts
|
|
13
|
+
// so they stay alongside quickback definitions and can be reviewed across compile runs.
|
|
14
|
+
it('classifies security report artifacts by kind payload', () => {
|
|
15
|
+
expect(isStateArtifactFile({
|
|
16
|
+
path: 'reports/security-contracts.report.json',
|
|
17
|
+
content: JSON.stringify({ kind: 'quickback-security-contract-report' }),
|
|
18
|
+
})).toBe(true);
|
|
19
|
+
expect(isStateArtifactFile({
|
|
20
|
+
path: 'reports/security-contracts.report.sig.json',
|
|
21
|
+
content: JSON.stringify({ kind: 'quickback-security-contract-signature' }),
|
|
22
|
+
})).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
// User story: As an API developer, I need runtime files to remain in outputDir so application code,
|
|
25
|
+
// handlers, and configs continue to compile and deploy from the generated runtime tree.
|
|
26
|
+
it('keeps non-state runtime files in runtime bucket', () => {
|
|
27
|
+
const files = [
|
|
28
|
+
{ path: 'src/index.ts', content: 'export {};' },
|
|
29
|
+
{ path: 'openapi.json', content: '{"openapi":"3.0.0"}' },
|
|
30
|
+
{ path: 'drizzle/auth/meta/_journal.json', content: '{"version":"1"}' },
|
|
31
|
+
];
|
|
32
|
+
const { runtimeFiles, stateFiles } = partitionGeneratedFiles(files);
|
|
33
|
+
expect(runtimeFiles.map((f) => f.path)).toEqual(['src/index.ts', 'openapi.json']);
|
|
34
|
+
expect(stateFiles.map((f) => f.path)).toEqual(['drizzle/auth/meta/_journal.json']);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=artifact-routing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-routing.test.js","sourceRoot":"","sources":["../../src/lib/artifact-routing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,+FAA+F;IAC/F,kGAAkG;IAClG,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,iCAAiC;YACvC,OAAO,EAAE,iBAAiB;SAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,kGAAkG;IAClG,wFAAwF;IACxF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,wCAAwC;YAC9C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;SACxE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,4CAA4C;YAClD,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAC;SAC3E,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,oGAAoG;IACpG,wFAAwF;IACxF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG;YACZ,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE;YAC/C,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,EAAE;YACxD,EAAE,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,iBAAiB,EAAE;SACxE,CAAC;QAEF,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;QACpE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
package/src/skill/SKILL.md
CHANGED
|
@@ -84,6 +84,16 @@ export default defineConfig({
|
|
|
84
84
|
});
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
+
## Compile Output and State Artifacts
|
|
88
|
+
|
|
89
|
+
When a project has a `quickback/` folder and compiles runtime output to project root:
|
|
90
|
+
|
|
91
|
+
- Runtime code stays in `build.outputDir` (for example `src/`, `wrangler.toml`, `package.json`).
|
|
92
|
+
- Drizzle migration/state artifacts are written to `quickback/drizzle/...`.
|
|
93
|
+
- Security contract report artifacts are written to `quickback/reports/...`.
|
|
94
|
+
|
|
95
|
+
Treat `quickback/drizzle` as the canonical migration state location for repeated compiles.
|
|
96
|
+
|
|
87
97
|
## Automatic Audit Fields
|
|
88
98
|
|
|
89
99
|
Quickback automatically injects these fields into every table:
|
|
@@ -100,40 +110,51 @@ Features live in `quickback/features/{name}/` with one file per table using `def
|
|
|
100
110
|
|
|
101
111
|
**Important**: Legacy mode (separate schema.ts + resource.ts) is no longer supported.
|
|
102
112
|
|
|
103
|
-
## Example:
|
|
113
|
+
## Example: todos.ts
|
|
104
114
|
|
|
105
115
|
```typescript
|
|
106
|
-
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
116
|
+
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
|
107
117
|
import { defineTable } from "@quickback/compiler";
|
|
108
118
|
|
|
109
|
-
export const
|
|
110
|
-
id:
|
|
119
|
+
export const todos = sqliteTable("todos", {
|
|
120
|
+
id: integer("id").primaryKey(),
|
|
121
|
+
title: text("title").notNull(),
|
|
122
|
+
description: text("description"),
|
|
123
|
+
completed: integer("completed", { mode: "boolean" }).default(false),
|
|
124
|
+
userId: text("user_id").notNull(),
|
|
111
125
|
organizationId: text("organization_id").notNull(),
|
|
112
|
-
name: text("name").notNull(),
|
|
113
|
-
email: text("email").notNull(),
|
|
114
|
-
phone: text("phone"),
|
|
115
|
-
resumeUrl: text("resume_url"),
|
|
116
|
-
source: text("source"),
|
|
117
126
|
});
|
|
118
127
|
|
|
119
|
-
export default defineTable(
|
|
128
|
+
export default defineTable(todos, {
|
|
120
129
|
firewall: {
|
|
121
|
-
organization: {},
|
|
130
|
+
organization: {}, // Auto-detects 'organizationId' column
|
|
131
|
+
owner: {}, // Auto-detects 'userId' column
|
|
122
132
|
},
|
|
133
|
+
|
|
123
134
|
crud: {
|
|
124
|
-
list: { access: { roles: ["
|
|
125
|
-
get: { access: { roles: ["
|
|
126
|
-
create: { access: { roles: ["
|
|
127
|
-
update: { access: { roles: ["
|
|
128
|
-
delete: { access: { roles: ["
|
|
135
|
+
list: { access: { roles: ["member", "admin"] } },
|
|
136
|
+
get: { access: { roles: ["member", "admin"] } },
|
|
137
|
+
create: { access: { roles: ["member", "admin"] } },
|
|
138
|
+
update: { access: { roles: ["admin"] } },
|
|
139
|
+
delete: { access: { roles: ["admin"] }, mode: "soft" },
|
|
129
140
|
},
|
|
141
|
+
|
|
130
142
|
guards: {
|
|
131
|
-
createable: ["
|
|
132
|
-
updatable: ["
|
|
143
|
+
createable: ["title", "description", "completed"],
|
|
144
|
+
updatable: ["title", "description", "completed"],
|
|
133
145
|
},
|
|
146
|
+
|
|
134
147
|
masking: {
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
userId: { type: "redact", show: { roles: ["admin"] } },
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
layouts: {
|
|
152
|
+
default: {
|
|
153
|
+
sections: [
|
|
154
|
+
{ label: "Details", columns: 2, fields: ["title", "completed"] },
|
|
155
|
+
{ label: "Audit", collapsed: true, fields: ["userId"] },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
137
158
|
},
|
|
138
159
|
});
|
|
139
160
|
```
|
|
@@ -144,12 +165,9 @@ Tables without a `defineTable()` default export get no API routes:
|
|
|
144
165
|
|
|
145
166
|
```typescript
|
|
146
167
|
// No default export = no API routes generated
|
|
147
|
-
export const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
score: integer('score').notNull(),
|
|
151
|
-
feedback: text('feedback'),
|
|
152
|
-
organizationId: text('organization_id').notNull(), // Always scope junction tables
|
|
168
|
+
export const roomAmenities = sqliteTable('room_amenities', {
|
|
169
|
+
roomId: text('room_id').notNull(),
|
|
170
|
+
amenityId: text('amenity_id').notNull(),
|
|
153
171
|
});
|
|
154
172
|
```
|
|
155
173
|
|
|
@@ -202,18 +220,18 @@ Role-based and record-based access control. Deny by default.
|
|
|
202
220
|
|
|
203
221
|
```typescript
|
|
204
222
|
crud: {
|
|
205
|
-
list: { access: { roles: ['
|
|
206
|
-
get: { access: { roles: ['
|
|
207
|
-
create: { access: { roles: ['
|
|
223
|
+
list: { access: { roles: ['member'] } },
|
|
224
|
+
get: { access: { roles: ['member'] } },
|
|
225
|
+
create: { access: { roles: ['admin', 'manager'] } },
|
|
208
226
|
update: {
|
|
209
227
|
access: {
|
|
210
228
|
or: [
|
|
211
|
-
{ roles: ['
|
|
229
|
+
{ roles: ['admin'] },
|
|
212
230
|
{ record: { createdBy: { equals: '$ctx.userId' } } },
|
|
213
231
|
],
|
|
214
232
|
},
|
|
215
233
|
},
|
|
216
|
-
delete: { access: { roles: ['
|
|
234
|
+
delete: { access: { roles: ['admin'] } },
|
|
217
235
|
}
|
|
218
236
|
```
|
|
219
237
|
|
|
@@ -244,10 +262,10 @@ Controls which fields can be modified.
|
|
|
244
262
|
|
|
245
263
|
```typescript
|
|
246
264
|
guards: {
|
|
247
|
-
createable: ['
|
|
248
|
-
updatable: ['
|
|
249
|
-
immutable: ['
|
|
250
|
-
protected: {
|
|
265
|
+
createable: ['name', 'description'], // Allowed on POST
|
|
266
|
+
updatable: ['description'], // Allowed on PATCH
|
|
267
|
+
immutable: ['invoiceNumber'], // Set once, never change
|
|
268
|
+
protected: { status: ['approve'] }, // Only via named actions
|
|
251
269
|
}
|
|
252
270
|
```
|
|
253
271
|
|
|
@@ -282,13 +300,13 @@ export default defineTable(external_orders, {
|
|
|
282
300
|
|
|
283
301
|
```typescript
|
|
284
302
|
masking: {
|
|
285
|
-
|
|
286
|
-
type: '
|
|
287
|
-
show: { roles: ['
|
|
303
|
+
ssn: {
|
|
304
|
+
type: 'ssn', // *****6789
|
|
305
|
+
show: { roles: ['admin', 'hr'] },
|
|
288
306
|
},
|
|
289
|
-
|
|
290
|
-
type: '
|
|
291
|
-
show: { roles: ['
|
|
307
|
+
email: {
|
|
308
|
+
type: 'email', // p***@e******.com
|
|
309
|
+
show: { roles: ['admin'], or: 'owner' },
|
|
292
310
|
},
|
|
293
311
|
}
|
|
294
312
|
```
|
|
@@ -324,92 +342,86 @@ The compiler warns if sensitive columns aren't explicitly configured:
|
|
|
324
342
|
Views are named projections that control which fields are visible based on role.
|
|
325
343
|
|
|
326
344
|
```typescript
|
|
327
|
-
export default defineTable(
|
|
345
|
+
export default defineTable(customers, {
|
|
328
346
|
// ... firewall, guards, etc.
|
|
329
347
|
|
|
330
348
|
views: {
|
|
331
|
-
|
|
332
|
-
fields: ['id', 'name', 'email'
|
|
333
|
-
access: { roles: ['
|
|
349
|
+
summary: {
|
|
350
|
+
fields: ['id', 'name', 'email'],
|
|
351
|
+
access: { roles: ['member', 'admin'] },
|
|
334
352
|
},
|
|
335
353
|
full: {
|
|
336
|
-
fields: ['id', 'name', 'email', 'phone', '
|
|
337
|
-
access: { roles: ['
|
|
354
|
+
fields: ['id', 'name', 'email', 'phone', 'ssn', 'address'],
|
|
355
|
+
access: { roles: ['admin'] },
|
|
338
356
|
},
|
|
339
357
|
},
|
|
340
358
|
});
|
|
341
359
|
```
|
|
342
360
|
|
|
343
361
|
**Generated endpoints**:
|
|
344
|
-
- `GET /api/v1/
|
|
345
|
-
- `GET /api/v1/
|
|
362
|
+
- `GET /api/v1/customers/views/summary` — returns only id, name, email
|
|
363
|
+
- `GET /api/v1/customers/views/full` — returns all fields (admin only)
|
|
346
364
|
|
|
347
365
|
Views support the same query parameters as list (filtering, sorting, pagination). Masking still applies to returned fields.
|
|
348
366
|
|
|
349
367
|
---
|
|
350
368
|
|
|
351
|
-
#
|
|
369
|
+
# Validation
|
|
352
370
|
|
|
353
|
-
|
|
371
|
+
Field-level validation rules compiled into the API:
|
|
354
372
|
|
|
355
373
|
```typescript
|
|
356
|
-
export default defineTable(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
374
|
+
export default defineTable(rooms, {
|
|
375
|
+
// ... other config
|
|
376
|
+
|
|
377
|
+
validation: {
|
|
378
|
+
name: { minLength: 1, maxLength: 100 },
|
|
379
|
+
capacity: { min: 1, max: 1000 },
|
|
380
|
+
roomType: { enum: ['meeting', 'conference', 'breakout'] },
|
|
381
|
+
email: { email: true },
|
|
382
|
+
website: { url: true },
|
|
383
|
+
code: { pattern: '^[A-Z]{3}$' },
|
|
362
384
|
},
|
|
363
|
-
// ...
|
|
364
385
|
});
|
|
365
386
|
```
|
|
366
387
|
|
|
367
|
-
Each key is a column name ending in `Id`, value is the camelCase target table name. These flow into schema-registry.json as `fkTarget` on each column, enabling the CMS to render typeahead/lookup inputs.
|
|
368
|
-
|
|
369
|
-
Convention-based matching (strip `Id` suffix) still works for simple cases like `projectId` → `project`. Use `references` only when the convention doesn't match.
|
|
370
|
-
|
|
371
388
|
---
|
|
372
389
|
|
|
373
|
-
#
|
|
390
|
+
# CMS Record Layouts
|
|
374
391
|
|
|
375
|
-
Control how the CMS
|
|
392
|
+
Control how fields are grouped on the CMS record detail page. Without layouts, fields are auto-grouped by naming heuristics.
|
|
376
393
|
|
|
377
394
|
```typescript
|
|
378
|
-
export default defineTable(
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
395
|
+
export default defineTable(contacts, {
|
|
396
|
+
// ... firewall, crud, guards, etc.
|
|
397
|
+
|
|
398
|
+
layouts: {
|
|
399
|
+
default: {
|
|
400
|
+
sections: [
|
|
401
|
+
{ label: "Contact Info", columns: 2, fields: ["name", "email", "phone", "mobile"] },
|
|
402
|
+
{ label: "Address", columns: 2, fields: ["address1", "address2", "city", "state", "zip"] },
|
|
403
|
+
{ label: "Internal Notes", collapsed: true, fields: ["notes", "internalNotes"] },
|
|
404
|
+
],
|
|
405
|
+
},
|
|
406
|
+
compact: {
|
|
407
|
+
sections: [
|
|
408
|
+
{ label: "Summary", fields: ["name", "status", "email"] },
|
|
409
|
+
],
|
|
410
|
+
},
|
|
385
411
|
},
|
|
386
|
-
// ...
|
|
387
412
|
});
|
|
388
413
|
```
|
|
389
414
|
|
|
390
|
-
|
|
415
|
+
### Section Options
|
|
391
416
|
|
|
392
|
-
|
|
417
|
+
| Property | Type | Default | Description |
|
|
418
|
+
|----------|------|---------|-------------|
|
|
419
|
+
| `label` | string | required | Section header text |
|
|
420
|
+
| `fields` | string[] | required | Column names to display |
|
|
421
|
+
| `columns` | `1 \| 2` | `1` | Number of columns for field layout |
|
|
422
|
+
| `collapsed` | boolean | `false` | Whether the section starts collapsed |
|
|
393
423
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
# Validation
|
|
397
|
-
|
|
398
|
-
Field-level validation rules compiled into the API:
|
|
399
|
-
|
|
400
|
-
```typescript
|
|
401
|
-
export default defineTable(jobs, {
|
|
402
|
-
// ... other config
|
|
403
|
-
|
|
404
|
-
validation: {
|
|
405
|
-
title: { minLength: 1, maxLength: 200 },
|
|
406
|
-
department: { minLength: 1, maxLength: 100 },
|
|
407
|
-
status: { enum: ['draft', 'open', 'closed'] },
|
|
408
|
-
salaryMin: { min: 0 },
|
|
409
|
-
salaryMax: { min: 0 },
|
|
410
|
-
},
|
|
411
|
-
});
|
|
412
|
-
```
|
|
424
|
+
Fields not assigned to any section are collected into an "Other Fields" section. When multiple layouts are defined, a dropdown appears in the CMS record detail header.
|
|
413
425
|
|
|
414
426
|
---
|
|
415
427
|
|
|
@@ -418,54 +430,51 @@ export default defineTable(jobs, {
|
|
|
418
430
|
Actions are custom API endpoints for business logic beyond CRUD. Defined in a separate `actions.ts` file using `defineActions()`.
|
|
419
431
|
|
|
420
432
|
```typescript
|
|
421
|
-
// quickback/features/
|
|
422
|
-
import {
|
|
433
|
+
// quickback/features/todos/actions.ts
|
|
434
|
+
import { todos } from './todos';
|
|
423
435
|
import { defineActions } from '@quickback/compiler';
|
|
424
436
|
import { z } from 'zod';
|
|
425
437
|
|
|
426
|
-
export default defineActions(
|
|
427
|
-
|
|
428
|
-
description: "
|
|
438
|
+
export default defineActions(todos, {
|
|
439
|
+
complete: {
|
|
440
|
+
description: "Mark todo as complete",
|
|
429
441
|
input: z.object({
|
|
430
|
-
|
|
431
|
-
notes: z.string().optional(),
|
|
442
|
+
completedAt: z.string().datetime().optional(),
|
|
432
443
|
}),
|
|
433
|
-
|
|
434
|
-
roles: ["
|
|
435
|
-
record: {
|
|
444
|
+
guard: {
|
|
445
|
+
roles: ["member", "admin"],
|
|
446
|
+
record: { completed: { equals: false } },
|
|
436
447
|
},
|
|
437
448
|
execute: async ({ db, record, ctx, input }) => {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
.returning();
|
|
442
|
-
return updated;
|
|
449
|
+
// Inline handler
|
|
450
|
+
await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
|
|
451
|
+
return { success: true };
|
|
443
452
|
},
|
|
444
453
|
sideEffects: "sync",
|
|
445
454
|
},
|
|
446
455
|
|
|
447
|
-
|
|
448
|
-
description: "
|
|
449
|
-
input: z.object({
|
|
450
|
-
|
|
451
|
-
handler: "./handlers/
|
|
456
|
+
archive: {
|
|
457
|
+
description: "Archive a todo",
|
|
458
|
+
input: z.object({}),
|
|
459
|
+
guard: { roles: ["admin"] },
|
|
460
|
+
handler: "./handlers/archive", // OR: external file handler
|
|
452
461
|
},
|
|
453
462
|
});
|
|
454
463
|
```
|
|
455
464
|
|
|
456
|
-
**Generated Route**: `POST /api/v1/
|
|
465
|
+
**Generated Route**: `POST /api/v1/todos/:id/complete`
|
|
457
466
|
|
|
458
467
|
### Record-based vs Standalone Actions
|
|
459
468
|
|
|
460
469
|
**Record-based** (default) — operates on a specific record via `:id`:
|
|
461
470
|
```typescript
|
|
462
|
-
|
|
463
|
-
description: "
|
|
464
|
-
input: z.object({
|
|
465
|
-
|
|
466
|
-
handler: "./handlers/
|
|
471
|
+
approve: {
|
|
472
|
+
description: "Approve an invoice",
|
|
473
|
+
input: z.object({ notes: z.string().optional() }),
|
|
474
|
+
guard: { roles: ["admin"] },
|
|
475
|
+
handler: "./handlers/approve",
|
|
467
476
|
}
|
|
468
|
-
// → POST /api/v1/
|
|
477
|
+
// → POST /api/v1/invoices/:id/approve
|
|
469
478
|
```
|
|
470
479
|
|
|
471
480
|
**Standalone** — custom endpoint not tied to a record:
|
|
@@ -476,10 +485,10 @@ chat: {
|
|
|
476
485
|
method: "POST",
|
|
477
486
|
responseType: "stream",
|
|
478
487
|
input: z.object({ message: z.string() }),
|
|
479
|
-
|
|
488
|
+
guard: { roles: ["member"] },
|
|
480
489
|
handler: "./handlers/chat",
|
|
481
490
|
}
|
|
482
|
-
// → POST /api/v1/
|
|
491
|
+
// → POST /api/v1/todos/chat
|
|
483
492
|
```
|
|
484
493
|
|
|
485
494
|
### Action Options
|
|
@@ -583,7 +592,7 @@ OR'd LIKE across all `text()` schema columns (system columns excluded). Combine
|
|
|
583
592
|
|
|
584
593
|
```json
|
|
585
594
|
{
|
|
586
|
-
"data": [{ "id": "...", "
|
|
595
|
+
"data": [{ "id": "...", "title": "Todo 1" }],
|
|
587
596
|
"pagination": {
|
|
588
597
|
"limit": 10,
|
|
589
598
|
"offset": 0,
|
|
@@ -764,17 +773,34 @@ Detect from `quickback.config.ts` and use the correct imports:
|
|
|
764
773
|
|
|
765
774
|
# Documentation
|
|
766
775
|
|
|
776
|
+
## CLI Docs (Recommended)
|
|
777
|
+
|
|
778
|
+
The fastest way to access documentation is via the Quickback CLI. It bundles all docs offline:
|
|
779
|
+
|
|
780
|
+
```bash
|
|
781
|
+
quickback docs # List all available topics
|
|
782
|
+
quickback docs <topic> # Show docs for a specific topic
|
|
783
|
+
quickback docs firewall # Example: firewall docs
|
|
784
|
+
quickback docs cms/record-layouts # Example: CMS record layouts
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
## Online Docs
|
|
788
|
+
|
|
767
789
|
Full documentation at https://docs.quickback.dev
|
|
768
790
|
|
|
769
791
|
- [Getting Started](https://docs.quickback.dev/compiler/getting-started)
|
|
770
792
|
- [Concepts](https://docs.quickback.dev/compiler/definitions/concepts)
|
|
771
|
-
- [Full Example](https://docs.quickback.dev/compiler/getting-started/full-example)
|
|
772
793
|
- [Database Schema](https://docs.quickback.dev/compiler/definitions/schema)
|
|
773
|
-
- [CRUD & API](https://docs.quickback.dev/compiler/using-the-api)
|
|
774
|
-
- [Views](https://docs.quickback.dev/compiler/definitions/views)
|
|
775
|
-
- [Actions](https://docs.quickback.dev/compiler/definitions/actions)
|
|
776
794
|
- [Firewall](https://docs.quickback.dev/compiler/definitions/firewall)
|
|
777
795
|
- [Access](https://docs.quickback.dev/compiler/definitions/access)
|
|
778
796
|
- [Guards](https://docs.quickback.dev/compiler/definitions/guards)
|
|
779
797
|
- [Masking](https://docs.quickback.dev/compiler/definitions/masking)
|
|
798
|
+
- [Views](https://docs.quickback.dev/compiler/definitions/views)
|
|
799
|
+
- [Validation](https://docs.quickback.dev/compiler/definitions/validation)
|
|
800
|
+
- [Actions](https://docs.quickback.dev/compiler/definitions/actions)
|
|
801
|
+
- [CRUD API](https://docs.quickback.dev/compiler/using-the-api/crud)
|
|
802
|
+
- [Query Parameters](https://docs.quickback.dev/compiler/using-the-api/query-params)
|
|
780
803
|
- [CLI Reference](https://docs.quickback.dev/compiler/cloud-compiler/cli)
|
|
804
|
+
- [CMS Overview](https://docs.quickback.dev/cms)
|
|
805
|
+
- [CMS Record Layouts](https://docs.quickback.dev/cms/record-layouts)
|
|
806
|
+
- [CMS Schema Format](https://docs.quickback.dev/cms/schema-format)
|
|
@@ -19,6 +19,7 @@ You deeply understand:
|
|
|
19
19
|
- **Actions**: Custom endpoints using `defineActions()` with Zod schemas
|
|
20
20
|
- **Views**: Column-level security with named projections
|
|
21
21
|
- **Validation**: Field-level validation rules
|
|
22
|
+
- **Layouts**: CMS record page field grouping with sections, columns, and collapsed state
|
|
22
23
|
|
|
23
24
|
## When Invoked
|
|
24
25
|
|
|
@@ -44,6 +45,11 @@ Generate files in `quickback/features/{name}/`:
|
|
|
44
45
|
- `actions.ts` - Custom actions via `defineActions()` with Zod schemas (if needed)
|
|
45
46
|
- `handlers/` - Action handler files (if needed)
|
|
46
47
|
|
|
48
|
+
When explaining compile outputs:
|
|
49
|
+
- Runtime outputs remain in `build.outputDir`.
|
|
50
|
+
- Drizzle and migration state artifacts should live in `quickback/drizzle/...` when a `quickback/` folder exists.
|
|
51
|
+
- Security contract reports should live in `quickback/reports/...` when a `quickback/` folder exists.
|
|
52
|
+
|
|
47
53
|
Detect the database dialect from `quickback.config.ts`:
|
|
48
54
|
- Cloudflare D1 / SQLite: Use `sqliteTable`, `text`, `integer` from `drizzle-orm/sqlite-core`
|
|
49
55
|
- Supabase / PostgreSQL: Use `pgTable`, `text`, `boolean`, `timestamp` from `drizzle-orm/pg-core`
|
|
@@ -51,37 +57,35 @@ Detect the database dialect from `quickback.config.ts`:
|
|
|
51
57
|
### Table Definition Pattern
|
|
52
58
|
|
|
53
59
|
```typescript
|
|
54
|
-
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
60
|
+
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
|
55
61
|
import { defineTable } from "@quickback/compiler";
|
|
56
62
|
|
|
57
|
-
export const
|
|
58
|
-
id:
|
|
63
|
+
export const todos = sqliteTable("todos", {
|
|
64
|
+
id: integer("id").primaryKey(),
|
|
65
|
+
title: text("title").notNull(),
|
|
66
|
+
completed: integer("completed", { mode: "boolean" }).default(false),
|
|
67
|
+
userId: text("user_id").notNull(),
|
|
59
68
|
organizationId: text("organization_id").notNull(),
|
|
60
|
-
name: text("name").notNull(),
|
|
61
|
-
email: text("email").notNull(),
|
|
62
|
-
phone: text("phone"),
|
|
63
|
-
resumeUrl: text("resume_url"),
|
|
64
|
-
source: text("source"),
|
|
65
69
|
});
|
|
66
70
|
|
|
67
|
-
export default defineTable(
|
|
71
|
+
export default defineTable(todos, {
|
|
68
72
|
firewall: {
|
|
69
|
-
organization: {},
|
|
73
|
+
organization: {}, // Auto-detects 'organizationId' column
|
|
74
|
+
owner: {}, // Auto-detects 'userId' column
|
|
70
75
|
},
|
|
71
76
|
crud: {
|
|
72
|
-
list: { access: { roles: ["
|
|
73
|
-
get: { access: { roles: ["
|
|
74
|
-
create: { access: { roles: ["
|
|
75
|
-
update: { access: { roles: ["
|
|
76
|
-
delete: { access: { roles: ["
|
|
77
|
+
list: { access: { roles: ["member", "admin"] } },
|
|
78
|
+
get: { access: { roles: ["member", "admin"] } },
|
|
79
|
+
create: { access: { roles: ["member", "admin"] } },
|
|
80
|
+
update: { access: { roles: ["admin"] } },
|
|
81
|
+
delete: { access: { roles: ["admin"] }, mode: "soft" },
|
|
77
82
|
},
|
|
78
83
|
guards: {
|
|
79
|
-
createable: ["
|
|
80
|
-
updatable: ["
|
|
84
|
+
createable: ["title", "completed"],
|
|
85
|
+
updatable: ["title", "completed"],
|
|
81
86
|
},
|
|
82
87
|
masking: {
|
|
83
|
-
|
|
84
|
-
phone: { type: "phone", show: { roles: ["hiring-manager", "recruiter"] } },
|
|
88
|
+
userId: { type: "redact", show: { roles: ["admin"] } },
|
|
85
89
|
},
|
|
86
90
|
});
|
|
87
91
|
```
|
|
@@ -89,28 +93,24 @@ export default defineTable(candidates, {
|
|
|
89
93
|
### Actions Pattern
|
|
90
94
|
|
|
91
95
|
```typescript
|
|
92
|
-
// quickback/features/
|
|
93
|
-
import {
|
|
96
|
+
// quickback/features/todos/actions.ts
|
|
97
|
+
import { todos } from './todos';
|
|
94
98
|
import { defineActions } from '@quickback/compiler';
|
|
95
99
|
import { z } from 'zod';
|
|
96
100
|
|
|
97
|
-
export default defineActions(
|
|
98
|
-
|
|
99
|
-
description: "
|
|
101
|
+
export default defineActions(todos, {
|
|
102
|
+
complete: {
|
|
103
|
+
description: "Mark todo as complete",
|
|
100
104
|
input: z.object({
|
|
101
|
-
|
|
102
|
-
notes: z.string().optional(),
|
|
105
|
+
completedAt: z.string().datetime().optional(),
|
|
103
106
|
}),
|
|
104
|
-
|
|
105
|
-
roles: ["
|
|
106
|
-
record: {
|
|
107
|
+
guard: {
|
|
108
|
+
roles: ["member", "admin"],
|
|
109
|
+
record: { completed: { equals: false } },
|
|
107
110
|
},
|
|
108
111
|
execute: async ({ db, record, ctx, input }) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.where(eq(applications.id, record.id))
|
|
112
|
-
.returning();
|
|
113
|
-
return updated;
|
|
112
|
+
await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
|
|
113
|
+
return { success: true };
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
116
|
});
|
|
@@ -143,29 +143,29 @@ firewall: {
|
|
|
143
143
|
### Workflow with protected status
|
|
144
144
|
```typescript
|
|
145
145
|
guards: {
|
|
146
|
-
protected: {
|
|
146
|
+
protected: { status: ['approve', 'reject'] }
|
|
147
147
|
}
|
|
148
|
-
// Plus defineActions() for
|
|
148
|
+
// Plus defineActions() for approve/reject
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
### PII masking
|
|
152
152
|
```typescript
|
|
153
153
|
masking: {
|
|
154
|
-
email: { type: 'email', show: { roles: ['
|
|
155
|
-
|
|
154
|
+
email: { type: 'email', show: { roles: ['admin'] } },
|
|
155
|
+
ssn: { type: 'ssn', show: { roles: ['hr'] } }
|
|
156
156
|
}
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
### Views (column-level security)
|
|
160
160
|
```typescript
|
|
161
161
|
views: {
|
|
162
|
-
|
|
163
|
-
fields: ['id', 'name', '
|
|
164
|
-
access: { roles: ['
|
|
162
|
+
summary: {
|
|
163
|
+
fields: ['id', 'name', 'email'],
|
|
164
|
+
access: { roles: ['member', 'admin'] },
|
|
165
165
|
},
|
|
166
166
|
full: {
|
|
167
|
-
fields: ['id', 'name', 'email', 'phone', '
|
|
168
|
-
access: { roles: ['
|
|
167
|
+
fields: ['id', 'name', 'email', 'phone', 'ssn'],
|
|
168
|
+
access: { roles: ['admin'] },
|
|
169
169
|
},
|
|
170
170
|
}
|
|
171
171
|
```
|
|
@@ -179,7 +179,7 @@ chat: {
|
|
|
179
179
|
method: "POST",
|
|
180
180
|
responseType: "stream",
|
|
181
181
|
input: z.object({ message: z.string() }),
|
|
182
|
-
|
|
182
|
+
guard: { roles: ["member"] },
|
|
183
183
|
handler: "./handlers/chat",
|
|
184
184
|
}
|
|
185
185
|
```
|
|
@@ -194,10 +194,24 @@ Before finishing, verify:
|
|
|
194
194
|
- [ ] Masking for any PII fields
|
|
195
195
|
- [ ] Views for different visibility levels (if needed)
|
|
196
196
|
- [ ] Validation rules for constrained fields (if needed)
|
|
197
|
+
- [ ] Layouts for CMS record page field grouping (if needed)
|
|
197
198
|
- [ ] No audit fields in schema (auto-injected)
|
|
198
199
|
- [ ] Using `defineTable()` combined mode (not separate schema.ts + resource.ts)
|
|
199
200
|
- [ ] Actions use `defineActions()` with Zod schemas (not JSON schema)
|
|
200
201
|
|
|
202
|
+
## Accessing Documentation
|
|
203
|
+
|
|
204
|
+
When you need to look up Quickback docs, use the CLI — it bundles all docs offline:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
quickback docs # List all available topics
|
|
208
|
+
quickback docs <topic> # Show docs for a specific topic
|
|
209
|
+
quickback docs firewall # Example: firewall docs
|
|
210
|
+
quickback docs cms/record-layouts # Example: CMS record layouts
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Full online docs: https://docs.quickback.dev
|
|
214
|
+
|
|
201
215
|
## Response Style
|
|
202
216
|
|
|
203
217
|
- Be direct and practical
|