@duckcodeailabs/dql-project 1.4.4 → 1.5.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/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export { RegistrySync } from './sync.js';
5
5
  export type { SyncResult, SyncOptions, ParsedBlock } from './sync.js';
6
6
  export { MemoryStorage } from './memory-storage.js';
7
7
  export { SQLiteStorage } from './sqlite-storage.js';
8
+ export { LocalAppStorage, defaultLocalAppsDbPath, } from './local-app-storage.js';
9
+ export type { LocalAiPin, CreateLocalAiPinInput, LocalAiPinRefreshCadence, LocalAiPinReviewStatus, LocalAppVisibility, } from './local-app-storage.js';
8
10
  export { ManifestCache } from './manifest-cache.js';
9
11
  export type { TrackedFile, CacheHit, CacheMiss, CacheLookup, ManifestCacheOptions, } from './manifest-cache.js';
10
12
  export { PersonaRegistry, defaultPersonaRegistry, personaFromMember, OWNER_DEFAULT, } from './persona.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,WAAW,EACX,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,eAAe,EACf,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,UAAU,EACV,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,WAAW,EACX,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export { VersionManager } from './version-manager.js';
3
3
  export { RegistrySync } from './sync.js';
4
4
  export { MemoryStorage } from './memory-storage.js';
5
5
  export { SQLiteStorage } from './sqlite-storage.js';
6
+ export { LocalAppStorage, defaultLocalAppsDbPath, } from './local-app-storage.js';
6
7
  export { ManifestCache } from './manifest-cache.js';
7
8
  // Persona registry — runtime active-user state used by the governance and
