@kardoe/quickback 0.6.10 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +61 -5
- package/dist/commands/compile.js.map +1 -1
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +17 -12
- package/dist/docs/content.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +13 -0
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +62 -2
- package/dist/lib/api-client.js.map +1 -1
- package/dist/skill/skill/SKILL.md +21 -0
- package/package.json +1 -1
- package/src/skill/SKILL.md +21 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA4FH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA4FH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAoS7C"}
|
package/dist/commands/compile.js
CHANGED
|
@@ -211,15 +211,58 @@ export async function compile() {
|
|
|
211
211
|
existingFiles: drizzleMeta,
|
|
212
212
|
}, // Type assertion for existingFiles
|
|
213
213
|
(msg) => spinner.text = msg);
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
const totalSecs = result.meta.timings ? (result.meta.timings.totalMs / 1000).toFixed(1) : null;
|
|
215
|
+
spinner.succeed(`Compiled ${result.meta.fileCount} files (v${result.meta.version})${totalSecs ? ` in ${totalSecs}s` : ''}`);
|
|
216
|
+
// Show what was generated — SPA builds, schema registry, OpenAPI
|
|
217
|
+
const spaBuilds = result.meta.timings?.commands?.filter((c) => c.description.includes('SPA build')) || [];
|
|
218
|
+
for (const spa of spaBuilds) {
|
|
219
|
+
const name = spa.description.replace(' SPA build', '');
|
|
220
|
+
const secs = (spa.ms / 1000).toFixed(1);
|
|
221
|
+
if (spa.success) {
|
|
222
|
+
// Count SPA files in the output
|
|
223
|
+
const spaPrefix = `src/apps/${name}/`;
|
|
224
|
+
const spaFiles = result.files.filter((f) => f.path.startsWith(spaPrefix));
|
|
225
|
+
const assetFiles = spaFiles.filter((f) => f.path.includes('/assets/'));
|
|
226
|
+
const info = assetFiles.length > 0
|
|
227
|
+
? `${assetFiles.length} assets, ${secs}s`
|
|
228
|
+
: `${secs}s`;
|
|
229
|
+
console.log(pc.gray(` ${pc.green('●')} ${name} SPA built (${info})`));
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
console.log(pc.yellow(` ${pc.red('●')} ${name} SPA build failed`));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Show skipped SPAs
|
|
236
|
+
const cmsObj = typeof config.cms === 'object' ? config.cms : null;
|
|
237
|
+
const accountObj = typeof config.account === 'object' ? config.account : null;
|
|
238
|
+
if (config.cms && cmsObj?.build === false) {
|
|
239
|
+
console.log(pc.gray(` ${pc.dim('○')} cms SPA skipped (build: false)`));
|
|
240
|
+
}
|
|
241
|
+
if (config.account && accountObj?.build === false) {
|
|
242
|
+
console.log(pc.gray(` ${pc.dim('○')} account SPA skipped (build: false)`));
|
|
243
|
+
}
|
|
216
244
|
const hasSchemaRegistry = result.files.some((f) => f.path === 'schema-registry.json');
|
|
217
245
|
if (hasSchemaRegistry) {
|
|
218
|
-
console.log(pc.gray(`
|
|
246
|
+
console.log(pc.gray(` ${pc.green('●')} CMS schema registry`));
|
|
219
247
|
}
|
|
220
248
|
const hasOpenAPI = result.files.some((f) => f.path === 'openapi.json');
|
|
221
249
|
if (hasOpenAPI) {
|
|
222
|
-
console.log(pc.gray(`
|
|
250
|
+
console.log(pc.gray(` ${pc.green('●')} OpenAPI specification`));
|
|
251
|
+
}
|
|
252
|
+
// Show timing breakdown
|
|
253
|
+
if (result.meta.timings) {
|
|
254
|
+
const t = result.meta.timings;
|
|
255
|
+
const migrationCmd = t.commands.find((c) => c.description.includes('migration'));
|
|
256
|
+
const parts = [];
|
|
257
|
+
parts.push(`parse ${(t.parseMs / 1000).toFixed(1)}s`);
|
|
258
|
+
parts.push(`generate ${(t.generateMs / 1000).toFixed(1)}s`);
|
|
259
|
+
if (migrationCmd)
|
|
260
|
+
parts.push(`migrations ${(migrationCmd.ms / 1000).toFixed(1)}s`);
|
|
261
|
+
if (spaBuilds.length > 0) {
|
|
262
|
+
const spaTotal = spaBuilds.reduce((sum, s) => sum + s.ms, 0);
|
|
263
|
+
parts.push(`SPAs ${(spaTotal / 1000).toFixed(1)}s`);
|
|
264
|
+
}
|
|
265
|
+
console.log(pc.dim(` ⏱ ${parts.join(' → ')}`));
|
|
223
266
|
}
|
|
224
267
|
// Display warnings if any
|
|
225
268
|
if (result.warnings && result.warnings.length > 0) {
|
|
@@ -233,8 +276,21 @@ export async function compile() {
|
|
|
233
276
|
const shouldRouteStateArtifactsToQuickback = Boolean(quickbackStateDir);
|
|
234
277
|
const { runtimeFiles, stateFiles } = partitionGeneratedFiles(result.files);
|
|
235
278
|
spinner.start('Writing output...');
|
|
279
|
+
// Clean stale SPA asset directories before writing fresh ones.
|
|
280
|
+
// SPA builds produce content-hashed filenames, so old files would accumulate.
|
|
281
|
+
const filesToWrite = shouldRouteStateArtifactsToQuickback ? runtimeFiles : result.files;
|
|
282
|
+
const spaAssetDirs = new Set();
|
|
283
|
+
for (const f of filesToWrite) {
|
|
284
|
+
const match = f.path.match(/^(src\/apps\/cms\/assets|src\/apps\/account\/assets|src\/apps\/assets|src\/cms\/account\/assets|src\/cms\/assets|src\/account\/assets)\//);
|
|
285
|
+
if (match)
|
|
286
|
+
spaAssetDirs.add(match[1]);
|
|
287
|
+
}
|
|
288
|
+
for (const dir of spaAssetDirs) {
|
|
289
|
+
const fullDir = join(outputDir, dir);
|
|
290
|
+
await fs.rm(fullDir, { recursive: true, force: true }).catch(() => { });
|
|
291
|
+
}
|
|
236
292
|
// Use merge strategy - don't wipe existing files, just update generated ones
|
|
237
|
-
await writeFilesWithMerge(outputDir,
|
|
293
|
+
await writeFilesWithMerge(outputDir, filesToWrite);
|
|
238
294
|
if (quickbackStateDir && stateFiles.length > 0) {
|
|
239
295
|
await writeFilesWithMerge(quickbackStateDir, stateFiles);
|
|
240
296
|
spinner.succeed(`Output written to ${pc.cyan(outputDir)} (state artifacts synced to ${pc.cyan(quickbackStateDir)})`);
|
|
@@ -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":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClJ,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,0BAA0B,GAAG;IACjC,mBAAmB;IACnB,uBAAuB;IACvB,oBAAoB;IACpB,uBAAuB;IACvB,oBAAoB;IACpB,cAAc;CACN,CAAC;AAEX,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,wBAAwB,CAAC,WAAmB,EAAE,SAAiB;IAC5E,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,WAAW,CAAC,YAAY,EAAE,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3D,OAAO,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,WAAmB,EAAE,SAAiB;IAC9E,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,WAAW,CAAC,YAAY,EAAE,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,CAAC;IAE9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,eAAe,IAAI,0BAA0B,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS;QAE3C,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACrF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEjC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;QACtD,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5D,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,8BAA8B,CAC3C,WAAmB,EACnB,SAAiB,EACjB,cAAwD;IAExD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,WAAW,CAAC,YAAY,EAAE,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,CAAC;IAE9C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACjD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAC7E,CAAC;IAEF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAE3C,mBAAmB;IACnB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,MAAM,YAAY,GAAG,MAAM,cAAc,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE7E,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACpD,CAAC;SAAM,IAAI,YAAY,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,KAAK,IAAI,SAAS,WAAW,CAAC,CAAC,CAAC;IACrE,CAAC;SAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;IAExD,IAAI,CAAC;QACH,mBAAmB;QACnB,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;QAC1C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YACxC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,uDAAuD;QACvD,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC;YACpD,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAE,uDAAuD;YAChF,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAS,sCAAsC;QAEjE,cAAc;QACd,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjE,gBAAgB;QAChB,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO,CAAC,OAAO,CAAC,UAAU,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;QAExD,+CAA+C;QAC/C,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3E,MAAM,UAAU,GAAG,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;QACjD,MAAM,aAAa,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;QACtD,MAAM,cAAc,GAAG,QAAQ,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,cAAc,CAAC;QAClE,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,UAAU,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,WAAW,CAAC,CAAC;YACzD,IAAI,aAAa,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,aAAa,wBAAwB,CAAC,CAAC;YAC5E,IAAI,cAAc,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,sBAAsB,CAAC,CAAC;YAC5E,OAAO,CAAC,OAAO,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACtC,CAAC;QAED,sEAAsE;QACtE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS;YACvC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;YAC5C,CAAC,CAAC,WAAW,CAAC;QAEhB,wDAAwD;QACxD,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,qCAAqC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC;QACtG,CAAC;QAED,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACtC,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;SACjB,CAAC,CAAC,CACJ,CAAC;QACF,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;QAClC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,SAAS,qBAAqB,CAAC,CAAC,CAAC;QAClE,CAAC;QAED,2BAA2B;QAC3B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B;YACE,MAAM;YACN,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,aAAa,EAAE,CAAC,CAAC,aAAa;gBAC9B,YAAY,EAAE,CAAC,CAAC,YAAY;aAC7B,CAAC,CAAC;YACH,iEAAiE;YACjE,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC1C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACpC,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;iBACjB,CAAC,CAAC;gBACH,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxC,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,MAAM,EAAE,CAAC,CAAC,MAAM;iBACjB,CAAC,CAAC;gBACH,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC5C,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,CAAC,CAAC,MAAM;oBACrB,MAAM,EAAE,CAAC,CAAC,UAAU;iBACrB,CAAC,CAAC;gBACH,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;aAClD,CAAC,CAAC,CAAC,SAAS;YACb,8DAA8D;YAC9D,aAAa,EAAE,WAAW;SACpB,EAAE,mCAAmC;QAC7C,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,CAC5B,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/F,OAAO,CAAC,OAAO,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,SAAS,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAE5H,iEAAiE;QACjE,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1G,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChB,gCAAgC;gBAChC,MAAM,SAAS,GAAG,YAAY,IAAI,GAAG,CAAC;gBACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC1E,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;gBACvE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC;oBAChC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,YAAY,IAAI,GAAG;oBACzC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC;YACzE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,mBAAmB,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAA8B,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7F,MAAM,UAAU,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAkC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzG,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,EAAE,KAAK,KAAK,KAAK,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,IAAI,UAAU,EAAE,KAAK,KAAK,KAAK,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC;QACtF,IAAI,iBAAiB,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QACvE,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,wBAAwB;QACxB,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;YAC9B,MAAM,YAAY,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;YACjF,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC5D,IAAI,YAAY;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACnF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC7D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,0BAA0B;QAC1B,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACpD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,wBAAwB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACjF,MAAM,oCAAoC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACxE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE3E,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAEnC,+DAA+D;QAC/D,8EAA8E;QAC9E,MAAM,YAAY,GAAG,oCAAoC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACxF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,0IAA0I,CAAC,CAAC;YACvK,IAAI,KAAK;gBAAE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACrC,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACzE,CAAC;QAED,6EAA6E;QAC7E,MAAM,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACnD,IAAI,iBAAiB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,mBAAmB,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YACzD,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,+BAA+B,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACrH,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACrD,IAAI,MAAM,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,sGAAsG,CAAC,CAAC,CAAC;YACjI,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,2CAA2C;QAC3C,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC,CAAC;YAE7D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAClC,sDAAsD;gBACtD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC;gBAEtE,6DAA6D;gBAC7D,0DAA0D;gBAC1D,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;gBAElE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC/B,IAAI,CAAC;oBACH,MAAM,UAAU,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;oBAC/C,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACnC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;wBACjB,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,WAAW,YAAY,CAAC,CAAC;oBAC/C,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;wBAC9B,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,0BAA0B,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACjF,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,eAAe,4CAA4C,CAAC,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,yBAAyB,GAAG,oCAAoC;YACpE,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,MAAM,8BAA8B,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/E,IAAI,yBAAyB,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,yBAAyB,+CAA+C,CAAC,CAAC,CAAC;QAC7G,CAAC;QAED,mBAAmB;QACnB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;QACnG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IAExC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAEnC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAEjD,iCAAiC;YACjC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBACrD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,CAAC;gBAClE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACtC,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC,CAAC;gBACpE,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -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,CA6bzC,CAAC;AAEF,eAAO,MAAM,UAAU,UAgHtB,CAAC"}
|
package/dist/docs/content.js
CHANGED
|
@@ -11,7 +11,7 @@ export const DOCS = {
|
|
|
11
11
|
},
|
|
12
12
|
"account-ui/features/admin": {
|
|
13
13
|
"title": "Admin Panel",
|
|
14
|
-
"content": "
|
|
14
|
+
"content": "The admin panel provides a user management dashboard for administrators. It's part of the Account UI SPA — when enabled, the `/admin` route is included in the build.\n\n## Enabling Admin\n\nSet `auth.admin` to `true` in your account config:\n\n```typescript title=\"quickback/quickback.config.ts\"\naccount: {\n auth: {\n admin: true,\n },\n},\n```\n\nThis does two things:\n1. Includes admin route files in the Account SPA build (compile-time gating)\n2. Ensures the Better Auth `admin` plugin is enabled on the backend\n\nWhen `auth.admin` is `false` (the default), admin routes are excluded from the SPA bundle entirely — they don't exist in production.\n\n## What It Can Do\n\n- **View all users** — Paginated list with search\n- **Create users** — Manually create accounts with email/password\n- **Ban/unban users** — Suspend or reactivate user accounts\n- **Reset passwords** — Generate password reset for any user\n- **View sessions** — See active sessions for any user\n\n## Access Control\n\nThe admin panel is restricted to users with `role: \"admin\"` on their Better Auth user record. Non-admin users are redirected away from `/admin`.\n\nTo grant admin access to a user, use the Better Auth admin API:\n\n```bash\ncurl -X POST https://api.example.com/admin/v1/set-role \\\n -H \"Authorization: Bearer $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d '{ \"userId\": \"user_123\", \"role\": \"admin\" }'\n```\n\n## Custom Admin Domain\n\nGive the admin panel its own subdomain with `adminDomain`:\n\n```typescript title=\"quickback/quickback.config.ts\"\naccount: {\n domain: \"auth.example.com\",\n adminDomain: \"admin.example.com\",\n auth: { password: true, admin: true },\n},\ntrustedOrigins: [\n \"https://auth.example.com\",\n \"https://admin.example.com\",\n],\n```\n\nThe admin domain serves the same Account SPA at root (`/`). The SPA's client-side router handles showing the admin page at `admin.example.com/admin`. Authentication cookies are shared across subdomains automatically via [cross-subdomain cookie configuration](/compiler/config/domains#cross-subdomain-authentication).\n\n## CMS Access Control\n\nWhen both CMS and Account UI are enabled, the admin panel's profile page shows a \"Go to CMS\" button. You can restrict this to admin users only:\n\n```typescript\ncms: { domain: \"cms.example.com\", access: \"admin\" },\n```\n\nWith `access: \"admin\"`, only users with the admin role see the CMS link. Regular users don't see it.\n\n## Related\n\n- [Configuration](/compiler/config) — `auth.admin` and `adminDomain` options\n- [Multi-Domain Architecture](/compiler/config/domains) — Custom domains and hostname routing\n- [Access Control](/compiler/definitions/access) — Role-based permissions in your API"
|
|
15
15
|
},
|
|
16
16
|
"account-ui/features/api-keys": {
|
|
17
17
|
"title": "API Key Management",
|
|
@@ -47,7 +47,7 @@ export const DOCS = {
|
|
|
47
47
|
},
|
|
48
48
|
"account-ui": {
|
|
49
49
|
"title": "Account UI",
|
|
50
|
-
"content": "# Quickback Account UI\n\nA
|
|
50
|
+
"content": "# Quickback Account UI\n\nA complete authentication and account management frontend. It handles login, signup, password reset, profile management, device sessions, passkeys, organizations, and admin — so you don't have to build any of it.\n\n## What's Included\n\nAccount UI is a single React SPA that contains three distinct sections:\n\n### Account (every user)\n\nLogin, signup, profile editing, password management, device sessions, email changes, and account deletion. This is what every user interacts with.\n\nServed on its own domain (e.g., `auth.example.com`) or at `/account/` when embedded alongside the CMS.\n\n### Organization Management (multi-tenant)\n\nDashboard with org switching, org creation, member invitations, role management, and org settings. Only available when `auth.organizations` is enabled.\n\n### Admin Panel (admin users only)\n\nUser management dashboard — view all users, search, create accounts, ban/unban, reset passwords, and manage sessions. Only accessible to users with the `admin` role. Can be served on its own domain (e.g., `admin.example.com`) via the `adminDomain` config.\n\n## Quick Start (Compiler-Embedded)\n\nThe recommended approach: add `account` to your `quickback.config.ts` and compile. The compiler builds the SPA from source with your project-specific settings baked in.\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default {\n name: \"my-app\",\n template: \"hono\",\n cms: { domain: \"cms.example.com\" },\n account: {\n domain: \"auth.example.com\",\n name: \"My App\",\n auth: {\n password: true,\n passkey: true,\n organizations: true,\n admin: true,\n },\n },\n // ...providers\n};\n```\n\n```bash\nquickback compile\nnpx wrangler deploy\n```\n\nThat's it. The compiler:\n1. Reads your auth feature flags and branding from the config\n2. Generates a `.env` file with the correct `VITE_*` variables\n3. Builds the SPA from source with Vite (inside Docker)\n4. Excludes routes for disabled features (compile-time tree shaking)\n5. Outputs the built assets alongside your API code\n\nNo manual `.env` configuration needed. No separate deployment.\n\nSee [Configuration](/compiler/config) for all `account` options and [Multi-Domain Architecture](/compiler/config/domains) for custom domain setup.\n\n### Skip SPA Rebuild\n\nAfter the first compile, skip rebuilding the Account SPA on subsequent compiles:\n\n```typescript\naccount: { build: false, /* ...other options */ }\n```\n\nUseful when iterating on API features — saves significant compile time. Set back to `true` (or omit) when you need to update the Account UI.\n\n### Custom Output Directory\n\n```typescript\naccount: { outputDir: \"my-custom-path/account\" }\n```\n\nChanges where compiled Account assets are placed, instead of the default `src/apps/account/`.\n\n## Compile-Time Feature Gating\n\nAuth feature flags control which pages are included in the bundle:\n\n| Flag | Pages Included |\n|------|---------------|\n| `auth.password` | Password login, inline password change on profile |\n| `auth.emailOTP` | Email OTP login flow, email-based password reset |\n| `auth.passkey` | Passkey setup and management |\n| `auth.organizations` | Dashboard, org creation, member management, invitations |\n| `auth.admin` | Admin panel (user management) |\n\nWhen a flag is `false`, the corresponding route files are **removed before the Vite build** — they never appear in the JavaScript bundle. This keeps production bundles minimal.\n\n## Standalone Usage\n\nAccount UI also works outside of Quickback:\n\n### Template (own the source)\n\nClone the repo and customize directly:\n\n```bash\nnpx degit Kardoe-com/quickback-better-auth-account-ui my-account-app\ncd my-account-app\nnpm install\n```\n\nConfigure via `.env` files and deploy as a standalone Cloudflare Worker. See [Standalone Usage](/account-ui/standalone) for Better Auth backends or [With Quickback](/account-ui/with-quickback) for Quickback-compiled backends.\n\n### Library (npm package)\n\nInstall as a dependency:\n\n```bash\nnpm install quickback-better-auth-account-ui\n```\n\n```tsx\n\nsetAppConfig({\n authRoute: 'quickback',\n name: 'My App',\n});\n```\n\nSee [Library Usage](/account-ui/library-usage) for details.\n\n## Features\n\n- **Authentication** — Email/password, passkeys (WebAuthn), email OTP, magic links, email verification, password reset\n- **Account Management** — Profile editing, avatar upload, password changes, device/session management, account deletion\n- **Organizations** — Multi-tenant org management with owner/admin/member roles, invitations, and org settings\n- **Admin Panel** — User management dashboard with search, create, ban/unban, password reset, and session viewing\n- **API Keys** — Generate and manage API keys for programmatic access\n- **CLI Authorization** — Device authorization flow for `quickback login`\n\n## Next Steps\n\n- **[With Quickback](/account-ui/with-quickback)** — Compiler-embedded and standalone setup\n- **[Standalone Usage](/account-ui/standalone)** — Use with any Better Auth backend\n- **[Library Usage](/account-ui/library-usage)** — Import as an npm package\n- **[Feature Flags](/account-ui/features)** — Enable and disable features\n- **[Environment Variables](/account-ui/environment-variables)** — Configuration reference\n- **[Customization](/account-ui/customization)** — Branding, labels, and theming\n- **[Multi-Domain Architecture](/compiler/config/domains)** — Custom domains and hostname routing"
|
|
51
51
|
},
|
|
52
52
|
"account-ui/library-usage": {
|
|
53
53
|
"title": "Library Usage",
|
|
@@ -59,7 +59,7 @@ export const DOCS = {
|
|
|
59
59
|
},
|
|
60
60
|
"account-ui/with-quickback": {
|
|
61
61
|
"title": "With Quickback",
|
|
62
|
-
"content": "When using Account UI with a Quickback-compiled backend,
|
|
62
|
+
"content": "When using Account UI with a Quickback-compiled backend, the recommended approach is to let the compiler build and embed the SPA directly into your Worker.\n\n## Compiler-Embedded (Recommended)\n\nAdd `account` to your `quickback.config.ts`:\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default {\n name: \"my-app\",\n template: \"hono\",\n account: {\n domain: \"auth.example.com\",\n name: \"My App\",\n companyName: \"My Company\",\n auth: {\n password: true,\n passkey: true,\n organizations: true,\n admin: true,\n },\n },\n // ...providers\n};\n```\n\nThen compile and deploy:\n\n```bash\nquickback compile\nnpx wrangler deploy\n```\n\n### What Happens During Compilation\n\n1. The compiler reads your `account` config and generates a `.env` file with the correct Vite environment variables (`VITE_API_URL`, `VITE_ENABLE_PASSWORD`, branding, etc.)\n2. The Account SPA source is copied to a temp directory, with disabled feature routes excluded\n3. Pre-installed dependencies are symlinked (no `npm install` during build)\n4. Vite builds the SPA with your settings baked in\n5. Built assets (content-hashed filenames) are placed in the output directory\n\nWhen CMS is also enabled, Account assets go to `src/apps/account/` and are served at `/account/`. When Account is the only SPA, assets go to `src/apps/` and are served at root.\n\n### Custom Domains\n\nWith a custom domain, the Account SPA is served at root (`/`) on that domain:\n\n```typescript\naccount: { domain: \"auth.example.com\" }\n```\n\nAdd an admin domain to serve the admin panel on its own subdomain:\n\n```typescript\naccount: {\n domain: \"auth.example.com\",\n adminDomain: \"admin.example.com\",\n}\n```\n\nSee [Multi-Domain Architecture](/compiler/config/domains) for details on hostname routing and cross-subdomain cookies.\n\n### Auth Feature Flags\n\nFeature flags control which pages are included in the build:\n\n```typescript\nauth: {\n password: true, // Email/password login + inline password change\n emailOTP: false, // Email OTP login flow\n passkey: true, // WebAuthn passkey setup + management\n organizations: true, // Dashboard, org management, invitations\n admin: true, // Admin panel (user management)\n}\n```\n\nDisabled features are excluded at compile time — their route files are removed before the Vite build. See [Configuration](/compiler/config) for all options.\n\n## Manual Deployment\n\nIf you need Account UI as a separate Worker (not embedded in the API Worker), you can deploy it standalone.\n\n### 1. Clone the Template\n\n```bash\nnpx degit Kardoe-com/quickback-better-auth-account-ui my-account-app\ncd my-account-app\nnpm install\n```\n\n### 2. Configure for Quickback\n\nSet the auth route mode to `quickback` to match Quickback's API paths:\n\n```bash title=\".env\"\nVITE_AUTH_ROUTE=quickback\nVITE_API_URL=https://api.example.com\nVITE_ACCOUNT_APP_URL=https://account.example.com\nVITE_APP_URL=https://app.example.com\n```\n\nIn Quickback mode, Account UI routes requests to three API paths:\n\n| Path | Purpose | Examples |\n|------|---------|---------|\n| `/auth/v1/*` | Authentication | Login, signup, sessions, passkeys |\n| `/api/v1/*` | Data API | Organizations, API keys |\n| `/storage/v1/*` | File storage | Avatar uploads, file management |\n\n### 3. Configure Features\n\nMatch your `quickback.config.ts` plugins:\n\n```bash title=\".env\"\nVITE_APP_NAME=My App\nVITE_APP_TAGLINE=Build faster, ship sooner\nENABLE_SIGNUP=true\nENABLE_ORGANIZATIONS=true\nENABLE_PASSKEY=true\nENABLE_ADMIN=true\n```\n\n### 4. Build and Deploy\n\n```bash\nnpm run build\nnpx wrangler deploy\n```\n\n## Library Mode\n\nInstall as a dependency instead of cloning:\n\n```bash\nnpm install quickback-better-auth-account-ui\n```\n\n```tsx\n\nsetAppConfig({\n authRoute: 'quickback',\n name: 'My App',\n companyName: 'My Company',\n});\n```\n\nSee [Library Usage](/account-ui/library-usage) for the complete guide.\n\n## Next Steps\n\n- [Configuration](/compiler/config) — CMS and Account config reference\n- [Multi-Domain Architecture](/compiler/config/domains) — Custom domains and hostname routing\n- [Environment Variables](/account-ui/environment-variables) — Complete variable reference\n- [Feature Flags](/account-ui/features) — Enable and disable features\n- [Customization](/account-ui/customization) — Branding, labels, and theming"
|
|
63
63
|
},
|
|
64
64
|
"account-ui/worker": {
|
|
65
65
|
"title": "Worker Setup",
|
|
@@ -79,7 +79,7 @@ export const DOCS = {
|
|
|
79
79
|
},
|
|
80
80
|
"cms/connecting": {
|
|
81
81
|
"title": "Connecting",
|
|
82
|
-
"content": "# Connecting\n\nThe CMS supports two modes: **demo mode** for development and testing, and **live mode** for connecting to a real Quickback API.\n\n## Demo Mode\n\nWhen no `VITE_API_URL` is set, the CMS runs in demo mode:\n\n- Uses a **mock API client** backed by `localStorage`\n- Loads seed data from JSON files in `data/mock/`\n- Provides a **role switcher** in the header to test owner/admin/member access\n- Simulates authentication sessions without a real backend\n\nDemo mode is useful for prototyping your schema, testing guard behavior across roles, and verifying masking rules before deploying.\n\n```bash title=\".env.development\"\n# No VITE_API_URL — CMS runs in demo mode\n```\n\n### Mock Data\n\nPlace JSON files in `data/mock/` matching your table names:\n\n```\ndata/mock/\n contact.json # Array of contact records\n project.json # Array of project records\n invoice.json # Array of invoice records\n _meta.json # Mock session and org metadata\n```\n\nEach file contains an array of records. The mock client loads them on startup and persists changes to `localStorage`.\n\n### Role Switcher\n\nIn demo mode, the header displays a role switcher dropdown allowing you to switch between `owner`, `admin`, and `member` roles in real time. This lets you verify:\n\n- Which CRUD buttons appear per role\n- Which form fields are editable\n- Which masking rules apply\n- Which actions are available\n- Which views are accessible\n\n## Live Mode\n\nSet `VITE_API_URL` to connect to a real Quickback API:\n\n```bash title=\".env.production\"\nVITE_API_URL=https://api.example.com\n```\n\nIn live mode, the CMS:\n\n- Reads the **Better Auth session** from cookies\n- Fetches the user's **organization membership** and role\n- Makes real API calls to the Quickback backend for all CRUD operations\n- Applies server-side security (firewall, guards, masking) in addition to client-side UI filtering\n\n## API Client Interface\n\nThe CMS communicates with the backend through a standard interface:\n\n```typescript\ninterface IApiClient {\n list(table: string, params?: ListParams): Promise\n\n## How the Client is Created\n\nThe CMS auto-creates the API client based on configuration:\n\n1. **No `VITE_API_URL`** — Instantiates the mock client, loads seed data from `data/mock/`, and uses `localStorage` for persistence.\n2. **`VITE_API_URL` is set** — Instantiates the live client, reads the auth session cookie, and makes fetch requests to the Quickback API using the standard REST endpoints (`/api/v1/{table}`).\n\nThe client is provided via React context (`ApiClientContext`) and available throughout the component tree.\n\n## Embedded Mode (Recommended)\n\nSet `cms: true` in your config to embed the CMS directly in your compiled Worker:\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default defineConfig({\n name: \"my-app\",\n cms: true,\n // ...providers\n});\n```\n\nWhen you run `quickback compile`, the CLI:\n1.
|
|
82
|
+
"content": "# Connecting\n\nThe CMS supports two modes: **demo mode** for development and testing, and **live mode** for connecting to a real Quickback API.\n\n## Demo Mode\n\nWhen no `VITE_API_URL` is set, the CMS runs in demo mode:\n\n- Uses a **mock API client** backed by `localStorage`\n- Loads seed data from JSON files in `data/mock/`\n- Provides a **role switcher** in the header to test owner/admin/member access\n- Simulates authentication sessions without a real backend\n\nDemo mode is useful for prototyping your schema, testing guard behavior across roles, and verifying masking rules before deploying.\n\n```bash title=\".env.development\"\n# No VITE_API_URL — CMS runs in demo mode\n```\n\n### Mock Data\n\nPlace JSON files in `data/mock/` matching your table names:\n\n```\ndata/mock/\n contact.json # Array of contact records\n project.json # Array of project records\n invoice.json # Array of invoice records\n _meta.json # Mock session and org metadata\n```\n\nEach file contains an array of records. The mock client loads them on startup and persists changes to `localStorage`.\n\n### Role Switcher\n\nIn demo mode, the header displays a role switcher dropdown allowing you to switch between `owner`, `admin`, and `member` roles in real time. This lets you verify:\n\n- Which CRUD buttons appear per role\n- Which form fields are editable\n- Which masking rules apply\n- Which actions are available\n- Which views are accessible\n\n## Live Mode\n\nSet `VITE_API_URL` to connect to a real Quickback API:\n\n```bash title=\".env.production\"\nVITE_API_URL=https://api.example.com\n```\n\nIn live mode, the CMS:\n\n- Reads the **Better Auth session** from cookies\n- Fetches the user's **organization membership** and role\n- Makes real API calls to the Quickback backend for all CRUD operations\n- Applies server-side security (firewall, guards, masking) in addition to client-side UI filtering\n\n## API Client Interface\n\nThe CMS communicates with the backend through a standard interface:\n\n```typescript\ninterface IApiClient {\n list(table: string, params?: ListParams): Promise\n\n## How the Client is Created\n\nThe CMS auto-creates the API client based on configuration:\n\n1. **No `VITE_API_URL`** — Instantiates the mock client, loads seed data from `data/mock/`, and uses `localStorage` for persistence.\n2. **`VITE_API_URL` is set** — Instantiates the live client, reads the auth session cookie, and makes fetch requests to the Quickback API using the standard REST endpoints (`/api/v1/{table}`).\n\nThe client is provided via React context (`ApiClientContext`) and available throughout the component tree.\n\n## Embedded Mode (Recommended)\n\nSet `cms: true` in your config to embed the CMS directly in your compiled Worker:\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default defineConfig({\n name: \"my-app\",\n cms: true,\n // ...providers\n});\n```\n\nWhen you run `quickback compile`, the CLI:\n1. Builds the CMS SPA from source and places assets in `src/apps/cms/`\n2. Adds `[assets]` config to `wrangler.toml` with `run_worker_first = true`\n3. Generates Worker routing to serve the CMS SPA\n\nRun `wrangler dev` and the CMS is served at `/cms/`. API routes (`/api/*`, `/auth/*`, etc.) pass through to your Hono app. Same origin — no CORS, auth cookies work naturally. On a custom domain, the CMS is served at root (`/`).\n\n### Custom CMS Domain\n\nOptionally serve the CMS on a separate subdomain:\n\n```typescript\ncms: { domain: \"cms.example.com\" }\n```\n\nThis adds a custom domain route to `wrangler.toml`. Both `api.example.com` and `cms.example.com` point to the same Worker. The compiler auto-configures hostname-based routing and cross-subdomain cookies.\n\nYou can also restrict who sees the CMS link in Account UI:\n\n```typescript\ncms: { domain: \"cms.example.com\", access: \"admin\" }\n```\n\nSee [Multi-Domain Architecture](/compiler/config/domains) for details on multi-domain routing.\n\n## Multi-Tenant vs Single-Tenant\n\nThe CMS supports two authentication modes depending on your project's organization configuration.\n\n### Multi-Tenant (Default)\n\nIn multi-tenant mode, the CMS gates access behind organization membership:\n\n1. User logs in via Better Auth session\n2. CMS fetches the user's organization memberships\n3. If the user belongs to multiple organizations, an **org selector** is displayed\n4. Once an org is selected, the user's role within that org determines their CMS permissions\n\nThis is the default behavior for all Quickback projects.\n\n### Single-Tenant Mode\n\nWhen your project disables organizations (`features.organizations: false` in config), the compiler sets `singleTenant: true` in the schema registry. In this mode:\n\n- No org gate or org selector is shown\n- The user's role is read directly from `user.role` on the session\n- All data is unscoped (no `organizationId` filtering)\n\nSingle-tenant mode is useful for internal tools, personal projects, or apps that don't need multi-org isolation.\n\n## Next Steps\n\n- **[Table Views](/cms/table-views)** — Browse and Data Table view modes\n- **[Security](/cms/security)** — How roles, guards, and masking work in the CMS"
|
|
83
83
|
},
|
|
84
84
|
"cms/dashboard": {
|
|
85
85
|
"title": "Dashboard",
|
|
@@ -87,7 +87,7 @@ export const DOCS = {
|
|
|
87
87
|
},
|
|
88
88
|
"cms": {
|
|
89
89
|
"title": "Quickback CMS",
|
|
90
|
-
"content": "# Quickback CMS\n\nA schema-driven admin interface that reads `schema-registry.json` generated by the Quickback compiler. Every table, column, action, view, and security rule is rendered automatically. Zero UI code per table.\n\n## Overview\n\nThe CMS generates its entire UI from your Quickback definitions. Define a table with columns, guards, masking, views, and actions in your feature files. Run the compiler. The CMS reads the resulting schema registry and renders a complete admin interface — data tables, inline editing, action dialogs, role-based access, and field masking — all without writing a single line of UI code.\n\n## Key Features\n\n- **Schema-driven** — Zero UI code per table. Add a table, recompile, and it appears in the CMS.\n- **Dashboard** — Stats grid and feature cards showing tables, columns, actions, views, and masked fields at a glance.\n- **Custom pages** — Split-panel layouts with drag-and-drop, matching engine, and page-level actions for workflows like reconciliation.\n- **Embedded in your Worker** — Set `cms: true` in config. The CMS is served as static assets from the same Cloudflare Worker as your API — same origin, no CORS, auth cookies work naturally.\n- **Dual view modes** — Table browse mode for navigation and Data Table mode for spreadsheet-style editing.\n- **Role-based access** — Owner, admin, and member roles with live switching. CRUD buttons hidden when unauthorized.\n- **Multi-tenant & single-tenant** — Org-scoped access by default, with single-tenant mode for simpler projects.\n- **Inline spreadsheet editing** — Excel/Google Sheets-like editing with keyboard navigation (arrows, Tab, Enter, Escape).\n- **FK typeahead** — Server-side search for foreign key fields with debounced queries and keyboard navigation.\n- **Field masking** — Email, phone, SSN, and redaction patterns applied per role. Masked fields show a lock icon.\n- **Custom actions** — Action dialogs with auto-generated input forms, access filtering, CMS metadata (icons, categories, confirmations), and side effects warnings.\n- **Views** — Named column-level projections per role. \"All Fields\" plus custom views in the toolbar.\n- **Auto-form generation** — Create and edit forms built from guards (createable/updatable fields).\n- **Display column auto-detection** — FK labels resolved automatically from `name`, `title`, `label`, `code`, and other common patterns.\n\n## Architecture\n\nThe CMS sits at the end of the Quickback compilation pipeline:\n\n```\nQuickback Definitions (feature files)\n |\n v\n Compiler\n |\n v\n schema-registry.json\n |\n v\n CMS reads it\n |\n v\n Renders admin UI\n```\n\nYour feature definitions are the single source of truth. The compiler extracts all metadata — columns, types, guards, masking rules, views, actions, validation, and firewall config — into a static JSON file. The CMS consumes that file and renders the appropriate UI for each table.\n\n### How Embedded Serving Works\n\nWhen `cms: true` is set, the compiler
|
|
90
|
+
"content": "# Quickback CMS\n\nA schema-driven admin interface that reads `schema-registry.json` generated by the Quickback compiler. Every table, column, action, view, and security rule is rendered automatically. Zero UI code per table.\n\n## Overview\n\nThe CMS generates its entire UI from your Quickback definitions. Define a table with columns, guards, masking, views, and actions in your feature files. Run the compiler. The CMS reads the resulting schema registry and renders a complete admin interface — data tables, inline editing, action dialogs, role-based access, and field masking — all without writing a single line of UI code.\n\n## Key Features\n\n- **Schema-driven** — Zero UI code per table. Add a table, recompile, and it appears in the CMS.\n- **Dashboard** — Stats grid and feature cards showing tables, columns, actions, views, and masked fields at a glance.\n- **Custom pages** — Split-panel layouts with drag-and-drop, matching engine, and page-level actions for workflows like reconciliation.\n- **Embedded in your Worker** — Set `cms: true` in config. The CMS is served as static assets from the same Cloudflare Worker as your API — same origin, no CORS, auth cookies work naturally.\n- **Dual view modes** — Table browse mode for navigation and Data Table mode for spreadsheet-style editing.\n- **Role-based access** — Owner, admin, and member roles with live switching. CRUD buttons hidden when unauthorized.\n- **Multi-tenant & single-tenant** — Org-scoped access by default, with single-tenant mode for simpler projects.\n- **Inline spreadsheet editing** — Excel/Google Sheets-like editing with keyboard navigation (arrows, Tab, Enter, Escape).\n- **FK typeahead** — Server-side search for foreign key fields with debounced queries and keyboard navigation.\n- **Field masking** — Email, phone, SSN, and redaction patterns applied per role. Masked fields show a lock icon.\n- **Custom actions** — Action dialogs with auto-generated input forms, access filtering, CMS metadata (icons, categories, confirmations), and side effects warnings.\n- **Views** — Named column-level projections per role. \"All Fields\" plus custom views in the toolbar.\n- **Auto-form generation** — Create and edit forms built from guards (createable/updatable fields).\n- **Display column auto-detection** — FK labels resolved automatically from `name`, `title`, `label`, `code`, and other common patterns.\n\n## Architecture\n\nThe CMS sits at the end of the Quickback compilation pipeline:\n\n```\nQuickback Definitions (feature files)\n |\n v\n Compiler\n |\n v\n schema-registry.json\n |\n v\n CMS reads it\n |\n v\n Renders admin UI\n```\n\nYour feature definitions are the single source of truth. The compiler extracts all metadata — columns, types, guards, masking rules, views, actions, validation, and firewall config — into a static JSON file. The CMS consumes that file and renders the appropriate UI for each table.\n\n### How Embedded Serving Works\n\nWhen `cms: true` is set, the compiler builds the CMS SPA from source at compile time (with your project-specific env vars baked in) and outputs the assets to `src/apps/cms/`. It also configures `wrangler.toml`:\n\n```toml\n[assets]\nbinding = \"ASSETS\"\ndirectory = \"src/apps\"\nnot_found_handling = \"none\"\nrun_worker_first = true\n```\n\nAll requests go through the Worker first. The Worker handles SPA routing — serving CMS at `/cms/` on the unified domain and at root (`/`) on a custom CMS domain. API paths (`/api/*`, `/auth/*`, etc.) are handled by Hono as normal.\n\nSee [Multi-Domain Architecture](/compiler/config/domains) for details on hostname-based routing.\n\n## Quick Start\n\n### 1. Enable CMS in config\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default defineConfig({\n name: \"my-app\",\n cms: true,\n // ...providers\n});\n```\n\n### 2. Compile\n\n```bash\nquickback compile\n```\n\nThe compiler generates `schema-registry.json` and copies CMS static assets to `src/apps/`. It also adds an `[assets]` section to `wrangler.toml` so Cloudflare serves the CMS SPA automatically.\n\n### 3. Run\n\n```bash\nnpm run dev\n```\n\nOpen your Worker URL in a browser — the CMS is served at the root. API routes (`/api/*`, `/auth/*`, etc.) pass through to your Hono app as normal. Everything runs on the same origin — no CORS configuration needed, auth cookies work naturally.\n\n### Optional: Custom CMS domain\n\n```typescript\ncms: { domain: \"cms.example.com\" }\n```\n\nThis adds a custom domain route to `wrangler.toml`. Both domains serve the same Worker — `api.example.com` for the API, `cms.example.com` for the CMS. The compiler also auto-infers a unified `quickback.example.com` domain where everything is available. See [Multi-Domain Architecture](/compiler/config/domains).\n\n### Optional: Restrict CMS access\n\nControl who sees the \"Go to CMS\" button in Account UI:\n\n```typescript\ncms: { domain: \"cms.example.com\", access: \"admin\" }\n```\n\nWith `access: \"admin\"`, only users with the `admin` role see the CMS link in their profile. The CMS itself still requires authentication — this just controls the link visibility.\n\n### Optional: Skip SPA rebuild\n\nAfter the first compile, you can skip rebuilding the CMS SPA on subsequent compiles:\n\n```typescript\ncms: { build: false }\n```\n\nThis is useful when you're iterating on API features and don't need to rebuild the CMS UI each time — it saves significant compile time. Set `build: true` (or omit it) when you need to update the CMS assets.\n\n### Optional: Custom output directory\n\n```typescript\ncms: { outputDir: \"my-custom-path/cms\" }\n```\n\nThis changes where the compiled CMS assets are placed (relative to project root), instead of the default `src/apps/cms/`.\n\n## Next Steps\n\n- **[Schema Registry](/cms/schema-registry)** — Understand the JSON format the compiler generates\n- **[Connecting](/cms/connecting)** — Demo mode, live mode, CLI command, and auth modes\n- **[Dashboard](/cms/dashboard)** — Stats grid and feature navigation\n- **[Table Views](/cms/table-views)** — Browse and Data Table view modes\n- **[Custom Pages](/cms/pages)** — Split-panel layouts, matching engine, and drag-drop\n- **[Inline Editing](/cms/inline-editing)** — Spreadsheet-style editing and FK typeahead\n- **[Security](/cms/security)** — How the CMS enforces all four security layers\n- **[Actions](/cms/actions)** — Custom actions with input forms, access filtering, and CMS metadata\n- **[Schema Format Reference](/cms/schema-format)** — Full TypeScript types for schema-registry.json\n- **[Components Reference](/cms/components)** — All CMS components and their props"
|
|
91
91
|
},
|
|
92
92
|
"cms/inline-editing": {
|
|
93
93
|
"title": "Inline Editing",
|
|
@@ -103,11 +103,11 @@ export const DOCS = {
|
|
|
103
103
|
},
|
|
104
104
|
"cms/schema-format": {
|
|
105
105
|
"title": "Schema Format Reference",
|
|
106
|
-
"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 singleTenant?: boolean;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n pages: Record<string, PageMeta>;\n pagesByFeature: 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| `singleTenant` | When `true`, project has no organization layer (single-tenant mode) |\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| `pages` | Map of page slug to full page metadata |\n| `pagesByFeature` | Map of feature name to array of page slugs 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## PageMeta\n\nFull metadata for a custom page:\n\n```typescript\ninterface PageMeta {\n slug: string;\n title: string;\n description?: string;\n icon?: string;\n feature: string;\n access?: { roles: string[] };\n dataSources: Record<string, PageDataSource>;\n layout: PageLayout;\n matching?: PageMatching;\n pageActions?: Record<string, PageAction>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `slug` | URL-safe page identifier |\n| `title` | Display title |\n| `description` | Human-readable description |\n| `icon` | Icon name for sidebar |\n| `feature` | Parent feature name |\n| `access` | Role-based access control |\n| `dataSources` | Named data source bindings |\n| `layout` | Layout configuration |\n| `matching` | Matching/reconciliation rules |\n| `pageActions` | Actions triggered from the page |\n\n### PageDataSource\n\n```typescript\ninterface PageDataSource {\n table: string;\n defaultFilters?: Record<string, unknown>;\n defaultSort?: { field: string; order: 'asc' | 'desc' };\n displayColumns?: string[];\n}\n```\n\n### PageLayout\n\n```typescript\ninterface PageLayout {\n type: 'split-panel';\n panels: PagePanel[];\n}\n\ninterface PagePanel {\n id: string;\n title: string;\n dataSource: string;\n position: 'left' | 'right';\n features?: string[];\n}\n```\n\nPanel `features` can include `\"drag-source\"` and `\"drop-target\"` for drag-and-drop interactions.\n\n### PageMatching\n\n```typescript\ninterface PageMatching {\n enabled: boolean;\n rules: MatchingRule[];\n confidenceThreshold?: number;\n}\n\ninterface MatchingRule {\n name: string;\n weight: number;\n condition: {\n left: string;\n right: string;\n operator: 'abs-equals' | 'within-days' | 'fuzzy-match';\n value?: number;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `enabled` | Whether matching is active |\n| `rules` | Array of matching rules with weights (0-1) |\n| `confidenceThreshold` | Minimum score to display a match suggestion (0-1, default 0.5) |\n| `condition.left` | Left field reference (`dataSourceName.fieldName`) |\n| `condition.right` | Right field reference |\n| `condition.operator` | Comparison operator |\n| `condition.value` | Operator parameter (e.g., max days for `within-days`) |\n\n### PageAction\n\n```typescript\ninterface PageAction {\n table: string;\n action: string;\n inputMapping: Record<string, string>;\n label?: string;\n icon?: string;\n confirm?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `table` | Target table for the action |\n| `action` | Action name on that table |\n| `inputMapping` | Maps action input fields to data source field references (`\"dataSourceName.$fieldName\"`) |\n| `label` | Button label (defaults to action name) |\n| `icon` | Button icon name |\n| `confirm` | Confirmation prompt shown before execution |\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"
|
|
106
|
+
"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 singleTenant?: boolean;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n pages: Record<string, PageMeta>;\n pagesByFeature: 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| `singleTenant` | When `true`, project has no organization layer (single-tenant mode) |\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| `pages` | Map of page slug to full page metadata |\n| `pagesByFeature` | Map of feature name to array of page slugs 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 defaultSort?: { field: string; order: 'asc' | 'desc' };\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| `defaultSort` | Default sort for CMS table list view (e.g., `{ field: \"createdAt\", order: \"desc\" }`) |\n| `inputHints` | Map of column name to preferred CMS input type (e.g., `\"richtext\"`, `\"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## PageMeta\n\nFull metadata for a custom page:\n\n```typescript\ninterface PageMeta {\n slug: string;\n title: string;\n description?: string;\n icon?: string;\n feature: string;\n access?: { roles: string[] };\n dataSources: Record<string, PageDataSource>;\n layout: PageLayout;\n matching?: PageMatching;\n pageActions?: Record<string, PageAction>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `slug` | URL-safe page identifier |\n| `title` | Display title |\n| `description` | Human-readable description |\n| `icon` | Icon name for sidebar |\n| `feature` | Parent feature name |\n| `access` | Role-based access control |\n| `dataSources` | Named data source bindings |\n| `layout` | Layout configuration |\n| `matching` | Matching/reconciliation rules |\n| `pageActions` | Actions triggered from the page |\n\n### PageDataSource\n\n```typescript\ninterface PageDataSource {\n table: string;\n defaultFilters?: Record<string, unknown>;\n defaultSort?: { field: string; order: 'asc' | 'desc' };\n displayColumns?: string[];\n}\n```\n\n### PageLayout\n\n```typescript\ninterface PageLayout {\n type: 'split-panel';\n panels: PagePanel[];\n}\n\ninterface PagePanel {\n id: string;\n title: string;\n dataSource: string;\n position: 'left' | 'right';\n features?: string[];\n}\n```\n\nPanel `features` can include `\"drag-source\"` and `\"drop-target\"` for drag-and-drop interactions.\n\n### PageMatching\n\n```typescript\ninterface PageMatching {\n enabled: boolean;\n rules: MatchingRule[];\n confidenceThreshold?: number;\n}\n\ninterface MatchingRule {\n name: string;\n weight: number;\n condition: {\n left: string;\n right: string;\n operator: 'abs-equals' | 'within-days' | 'fuzzy-match';\n value?: number;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `enabled` | Whether matching is active |\n| `rules` | Array of matching rules with weights (0-1) |\n| `confidenceThreshold` | Minimum score to display a match suggestion (0-1, default 0.5) |\n| `condition.left` | Left field reference (`dataSourceName.fieldName`) |\n| `condition.right` | Right field reference |\n| `condition.operator` | Comparison operator |\n| `condition.value` | Operator parameter (e.g., max days for `within-days`) |\n\n### PageAction\n\n```typescript\ninterface PageAction {\n table: string;\n action: string;\n inputMapping: Record<string, string>;\n label?: string;\n icon?: string;\n confirm?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `table` | Target table for the action |\n| `action` | Action name on that table |\n| `inputMapping` | Maps action input fields to data source field references (`\"dataSourceName.$fieldName\"`) |\n| `label` | Button label (defaults to action name) |\n| `icon` | Button icon name |\n| `confirm` | Confirmation prompt shown before execution |\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"
|
|
107
107
|
},
|
|
108
108
|
"cms/schema-registry": {
|
|
109
109
|
"title": "Schema Registry",
|
|
110
|
-
"content": "# Schema Registry\n\nThe schema registry is a static JSON file generated by the Quickback compiler. It contains full metadata about every table in your project — columns, types, guards, masking rules, views, actions, validation, and firewall config. The CMS reads this file to render its entire UI.\n\n## Generation\n\nSchema registry generation is **enabled by default**. Run `quickback compile` and the compiler outputs `schema-registry.json` alongside your compiled API files.\n\nTo disable generation:\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default defineConfig({\n schemaRegistry: { generate: false },\n // ... rest of your config\n});\n```\n\n## Output Shape\n\nThe top-level structure of `schema-registry.json`:\n\n```json\n{\n \"generatedAt\": \"2026-02-14T06:26:53.554Z\",\n \"generatedBy\": \"quickback-compiler\",\n \"version\": \"1.0.0\",\n \"singleTenant\": false,\n \"features\": { ... },\n \"tables\": { ... },\n \"tablesByFeature\": { ... },\n \"pages\": { ... },\n \"pagesByFeature\": { ... }\n}\n```\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `generatedAt` | `string` | ISO timestamp of generation |\n| `generatedBy` | `string` | Always `\"quickback-compiler\"` |\n| `version` | `string` | Compiler version used |\n| `singleTenant` | `boolean?` | When `true`, no organization layer |\n| `features` | `Record<string, string[]>` | Feature name to file list mapping |\n| `tables` | `Record<string, TableMeta>` | Table name to full metadata |\n| `tablesByFeature` | `Record<string, string[]>` | Feature name to table name list |\n| `pages` | `Record<string, PageMeta>` | Page slug to full page metadata |\n| `pagesByFeature` | `Record<string, string[]>` | Feature name to page slug list |\n\n## TableMeta\n\nEach table entry contains everything the CMS needs to render its UI:\n\n```typescript\ninterface TableMeta {\n name: string; // camelCase table name (e.g., \"accountCode\")\n dbName: string; // SQL table name (e.g., \"account_code\")\n feature: string; // Parent feature name\n columns: ColumnMeta[]; // All columns including audit fields\n firewall: Record<string, unknown>; // Tenant isolation config\n crud: Record<string, CrudConfig>; // Per-operation access rules\n guards: {\n createable: string[]; // Fields allowed on create\n updatable: string[]; // Fields allowed on update\n immutable: string[]; // Fields locked after creation\n protected: Record<string, string[]>; // Fields only updatable via actions\n };\n masking: Record<string, MaskingRule>; // Per-field masking rules\n views: Record<string, ViewConfig>; // Named column projections\n validation: Record<string, ValidationRule>; // Per-field validation\n actions: ActionMeta[]; // Available actions for this table\n displayColumn?: string; // Human-readable label column\n internal?: boolean; // Hidden from CMS sidebar when true\n}\n```\n\n## ColumnMeta\n\nEach column in the `columns` array:\n\n```typescript\ninterface ColumnMeta {\n name: string; // Property name (camelCase)\n dbName: string; // SQL column name (snake_case)\n type: \"text\" | \"integer\" | \"real\" | \"blob\"; // SQLite type\n mode?: \"boolean\"; // When an integer represents a boolean\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string; // Target table name for FK columns\n}\n```\n\nThe compiler automatically includes audit fields (`id`, `organizationId`, `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy`, `deletedAt`) at the beginning of every table's column list.\n\n### fkTarget — FK Resolution\n\nColumns ending in `Id` may have a `fkTarget` property indicating which table they reference. This is resolved in priority order:\n\n1. **Explicit `references`** — from your `defineTable()` config (highest priority)\n2. **Drizzle `.references()`** — parsed from schema source code\n3. **Convention** — strip `Id` suffix, match table name directly\n\n```json\n{\n \"name\": \"vendorId\",\n \"type\": \"text\",\n \"fkTarget\": \"contact\"\n}\n```\n\nThe CMS uses `fkTarget` to render typeahead/lookup inputs that search the correct table instead of showing raw IDs.\n\n## Input Hints\n\nTables with `inputHints` configured in `defineTable()` include an `inputHints` map in their metadata:\n\n```json\n{\n \"name\": \"invoice\",\n \"inputHints\": {\n \"status\": \"select\",\n \"sortOrder\": \"radio\",\n \"isPartialPaymentDisabled\": \"checkbox\",\n \"headerMessage\": \"textarea\"\n }\n}\n```\n\nThe CMS reads these hints to render the appropriate form control for each field. See [Input Hints](/compiler/definitions/schema#input-hints) for the full list of supported values.\n\n## Display Column\n\nThe `displayColumn` field tells the CMS which column to use as a human-readable label for a record. This is used in:\n\n- FK typeahead dropdowns (showing names instead of IDs)\n- Record titles in detail views\n- Breadcrumb labels\n\n### Auto-Detection\n\nIf you don't explicitly set `displayColumn` in your resource config, the compiler auto-detects it by scanning column names in priority order:\n\n1. `name`\n2. `title`\n3. `label`\n4. `headline`\n5. `subject`\n6. `code`\n7. `displayName`\n8. `fullName`\n9. `description`\n\nThe first match wins. If no candidate matches, the table has no display column and the CMS falls back to showing IDs.\n\n### Explicit Config\n\nSet it explicitly in your table definition:\n\n```typescript\nexport default defineTable(contacts, {\n displayColumn: \"companyName\",\n // ...\n});\n```\n\n## FK Label Resolution\n\nWhen a table has foreign key columns (ending in `Id`), the API enriches list responses with `_label` fields. For example, a `roomTypeId` column gets a corresponding `roomType_label` field containing the display column value from the referenced table.\n\nThe CMS uses these `_label` fields to show human-readable names in table cells and FK typeahead dropdowns instead of raw UUIDs.\n\n```\nroomTypeId: \"rt_abc123\" → displayed as \"Master Bedroom\"\naccountCodeId: \"ac_xyz789\" → displayed as \"4100 - Revenue\"\n```\n\nThe FK target table is resolved from the `fkTarget` property on each column. For simple cases like `roomTypeId` → `roomType`, the compiler auto-detects it. For non-obvious mappings (e.g., `vendorId` → `contact`), use explicit [`references`](/compiler/definitions/schema#references) in your `defineTable()` config.\n\n## Pages\n\nWhen features include `definePage()` files (in `features/{name}/pages/`), the compiler includes them in the registry under two fields:\n\n- **`pages`** — Map of page slug to full `PageMeta` object (data sources, layout, matching rules, page actions)\n- **`pagesByFeature`** — Map of feature name to array of page slugs belonging to that feature\n\nThe CMS reads these fields to render custom pages in the sidebar and route to the page renderer. See [Custom Pages](/cms/pages) for the full `definePage()` API.\n\n## Single-Tenant Mode\n\nWhen `singleTenant` is `true` in the registry (set when the project config has `features.organizations: false`), the CMS skips the organization gate and reads the user's role directly from `user.role` on the session instead of from organization membership.\n\n## Next Steps\n\n- **[Connecting](/cms/connecting)** — Demo mode vs. live mode setup\n- **[Schema Format Reference](/cms/schema-format)** — Full TypeScript types"
|
|
110
|
+
"content": "# Schema Registry\n\nThe schema registry is a static JSON file generated by the Quickback compiler. It contains full metadata about every table in your project — columns, types, guards, masking rules, views, actions, validation, and firewall config. The CMS reads this file to render its entire UI.\n\n## Generation\n\nSchema registry generation is **enabled by default**. Run `quickback compile` and the compiler outputs `schema-registry.json` alongside your compiled API files.\n\nTo disable generation:\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default defineConfig({\n schemaRegistry: { generate: false },\n // ... rest of your config\n});\n```\n\n## Output Shape\n\nThe top-level structure of `schema-registry.json`:\n\n```json\n{\n \"generatedAt\": \"2026-02-14T06:26:53.554Z\",\n \"generatedBy\": \"quickback-compiler\",\n \"version\": \"1.0.0\",\n \"singleTenant\": false,\n \"features\": { ... },\n \"tables\": { ... },\n \"tablesByFeature\": { ... },\n \"pages\": { ... },\n \"pagesByFeature\": { ... }\n}\n```\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `generatedAt` | `string` | ISO timestamp of generation |\n| `generatedBy` | `string` | Always `\"quickback-compiler\"` |\n| `version` | `string` | Compiler version used |\n| `singleTenant` | `boolean?` | When `true`, no organization layer |\n| `features` | `Record<string, string[]>` | Feature name to file list mapping |\n| `tables` | `Record<string, TableMeta>` | Table name to full metadata |\n| `tablesByFeature` | `Record<string, string[]>` | Feature name to table name list |\n| `pages` | `Record<string, PageMeta>` | Page slug to full page metadata |\n| `pagesByFeature` | `Record<string, string[]>` | Feature name to page slug list |\n\n## TableMeta\n\nEach table entry contains everything the CMS needs to render its UI:\n\n```typescript\ninterface TableMeta {\n name: string; // camelCase table name (e.g., \"accountCode\")\n dbName: string; // SQL table name (e.g., \"account_code\")\n feature: string; // Parent feature name\n columns: ColumnMeta[]; // All columns including audit fields\n firewall: Record<string, unknown>; // Tenant isolation config\n crud: Record<string, CrudConfig>; // Per-operation access rules\n guards: {\n createable: string[]; // Fields allowed on create\n updatable: string[]; // Fields allowed on update\n immutable: string[]; // Fields locked after creation\n protected: Record<string, string[]>; // Fields only updatable via actions\n };\n masking: Record<string, MaskingRule>; // Per-field masking rules\n views: Record<string, ViewConfig>; // Named column projections\n validation: Record<string, ValidationRule>; // Per-field validation\n actions: ActionMeta[]; // Available actions for this table\n displayColumn?: string; // Human-readable label column\n internal?: boolean; // Hidden from CMS sidebar when true\n}\n```\n\n## ColumnMeta\n\nEach column in the `columns` array:\n\n```typescript\ninterface ColumnMeta {\n name: string; // Property name (camelCase)\n dbName: string; // SQL column name (snake_case)\n type: \"text\" | \"integer\" | \"real\" | \"blob\"; // SQLite type\n mode?: \"boolean\"; // When an integer represents a boolean\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string; // Target table name for FK columns\n}\n```\n\nThe compiler automatically includes audit fields (`id`, `organizationId`, `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy`, `deletedAt`) at the beginning of every table's column list.\n\n### fkTarget — FK Resolution\n\nColumns ending in `Id` may have a `fkTarget` property indicating which table they reference. This is resolved in priority order:\n\n1. **Explicit `references`** — from your `defineTable()` config (highest priority)\n2. **Drizzle `.references()`** — parsed from schema source code\n3. **Convention** — strip `Id` suffix, match table name directly\n\n```json\n{\n \"name\": \"vendorId\",\n \"type\": \"text\",\n \"fkTarget\": \"contact\"\n}\n```\n\nThe CMS uses `fkTarget` to render typeahead/lookup inputs that search the correct table instead of showing raw IDs.\n\n## Input Hints\n\nTables with `inputHints` configured in `defineTable()` include an `inputHints` map in their metadata:\n\n```json\n{\n \"name\": \"invoice\",\n \"inputHints\": {\n \"status\": \"select\",\n \"sortOrder\": \"radio\",\n \"isPartialPaymentDisabled\": \"checkbox\",\n \"headerMessage\": \"textarea\",\n \"description\": \"richtext\"\n }\n}\n```\n\nThe CMS reads these hints to render the appropriate form control for each field. The `\"richtext\"` hint renders a tiptap editor in edit mode and formatted HTML in view mode. See [Input Hints](/compiler/definitions/schema#input-hints) for the full list of supported values.\n\n## Display Column\n\nThe `displayColumn` field tells the CMS which column to use as a human-readable label for a record. This is used in:\n\n- FK typeahead dropdowns (showing names instead of IDs)\n- Record titles in detail views\n- Breadcrumb labels\n\n### Auto-Detection\n\nIf you don't explicitly set `displayColumn` in your resource config, the compiler auto-detects it by scanning column names in priority order:\n\n1. `name`\n2. `title`\n3. `label`\n4. `headline`\n5. `subject`\n6. `code`\n7. `displayName`\n8. `fullName`\n9. `description`\n\nThe first match wins. If no candidate matches, the table has no display column and the CMS falls back to showing IDs.\n\n### Explicit Config\n\nSet it explicitly in your table definition:\n\n```typescript\nexport default defineTable(contacts, {\n displayColumn: \"companyName\",\n // ...\n});\n```\n\n## FK Label Resolution\n\nWhen a table has foreign key columns (ending in `Id`), the API enriches list responses with `_label` fields. For example, a `roomTypeId` column gets a corresponding `roomType_label` field containing the display column value from the referenced table.\n\nThe CMS uses these `_label` fields to show human-readable names in table cells and FK typeahead dropdowns instead of raw UUIDs.\n\n```\nroomTypeId: \"rt_abc123\" → displayed as \"Master Bedroom\"\naccountCodeId: \"ac_xyz789\" → displayed as \"4100 - Revenue\"\n```\n\nThe FK target table is resolved from the `fkTarget` property on each column. For simple cases like `roomTypeId` → `roomType`, the compiler auto-detects it. For non-obvious mappings (e.g., `vendorId` → `contact`), use explicit [`references`](/compiler/definitions/schema#references) in your `defineTable()` config.\n\n## Pages\n\nWhen features include `definePage()` files (in `features/{name}/pages/`), the compiler includes them in the registry under two fields:\n\n- **`pages`** — Map of page slug to full `PageMeta` object (data sources, layout, matching rules, page actions)\n- **`pagesByFeature`** — Map of feature name to array of page slugs belonging to that feature\n\nThe CMS reads these fields to render custom pages in the sidebar and route to the page renderer. See [Custom Pages](/cms/pages) for the full `definePage()` API.\n\n## Single-Tenant Mode\n\nWhen `singleTenant` is `true` in the registry (set when the project config has `features.organizations: false`), the CMS skips the organization gate and reads the user's role directly from `user.role` on the session instead of from organization membership.\n\n## Next Steps\n\n- **[Connecting](/cms/connecting)** — Demo mode vs. live mode setup\n- **[Schema Format Reference](/cms/schema-format)** — Full TypeScript types"
|
|
111
111
|
},
|
|
112
112
|
"cms/security": {
|
|
113
113
|
"title": "Security",
|
|
@@ -115,7 +115,7 @@ export const DOCS = {
|
|
|
115
115
|
},
|
|
116
116
|
"cms/table-views": {
|
|
117
117
|
"title": "Table Views",
|
|
118
|
-
"content": "# Table Views\n\nThe CMS provides two view modes for every table: **Table** mode for browsing and navigating records, and **Data Table** mode for spreadsheet-style inline editing. Switch between them with the toolbar toggle.\n\n## Table Mode\n\nTable mode is the default browse experience:\n\n- **Click rows** to navigate to the record detail view\n- **Row action menus** (three-dot icon) with view, edit, delete, and custom actions\n- **Column headers** are sortable — click to toggle ascending/descending\n- **Search bar** for full-text search across all fields\n- **Responsive columns** that adapt to available space\n\nEach row shows the most relevant columns for the table. Foreign key columns display human-readable labels (resolved via `_label` fields) instead of raw UUIDs. Boolean columns render as colored Yes/No badges. Enum columns use color-coded pills.\n\n### Row Actions\n\nThe three-dot menu on each row provides:\n\n| Action | Visibility | Description |\n|--------|-----------|-------------|\n| View details | Always | Navigate to the record detail page |\n| Edit | When role has `update` access | Navigate to the edit form |\n| Custom actions | Filtered by role + record state | Run actions like approve, void, post |\n| Delete | When role has `delete` access | Delete with confirmation |\n\nActions are filtered by the current role's CRUD permissions and the action's access conditions. For example, an \"approve\" action that requires `status === \"pending\"` only appears on pending records.\n\n## Data Table Mode\n\nData Table mode provides an Excel/Google Sheets-like editing experience:\n\n- **Cell selection** with a blue focus ring\n- **Keyboard navigation** using arrow keys, Tab, Enter, and Escape\n- **Type-to-edit** — start typing to enter edit mode on the selected cell\n- **Row numbers** displayed in the leftmost column\n- **Hint bar** at the bottom showing keyboard shortcuts\n\n### Editable Fields\n\nWhich cells are editable is determined by the table's guards:\n\n- Fields in `guards.updatable` are editable\n- Fields in `guards.immutable` are read-only (shown with a disabled style)\n- Fields in `guards.protected` are read-only (marked \"Updated via actions only\")\n- Audit fields (`createdAt`, `createdBy`, `modifiedAt`, `modifiedBy`) are always read-only\n\nNon-editable cells can still be selected and copied, but they don't enter edit mode.\n\n### Cell Types\n\n| Column Type | Edit Control | Behavior |\n|-------------|-------------|----------|\n| Text | Text input | Free-text entry |\n| Number | Number input | Numeric entry with step controls |\n| Boolean | Yes/No dropdown | Toggle between Yes and No |\n| FK reference | Typeahead dropdown | Server-side search with debounced queries |\n| Enum | Select dropdown | Choose from allowed values |\n\n### Saving\n\nChanges are auto-saved when you:\n\n- Press **Enter** to confirm and move down\n- Press **Tab** to confirm and move to the next editable cell\n- **Click away** from the editing cell (blur)\n\nPress **Escape** to cancel an edit and revert to the previous value.\n\n## Views\n\nViews are named column projections defined in your table's resource config. They control which columns appear in the table based on the current role.\n\n### Toolbar\n\nThe toolbar shows a view dropdown when the table has views defined. Options include:\n\n- **All Fields** — Shows all columns (default)\n- Custom views — Only show the columns specified in the view config\n\nViews are filtered by role access. If a view's access rules require `admin` and the current user is a `member`, that view won't appear in the dropdown.\n\n### Example\n\nGiven this definition:\n\n```typescript\nviews: {\n summary: {\n fields: ['id', 'name', 'status'],\n access: { roles: ['member', 'admin'] },\n },\n full: {\n fields: ['id', 'name', 'status', 'ssn', 'internalNotes'],\n access: { roles: ['admin'] },\n },\n}\n```\n\n- Members see: \"All Fields\" and \"summary\"\n- Admins see: \"All Fields\", \"summary\", and \"full\"\n- Owners see: \"All Fields\", \"summary\", and \"full\"\n\nWhen a view is selected, the CMS calls the `listView` API endpoint instead of the standard `list`, fetching only the projected columns.\n\n## Pagination\n\nThe bottom of every table view shows pagination controls:\n\n- **Page range indicator** — \"Showing 1-25 of 142\"\n- **Page buttons** — Navigate directly to a page, with ellipsis for large page counts\n- **Previous/Next** arrows\n\nThe default page size is 25 records. The CMS resets to page 1 when you change the search query or switch views.\n\n## Search\n\nThe search bar performs full-text search across all columns. Type a query and the CMS debounces the request, then fetches matching records from the API.\n\nSearch works in both Table and Data Table modes, and works with views (searching within the projected columns).\n\n## Next Steps\n\n- **[Inline Editing](/cms/inline-editing)** — Deep dive into spreadsheet editing, FK typeahead, and keyboard shortcuts\n- **[Security](/cms/security)** — How roles and guards affect the table UI\n- **[Actions](/cms/actions)** — Custom actions in the row menu and detail view"
|
|
118
|
+
"content": "# Table Views\n\nThe CMS provides two view modes for every table: **Table** mode for browsing and navigating records, and **Data Table** mode for spreadsheet-style inline editing. Switch between them with the toolbar toggle.\n\n## Table Mode\n\nTable mode is the default browse experience:\n\n- **Click rows** to navigate to the record detail view\n- **Row action menus** (three-dot icon) with view, edit, delete, and custom actions\n- **Column headers** are sortable — click to toggle ascending/descending\n- **Search bar** for full-text search across all fields\n- **Responsive columns** that adapt to available space\n\nEach row shows the most relevant columns for the table. Foreign key columns display human-readable labels (resolved via `_label` fields) instead of raw UUIDs. Boolean columns render as colored Yes/No badges. Enum columns use color-coded pills.\n\n### Row Actions\n\nThe three-dot menu on each row provides:\n\n| Action | Visibility | Description |\n|--------|-----------|-------------|\n| View details | Always | Navigate to the record detail page |\n| Edit | When role has `update` access | Navigate to the edit form |\n| Custom actions | Filtered by role + record state | Run actions like approve, void, post |\n| Delete | When role has `delete` access | Delete with confirmation |\n\nActions are filtered by the current role's CRUD permissions and the action's access conditions. For example, an \"approve\" action that requires `status === \"pending\"` only appears on pending records.\n\n## Data Table Mode\n\nData Table mode provides an Excel/Google Sheets-like editing experience:\n\n- **Cell selection** with a blue focus ring\n- **Keyboard navigation** using arrow keys, Tab, Enter, and Escape\n- **Type-to-edit** — start typing to enter edit mode on the selected cell\n- **Row numbers** displayed in the leftmost column\n- **Hint bar** at the bottom showing keyboard shortcuts\n\n### Editable Fields\n\nWhich cells are editable is determined by the table's guards:\n\n- Fields in `guards.updatable` are editable\n- Fields in `guards.immutable` are read-only (shown with a disabled style)\n- Fields in `guards.protected` are read-only (marked \"Updated via actions only\")\n- Audit fields (`createdAt`, `createdBy`, `modifiedAt`, `modifiedBy`) are always read-only\n\nNon-editable cells can still be selected and copied, but they don't enter edit mode.\n\n### Cell Types\n\n| Column Type | Edit Control | Behavior |\n|-------------|-------------|----------|\n| Text | Text input | Free-text entry |\n| Number | Number input | Numeric entry with step controls |\n| Boolean | Yes/No dropdown | Toggle between Yes and No |\n| FK reference | Typeahead dropdown | Server-side search with debounced queries |\n| Enum | Select dropdown | Choose from allowed values |\n\n### Saving\n\nChanges are auto-saved when you:\n\n- Press **Enter** to confirm and move down\n- Press **Tab** to confirm and move to the next editable cell\n- **Click away** from the editing cell (blur)\n\nPress **Escape** to cancel an edit and revert to the previous value.\n\n## Views\n\nViews are named column projections defined in your table's resource config. They control which columns appear in the table based on the current role.\n\n### Toolbar\n\nThe toolbar shows a view dropdown when the table has views defined. Options include:\n\n- **All Fields** — Shows all columns (default)\n- Custom views — Only show the columns specified in the view config\n\nViews are filtered by role access. If a view's access rules require `admin` and the current user is a `member`, that view won't appear in the dropdown.\n\n### Example\n\nGiven this definition:\n\n```typescript\nviews: {\n summary: {\n fields: ['id', 'name', 'status'],\n access: { roles: ['member', 'admin'] },\n },\n full: {\n fields: ['id', 'name', 'status', 'ssn', 'internalNotes'],\n access: { roles: ['admin'] },\n },\n}\n```\n\n- Members see: \"All Fields\" and \"summary\"\n- Admins see: \"All Fields\", \"summary\", and \"full\"\n- Owners see: \"All Fields\", \"summary\", and \"full\"\n\nWhen a view is selected, the CMS calls the `listView` API endpoint instead of the standard `list`, fetching only the projected columns.\n\n## Default Sort\n\nYou can set a default sort order for a table by adding `defaultSort` to your resource config:\n\n```typescript\nexport default defineTable(podcastEpisodes, {\n defaultSort: { field: \"createdAt\", order: \"desc\" },\n // ...\n});\n```\n\nWhen the CMS loads the table, it applies this sort automatically. Users can still click column headers to change the sort — `defaultSort` only sets the initial state.\n\n## Pagination\n\nThe bottom of every table view shows pagination controls:\n\n- **Page range indicator** — \"Showing 1-25 of 142\"\n- **Page buttons** — Navigate directly to a page, with ellipsis for large page counts\n- **Previous/Next** arrows\n\nThe default page size is 25 records. The CMS resets to page 1 when you change the search query or switch views.\n\n## Search\n\nThe search bar performs full-text search across all columns. Type a query and the CMS debounces the request, then fetches matching records from the API.\n\nSearch works in both Table and Data Table modes, and works with views (searching within the projected columns).\n\n## Next Steps\n\n- **[Inline Editing](/cms/inline-editing)** — Deep dive into spreadsheet editing, FK typeahead, and keyboard shortcuts\n- **[Security](/cms/security)** — How roles and guards affect the table UI\n- **[Actions](/cms/actions)** — Custom actions in the row menu and detail view"
|
|
119
119
|
},
|
|
120
120
|
"compiler/cloud-compiler/authentication": {
|
|
121
121
|
"title": "Authentication",
|
|
@@ -135,19 +135,23 @@ export const DOCS = {
|
|
|
135
135
|
},
|
|
136
136
|
"compiler/cloud-compiler/local-compiler": {
|
|
137
137
|
"title": "Local Compiler",
|
|
138
|
-
"content": "Run the Quickback compiler locally using Docker
|
|
138
|
+
"content": "Run the Quickback compiler locally using Docker. The local compiler uses the exact same Docker image as the cloud compiler, ensuring identical behavior — including SPA builds with correct environment variables.\n\n## Prerequisites\n\n- Docker Desktop installed and running\n- Quickback monorepo cloned locally\n- Authenticated via `quickback login`\n\n## Quick Start\n\nFrom the monorepo root:\n\n```bash\ncd apps/compiler-local && bash dev.sh\n```\n\nThis will:\n1. Ensure Docker Desktop is running\n2. Stop any existing compiler container\n3. Build the Docker image from `apps/compiler/Dockerfile`\n4. Run it on port 3000\n\n### Custom Port\n\n```bash\nbash dev.sh 3001\n```\n\n## Compiling a Project\n\nPoint the CLI to your local compiler:\n\n```bash\nQUICKBACK_API_URL=http://localhost:3000 quickback compile\n```\n\nOr export it for the session:\n\n```bash\nexport QUICKBACK_API_URL=http://localhost:3000\nquickback compile\n```\n\nAuthentication is always required. Run `quickback login` first if you haven't already.\n\n## Manual Build & Run\n\nYou can also build and run the Docker image directly from the monorepo root:\n\n```bash\n# Build\ndocker build -t quickback-compiler -f apps/compiler/Dockerfile .\n\n# Run\ndocker run --rm -p 3000:3000 quickback-compiler\n```\n\n## Verify\n\nCheck the compiler is running:\n\n```bash\ncurl http://localhost:3000/health\n```\n\n## How It Works\n\nThe Docker image includes:\n- Pre-installed dependencies for compiled projects (`/deps/node_modules`)\n- CMS and Account SPA source code (`/spa/cms/`, `/spa/account/`)\n- Pre-installed SPA dependencies (`/spa-deps/cms/`, `/spa-deps/account/`)\n\nWhen compiling a project with `cms: true` or `account: true`, the compiler builds the SPAs from source inside the container with the correct Vite environment variables (e.g., `VITE_API_URL`, `VITE_ACCOUNT_URL`). This ensures each project gets properly configured SPA assets without manual intervention.\n\n## Deploying to Cloud\n\nAfter making changes to the compiler, deploy to `compiler.quickback.dev`:\n\n```bash\ncd apps/compiler-cloud && bash deploy.sh\n```\n\n## Troubleshooting\n\n### Container not starting\n\n```bash\ndocker logs quickback-compiler-local\n```\n\n### Port already in use\n\n```bash\n# Find what's using the port\nlsof -i :3000\n\n# Use a different port\nbash dev.sh 3001\n```\n\n### Docker out of disk space\n\n```bash\ndocker system prune -af\n```\n\n### SPA build warnings\n\nIf you see SPA build warnings during compilation, ensure the SPA dependency files are up to date:\n- `apps/compiler/deps-spa-cms-package.json`\n- `apps/compiler/deps-spa-account-package.json`\n\nThese must include all dependencies from `packages/cms/package.json` and `packages/account/package.json` respectively."
|
|
139
139
|
},
|
|
140
140
|
"compiler/cloud-compiler/troubleshooting": {
|
|
141
141
|
"title": "Troubleshooting",
|
|
142
142
|
"content": "## 401 Unauthorized\n\nYour session may have expired (sessions last 7 days). Re-authenticate:\n\n```bash\nquickback logout\nquickback login\n```\n\n## Compilation timeout\n\nLarge projects may take longer to compile. The cloud compiler uses [Cloudflare Containers](https://developers.cloudflare.com/containers/) to run compilation in isolated environments. If you hit timeouts, try [running the compiler locally](/compiler/cloud-compiler/local-compiler).\n\n## \"Command not found: quickback\"\n\nMake sure the CLI is installed globally:\n```bash\nnpm install -g @kardoe/quickback\n```\n\nOr use npx:\n```bash\nnpx @kardoe/quickback create cloudflare my-app\n```\n\n## Compile errors\n\n1. Check your `quickback.config.ts` exists and is valid\n2. Ensure all tables in `quickback/features/` have valid exports\n3. Run `quickback compile` with `--verbose` for detailed output\n\n## Drizzle rename prompts in CI/headless compile\n\nIf compilation fails with an interactive Drizzle message like:\n\n- `drizzle-kit requested interactive rename input, but Quickback compile is running headless`\n- `Missing rename hint for table/column ...`\n\nthen add explicit rename hints in `quickback.config.ts`:\n\n```typescript\nexport default defineConfig({\n // ...\n compiler: {\n migrations: {\n renames: {\n tables: {\n events_v2: \"events\",\n },\n columns: {\n events: {\n summary_text: \"summary\",\n },\n },\n },\n },\n },\n});\n```\n\n`tables` and `columns` mappings are always `new_name -> old_name`.\n\nIf a hint is missing, compile now fails loudly with the exact key path to add, for example:\n\n- `Expected hint key: compiler.migrations.renames.tables[\"events_v2\"]`\n- `Expected hint key: compiler.migrations.renames.columns[\"events\"][\"summary_text\"]`\n\n## \"Could not load organizations\"\n\nThis can happen if your session token expired or if the API is temporarily unavailable. Re-login:\n```bash\nquickback logout\nquickback login\n```"
|
|
143
143
|
},
|
|
144
|
+
"compiler/config/domains": {
|
|
145
|
+
"title": "Multi-Domain Architecture",
|
|
146
|
+
"content": "A single Quickback-compiled Cloudflare Worker can serve your API, CMS, Account UI, and Admin panel on separate custom domains. The compiler generates hostname-based routing so each domain serves the right content.\n\n## How It Works\n\nWhen you configure custom domains for CMS, Account, or Admin, the compiler:\n\n1. Adds `custom_domain` routes to `wrangler.toml`\n2. Generates hostname-based middleware in the Worker\n3. Auto-configures cross-subdomain cookies for shared authentication\n4. Auto-infers a unified `quickback.{baseDomain}` fallback domain\n\nAll five domains point to the **same Worker** — there's only one deployment.\n\n## Domain Types\n\n| Domain | Config | Serves | API Routes |\n|--------|--------|--------|-----------|\n| `api.example.com` | `providers.runtime.config.routes` | API only | All |\n| `cms.example.com` | `cms: { domain }` | CMS SPA | Blocked (404) |\n| `auth.example.com` | `account: { domain }` | Account SPA | Pass-through |\n| `admin.example.com` | `account: { adminDomain }` | Account SPA | Pass-through |\n| `quickback.example.com` | Auto-inferred | Everything | All |\n\n### CMS Domain\n\nServes the CMS SPA at root (`/`). API routes (`/api/`, `/auth/`, `/admin/`, `/storage/`, `/health`) return 404 — preventing direct API access on the CMS domain.\n\n### Account Domain\n\nServes the Account SPA at root (`/`). API and auth routes pass through to the Worker so authentication flows work directly on this domain.\n\n### Admin Domain\n\nIdentical behavior to the Account domain — serves the same Account SPA at root. The Account SPA's client-side router handles the `/admin` route, restricting access to users with the `admin` role.\n\n### Unified Domain\n\nThe compiler auto-infers a `quickback.{baseDomain}` domain from your configured custom domains. For example, if you have `cms.example.com`, it creates `quickback.example.com`.\n\nOn this domain, **everything is available** on a single origin:\n\n| Path | Content |\n|------|---------|\n| `/` | Redirects to `/cms/` |\n| `/cms/` | CMS SPA |\n| `/account/` | Account SPA |\n| `/api/v1/...` | API routes |\n| `/auth/...` | Auth routes |\n| `/admin/...` | Admin API routes |\n| `/storage/...` | File storage |\n| `/health` | Health check |\n| `/openapi.json` | OpenAPI spec |\n\nThe unified domain is useful for development and debugging. You can override it with an explicit `domain` field in your config.\n\n## Configuration\n\n```typescript title=\"quickback/quickback.config.ts\"\nexport default {\n name: \"my-app\",\n template: \"hono\",\n cms: { domain: \"cms.example.com\", access: \"admin\" },\n account: {\n domain: \"auth.example.com\",\n adminDomain: \"admin.example.com\",\n name: \"My App\",\n auth: { password: true, admin: true },\n },\n trustedOrigins: [\n \"https://auth.example.com\",\n \"https://admin.example.com\",\n \"https://cms.example.com\",\n ],\n providers: {\n runtime: { name: \"cloudflare\", config: {\n routes: [{ pattern: \"api.example.com\", custom_domain: true }],\n }},\n // ...database, auth\n },\n};\n```\n\nThis generates the following `wrangler.toml` routes:\n\n```toml\nroutes = [\n { pattern = \"api.example.com\", custom_domain = true },\n { pattern = \"cms.example.com\", custom_domain = true },\n { pattern = \"auth.example.com\", custom_domain = true },\n { pattern = \"admin.example.com\", custom_domain = true },\n { pattern = \"quickback.example.com\", custom_domain = true }\n]\n```\n\n## Cross-Subdomain Authentication\n\nWhen two or more custom domains share a parent domain (e.g., `cms.example.com` + `auth.example.com`), the compiler automatically configures Better Auth for cross-subdomain cookie sharing:\n\n- Sets `crossSubDomainCookies: { enabled: true, domain: '.example.com' }`\n- Sets `sameSite: 'none'` and `secure: true` on auth cookies\n\nThis means a user who logs in on `auth.example.com` is automatically authenticated on `cms.example.com` and `admin.example.com` — no additional setup needed.\n\n## Compile-Time Feature Gating\n\nWhen the compiler builds the Account SPA, it excludes route files for disabled features **before** the Vite build. This means disabled features never appear in the JavaScript bundle.\n\n| Feature Flag | Routes Excluded When `false` |\n|-------------|------------------------------|\n| `auth.organizations` | Dashboard, organization CRUD, org switching (`$slug`) |\n| `auth.passkey` | Passkey management and setup |\n| `auth.admin` | Admin panel routes |\n\nThis keeps bundle sizes minimal and prevents dead code in production. Users can't access disabled features even if they navigate to the URL directly — the routes don't exist in the build.\n\n## Hostname Routing Details\n\nThe compiler generates middleware that checks `new URL(c.req.url).hostname` on every request:\n\n**CMS domain** — Blocks API routes with 404. All other paths are mapped to the `/cms/` asset prefix and served with SPA fallback to `/cms/index.html`.\n\n**Account/Admin domain** — API and auth routes (`/api/`, `/auth/`, `/admin/`, `/storage/`, `/health`) pass through to Hono handlers. All other paths are mapped to the `/account/` asset prefix and served with SPA fallback to `/account/index.html`.\n\n**Unified domain** — No hostname filtering. CMS is served at `/cms/`, Account at `/account/`. Root (`/`) redirects to `/cms/`. API routes work at their standard paths.\n\n## Without Custom Domains\n\nIf you enable `cms` and `account` without custom domains, everything is served on a single domain:\n\n- CMS at `/cms/` (root `/` redirects to `/cms/`)\n- Account UI at `/account/`\n- API at `/api/v1/`\n- Auth at `/auth/`\n\nThis is the simplest setup — no DNS configuration needed, no cross-subdomain cookies. Auth cookies work naturally because everything is same-origin.\n\n## See Also\n\n- [Configuration](/compiler/config) — CMS and Account config options\n- [Output Structure](/compiler/config/output) — Generated file and directory layout\n- [CMS](/cms) — Schema-driven admin interface\n- [Account UI](/account-ui) — Authentication and account management"
|
|
147
|
+
},
|
|
144
148
|
"compiler/config": {
|
|
145
149
|
"title": "Configuration",
|
|
146
|
-
"content": "The `quickback.config.ts` file configures your Quickback project. It defines which providers to use, which features to enable, and how the compiler generates code.\n\n```typescript\n\nexport default defineConfig({\n name: \"my-app\",\n template: \"hono\",\n features: { organizations: true },\n providers: {\n runtime: defineRuntime(\"cloudflare\"),\n database: defineDatabase(\"cloudflare-d1\"),\n auth: defineAuth(\"better-auth\"),\n },\n});\n```\n\n## Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `name` | `string` | Project name |\n| `template` | `\"hono\"` | Application template (`\"nextjs\"` is experimental) |\n| `providers` | `object` | Runtime, database, and auth provider configuration |\n\n## Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `features` | `object` | Feature flags — see [Single-Tenant Mode](/compiler/config/single-tenant) |\n| `build` | `object` | Build options (`outputDir`, `packageManager`, `dependencies`) |\n| `compiler` | `object` | Compiler options (including migration rename hints for headless CI) |\n| `openapi` | `object` | OpenAPI spec generation (`generate`, `publish`) — see [OpenAPI](/compiler/using-the-api/openapi) |\n| `schemaRegistry` | `object` | Schema registry generation for the CMS (enabled by default, `{ generate: false }` to disable) — see [Schema Registry](/cms/schema-registry) |\n| `etag` | `object` | ETag caching for GET responses (enabled by default, `{ enabled: false }` to disable) — see [Caching & ETags](/compiler/using-the-api/caching) |\n\n## Custom Dependencies\n\nAdd third-party npm packages to the generated `package.json` using `build.dependencies`. This is useful when your action handlers import external libraries.\n\n```typescript\nexport default defineConfig({\n name: \"my-app\",\n template: \"hono\",\n build: {\n dependencies: {\n \"fast-xml-parser\": \"^4.5.0\",\n \"lodash-es\": \"^4.17.21\",\n },\n },\n providers: {\n runtime: defineRuntime(\"cloudflare\"),\n database: defineDatabase(\"cloudflare-d1\"),\n auth: defineAuth(\"better-auth\"),\n },\n});\n```\n\nThese are merged into the generated `package.json` alongside Quickback's own dependencies. Run `npm install` after compiling to install them.\n\n## Headless Migration Rename Hints\n\nWhen `drizzle-kit generate` detects a potential rename, it normally prompts for confirmation. Cloud/CI compiles are non-interactive, so you must provide explicit rename hints.\n\nAdd hints in `compiler.migrations.renames`:\n\n```typescript\nexport default defineConfig({\n // ...\n compiler: {\n migrations: {\n renames: {\n // Keys are NEW names, values are OLD names\n tables: {\n events_v2: \"events\",\n },\n columns: {\n events: {\n summary_text: \"summary\",\n },\n },\n },\n },\n },\n});\n```\n\nRules:\n- `tables`: `new_table_name -> old_table_name`\n- `columns.<table>`: `new_column_name -> old_column_name`\n- Keys must match the names in your current schema (the new names)\n- Validation fails fast for malformed rename config, unsupported keys, or conflicting legacy/new rename paths.\n\n## Security Contract Reports and Signing\n\nAfter generation, Quickback verifies machine-checkable security contracts for Hono routes and RLS SQL.\n\nIt also emits a report artifact and signature artifact by default:\n\n- `reports/security-contracts.report.json`\n- `reports/security-contracts.report.sig.json`\n\nYou can configure output paths and signing behavior:\n\n```typescript\nexport default defineConfig({\n // ...\n compiler: {\n securityContracts: {\n failMode: \"error\", // or \"warn\"\n report: {\n path: \"reports/security-contracts.report.json\",\n signature: {\n enabled: true,\n required: true,\n keyEnv: \"QUICKBACK_SECURITY_REPORT_SIGNING_KEY\",\n keyId: \"prod-k1\",\n path: \"reports/security-contracts.report.sig.json\",\n },\n },\n },\n },\n});\n```\n\nIf `signature.required: true` and no key is available, compilation fails with a clear error message (or warning in `failMode: \"warn\"`).\n\nSee the sub-pages for detailed reference on each section:\n- [Providers](/compiler/config/providers) — Runtime, database, and auth options\n- [Variables](/compiler/config/variables) — Environment variables and flags\n- [Output](/compiler/config/output) — Generated file structure\n- [Single-Tenant Mode](/compiler/config/single-tenant) — Admin-only and public-facing apps without organizations"
|
|
150
|
+
"content": "The `quickback.config.ts` file configures your Quickback project. It defines which providers to use, which features to enable, and how the compiler generates code.\n\n```typescript\n\nexport default defineConfig({\n name: \"my-app\",\n template: \"hono\",\n features: { organizations: true },\n providers: {\n runtime: defineRuntime(\"cloudflare\"),\n database: defineDatabase(\"cloudflare-d1\"),\n auth: defineAuth(\"better-auth\"),\n },\n});\n```\n\n## Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `name` | `string` | Project name |\n| `template` | `\"hono\"` | Application template (`\"nextjs\"` is experimental) |\n| `providers` | `object` | Runtime, database, and auth provider configuration |\n\n## Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `features` | `object` | Feature flags — see [Single-Tenant Mode](/compiler/config/single-tenant) |\n| `build` | `object` | Build options (`outputDir`, `packageManager`, `dependencies`) |\n| `compiler` | `object` | Compiler options (including migration rename hints for headless CI) |\n| `openapi` | `object` | OpenAPI spec generation (`generate`, `publish`) — see [OpenAPI](/compiler/using-the-api/openapi) |\n| `schemaRegistry` | `object` | Schema registry generation for the CMS (enabled by default, `{ generate: false }` to disable) — see [Schema Registry](/cms/schema-registry) |\n| `etag` | `object` | ETag caching for GET responses (enabled by default, `{ enabled: false }` to disable) — see [Caching & ETags](/compiler/using-the-api/caching) |\n| `cms` | `boolean \\| object` | Embed CMS in compiled Worker — see [CMS](/cms) |\n| `account` | `boolean \\| object` | Embed Account UI in compiled Worker — see [Account UI](/account-ui) |\n| `trustedOrigins` | `string[]` | CORS trusted origins for cross-domain auth |\n| `domain` | `string` | Primary API domain (auto-inferred from custom domains if not set) |\n| `email` | `object` | Email delivery config (`region`, `from`, `fromName`) |\n\n## Custom Dependencies\n\nAdd third-party npm packages to the generated `package.json` using `build.dependencies`. This is useful when your action handlers import external libraries.\n\n```typescript\nexport default defineConfig({\n name: \"my-app\",\n template: \"hono\",\n build: {\n dependencies: {\n \"fast-xml-parser\": \"^4.5.0\",\n \"lodash-es\": \"^4.17.21\",\n },\n },\n providers: {\n runtime: defineRuntime(\"cloudflare\"),\n database: defineDatabase(\"cloudflare-d1\"),\n auth: defineAuth(\"better-auth\"),\n },\n});\n```\n\nThese are merged into the generated `package.json` alongside Quickback's own dependencies. Run `npm install` after compiling to install them.\n\n## Headless Migration Rename Hints\n\nWhen `drizzle-kit generate` detects a potential rename, it normally prompts for confirmation. Cloud/CI compiles are non-interactive, so you must provide explicit rename hints.\n\nAdd hints in `compiler.migrations.renames`:\n\n```typescript\nexport default defineConfig({\n // ...\n compiler: {\n migrations: {\n renames: {\n // Keys are NEW names, values are OLD names\n tables: {\n events_v2: \"events\",\n },\n columns: {\n events: {\n summary_text: \"summary\",\n },\n },\n },\n },\n },\n});\n```\n\nRules:\n- `tables`: `new_table_name -> old_table_name`\n- `columns.<table>`: `new_column_name -> old_column_name`\n- Keys must match the names in your current schema (the new names)\n- Validation fails fast for malformed rename config, unsupported keys, or conflicting legacy/new rename paths.\n\n## Security Contract Reports and Signing\n\nAfter generation, Quickback verifies machine-checkable security contracts for Hono routes and RLS SQL.\n\nIt also emits a report artifact and signature artifact by default:\n\n- `reports/security-contracts.report.json`\n- `reports/security-contracts.report.sig.json`\n\nYou can configure output paths and signing behavior:\n\n```typescript\nexport default defineConfig({\n // ...\n compiler: {\n securityContracts: {\n failMode: \"error\", // or \"warn\"\n report: {\n path: \"reports/security-contracts.report.json\",\n signature: {\n enabled: true,\n required: true,\n keyEnv: \"QUICKBACK_SECURITY_REPORT_SIGNING_KEY\",\n keyId: \"prod-k1\",\n path: \"reports/security-contracts.report.sig.json\",\n },\n },\n },\n },\n});\n```\n\nIf `signature.required: true` and no key is available, compilation fails with a clear error message (or warning in `failMode: \"warn\"`).\n\n## CMS Configuration\n\nEmbed the [Quickback CMS](/cms) in your compiled Worker. The CMS reads your schema registry and renders a complete admin interface — zero UI code per table.\n\n```typescript\n// Simple — embed CMS at root\ncms: true,\n\n// With custom domain\ncms: { domain: \"cms.example.com\" },\n\n// With access control (only admins see CMS link in Account UI)\ncms: { domain: \"cms.example.com\", access: \"admin\" },\n```\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `domain` | `string` | — | Custom domain for CMS. Adds a `custom_domain` route to `wrangler.toml`. |\n| `access` | `\"user\" \\| \"admin\"` | `\"user\"` | Who can see the \"Go to CMS\" button in Account UI. Set to `\"admin\"` to restrict the link to admin users only. |\n\n## Account UI Configuration\n\nEmbed the [Account UI](/account-ui) in your compiled Worker. Provides login, signup, profile management, organization management, and admin — all built from your config at compile time.\n\n```typescript\n// Simple — embed Account UI with defaults\naccount: true,\n\n// Full configuration\naccount: {\n domain: \"auth.example.com\",\n adminDomain: \"admin.example.com\",\n name: \"My App\",\n companyName: \"My Company\",\n auth: {\n password: true,\n emailOTP: false,\n passkey: true,\n organizations: true,\n admin: true,\n },\n},\n```\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `domain` | `string` | Custom domain for Account UI (e.g., `auth.example.com`) |\n| `adminDomain` | `string` | Custom domain for admin-only access (e.g., `admin.example.com`). Serves the same Account SPA — the client-side router handles admin routing. |\n| `name` | `string` | App display name shown on login, profile, and email templates |\n| `companyName` | `string` | Company name for branding |\n| `tagline` | `string` | App tagline shown on login page |\n| `description` | `string` | App description |\n\n### Auth Feature Flags\n\nControl which authentication features are included in the Account UI bundle. Disabled features are excluded at compile time — their routes are removed before the Vite build, keeping bundle sizes minimal.\n\n| Flag | Type | Default | Description |\n|------|------|---------|-------------|\n| `auth.password` | `boolean` | `true` | Email/password authentication |\n| `auth.emailOTP` | `boolean` | `false` | Email one-time password login |\n| `auth.passkey` | `boolean` | `false` | WebAuthn/FIDO2 passkey authentication |\n| `auth.signup` | `boolean` | `true` | Self-service account registration |\n| `auth.organizations` | `boolean` | `false` | Multi-tenant organization management (dashboard, invitations, roles) |\n| `auth.admin` | `boolean` | `false` | Admin panel for user management (requires Better Auth admin plugin) |\n| `auth.emailVerification` | `boolean` | `false` | Require email verification after signup |\n\n## Trusted Origins\n\nList of origins allowed to make cross-origin requests to your API. Required when your CMS, Account UI, or frontend app run on different domains.\n\n```typescript\ntrustedOrigins: [\n \"https://auth.example.com\",\n \"https://admin.example.com\",\n \"https://cms.example.com\",\n \"https://app.example.com\",\n],\n```\n\n## Email Configuration\n\nConfigure email delivery for authentication emails (verification, password reset, invitations). Requires AWS SES credentials set as secrets.\n\n```typescript\nemail: {\n region: \"us-east-2\",\n from: \"noreply@example.com\",\n fromName: \"My App\",\n},\n```\n\n## Multi-Domain Example\n\nA complete config with CMS, Account UI, and Admin on separate subdomains:\n\n```typescript\nexport default {\n name: \"my-app\",\n template: \"hono\",\n cms: { domain: \"cms.example.com\", access: \"admin\" },\n account: {\n domain: \"auth.example.com\",\n adminDomain: \"admin.example.com\",\n name: \"My App\",\n companyName: \"Example Inc.\",\n auth: {\n password: true,\n emailOTP: false,\n passkey: true,\n organizations: false,\n admin: true,\n },\n },\n email: {\n region: \"us-east-2\",\n from: \"noreply@example.com\",\n fromName: \"My App\",\n },\n trustedOrigins: [\n \"https://auth.example.com\",\n \"https://admin.example.com\",\n \"https://cms.example.com\",\n \"https://example.com\",\n ],\n providers: {\n runtime: { name: \"cloudflare\", config: {\n routes: [{ pattern: \"api.example.com\", custom_domain: true }],\n }},\n database: { name: \"cloudflare-d1\", config: { binding: \"DB\" } },\n auth: { name: \"better-auth\", config: { plugins: [\"admin\"] } },\n },\n};\n```\n\nThis produces a single Cloudflare Worker serving five domains. See [Multi-Domain Architecture](/compiler/config/domains) for details on hostname routing, cross-subdomain cookies, and the unified fallback domain.\n\n---\n\nSee the sub-pages for detailed reference on each section:\n- [Providers](/compiler/config/providers) — Runtime, database, and auth options\n- [Variables](/compiler/config/variables) — Environment variables and flags\n- [Output](/compiler/config/output) — Generated file structure\n- [Single-Tenant Mode](/compiler/config/single-tenant) — Admin-only and public-facing apps without organizations\n- [Multi-Domain Architecture](/compiler/config/domains) — Custom domains, hostname routing, and cross-subdomain auth"
|
|
147
151
|
},
|
|
148
152
|
"compiler/config/output": {
|
|
149
153
|
"title": "Output Structure",
|
|
150
|
-
"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\nquickback/drizzle/\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\nquickback/drizzle/ # 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 | `quickback/drizzle/auth/` + `quickback/drizzle/features/` | `quickback/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\nquickback/drizzle/\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\nquickback/drizzle/\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\nquickback/drizzle/\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- `quickback/drizzle/auth/meta/`\n- `quickback/drizzle/features/meta/`\n- `quickback/drizzle/files/meta/`\n- `quickback/drizzle/webhooks/meta/`\n- `quickback/drizzle/meta/` (single database mode)\n- `drizzle/...` (legacy paths, checked as fallback)\n\nMigration and report artifacts are written to the `quickback/` state directory:\n\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\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"
|
|
154
|
+
"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\nquickback/drizzle/\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\nquickback/drizzle/ # 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 | `quickback/drizzle/auth/` + `quickback/drizzle/features/` | `quickback/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\nquickback/drizzle/\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\nquickback/drizzle/\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\nquickback/drizzle/\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- `quickback/drizzle/auth/meta/`\n- `quickback/drizzle/features/meta/`\n- `quickback/drizzle/files/meta/`\n- `quickback/drizzle/webhooks/meta/`\n- `quickback/drizzle/meta/` (single database mode)\n- `drizzle/...` (legacy paths, checked as fallback)\n\nMigration and report artifacts are written to the `quickback/` state directory:\n\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\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## CMS and Account UI Assets\n\nWhen `cms` and/or `account` are enabled, the compiler builds the SPAs from source at compile time and includes the assets in the output.\n\nEach SPA is placed in its own subdirectory under `src/apps/`:\n\n```\nsrc/apps/ # Root assets directory\n├── cms/ # CMS SPA (served at /cms/ on unified domain)\n│ ├── index.html\n│ └── assets/\n│ ├── app.abc123.js # Content-hashed filenames from Vite\n│ └── app.xyz456.css\n└── account/ # Account SPA (served at /account/ on unified domain)\n ├── index.html\n └── assets/\n ├── app.def789.js\n └── app.ghi012.css\n```\n\nOn custom domains, each SPA is served at root (`/`) via hostname-based routing. On the unified domain, CMS is at `/cms/` and Account is at `/account/`.\n\n### Generated Wrangler Assets Config\n\nThe compiler always generates `run_worker_first = true` when SPAs are enabled — the Worker handles all SPA routing (per hostname and per path prefix):\n\n```toml\n[assets]\nbinding = \"ASSETS\"\ndirectory = \"src/apps\"\nnot_found_handling = \"none\"\nrun_worker_first = true\n```\n\nSee [Multi-Domain Architecture](/compiler/config/domains) for details on hostname routing.\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\n- [Multi-Domain Architecture](/compiler/config/domains) — Custom domains and hostname routing"
|
|
151
155
|
},
|
|
152
156
|
"compiler/config/providers": {
|
|
153
157
|
"title": "Providers",
|
|
@@ -191,7 +195,7 @@ export const DOCS = {
|
|
|
191
195
|
},
|
|
192
196
|
"compiler/definitions/schema": {
|
|
193
197
|
"title": "Database Schema",
|
|
194
|
-
"content": "Quickback uses [Drizzle ORM](https://orm.drizzle.team/) to define your database schema. With `defineTable`, you combine your schema definition and security configuration in a single file.\n\n## Defining Tables with defineTable\n\nEach table gets its own file with schema and config together. Use the Drizzle dialect that matches your target database:\n\n| Target Database | Import From | Table Function |\n|-----------------|-------------|----------------|\n| Cloudflare D1, Turso, SQLite | `drizzle-orm/sqlite-core` | `sqliteTable` |\n| Supabase, Neon, PostgreSQL | `drizzle-orm/pg-core` | `pgTable` |\n| PlanetScale, MySQL | `drizzle-orm/mysql-core` | `mysqlTable` |\n\n```typescript\n// quickback/features/jobs/jobs.ts\n// For D1/SQLite targets:\n\nexport const jobs = sqliteTable('jobs', {\n id: text('id').primaryKey(),\n organizationId: text('organization_id').notNull(),\n title: text('title').notNull(),\n department: text('department').notNull(),\n status: text('status').notNull(), // \"draft\" | \"open\" | \"closed\"\n salaryMin: integer('salary_min'),\n salaryMax: integer('salary_max'),\n});\n\nexport default defineTable(jobs, {\n firewall: { organization: {} },\n guards: {\n createable: [\"title\", \"department\", \"status\", \"salaryMin\", \"salaryMax\"],\n updatable: [\"title\", \"department\", \"status\"],\n },\n crud: {\n list: { access: { roles: [\"owner\", \"hiring-manager\", \"recruiter\", \"interviewer\"] } },\n get: { access: { roles: [\"owner\", \"hiring-manager\", \"recruiter\", \"interviewer\"] } },\n create: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n update: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n delete: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n },\n});\n\nexport type Job = typeof jobs.$inferSelect;\n```\n\n## Column Types\n\nDrizzle supports all standard SQL column types:\n\n| Type | Drizzle Function | Example |\n|------|------------------|---------|\n| String | `text()`, `varchar()` | `text('name')` |\n| Integer | `integer()`, `bigint()` | `integer('count')` |\n| Boolean | `boolean()` | `boolean('is_active')` |\n| Timestamp | `timestamp()` | `timestamp('created_at')` |\n| JSON | `json()`, `jsonb()` | `jsonb('metadata')` |\n| UUID | `uuid()` | `uuid('id')` |\n| Decimal | `decimal()`, `numeric()` | `decimal('price', { precision: 10, scale: 2 })` |\n\n## Column Modifiers\n\n```typescript\n// Required field\nname: text('name').notNull()\n\n// Default value\nisActive: boolean('is_active').default(true)\n\n// Primary key\nid: text('id').primaryKey()\n\n// Unique constraint\nemail: text('email').unique()\n\n// Default to current timestamp\ncreatedAt: timestamp('created_at').defaultNow()\n```\n\n## File Organization\n\nOrganize your tables by feature. Each feature directory contains table files:\n\n```\nquickback/\n├── quickback.config.ts\n└── features/\n ├── jobs/\n │ ├── jobs.ts # Main table + config\n │ ├── applications.ts # Related table + config\n │ └── actions.ts # Custom actions\n ├── candidates/\n │ ├── candidates.ts # Table + config\n │ └── candidate-notes.ts # Related table\n └── organizations/\n └── organizations.ts\n```\n\n**Key points:**\n- Tables with `export default defineTable(...)` get CRUD routes generated\n- Tables without a default export are internal (no routes, used for joins/relations)\n- Route paths are derived from filenames: `applications.ts` → `/api/v1/applications`\n\n### defineTable vs defineResource\n\n- **`defineTable`** — The standard function for defining tables with CRUD routes\n- **`defineResource`** — Deprecated. Still works but emits a warning during compilation. Use `defineTable` instead.\n\n```typescript\n// Preferred:\nexport default defineTable(jobs, { /* config */ });\n```\n\n## 1 Resource = 1 Security Boundary\n\nEach `defineTable()` call defines a complete, self-contained security boundary. The security config you write — firewall, access, guards, and masking — is compiled into a single resource file that wraps all CRUD routes for that table.\n\nThis is a deliberate design choice. Mixing two resources with different security rules in one configuration would create ambiguity about which firewall, access, or masking rules apply to which table. By keeping it 1:1, there's never any question.\n\n| Scenario | What to do |\n|----------|------------|\n| Table needs its own API routes + security | Own file with `defineTable()` |\n| Table is internal/supporting (no direct API) | Extra `.ts` file in the parent feature directory, no `defineTable()` |\n\nA supporting table without `defineTable()` is useful when it's accessed internally — by action handlers, joins, or background jobs — but should never be directly exposed as its own API endpoint.\n\n## Internal Tables (No Routes)\n\nFor junction tables or internal data structures that shouldn't have API routes, simply omit the `defineTable` export:\n\n```typescript\n// quickback/features/jobs/interview-scores.ts\n\n// Internal scoring table - no routes needed\nexport const interviewScores = sqliteTable('interview_scores', {\n applicationId: text('application_id').notNull(),\n interviewerId: text('interviewer_id').notNull(),\n score: integer('score'),\n organizationId: text('organization_id').notNull(), // Always scope junction tables\n});\n\n// No default export = no CRUD routes generated\n```\n\nThese internal tables still participate in the database schema and migrations — they just don't get API routes or security configuration.\n\nThe compiler automatically injects **audit fields** (`createdAt`, `modifiedAt`, `deletedAt`, etc.) and **`organizationId`** into child/junction tables when the parent feature is org-scoped. This ensures cascade soft deletes and scoped queries work correctly without manual column definitions.\n\n## Audit Fields\n\nQuickback automatically adds and manages these audit fields on **all tables** in a feature (including child/junction tables without `defineTable`) - you don't need to define them:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `createdAt` | timestamp | Set when record is created |\n| `createdBy` | text | User ID who created the record |\n| `modifiedAt` | timestamp | Updated on every change |\n| `modifiedBy` | text | User ID who last modified |\n| `deletedAt` | timestamp | Set on soft delete (optional) |\n| `deletedBy` | text | User ID who deleted (optional) |\n\nThe soft delete fields (`deletedAt`, `deletedBy`) are only added if your resource uses soft delete mode.\n\n### Disabling Audit Fields\n\nTo disable automatic audit fields for your project:\n\n```typescript\n// quickback.config.ts\nexport default defineConfig({\n // ...\n compiler: {\n features: {\n auditFields: false, // Disable for entire project\n }\n }\n});\n```\n\n### Protected System Fields\n\nThese fields are always protected and cannot be set by clients, even with `guards: false`:\n\n- `id` (when `generateId` is not `false`)\n- `createdAt`, `createdBy`\n- `modifiedAt`, `modifiedBy`\n- `deletedAt`, `deletedBy`\n\n## Ownership Fields\n\nFor the firewall to work, include the appropriate ownership columns:\n\n```typescript\n// For organization-scoped data (most common)\norganizationId: text('organization_id').notNull()\n\n// For user-owned data (personal data)\nownerId: text('owner_id').notNull()\n\n// For team-scoped data\nteamId: text('team_id').notNull()\n```\n\n## Display Column\n\nWhen a table has foreign key columns (e.g., `departmentId` referencing `departments`), Quickback can automatically resolve the human-readable label in GET and LIST responses. This eliminates the need for frontend lookup calls.\n\n### Auto-Detection\n\nQuickback auto-detects the display column by checking for common column names in this order:\n\n`name` → `title` → `label` → `headline` → `subject` → `code` → `displayName` → `fullName` → `description`\n\nIf your `departments` table has a `name` column, it's automatically used as the display column. No config needed.\n\n### Explicit Override\n\nOverride the auto-detected column with `displayColumn`:\n\n```typescript\nexport default defineTable(interviewStages, {\n displayColumn: 'label', // Use 'label' instead of auto-detected 'name'\n firewall: { organization: {} },\n crud: {\n list: { access: { roles: [\"hiring-manager\", \"recruiter\"] } },\n get: { access: { roles: [\"hiring-manager\", \"recruiter\"] } },\n },\n});\n```\n\n### How Labels Appear in Responses\n\nFor any FK column ending in `Id`, the API adds a `_label` field with the resolved display value:\n\n```json\n{\n \"id\": \"job_abc\",\n \"title\": \"Senior Engineer\",\n \"departmentId\": \"dept_xyz\",\n \"department_label\": \"Engineering\",\n \"locationId\": \"loc_123\",\n \"location_label\": \"San Francisco\"\n}\n```\n\nThe pattern is `{columnWithoutId}_label`. The frontend can find all labels with:\n\n```typescript\nObject.keys(record).filter(k => k.endsWith('_label'))\n```\n\nLabel resolution works within the same feature (tables in the same feature directory). System columns (`organizationId`, `createdBy`, `modifiedBy`) are never resolved.\n\nFor LIST endpoints, labels are batch-resolved efficiently — one query per FK column, not per record.\n\n## References\n\nWhen your FK columns don't match the target table name by convention (e.g., `vendorId` actually points to the `contact` table), declare explicit references so the CMS and schema registry know the correct target:\n\n```typescript\nexport default defineTable(applications, {\n references: {\n candidateId: \"candidate\",\n jobId: \"job\",\n referredById: \"candidate\",\n },\n // ... firewall, guards, crud\n});\n```\n\nEach key is a column name ending in `Id`, and the value is the camelCase table name it references. These mappings flow into the schema registry as `fkTarget` on each column, enabling the CMS to render typeahead/lookup inputs that search the correct table.\n\nConvention-based matching (strip `Id` suffix, look for a matching table) still works for simple cases like `projectId` → `project`. Use `references` only for columns where the convention doesn't match.\n\n## Input Hints\n\nControl how the CMS renders form inputs for specific columns. By default the CMS infers input types from the column's SQL type — `inputHints` lets you override that:\n\n```typescript\nexport default defineTable(jobs, {\n inputHints: {\n status: \"select\",\n department: \"select\",\n salaryMin: \"currency\",\n salaryMax: \"currency\",\n description: \"textarea\",\n },\n // ... firewall, guards, crud\n});\n```\n\n### Available Hint Values\n\n| Hint | Renders As |\n|------|-----------|\n| `select` | Dropdown select (single value) |\n| `multi-select` | Multi-value select |\n| `radio` | Radio button group |\n| `checkbox` | Checkbox toggle |\n| `textarea` | Multi-line text input |\n| `lookup` | FK typeahead search |\n| `hidden` | Hidden from forms |\n| `color` | Color picker |\n| `date` | Date picker |\n| `datetime` | Date + time picker |\n| `time` | Time picker |\n| `currency` | Currency input with formatting |\n\nInput hints are emitted in the schema registry as `inputHints` on the table metadata, and the CMS reads them to render the appropriate form controls.\n\n## Relations (Optional)\n\nDrizzle supports defining relations for type-safe joins:\n\n```typescript\n\nexport const jobsRelations = relations(jobs, ({ one, many }) => ({\n organization: one(organizations, {\n fields: [jobs.organizationId],\n references: [organizations.id],\n }),\n applications: many(applications),\n}));\n```\n\n## Database Configuration\n\nConfigure database options in your Quickback config:\n\n```typescript\n// quickback.config.ts\nexport default defineConfig({\n name: 'my-app',\n providers: {\n database: defineDatabase('cloudflare-d1', {\n generateId: 'prefixed', // 'uuid' | 'cuid' | 'nanoid' | 'prefixed' | 'serial' | false\n namingConvention: 'snake_case', // 'camelCase' | 'snake_case'\n usePlurals: false, // Auth table names: 'users' vs 'user'\n }),\n },\n compiler: {\n features: {\n auditFields: true, // Auto-manage audit timestamps\n }\n }\n});\n```\n\n## Choosing Your Dialect\n\nUse the Drizzle dialect that matches your database provider:\n\n### SQLite (D1, Turso, better-sqlite3)\n\n```typescript\n\nexport const jobs = sqliteTable('jobs', {\n id: text('id').primaryKey(),\n title: text('title').notNull(),\n metadata: text('metadata', { mode: 'json' }), // JSON stored as text\n isOpen: integer('is_open', { mode: 'boolean' }).default(false),\n organizationId: text('organization_id').notNull(),\n});\n```\n\n### PostgreSQL (Supabase, Neon)\n\n```typescript\n\nexport const jobs = pgTable('jobs', {\n id: serial('id').primaryKey(),\n title: text('title').notNull(),\n metadata: jsonb('metadata'), // Native JSONB\n isOpen: boolean('is_open').default(false),\n organizationId: text('organization_id').notNull(),\n});\n```\n\n### Key Differences\n\n| Feature | SQLite | PostgreSQL |\n|---------|--------|------------|\n| Boolean | `integer({ mode: 'boolean' })` | `boolean()` |\n| JSON | `text({ mode: 'json' })` | `jsonb()` or `json()` |\n| Auto-increment | `integer().primaryKey()` | `serial()` |\n| UUID | `text()` | `uuid()` |\n\n## Next Steps\n\n- [Configure the firewall](/compiler/definitions/firewall) for data isolation\n- [Set up access control](/compiler/definitions/access) for CRUD operations\n- [Define guards](/compiler/definitions/guards) for field modification rules\n- [Add custom actions](/compiler/definitions/actions) for business logic"
|
|
198
|
+
"content": "Quickback uses [Drizzle ORM](https://orm.drizzle.team/) to define your database schema. With `defineTable`, you combine your schema definition and security configuration in a single file.\n\n## Defining Tables with defineTable\n\nEach table gets its own file with schema and config together. Use the Drizzle dialect that matches your target database:\n\n| Target Database | Import From | Table Function |\n|-----------------|-------------|----------------|\n| Cloudflare D1, Turso, SQLite | `drizzle-orm/sqlite-core` | `sqliteTable` |\n| Supabase, Neon, PostgreSQL | `drizzle-orm/pg-core` | `pgTable` |\n| PlanetScale, MySQL | `drizzle-orm/mysql-core` | `mysqlTable` |\n\n```typescript\n// quickback/features/jobs/jobs.ts\n// For D1/SQLite targets:\n\nexport const jobs = sqliteTable('jobs', {\n id: text('id').primaryKey(),\n organizationId: text('organization_id').notNull(),\n title: text('title').notNull(),\n department: text('department').notNull(),\n status: text('status').notNull(), // \"draft\" | \"open\" | \"closed\"\n salaryMin: integer('salary_min'),\n salaryMax: integer('salary_max'),\n});\n\nexport default defineTable(jobs, {\n firewall: { organization: {} },\n guards: {\n createable: [\"title\", \"department\", \"status\", \"salaryMin\", \"salaryMax\"],\n updatable: [\"title\", \"department\", \"status\"],\n },\n crud: {\n list: { access: { roles: [\"owner\", \"hiring-manager\", \"recruiter\", \"interviewer\"] } },\n get: { access: { roles: [\"owner\", \"hiring-manager\", \"recruiter\", \"interviewer\"] } },\n create: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n update: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n delete: { access: { roles: [\"owner\", \"hiring-manager\"] } },\n },\n});\n\nexport type Job = typeof jobs.$inferSelect;\n```\n\n## Column Types\n\nDrizzle supports all standard SQL column types:\n\n| Type | Drizzle Function | Example |\n|------|------------------|---------|\n| String | `text()`, `varchar()` | `text('name')` |\n| Integer | `integer()`, `bigint()` | `integer('count')` |\n| Boolean | `boolean()` | `boolean('is_active')` |\n| Timestamp | `timestamp()` | `timestamp('created_at')` |\n| JSON | `json()`, `jsonb()` | `jsonb('metadata')` |\n| UUID | `uuid()` | `uuid('id')` |\n| Decimal | `decimal()`, `numeric()` | `decimal('price', { precision: 10, scale: 2 })` |\n\n## Column Modifiers\n\n```typescript\n// Required field\nname: text('name').notNull()\n\n// Default value\nisActive: boolean('is_active').default(true)\n\n// Primary key\nid: text('id').primaryKey()\n\n// Unique constraint\nemail: text('email').unique()\n\n// Default to current timestamp\ncreatedAt: timestamp('created_at').defaultNow()\n```\n\n## File Organization\n\nOrganize your tables by feature. Each feature directory contains table files:\n\n```\nquickback/\n├── quickback.config.ts\n└── features/\n ├── jobs/\n │ ├── jobs.ts # Main table + config\n │ ├── applications.ts # Related table + config\n │ └── actions.ts # Custom actions\n ├── candidates/\n │ ├── candidates.ts # Table + config\n │ └── candidate-notes.ts # Related table\n └── organizations/\n └── organizations.ts\n```\n\n**Key points:**\n- Tables with `export default defineTable(...)` get CRUD routes generated\n- Tables without a default export are internal (no routes, used for joins/relations)\n- Route paths are derived from filenames: `applications.ts` → `/api/v1/applications`\n\n### defineTable vs defineResource\n\n- **`defineTable`** — The standard function for defining tables with CRUD routes\n- **`defineResource`** — Deprecated. Still works but emits a warning during compilation. Use `defineTable` instead.\n\n```typescript\n// Preferred:\nexport default defineTable(jobs, { /* config */ });\n```\n\n## 1 Resource = 1 Security Boundary\n\nEach `defineTable()` call defines a complete, self-contained security boundary. The security config you write — firewall, access, guards, and masking — is compiled into a single resource file that wraps all CRUD routes for that table.\n\nThis is a deliberate design choice. Mixing two resources with different security rules in one configuration would create ambiguity about which firewall, access, or masking rules apply to which table. By keeping it 1:1, there's never any question.\n\n| Scenario | What to do |\n|----------|------------|\n| Table needs its own API routes + security | Own file with `defineTable()` |\n| Table is internal/supporting (no direct API) | Extra `.ts` file in the parent feature directory, no `defineTable()` |\n\nA supporting table without `defineTable()` is useful when it's accessed internally — by action handlers, joins, or background jobs — but should never be directly exposed as its own API endpoint.\n\n## Internal Tables (No Routes)\n\nFor junction tables or internal data structures that shouldn't have API routes, simply omit the `defineTable` export:\n\n```typescript\n// quickback/features/jobs/interview-scores.ts\n\n// Internal scoring table - no routes needed\nexport const interviewScores = sqliteTable('interview_scores', {\n applicationId: text('application_id').notNull(),\n interviewerId: text('interviewer_id').notNull(),\n score: integer('score'),\n organizationId: text('organization_id').notNull(), // Always scope junction tables\n});\n\n// No default export = no CRUD routes generated\n```\n\nThese internal tables still participate in the database schema and migrations — they just don't get API routes or security configuration.\n\nThe compiler automatically injects **audit fields** (`createdAt`, `modifiedAt`, `deletedAt`, etc.) and **`organizationId`** into child/junction tables when the parent feature is org-scoped. This ensures cascade soft deletes and scoped queries work correctly without manual column definitions.\n\n## Audit Fields\n\nQuickback automatically adds and manages these audit fields on **all tables** in a feature (including child/junction tables without `defineTable`) - you don't need to define them:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `createdAt` | timestamp | Set when record is created |\n| `createdBy` | text | User ID who created the record |\n| `modifiedAt` | timestamp | Updated on every change |\n| `modifiedBy` | text | User ID who last modified |\n| `deletedAt` | timestamp | Set on soft delete (optional) |\n| `deletedBy` | text | User ID who deleted (optional) |\n\nThe soft delete fields (`deletedAt`, `deletedBy`) are only added if your resource uses soft delete mode.\n\n### Disabling Audit Fields\n\nTo disable automatic audit fields for your project:\n\n```typescript\n// quickback.config.ts\nexport default defineConfig({\n // ...\n compiler: {\n features: {\n auditFields: false, // Disable for entire project\n }\n }\n});\n```\n\n### Protected System Fields\n\nThese fields are always protected and cannot be set by clients, even with `guards: false`:\n\n- `id` (when `generateId` is not `false`)\n- `createdAt`, `createdBy`\n- `modifiedAt`, `modifiedBy`\n- `deletedAt`, `deletedBy`\n\n## Ownership Fields\n\nFor the firewall to work, include the appropriate ownership columns:\n\n```typescript\n// For organization-scoped data (most common)\norganizationId: text('organization_id').notNull()\n\n// For user-owned data (personal data)\nownerId: text('owner_id').notNull()\n\n// For team-scoped data\nteamId: text('team_id').notNull()\n```\n\n## Display Column\n\nWhen a table has foreign key columns (e.g., `departmentId` referencing `departments`), Quickback can automatically resolve the human-readable label in GET and LIST responses. This eliminates the need for frontend lookup calls.\n\n### Auto-Detection\n\nQuickback auto-detects the display column by checking for common column names in this order:\n\n`name` → `title` → `label` → `headline` → `subject` → `code` → `displayName` → `fullName` → `description`\n\nIf your `departments` table has a `name` column, it's automatically used as the display column. No config needed.\n\n### Explicit Override\n\nOverride the auto-detected column with `displayColumn`:\n\n```typescript\nexport default defineTable(interviewStages, {\n displayColumn: 'label', // Use 'label' instead of auto-detected 'name'\n firewall: { organization: {} },\n crud: {\n list: { access: { roles: [\"hiring-manager\", \"recruiter\"] } },\n get: { access: { roles: [\"hiring-manager\", \"recruiter\"] } },\n },\n});\n```\n\n### Default Sort\n\nSet a default sort order for the CMS table list view with `defaultSort`:\n\n```typescript\nexport default defineTable(podcastEpisodes, {\n defaultSort: { field: \"createdAt\", order: \"desc\" },\n firewall: { exception: true },\n crud: {\n list: { access: { roles: [\"PUBLIC\"] } },\n get: { access: { roles: [\"PUBLIC\"] } },\n },\n});\n```\n\nThe CMS applies this sort when the table first loads. Users can still click column headers to change the sort order.\n\n### How Labels Appear in Responses\n\nFor any FK column ending in `Id`, the API adds a `_label` field with the resolved display value:\n\n```json\n{\n \"id\": \"job_abc\",\n \"title\": \"Senior Engineer\",\n \"departmentId\": \"dept_xyz\",\n \"department_label\": \"Engineering\",\n \"locationId\": \"loc_123\",\n \"location_label\": \"San Francisco\"\n}\n```\n\nThe pattern is `{columnWithoutId}_label`. The frontend can find all labels with:\n\n```typescript\nObject.keys(record).filter(k => k.endsWith('_label'))\n```\n\nLabel resolution works within the same feature (tables in the same feature directory). System columns (`organizationId`, `createdBy`, `modifiedBy`) are never resolved.\n\nFor LIST endpoints, labels are batch-resolved efficiently — one query per FK column, not per record.\n\n## References\n\nWhen your FK columns don't match the target table name by convention (e.g., `vendorId` actually points to the `contact` table), declare explicit references so the CMS and schema registry know the correct target:\n\n```typescript\nexport default defineTable(applications, {\n references: {\n candidateId: \"candidate\",\n jobId: \"job\",\n referredById: \"candidate\",\n },\n // ... firewall, guards, crud\n});\n```\n\nEach key is a column name ending in `Id`, and the value is the camelCase table name it references. These mappings flow into the schema registry as `fkTarget` on each column, enabling the CMS to render typeahead/lookup inputs that search the correct table.\n\nConvention-based matching (strip `Id` suffix, look for a matching table) still works for simple cases like `projectId` → `project`. Use `references` only for columns where the convention doesn't match.\n\n## Input Hints\n\nControl how the CMS renders form inputs for specific columns. By default the CMS infers input types from the column's SQL type — `inputHints` lets you override that:\n\n```typescript\nexport default defineTable(jobs, {\n inputHints: {\n status: \"select\",\n department: \"select\",\n salaryMin: \"currency\",\n salaryMax: \"currency\",\n description: \"richtext\",\n },\n // ... firewall, guards, crud\n});\n```\n\n### Available Hint Values\n\n| Hint | Renders As |\n|------|-----------|\n| `richtext` | Rich text editor (tiptap) — bold, italic, headings, lists, links. Stores HTML. Lazy-loaded in edit mode, rendered as formatted HTML in view mode. |\n| `select` | Dropdown select (single value) |\n| `multi-select` | Multi-value select |\n| `radio` | Radio button group |\n| `checkbox` | Checkbox toggle |\n| `textarea` | Multi-line text input |\n| `lookup` | FK typeahead search |\n| `hidden` | Hidden from forms |\n| `color` | Color picker |\n| `date` | Date picker |\n| `datetime` | Date + time picker |\n| `time` | Time picker |\n| `currency` | Currency input with formatting |\n\nInput hints are emitted in the schema registry as `inputHints` on the table metadata, and the CMS reads them to render the appropriate form controls.\n\n### Rich Text Example\n\nFor fields that contain HTML content (e.g., blog posts, descriptions from RSS feeds), use `\"richtext\"`:\n\n```typescript\nexport default defineTable(podcastEpisodes, {\n inputHints: { description: \"richtext\" },\n // ...\n});\n```\n\nThe CMS will:\n- **View mode**: Render the HTML with proper formatting (headings, lists, links, etc.)\n- **Edit mode**: Load a tiptap rich text editor with a toolbar (bold, italic, H2, H3, bullet/ordered lists, links, code, undo/redo)\n- **Storage**: HTML strings — no format conversion needed, compatible with external HTML content\n\n## Relations (Optional)\n\nDrizzle supports defining relations for type-safe joins:\n\n```typescript\n\nexport const jobsRelations = relations(jobs, ({ one, many }) => ({\n organization: one(organizations, {\n fields: [jobs.organizationId],\n references: [organizations.id],\n }),\n applications: many(applications),\n}));\n```\n\n## Database Configuration\n\nConfigure database options in your Quickback config:\n\n```typescript\n// quickback.config.ts\nexport default defineConfig({\n name: 'my-app',\n providers: {\n database: defineDatabase('cloudflare-d1', {\n generateId: 'prefixed', // 'uuid' | 'cuid' | 'nanoid' | 'prefixed' | 'serial' | false\n namingConvention: 'snake_case', // 'camelCase' | 'snake_case'\n usePlurals: false, // Auth table names: 'users' vs 'user'\n }),\n },\n compiler: {\n features: {\n auditFields: true, // Auto-manage audit timestamps\n }\n }\n});\n```\n\n## Choosing Your Dialect\n\nUse the Drizzle dialect that matches your database provider:\n\n### SQLite (D1, Turso, better-sqlite3)\n\n```typescript\n\nexport const jobs = sqliteTable('jobs', {\n id: text('id').primaryKey(),\n title: text('title').notNull(),\n metadata: text('metadata', { mode: 'json' }), // JSON stored as text\n isOpen: integer('is_open', { mode: 'boolean' }).default(false),\n organizationId: text('organization_id').notNull(),\n});\n```\n\n### PostgreSQL (Supabase, Neon)\n\n```typescript\n\nexport const jobs = pgTable('jobs', {\n id: serial('id').primaryKey(),\n title: text('title').notNull(),\n metadata: jsonb('metadata'), // Native JSONB\n isOpen: boolean('is_open').default(false),\n organizationId: text('organization_id').notNull(),\n});\n```\n\n### Key Differences\n\n| Feature | SQLite | PostgreSQL |\n|---------|--------|------------|\n| Boolean | `integer({ mode: 'boolean' })` | `boolean()` |\n| JSON | `text({ mode: 'json' })` | `jsonb()` or `json()` |\n| Auto-increment | `integer().primaryKey()` | `serial()` |\n| UUID | `text()` | `uuid()` |\n\n## Next Steps\n\n- [Configure the firewall](/compiler/definitions/firewall) for data isolation\n- [Set up access control](/compiler/definitions/access) for CRUD operations\n- [Define guards](/compiler/definitions/guards) for field modification rules\n- [Add custom actions](/compiler/definitions/actions) for business logic"
|
|
195
199
|
},
|
|
196
200
|
"compiler/definitions/validation": {
|
|
197
201
|
"title": "Validation",
|
|
@@ -478,6 +482,7 @@ export const TOPIC_LIST = [
|
|
|
478
482
|
"compiler/cloud-compiler",
|
|
479
483
|
"compiler/cloud-compiler/local-compiler",
|
|
480
484
|
"compiler/cloud-compiler/troubleshooting",
|
|
485
|
+
"compiler/config/domains",
|
|
481
486
|
"compiler/config",
|
|
482
487
|
"compiler/config/output",
|
|
483
488
|
"compiler/config/providers",
|
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,omNAAomN;KAChnN;IACD,2BAA2B,EAAE;QAC3B,OAAO,EAAE,aAAa;QACtB,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
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,8DAA8D;AAC9D,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api-client.d.ts
CHANGED
|
@@ -43,6 +43,19 @@ export interface CompilerOutput {
|
|
|
43
43
|
features: string[];
|
|
44
44
|
timestamp: string;
|
|
45
45
|
version: string;
|
|
46
|
+
timings?: {
|
|
47
|
+
parseMs: number;
|
|
48
|
+
generateMs: number;
|
|
49
|
+
installMs: number;
|
|
50
|
+
commandsMs: number;
|
|
51
|
+
collectMs: number;
|
|
52
|
+
totalMs: number;
|
|
53
|
+
commands: Array<{
|
|
54
|
+
description: string;
|
|
55
|
+
ms: number;
|
|
56
|
+
success: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
46
59
|
};
|
|
47
60
|
commands?: PostCompileCommand[];
|
|
48
61
|
warnings?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,GAAG,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5D,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,iBAAiB,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACpG,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACvC,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api-client.js
CHANGED
|
@@ -60,9 +60,10 @@ export async function callCompiler(input, onStatus) {
|
|
|
60
60
|
const body = JSON.stringify(input);
|
|
61
61
|
const maxRetries = 3;
|
|
62
62
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
63
|
+
// Try SSE streaming first for live progress updates
|
|
63
64
|
const response = await fetch(`${API_URL}/compile`, {
|
|
64
65
|
method: 'POST',
|
|
65
|
-
headers,
|
|
66
|
+
headers: { ...headers, 'Accept': 'text/event-stream' },
|
|
66
67
|
body,
|
|
67
68
|
});
|
|
68
69
|
if (!response.ok) {
|
|
@@ -79,7 +80,8 @@ export async function callCompiler(input, onStatus) {
|
|
|
79
80
|
throw new Error(`${error.error}\n${error.hint}`);
|
|
80
81
|
}
|
|
81
82
|
// Include detailed error info for debugging
|
|
82
|
-
|
|
83
|
+
// Prefer .message (specific reason) over .error (generic category like "Compilation failed")
|
|
84
|
+
const errorMsg = error.message || error.error || 'Compilation failed';
|
|
83
85
|
const details = error.details ? `\nDetails: ${JSON.stringify(error.details, null, 2)}` : '';
|
|
84
86
|
const stderr = error.stderr ? `\nStderr: ${error.stderr}` : '';
|
|
85
87
|
const stdout = error.stdout ? `\nStdout: ${error.stdout}` : '';
|
|
@@ -87,6 +89,12 @@ export async function callCompiler(input, onStatus) {
|
|
|
87
89
|
const status = `\nStatus: ${response.status} ${response.statusText}`;
|
|
88
90
|
throw new Error(errorMsg + status + details + stderr + stdout + raw);
|
|
89
91
|
}
|
|
92
|
+
const contentType = response.headers.get('content-type') || '';
|
|
93
|
+
// Handle SSE streaming response
|
|
94
|
+
if (contentType.includes('text/event-stream') && response.body) {
|
|
95
|
+
return consumeSSEStream(response.body, onStatus);
|
|
96
|
+
}
|
|
97
|
+
// Fallback: plain JSON response (server doesn't support streaming)
|
|
90
98
|
return response.json();
|
|
91
99
|
}
|
|
92
100
|
throw new Error('Compilation failed after retries');
|
|
@@ -101,6 +109,58 @@ export async function checkHealth() {
|
|
|
101
109
|
}
|
|
102
110
|
return response.json();
|
|
103
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Consume an SSE stream from the compiler, forwarding progress events to onStatus
|
|
114
|
+
* and returning the final CompilerOutput when the 'result' event arrives.
|
|
115
|
+
*/
|
|
116
|
+
async function consumeSSEStream(body, onStatus) {
|
|
117
|
+
const reader = body.getReader();
|
|
118
|
+
const decoder = new TextDecoder();
|
|
119
|
+
let buffer = '';
|
|
120
|
+
let currentEvent = '';
|
|
121
|
+
let result = null;
|
|
122
|
+
while (true) {
|
|
123
|
+
const { done, value } = await reader.read();
|
|
124
|
+
if (done)
|
|
125
|
+
break;
|
|
126
|
+
buffer += decoder.decode(value, { stream: true });
|
|
127
|
+
// Parse SSE events from buffer
|
|
128
|
+
const lines = buffer.split('\n');
|
|
129
|
+
buffer = lines.pop() || ''; // Keep incomplete line in buffer
|
|
130
|
+
for (const line of lines) {
|
|
131
|
+
if (line.startsWith('event: ')) {
|
|
132
|
+
currentEvent = line.slice(7).trim();
|
|
133
|
+
}
|
|
134
|
+
else if (line.startsWith('data: ')) {
|
|
135
|
+
const data = line.slice(6);
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(data);
|
|
138
|
+
if (currentEvent === 'progress') {
|
|
139
|
+
const secs = (parsed.elapsedMs / 1000).toFixed(1);
|
|
140
|
+
onStatus?.(`${parsed.message} (${secs}s)`);
|
|
141
|
+
}
|
|
142
|
+
else if (currentEvent === 'result') {
|
|
143
|
+
result = parsed;
|
|
144
|
+
}
|
|
145
|
+
else if (currentEvent === 'error') {
|
|
146
|
+
const errorMsg = parsed.message || parsed.error || 'Compilation failed';
|
|
147
|
+
throw new Error(errorMsg);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
if (e instanceof Error && e.message !== 'Compilation failed')
|
|
152
|
+
throw e;
|
|
153
|
+
// Ignore JSON parse errors for malformed lines
|
|
154
|
+
}
|
|
155
|
+
currentEvent = '';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (!result) {
|
|
160
|
+
throw new Error('Compilation stream ended without a result');
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
104
164
|
/**
|
|
105
165
|
* Wait for the compiler container to be ready.
|
|
106
166
|
* Cloud containers may need a cold start — this polls health until the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -146,6 +146,9 @@ export default defineTable(todos, {
|
|
|
146
146
|
masking: {
|
|
147
147
|
userId: { type: "redact", show: { roles: ["admin"] } },
|
|
148
148
|
},
|
|
149
|
+
inputHints: {
|
|
150
|
+
description: "richtext", // Rich text editor (tiptap) in CMS edit mode, rendered HTML in view mode
|
|
151
|
+
},
|
|
149
152
|
layouts: {
|
|
150
153
|
default: {
|
|
151
154
|
sections: [
|
|
@@ -170,6 +173,24 @@ export const roomAmenities = sqliteTable('room_amenities', {
|
|
|
170
173
|
|
|
171
174
|
---
|
|
172
175
|
|
|
176
|
+
## Input Hints
|
|
177
|
+
|
|
178
|
+
Control how the CMS renders form inputs. Key values:
|
|
179
|
+
|
|
180
|
+
| Hint | Renders As |
|
|
181
|
+
|------|-----------|
|
|
182
|
+
| `richtext` | Tiptap rich text editor (edit) / formatted HTML (view). Stores HTML. |
|
|
183
|
+
| `select` | Dropdown select |
|
|
184
|
+
| `textarea` | Multi-line text |
|
|
185
|
+
| `currency` | Currency input |
|
|
186
|
+
| `checkbox` | Checkbox toggle |
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
inputHints: { description: "richtext", status: "select" }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
173
194
|
## Four Security Layers
|
|
174
195
|
|
|
175
196
|
Every API request passes through four layers in order:
|
package/package.json
CHANGED
package/src/skill/SKILL.md
CHANGED
|
@@ -146,6 +146,9 @@ export default defineTable(todos, {
|
|
|
146
146
|
masking: {
|
|
147
147
|
userId: { type: "redact", show: { roles: ["admin"] } },
|
|
148
148
|
},
|
|
149
|
+
inputHints: {
|
|
150
|
+
description: "richtext", // Rich text editor (tiptap) in CMS edit mode, rendered HTML in view mode
|
|
151
|
+
},
|
|
149
152
|
layouts: {
|
|
150
153
|
default: {
|
|
151
154
|
sections: [
|
|
@@ -170,6 +173,24 @@ export const roomAmenities = sqliteTable('room_amenities', {
|
|
|
170
173
|
|
|
171
174
|
---
|
|
172
175
|
|
|
176
|
+
## Input Hints
|
|
177
|
+
|
|
178
|
+
Control how the CMS renders form inputs. Key values:
|
|
179
|
+
|
|
180
|
+
| Hint | Renders As |
|
|
181
|
+
|------|-----------|
|
|
182
|
+
| `richtext` | Tiptap rich text editor (edit) / formatted HTML (view). Stores HTML. |
|
|
183
|
+
| `select` | Dropdown select |
|
|
184
|
+
| `textarea` | Multi-line text |
|
|
185
|
+
| `currency` | Currency input |
|
|
186
|
+
| `checkbox` | Checkbox toggle |
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
inputHints: { description: "richtext", status: "select" }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
173
194
|
## Four Security Layers
|
|
174
195
|
|
|
175
196
|
Every API request passes through four layers in order:
|