@intentface/latch-drizzle 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter.shared.d.ts.map +1 -1
- package/dist/adapter.shared.js +10 -1
- package/dist/adapter.shared.js.map +1 -1
- package/dist/agent-store.d.ts +10 -0
- package/dist/agent-store.d.ts.map +1 -1
- package/dist/agent-store.js +513 -7
- package/dist/agent-store.js.map +1 -1
- package/dist/agent-versions.smoke.d.ts +2 -0
- package/dist/agent-versions.smoke.d.ts.map +1 -0
- package/dist/agent-versions.smoke.js +53 -0
- package/dist/agent-versions.smoke.js.map +1 -0
- package/dist/agent-versions.smoke.pg.d.ts +2 -0
- package/dist/agent-versions.smoke.pg.d.ts.map +1 -0
- package/dist/agent-versions.smoke.pg.js +53 -0
- package/dist/agent-versions.smoke.pg.js.map +1 -0
- package/dist/agent-versions.smoke.shared.d.ts +38 -0
- package/dist/agent-versions.smoke.shared.d.ts.map +1 -0
- package/dist/agent-versions.smoke.shared.js +299 -0
- package/dist/agent-versions.smoke.shared.js.map +1 -0
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +83 -0
- package/dist/migrate.js.map +1 -1
- package/dist/migrate.pg.d.ts.map +1 -1
- package/dist/migrate.pg.js +83 -0
- package/dist/migrate.pg.js.map +1 -1
- package/dist/schema.d.ts +506 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +97 -0
- package/dist/schema.js.map +1 -1
- package/dist/schema.pg.d.ts +478 -0
- package/dist/schema.pg.d.ts.map +1 -1
- package/dist/schema.pg.js +97 -0
- package/dist/schema.pg.js.map +1 -1
- package/package.json +7 -5
package/dist/migrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA6N7C;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC,CAgBf;AA2CD,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3D"}
|
package/dist/migrate.js
CHANGED
|
@@ -58,6 +58,32 @@ const DDL = [
|
|
|
58
58
|
max_steps INTEGER,
|
|
59
59
|
scope TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
60
60
|
`CREATE UNIQUE INDEX IF NOT EXISTS latch_agents_owner_name ON latch_agents (owner, name)`,
|
|
61
|
+
// Append-only publish history for `latch_agents`. The live row is always a
|
|
62
|
+
// copy of the version its `published_version` names; rollback appends a NEW
|
|
63
|
+
// version carrying an old record, so history is never rewritten.
|
|
64
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_versions (
|
|
65
|
+
id TEXT PRIMARY KEY, owner TEXT NOT NULL, name TEXT NOT NULL, version INTEGER NOT NULL,
|
|
66
|
+
record TEXT NOT NULL, author TEXT, source TEXT,
|
|
67
|
+
changed_fields TEXT, change_message TEXT, created_at INTEGER NOT NULL)`,
|
|
68
|
+
// Backstops the max(version)+1 race: a losing concurrent publish retries.
|
|
69
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS latch_agent_versions_owner_name_version
|
|
70
|
+
ON latch_agent_versions (owner, name, version)`,
|
|
71
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_versions_owner_name_idx
|
|
72
|
+
ON latch_agent_versions (owner, name)`,
|
|
73
|
+
// Who made which version live, and when. Activating an existing version
|
|
74
|
+
// appends no version, so without this a rollback leaves no trace.
|
|
75
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_activations (
|
|
76
|
+
id TEXT PRIMARY KEY, owner TEXT NOT NULL, name TEXT NOT NULL, version INTEGER NOT NULL,
|
|
77
|
+
actor TEXT, source TEXT, created_at INTEGER NOT NULL)`,
|
|
78
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_activations_owner_name_idx
|
|
79
|
+
ON latch_agent_activations (owner, name, created_at)`,
|
|
80
|
+
// One unpublished working copy per (agent, editor) — per PERSON, so two org
|
|
81
|
+
// admins can't overwrite each other's half-written prompt.
|
|
82
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_drafts (
|
|
83
|
+
owner TEXT NOT NULL, name TEXT NOT NULL, editor TEXT NOT NULL,
|
|
84
|
+
record TEXT NOT NULL, base_version INTEGER, updated_at INTEGER NOT NULL,
|
|
85
|
+
PRIMARY KEY (owner, name, editor))`,
|
|
86
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_drafts_owner_idx ON latch_agent_drafts (owner)`,
|
|
61
87
|
`CREATE TABLE IF NOT EXISTS latch_schedules (
|
|
62
88
|
id TEXT PRIMARY KEY, owner TEXT NOT NULL, agent TEXT NOT NULL, identity TEXT,
|
|
63
89
|
cron TEXT, timezone TEXT, prompt TEXT NOT NULL, delivery TEXT,
|
|
@@ -113,6 +139,10 @@ const ALTERS = [
|
|
|
113
139
|
`ALTER TABLE latch_chats ADD COLUMN kind TEXT NOT NULL DEFAULT 'user'`,
|
|
114
140
|
`ALTER TABLE latch_memory_chat_state ADD COLUMN last_extracted_key TEXT`,
|
|
115
141
|
`ALTER TABLE latch_agents ADD COLUMN attached_evals TEXT`,
|
|
142
|
+
`ALTER TABLE latch_agents ADD COLUMN published_version INTEGER`,
|
|
143
|
+
`ALTER TABLE latch_runs ADD COLUMN agent_version INTEGER`,
|
|
144
|
+
`ALTER TABLE latch_agent_versions ADD COLUMN changed_fields TEXT`,
|
|
145
|
+
`ALTER TABLE latch_agent_versions ADD COLUMN change_message TEXT`,
|
|
116
146
|
// AFTER the kind ALTER above — a pre-kind DB can't index the column earlier.
|
|
117
147
|
`CREATE INDEX IF NOT EXISTS latch_chats_sweep_idx ON latch_chats (kind, updated_at)`,
|
|
118
148
|
];
|
|
@@ -133,6 +163,57 @@ function isColumnExists(error) {
|
|
|
133
163
|
}
|
|
134
164
|
return false;
|
|
135
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Data backfills. Run AFTER `ALTERS` (they reference columns the ALTERs add)
|
|
168
|
+
* and written to be idempotent, so every `migrate()` can re-run them safely.
|
|
169
|
+
*/
|
|
170
|
+
const BACKFILL = [
|
|
171
|
+
// Every pre-existing agent becomes v1, so the prompt that was already live is
|
|
172
|
+
// a rollback target. Without this the FIRST publish would create v1 from the
|
|
173
|
+
// NEW content and the running prompt would be lost for good — the exact
|
|
174
|
+
// failure version history exists to prevent. `WHERE NOT EXISTS` makes it a
|
|
175
|
+
// no-op once an agent has any version.
|
|
176
|
+
//
|
|
177
|
+
// `json(col)` embeds the JSON columns as JSON rather than as a quoted string.
|
|
178
|
+
// `max_steps` is stored column-encoded (NULL=default, 0=unlimited, N=cap) and
|
|
179
|
+
// is decoded here to its `AgentRecord` form.
|
|
180
|
+
`INSERT INTO latch_agent_versions (id, owner, name, version, record, author, source, created_at)
|
|
181
|
+
SELECT 'agv_' || lower(hex(randomblob(10))), a.owner, a.name, 1,
|
|
182
|
+
json_object(
|
|
183
|
+
'name', a.name,
|
|
184
|
+
'title', a.title,
|
|
185
|
+
'description', a.description,
|
|
186
|
+
'modelId', a.model_id,
|
|
187
|
+
'instructions', a.instructions,
|
|
188
|
+
'connections', json(a.connections),
|
|
189
|
+
'tools', json(a.tools),
|
|
190
|
+
'exec', json(a.exec),
|
|
191
|
+
'subagents', json(a.subagents),
|
|
192
|
+
'attachedEvals', json(a.attached_evals),
|
|
193
|
+
'maxSteps', CASE WHEN a.max_steps IS NULL THEN NULL
|
|
194
|
+
WHEN a.max_steps = 0 THEN 'unlimited'
|
|
195
|
+
ELSE a.max_steps END,
|
|
196
|
+
'scope', a.scope),
|
|
197
|
+
NULL, 'backfill', a.created_at
|
|
198
|
+
FROM latch_agents a
|
|
199
|
+
WHERE NOT EXISTS (SELECT 1 FROM latch_agent_versions v
|
|
200
|
+
WHERE v.owner = a.owner AND v.name = a.name)`,
|
|
201
|
+
// Point every live row at its version. Only fills NULLs, so a row that has
|
|
202
|
+
// published since the backfill keeps its real version.
|
|
203
|
+
`UPDATE latch_agents SET published_version = (
|
|
204
|
+
SELECT MAX(v.version) FROM latch_agent_versions v
|
|
205
|
+
WHERE v.owner = latch_agents.owner AND v.name = latch_agents.name)
|
|
206
|
+
WHERE published_version IS NULL`,
|
|
207
|
+
// ...and record that activation, so the publish timeline is complete from the
|
|
208
|
+
// first row rather than starting at whenever this feature shipped.
|
|
209
|
+
`INSERT INTO latch_agent_activations (id, owner, name, version, actor, source, created_at)
|
|
210
|
+
SELECT 'aga_' || lower(hex(randomblob(10))), a.owner, a.name, a.published_version,
|
|
211
|
+
NULL, 'backfill', a.created_at
|
|
212
|
+
FROM latch_agents a
|
|
213
|
+
WHERE a.published_version IS NOT NULL
|
|
214
|
+
AND NOT EXISTS (SELECT 1 FROM latch_agent_activations x
|
|
215
|
+
WHERE x.owner = a.owner AND x.name = a.name)`,
|
|
216
|
+
];
|
|
136
217
|
/**
|
|
137
218
|
* Run the schema against any executor — a driver-agnostic seam so a consumer on
|
|
138
219
|
* a non-libsql driver (e.g. better-sqlite3's `db.run`) can create the tables
|
|
@@ -157,6 +238,8 @@ export async function migrateWith(exec) {
|
|
|
157
238
|
throw error;
|
|
158
239
|
}
|
|
159
240
|
}
|
|
241
|
+
for (const stmt of BACKFILL)
|
|
242
|
+
await exec(stmt);
|
|
160
243
|
}
|
|
161
244
|
/**
|
|
162
245
|
* One-off upgrade for DBs created before `latch_messages` moved to a composite
|
package/dist/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAEA,wEAAwE;AACxE,MAAM,GAAG,GAAG;IACV;;;+DAG6D;IAC7D,yEAAyE;IACzE,0EAA0E;IAC1E,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,mEAAmE;IACnE,4EAA4E;IAC5E,0EAA0E;IAC1E;;;gCAG8B;IAC9B,gGAAgG;IAChG;;;;;;;oDAOkD;IAClD,wEAAwE;IACxE,2FAA2F;IAC3F,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E;;;;;;iFAM+E;IAC/E,kHAAkH;IAClH;;;;sDAIoD;IACpD,yEAAyE;IACzE;;;+DAG6D;IAC7D,6EAA6E;IAC7E,uEAAuE;IACvE,+DAA+D;IAC/D;;;;;oFAKkF;IAClF,yFAAyF;IACzF;;;;;;kCAMgC;IAChC,iFAAiF;IACjF,8FAA8F;IAC9F,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,kEAAkE;IAClE;;;;;+DAK6D;IAC7D,qGAAqG;IACrG;;;;;;+DAM6D;IAC7D,+GAA+G;IAC/G;;;yCAGuC;IACvC;;;;iDAI+C;IAC/C,+EAA+E;IAC/E,sGAAsG;CACvG,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,GAAG;IACb,sDAAsD;IACtD,sDAAsD;IACtD,uDAAuD;IACvD,0DAA0D;IAC1D,mEAAmE;IACnE,oEAAoE;IACpE,6CAA6C;IAC7C,mDAAmD;IACnD,8DAA8D;IAC9D,+DAA+D;IAC/D,sEAAsE;IACtE,wEAAwE;IACxE,yDAAyD;IACzD,6EAA6E;IAC7E,oFAAoF;CACrF,CAAC;AAEF;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,GAAY,KAAK,CAAC;IACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,2CAA2C,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3E,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAiD;IAEjD,KAAK,MAAM,IAAI,IAAI,GAAG;QAAE,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uEAAuE;YACvE,yEAAyE;YACzE,mEAAmE;YACnE,2EAA2E;YAC3E,sEAAsE;YACtE,gEAAgE;YAChE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;QAC1C,CAAC;IACH,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/migrate.pg.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.pg.d.ts","sourceRoot":"","sources":["../src/migrate.pg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.pg.d.ts","sourceRoot":"","sources":["../src/migrate.pg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAsMtD,wBAAsB,eAAe,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF"}
|
package/dist/migrate.pg.js
CHANGED
|
@@ -54,6 +54,32 @@ const DDL = [
|
|
|
54
54
|
max_steps INTEGER,
|
|
55
55
|
scope TEXT NOT NULL, created_at BIGINT NOT NULL, updated_at BIGINT NOT NULL)`,
|
|
56
56
|
`CREATE UNIQUE INDEX IF NOT EXISTS latch_agents_owner_name ON latch_agents (owner, name)`,
|
|
57
|
+
// Append-only publish history for `latch_agents`. The live row is always a
|
|
58
|
+
// copy of the version its `published_version` names; rollback appends a NEW
|
|
59
|
+
// version carrying an old record, so history is never rewritten.
|
|
60
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_versions (
|
|
61
|
+
id TEXT PRIMARY KEY, owner TEXT NOT NULL, name TEXT NOT NULL, version INTEGER NOT NULL,
|
|
62
|
+
record JSONB NOT NULL, author TEXT, source TEXT,
|
|
63
|
+
changed_fields JSONB, change_message TEXT, created_at BIGINT NOT NULL)`,
|
|
64
|
+
// Backstops the max(version)+1 race: a losing concurrent publish retries.
|
|
65
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS latch_agent_versions_owner_name_version
|
|
66
|
+
ON latch_agent_versions (owner, name, version)`,
|
|
67
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_versions_owner_name_idx
|
|
68
|
+
ON latch_agent_versions (owner, name)`,
|
|
69
|
+
// Who made which version live, and when. Activating an existing version
|
|
70
|
+
// appends no version, so without this a rollback leaves no trace.
|
|
71
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_activations (
|
|
72
|
+
id TEXT PRIMARY KEY, owner TEXT NOT NULL, name TEXT NOT NULL, version INTEGER NOT NULL,
|
|
73
|
+
actor TEXT, source TEXT, created_at BIGINT NOT NULL)`,
|
|
74
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_activations_owner_name_idx
|
|
75
|
+
ON latch_agent_activations (owner, name, created_at)`,
|
|
76
|
+
// One unpublished working copy per (agent, editor) — per PERSON, so two org
|
|
77
|
+
// admins can't overwrite each other's half-written prompt.
|
|
78
|
+
`CREATE TABLE IF NOT EXISTS latch_agent_drafts (
|
|
79
|
+
owner TEXT NOT NULL, name TEXT NOT NULL, editor TEXT NOT NULL,
|
|
80
|
+
record JSONB NOT NULL, base_version INTEGER, updated_at BIGINT NOT NULL,
|
|
81
|
+
PRIMARY KEY (owner, name, editor))`,
|
|
82
|
+
`CREATE INDEX IF NOT EXISTS latch_agent_drafts_owner_idx ON latch_agent_drafts (owner)`,
|
|
57
83
|
`CREATE TABLE IF NOT EXISTS latch_schedules (
|
|
58
84
|
id TEXT PRIMARY KEY, owner TEXT NOT NULL, agent TEXT NOT NULL, identity JSONB,
|
|
59
85
|
cron TEXT, timezone TEXT, prompt TEXT NOT NULL, delivery JSONB,
|
|
@@ -108,13 +134,70 @@ const ALTERS = [
|
|
|
108
134
|
`ALTER TABLE latch_chats ADD COLUMN IF NOT EXISTS kind TEXT NOT NULL DEFAULT 'user'`,
|
|
109
135
|
`ALTER TABLE latch_memory_chat_state ADD COLUMN IF NOT EXISTS last_extracted_key TEXT`,
|
|
110
136
|
`ALTER TABLE latch_agents ADD COLUMN IF NOT EXISTS attached_evals JSONB`,
|
|
137
|
+
`ALTER TABLE latch_agents ADD COLUMN IF NOT EXISTS published_version INTEGER`,
|
|
138
|
+
`ALTER TABLE latch_runs ADD COLUMN IF NOT EXISTS agent_version INTEGER`,
|
|
139
|
+
`ALTER TABLE latch_agent_versions ADD COLUMN IF NOT EXISTS changed_fields JSONB`,
|
|
140
|
+
`ALTER TABLE latch_agent_versions ADD COLUMN IF NOT EXISTS change_message TEXT`,
|
|
111
141
|
// AFTER the kind ALTER above — a pre-kind DB can't index the column earlier.
|
|
112
142
|
`CREATE INDEX IF NOT EXISTS latch_chats_sweep_idx ON latch_chats (kind, updated_at)`,
|
|
113
143
|
];
|
|
144
|
+
/**
|
|
145
|
+
* Data backfills. Run AFTER `ALTERS` (they reference columns the ALTERs add)
|
|
146
|
+
* and written to be idempotent, so every migrate can re-run them safely.
|
|
147
|
+
*/
|
|
148
|
+
const BACKFILL = [
|
|
149
|
+
// Every pre-existing agent becomes v1, so the prompt that was already live is
|
|
150
|
+
// a rollback target. Without this the FIRST publish would create v1 from the
|
|
151
|
+
// NEW content and the running prompt would be lost for good — the exact
|
|
152
|
+
// failure version history exists to prevent. `WHERE NOT EXISTS` makes it a
|
|
153
|
+
// no-op once an agent has any version.
|
|
154
|
+
//
|
|
155
|
+
// `max_steps` is stored column-encoded (NULL=default, 0=unlimited, N=cap) and
|
|
156
|
+
// is decoded here to its `AgentRecord` form. `to_jsonb` on the integer keeps
|
|
157
|
+
// the numeric case a JSON number rather than a string.
|
|
158
|
+
`INSERT INTO latch_agent_versions (id, owner, name, version, record, author, source, created_at)
|
|
159
|
+
SELECT 'agv_' || replace(gen_random_uuid()::text, '-', ''), a.owner, a.name, 1,
|
|
160
|
+
jsonb_build_object(
|
|
161
|
+
'name', a.name,
|
|
162
|
+
'title', a.title,
|
|
163
|
+
'description', a.description,
|
|
164
|
+
'modelId', a.model_id,
|
|
165
|
+
'instructions', a.instructions,
|
|
166
|
+
'connections', a.connections,
|
|
167
|
+
'tools', a.tools,
|
|
168
|
+
'exec', a.exec,
|
|
169
|
+
'subagents', a.subagents,
|
|
170
|
+
'attachedEvals', a.attached_evals,
|
|
171
|
+
'maxSteps', CASE WHEN a.max_steps IS NULL THEN NULL
|
|
172
|
+
WHEN a.max_steps = 0 THEN to_jsonb('unlimited'::text)
|
|
173
|
+
ELSE to_jsonb(a.max_steps) END,
|
|
174
|
+
'scope', a.scope),
|
|
175
|
+
NULL, 'backfill', a.created_at
|
|
176
|
+
FROM latch_agents a
|
|
177
|
+
WHERE NOT EXISTS (SELECT 1 FROM latch_agent_versions v
|
|
178
|
+
WHERE v.owner = a.owner AND v.name = a.name)`,
|
|
179
|
+
// Point every live row at its version. Only fills NULLs, so a row that has
|
|
180
|
+
// published since the backfill keeps its real version.
|
|
181
|
+
`UPDATE latch_agents SET published_version = (
|
|
182
|
+
SELECT MAX(v.version) FROM latch_agent_versions v
|
|
183
|
+
WHERE v.owner = latch_agents.owner AND v.name = latch_agents.name)
|
|
184
|
+
WHERE published_version IS NULL`,
|
|
185
|
+
// ...and record that activation, so the publish timeline is complete from the
|
|
186
|
+
// first row rather than starting at whenever this feature shipped.
|
|
187
|
+
`INSERT INTO latch_agent_activations (id, owner, name, version, actor, source, created_at)
|
|
188
|
+
SELECT 'aga_' || replace(gen_random_uuid()::text, '-', ''), a.owner, a.name,
|
|
189
|
+
a.published_version, NULL, 'backfill', a.created_at
|
|
190
|
+
FROM latch_agents a
|
|
191
|
+
WHERE a.published_version IS NOT NULL
|
|
192
|
+
AND NOT EXISTS (SELECT 1 FROM latch_agent_activations x
|
|
193
|
+
WHERE x.owner = a.owner AND x.name = a.name)`,
|
|
194
|
+
];
|
|
114
195
|
export async function migratePostgres(db) {
|
|
115
196
|
for (const stmt of DDL)
|
|
116
197
|
await db.execute(sql.raw(stmt));
|
|
117
198
|
for (const stmt of ALTERS)
|
|
118
199
|
await db.execute(sql.raw(stmt));
|
|
200
|
+
for (const stmt of BACKFILL)
|
|
201
|
+
await db.execute(sql.raw(stmt));
|
|
119
202
|
}
|
|
120
203
|
//# sourceMappingURL=migrate.pg.js.map
|
package/dist/migrate.pg.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.pg.js","sourceRoot":"","sources":["../src/migrate.pg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC,MAAM,GAAG,GAAG;IACV;;;6DAG2D;IAC3D,yEAAyE;IACzE,0EAA0E;IAC1E,6EAA6E;IAC7E,uEAAuE;IACvE,qEAAqE;IACrE,kEAAkE;IAClE;;;gCAG8B;IAC9B,gGAAgG;IAChG;;;;;;;kDAOgD;IAChD,wEAAwE;IACxE,2FAA2F;IAC3F,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E;;;;;;iFAM+E;IAC/E,kHAAkH;IAClH;;;;iEAI+D;IAC/D,yEAAyE;IACzE;;;6DAG2D;IAC3D,6EAA6E;IAC7E;;;;;kFAKgF;IAChF,yFAAyF;IACzF;;;;;;iCAM+B;IAC/B,iFAAiF;IACjF,8FAA8F;IAC9F,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,kEAAkE;IAClE;;;;;6DAK2D;IAC3D,qGAAqG;IACrG;;;;;;6DAM2D;IAC3D,+GAA+G;IAC/G;;;yCAGuC;IACvC;;;;iDAI+C;IAC/C,wGAAwG;CACzG,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,GAAG;IACb,oEAAoE;IACpE,qEAAqE;IACrE,qEAAqE;IACrE,wEAAwE;IACxE,iFAAiF;IACjF,kFAAkF;IAClF,2DAA2D;IAC3D,iEAAiE;IACjE,4EAA4E;IAC5E,6EAA6E;IAC7E,oFAAoF;IACpF,sFAAsF;IACtF,wEAAwE;IACxE,6EAA6E;IAC7E,oFAAoF;CACrF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAA6B;IACjE,KAAK,MAAM,IAAI,IAAI,GAAG;QAAE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,MAAM;QAAE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.pg.js","sourceRoot":"","sources":["../src/migrate.pg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC,MAAM,GAAG,GAAG;IACV;;;6DAG2D;IAC3D,yEAAyE;IACzE,0EAA0E;IAC1E,6EAA6E;IAC7E,uEAAuE;IACvE,qEAAqE;IACrE,kEAAkE;IAClE;;;gCAG8B;IAC9B,gGAAgG;IAChG;;;;;;;kDAOgD;IAChD,wEAAwE;IACxE,2FAA2F;IAC3F,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E;;;;;;iFAM+E;IAC/E,kHAAkH;IAClH;;;;iEAI+D;IAC/D,yEAAyE;IACzE;;;6DAG2D;IAC3D,6EAA6E;IAC7E;;;;;kFAKgF;IAChF,yFAAyF;IACzF,2EAA2E;IAC3E,4EAA4E;IAC5E,iEAAiE;IACjE;;;4EAG0E;IAC1E,0EAA0E;IAC1E;oDACkD;IAClD;2CACyC;IACzC,wEAAwE;IACxE,kEAAkE;IAClE;;0DAEwD;IACxD;0DACwD;IACxD,4EAA4E;IAC5E,2DAA2D;IAC3D;;;wCAGsC;IACtC,uFAAuF;IACvF;;;;;;iCAM+B;IAC/B,iFAAiF;IACjF,8FAA8F;IAC9F,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,kEAAkE;IAClE;;;;;6DAK2D;IAC3D,qGAAqG;IACrG;;;;;;6DAM2D;IAC3D,+GAA+G;IAC/G;;;yCAGuC;IACvC;;;;iDAI+C;IAC/C,wGAAwG;CACzG,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,GAAG;IACb,oEAAoE;IACpE,qEAAqE;IACrE,qEAAqE;IACrE,wEAAwE;IACxE,iFAAiF;IACjF,kFAAkF;IAClF,2DAA2D;IAC3D,iEAAiE;IACjE,4EAA4E;IAC5E,6EAA6E;IAC7E,oFAAoF;IACpF,sFAAsF;IACtF,wEAAwE;IACxE,6EAA6E;IAC7E,uEAAuE;IACvE,gFAAgF;IAChF,+EAA+E;IAC/E,6EAA6E;IAC7E,oFAAoF;CACrF,CAAC;AAEF;;;GAGG;AACH,MAAM,QAAQ,GAAG;IACf,8EAA8E;IAC9E,6EAA6E;IAC7E,wEAAwE;IACxE,2EAA2E;IAC3E,uCAAuC;IACvC,EAAE;IACF,8EAA8E;IAC9E,6EAA6E;IAC7E,uDAAuD;IACvD;;;;;;;;;;;;;;;;;;;;sEAoBoE;IACpE,2EAA2E;IAC3E,uDAAuD;IACvD;;;mCAGiC;IACjC,8EAA8E;IAC9E,mEAAmE;IACnE;;;;;;sEAMoE;CACrE,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAA6B;IACjE,KAAK,MAAM,IAAI,IAAI,GAAG;QAAE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,MAAM;QAAE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,QAAQ;QAAE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/D,CAAC"}
|