8
9
  // RLS layers. The Apps/Dashboards file format itself lives in dql-core
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AASpD,0EAA0E;AAC1E,uEAAuE;AACvE,mEAAmE;AACnE,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,0EAA0E;AAC1E,yBAAyB;AACzB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,eAAe,EACf,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AASpD,0EAA0E;AAC1E,uEAAuE;AACvE,mEAAmE;AACnE,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,0EAA0E;AAC1E,yBAAyB;AACzB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,57 @@
1
+ export type LocalAppVisibility = 'mine' | 'shared' | 'template';
2
+ export type LocalAiPinRefreshCadence = 'none' | 'daily';
3
+ export type LocalAiPinReviewStatus = 'needs_review' | 'draft_created' | 'certified' | 'rejected';
4
+ export interface LocalAiPin {
5
+ id: string;
6
+ appId: string;
7
+ dashboardId: string;
8
+ tileId?: string;
9
+ title: string;
10
+ answer: string;
11
+ sql?: string;
12
+ sourceTier?: string;
13
+ certification: 'certified' | 'ai_generated';
14
+ reviewStatus: LocalAiPinReviewStatus;
15
+ refreshCadence: LocalAiPinRefreshCadence;
16
+ chartConfig?: Record<string, unknown>;
17
+ result?: unknown;
18
+ citations?: unknown[];
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ lastRefreshedAt?: string;
22
+ lastRefreshError?: string;
23
+ promotedBlockPath?: string;
24
+ }
25
+ export interface CreateLocalAiPinInput {
26
+ id?: string;
27
+ appId: string;
28
+ dashboardId: string;
29
+ tileId?: string;
30
+ title: string;
31
+ answer: string;
32
+ sql?: string;
33
+ sourceTier?: string;
34
+ certification?: 'certified' | 'ai_generated';
35
+ reviewStatus?: LocalAiPinReviewStatus;
36
+ refreshCadence?: LocalAiPinRefreshCadence;
37
+ chartConfig?: Record<string, unknown>;
38
+ result?: unknown;
39
+ citations?: unknown[];
40
+ }
41
+ export declare function defaultLocalAppsDbPath(projectRoot: string): string;
42
+ /**
43
+ * Local-only App state. Shared Apps remain file-backed under apps/<id>/;
44
+ * this store is intentionally for personal/private overlays and AI pins.
45
+ */
46
+ export declare class LocalAppStorage {
47
+ private db;
48
+ constructor(dbPath: string);
49
+ close(): void;
50
+ createAiPin(input: CreateLocalAiPinInput): LocalAiPin;
51
+ getAiPin(id: string): LocalAiPin | null;
52
+ listAiPins(appId?: string, dashboardId?: string): LocalAiPin[];
53
+ updateAiPinResult(id: string, result: unknown, error?: string): LocalAiPin | null;
54
+ markAiPinPromoted(id: string, blockPath: string): LocalAiPin | null;
55
+ private initSchema;
56
+ }
57
+ //# sourceMappingURL=local-app-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-app-storage.d.ts","sourceRoot":"","sources":["../src/local-app-storage.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAChE,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,OAAO,CAAC;AACxD,MAAM,MAAM,sBAAsB,GAAG,cAAc,GAAG,eAAe,GAAG,WAAW,GAAG,UAAU,CAAC;AAEjG,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,WAAW,GAAG,cAAc,CAAC;IAC5C,YAAY,EAAE,sBAAsB,CAAC;IACrC,cAAc,EAAE,wBAAwB,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC;IAC7C,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAO1B,KAAK,IAAI,IAAI;IAIb,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,UAAU;IA+CrD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAKvC,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAgB9D,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAUjF,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAUnE,OAAO,CAAC,UAAU;CA0DnB"}
@@ -0,0 +1,191 @@
1
+ import Database from 'better-sqlite3';
2
+ import { dirname } from 'node:path';
3
+ import { mkdirSync } from 'node:fs';
4
+ export function defaultLocalAppsDbPath(projectRoot) {
5
+ return `${projectRoot}/.dql/local/apps.sqlite`;
6
+ }
7
+ /**
8
+ * Local-only App state. Shared Apps remain file-backed under apps/<id>/;
9
+ * this store is intentionally for personal/private overlays and AI pins.
10
+ */
11
+ export class LocalAppStorage {
12
+ db;
13
+ constructor(dbPath) {
14
+ mkdirSync(dirname(dbPath), { recursive: true });
15
+ this.db = new Database(dbPath);
16
+ this.db.pragma('journal_mode = WAL');
17
+ this.initSchema();
18
+ }
19
+ close() {
20
+ this.db.close();
21
+ }
22
+ createAiPin(input) {
23
+ const now = new Date().toISOString();
24
+ const pin = {
25
+ id: input.id ?? `pin_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
26
+ appId: input.appId,
27
+ dashboardId: input.dashboardId,
28
+ tileId: input.tileId,
29
+ title: input.title,
30
+ answer: input.answer,
31
+ sql: input.sql,
32
+ sourceTier: input.sourceTier,
33
+ certification: input.certification ?? 'ai_generated',
34
+ reviewStatus: input.reviewStatus ?? 'needs_review',
35
+ refreshCadence: input.refreshCadence ?? 'none',
36
+ chartConfig: input.chartConfig,
37
+ result: input.result,
38
+ citations: input.citations,
39
+ createdAt: now,
40
+ updatedAt: now,
41
+ };
42
+ this.db.prepare(`
43
+ INSERT INTO ai_pins (
44
+ id, app_id, dashboard_id, tile_id, title, answer, sql, source_tier,
45
+ certification, review_status, refresh_cadence, chart_config, result,
46
+ citations, created_at, updated_at
47
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
48
+ `).run(pin.id, pin.appId, pin.dashboardId, pin.tileId ?? null, pin.title, pin.answer, pin.sql ?? null, pin.sourceTier ?? null, pin.certification, pin.reviewStatus, pin.refreshCadence, json(pin.chartConfig), json(pin.result), json(pin.citations ?? []), pin.createdAt, pin.updatedAt);
49
+ return pin;
50
+ }
51
+ getAiPin(id) {
52
+ const row = this.db.prepare('SELECT * FROM ai_pins WHERE id = ?').get(id);
53
+ return row ? rowToAiPin(row) : null;
54
+ }
55
+ listAiPins(appId, dashboardId) {
56
+ const clauses = [];
57
+ const params = [];
58
+ if (appId) {
59
+ clauses.push('app_id = ?');
60
+ params.push(appId);
61
+ }
62
+ if (dashboardId) {
63
+ clauses.push('dashboard_id = ?');
64
+ params.push(dashboardId);
65
+ }
66
+ const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
67
+ const rows = this.db.prepare(`SELECT * FROM ai_pins ${where} ORDER BY updated_at DESC`).all(...params);
68
+ return rows.map(rowToAiPin);
69
+ }
70
+ updateAiPinResult(id, result, error) {
71
+ const now = new Date().toISOString();
72
+ this.db.prepare(`
73
+ UPDATE ai_pins
74
+ SET result = ?, last_refreshed_at = ?, last_refresh_error = ?, updated_at = ?
75
+ WHERE id = ?
76
+ `).run(json(result), now, error ?? null, now, id);
77
+ return this.getAiPin(id);
78
+ }
79
+ markAiPinPromoted(id, blockPath) {
80
+ const now = new Date().toISOString();
81
+ this.db.prepare(`
82
+ UPDATE ai_pins
83
+ SET review_status = 'draft_created', promoted_block_path = ?, updated_at = ?
84
+ WHERE id = ?
85
+ `).run(blockPath, now, id);
86
+ return this.getAiPin(id);
87
+ }
88
+ initSchema() {
89
+ this.db.exec(`
90
+ CREATE TABLE IF NOT EXISTS personal_apps (
91
+ id TEXT PRIMARY KEY,
92
+ name TEXT NOT NULL,
93
+ domain TEXT NOT NULL,
94
+ description TEXT,
95
+ visibility TEXT NOT NULL DEFAULT 'mine',
96
+ payload TEXT NOT NULL DEFAULT '{}',
97
+ created_at TEXT NOT NULL,
98
+ updated_at TEXT NOT NULL
99
+ );
100
+
101
+ CREATE TABLE IF NOT EXISTS personal_dashboards (
102
+ id TEXT NOT NULL,
103
+ app_id TEXT NOT NULL,
104
+ title TEXT NOT NULL,
105
+ payload TEXT NOT NULL DEFAULT '{}',
106
+ created_at TEXT NOT NULL,
107
+ updated_at TEXT NOT NULL,
108
+ PRIMARY KEY (app_id, id)
109
+ );
110
+
111
+ CREATE TABLE IF NOT EXISTS layout_overrides (
112
+ app_id TEXT NOT NULL,
113
+ dashboard_id TEXT NOT NULL,
114
+ user_id TEXT NOT NULL DEFAULT 'local',
115
+ layout TEXT NOT NULL,
116
+ updated_at TEXT NOT NULL,
117
+ PRIMARY KEY (app_id, dashboard_id, user_id)
118
+ );
119
+
120
+ CREATE TABLE IF NOT EXISTS ai_pins (
121
+ id TEXT PRIMARY KEY,
122
+ app_id TEXT NOT NULL,
123
+ dashboard_id TEXT NOT NULL,
124
+ tile_id TEXT,
125
+ title TEXT NOT NULL,
126
+ answer TEXT NOT NULL,
127
+ sql TEXT,
128
+ source_tier TEXT,
129
+ certification TEXT NOT NULL,
130
+ review_status TEXT NOT NULL,
131
+ refresh_cadence TEXT NOT NULL DEFAULT 'none',
132
+ chart_config TEXT,
133
+ result TEXT,
134
+ citations TEXT,
135
+ created_at TEXT NOT NULL,
136
+ updated_at TEXT NOT NULL,
137
+ last_refreshed_at TEXT,
138
+ last_refresh_error TEXT,
139
+ promoted_block_path TEXT
140
+ );
141
+
142
+ CREATE INDEX IF NOT EXISTS idx_ai_pins_app_dashboard ON ai_pins(app_id, dashboard_id);
143
+ CREATE INDEX IF NOT EXISTS idx_ai_pins_review ON ai_pins(review_status);
144
+ `);
145
+ }
146
+ }
147
+ function rowToAiPin(row) {
148
+ return {
149
+ id: String(row.id),
150
+ appId: String(row.app_id),
151
+ dashboardId: String(row.dashboard_id),
152
+ tileId: optionalString(row.tile_id),
153
+ title: String(row.title),
154
+ answer: String(row.answer),
155
+ sql: optionalString(row.sql),
156
+ sourceTier: optionalString(row.source_tier),
157
+ certification: row.certification === 'certified' ? 'certified' : 'ai_generated',
158
+ reviewStatus: parseReviewStatus(row.review_status),
159
+ refreshCadence: row.refresh_cadence === 'daily' ? 'daily' : 'none',
160
+ chartConfig: parseJson(row.chart_config),
161
+ result: parseJson(row.result),
162
+ citations: parseJson(row.citations) ?? [],
163
+ createdAt: String(row.created_at),
164
+ updatedAt: String(row.updated_at),
165
+ lastRefreshedAt: optionalString(row.last_refreshed_at),
166
+ lastRefreshError: optionalString(row.last_refresh_error),
167
+ promotedBlockPath: optionalString(row.promoted_block_path),
168
+ };
169
+ }
170
+ function parseReviewStatus(value) {
171
+ if (value === 'draft_created' || value === 'certified' || value === 'rejected')
172
+ return value;
173
+ return 'needs_review';
174
+ }
175
+ function optionalString(value) {
176
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
177
+ }
178
+ function json(value) {
179
+ return value === undefined ? null : JSON.stringify(value);
180
+ }
181
+ function parseJson(value) {
182
+ if (typeof value !== 'string' || value.length === 0)
183
+ return undefined;
184
+ try {
185
+ return JSON.parse(value);
186
+ }
187
+ catch {
188
+ return undefined;
189
+ }
190
+ }
191
+ //# sourceMappingURL=local-app-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-app-storage.js","sourceRoot":"","sources":["../src/local-app-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local-app-storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-app-storage.test.d.ts","sourceRoot":"","sources":["../src/local-app-storage.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { mkdtempSync, rmSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { tmpdir } from 'node:os';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { LocalAppStorage } from './local-app-storage.js';
6
+ let dir;
7
+ let store;
8
+ beforeEach(() => {
9
+ dir = mkdtempSync(join(tmpdir(), 'dql-local-apps-'));
10
+ store = new LocalAppStorage(join(dir, '.dql', 'local', 'apps.sqlite'));
11
+ });
12
+ afterEach(() => {
13
+ store.close();
14
+ rmSync(dir, { recursive: true, force: true });
15
+ });
16
+ describe('LocalAppStorage', () => {
17
+ it('stores AI pins and refresh metadata locally', () => {
18
+ const pin = store.createAiPin({
19
+ appId: 'executive-cockpit',
20
+ dashboardId: 'bank-overview',
21
+ title: 'AI summary',
22
+ answer: 'Deposits are growing.',
23
+ sql: 'SELECT 1 AS value',
24
+ chartConfig: { chart: 'single_value' },
25
+ result: { columns: ['value'], rows: [{ value: 1 }], rowCount: 1 },
26
+ });
27
+ expect(pin.reviewStatus).toBe('needs_review');
28
+ expect(store.listAiPins('executive-cockpit', 'bank-overview')).toHaveLength(1);
29
+ const refreshed = store.updateAiPinResult(pin.id, { columns: ['value'], rows: [{ value: 2 }], rowCount: 1 });
30
+ expect(refreshed?.lastRefreshedAt).toBeTruthy();
31
+ expect(refreshed?.lastRefreshError).toBeUndefined();
32
+ const promoted = store.markAiPinPromoted(pin.id, 'apps/executive-cockpit/drafts/ai_summary.dql');
33
+ expect(promoted?.reviewStatus).toBe('draft_created');
34
+ expect(promoted?.promotedBlockPath).toBe('apps/executive-cockpit/drafts/ai_summary.dql');
35
+ });
36
+ });
37
+ //# sourceMappingURL=local-app-storage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-app-storage.test.js","sourceRoot":"","sources":["../src/local-app-storage.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,IAAI,GAAW,CAAC;AAChB,IAAI,KAAsB,CAAC;AAE3B,UAAU,CAAC,GAAG,EAAE;IACd,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACrD,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;AACzE,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC;YAC5B,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EAAE,eAAe;YAC5B,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,uBAAuB;YAC/B,GAAG,EAAE,mBAAmB;YACxB,WAAW,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE;YACtC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;SAClE,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAE/E,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7G,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,aAAa,EAAE,CAAC;QAEpD,MAAM,QAAQ,GAAG,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,8CAA8C,CAAC,CAAC;QACjG,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckcodeailabs/dql-project",
3
- "version": "1.4.4",
3
+ "version": "1.5.1",
4
4
  "description": "DQL project and block registry primitives: block metadata, versions, sync, and storage adapters",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -24,8 +24,8 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "better-sqlite3": "^11.7.0",
28
- "@duckcodeailabs/dql-core": "1.4.4"
27
+ "@duckcodeailabs/dql-core": "^1.5.1",
28
+ "better-sqlite3": "^11.7.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/better-sqlite3": "^7.6.0",