@absolutejs/artifacts 0.2.0 → 0.3.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/README.md CHANGED
@@ -24,6 +24,7 @@ routes, authorization, UI, or hosting.
24
24
  datasets, code, images, audio, video, email, archives, and generic files
25
25
  - An optional bridge to `@absolutejs/rag` ingestion
26
26
  - Provider-neutral generation registries with atomic multi-file bundles
27
+ - Staged, validate-before-commit multi-artifact batches with completion receipts
27
28
  - Revision-pinned or explicitly live publications
28
29
  - Durable lifecycle events designed for transactional outboxes
29
30
  - Per-revision RAG indexing state and an indexing coordinator
@@ -169,6 +170,45 @@ const report = await artifacts.createBundle("owner-123", {
169
170
  });
170
171
  ```
171
172
 
173
+ When one job must produce several artifacts together, stage the complete batch,
174
+ run domain validators before persistence, and commit it through a store that
175
+ implements `createBatch` (the package Drizzle and memory stores do):
176
+
177
+ ```ts
178
+ const staged = await artifacts.stageBatch(
179
+ "owner-123",
180
+ {
181
+ evidence: [{ sourceId: "research-run-123", sourceUrl: sourceUrl }],
182
+ items: [
183
+ { artifact: worksheetInput, key: "worksheet" },
184
+ { artifact: reportInput, key: "report" },
185
+ ],
186
+ provenance: { tool: "prospecting_mission", traceId: mission.id },
187
+ },
188
+ {
189
+ validators: [
190
+ ({ items }) =>
191
+ validateDomainEvidence(items).map((message) => ({
192
+ code: "evidence_invalid",
193
+ message,
194
+ })),
195
+ ],
196
+ },
197
+ );
198
+
199
+ const receipt = await staged.commit();
200
+ if (receipt.status !== "committed") throw new Error(receipt.error);
201
+ ```
202
+
203
+ Every artifact carries its batch id, item key, evidence, and provenance.
204
+ `commit()` returns the durable reconciliation receipt: artifact ids,
205
+ revisions, atomicity, validation outcome, and any archived compensation. The
206
+ default mode requires an atomic `ArtifactStore.createBatch`. Hosts that cannot
207
+ provide a transaction may explicitly select `archive_on_failure`; completed
208
+ earlier writes are then archived and reported as `rolled_back` or
209
+ `partial_failure`. Calling `rollback()` before commit releases all staged
210
+ asset transactions.
211
+
172
212
  ## Generation
173
213
 
174
214
  Generators are provider-neutral. They return validated structured content and
@@ -192,6 +232,27 @@ const deck = await generators.generate(artifacts, {
192
232
  });
193
233
  ```
194
234
 
235
+ Generators may expose a `validate` function. The bundled
236
+ `validateGeneratedArtifactFormats` validator checks CSV row structure, RFC 822
237
+ headers, ZIP readability, and PPTX package/XML integrity before persistence.
238
+ Generate several independent artifacts with one atomic receipt through the same
239
+ registry:
240
+
241
+ ```ts
242
+ const receipt = await generators.generateBatch(artifacts, {
243
+ ownerId: member.id,
244
+ items: [
245
+ { createdBy: "agent", key: "deck", kind: "presentation", title: "Deck" },
246
+ { createdBy: "agent", key: "email", kind: "email", title: "Email" },
247
+ ],
248
+ provenance: { tool: "campaign_generator" },
249
+ });
250
+ ```
251
+
252
+ Generation validators run after every output is staged and before anything is
253
+ committed. Validation failures return a rolled-back completion receipt keyed to
254
+ the invalid output.
255
+
195
256
  ## RAG ingestion
196
257
 
197
258
  The optional `@absolutejs/artifacts/rag` entry point resolves one current or
@@ -210,7 +271,10 @@ const upsert = await buildRAGUpsertInputFromUploads({ uploads });
210
271
 
211
272
  `createArtifactRAGIndexCoordinator` wraps that conversion with durable
212
273
  `pending`, `indexed`, and `failed` state. It removes document IDs from the
213
- previous indexed revision after the replacement succeeds.
274
+ previous indexed revision after the replacement succeeds. Set `failureMode` to
275
+ `"isolate_uploads"` to index structured content and assets independently. A bad
276
+ asset then produces a typed partial receipt while preserving successful
277
+ document ids; obsolete ids are removed only after a fully successful revision.
214
278
 
215
279
  ## Events and retention
216
280
 
package/dist/drizzle.js CHANGED
@@ -145,6 +145,17 @@ var createDrizzleArtifactStore = (options) => ({
145
145
  if (events.length > 0)
146
146
  await transaction.insert(artifactEvents).values(eventRows(events));
147
147
  }),
148
+ createBatch: (entries) => options.db.transaction(async (transaction) => {
149
+ if (entries.length === 0)
150
+ return;
151
+ for (const { events: events2 = [], record } of entries)
152
+ assertEventsBelongToArtifact(record, events2);
153
+ await transaction.insert(artifactRecords).values(entries.map(({ record }) => recordRow(record)));
154
+ await transaction.insert(artifactRevisions).values(entries.map(({ record }) => revisionRow(record)));
155
+ const events = entries.flatMap((entry) => entry.events ?? []);
156
+ if (events.length > 0)
157
+ await transaction.insert(artifactEvents).values(eventRows(events));
158
+ }),
148
159
  get: async (ownerId, artifactId) => {
149
160
  const [row] = await options.db.select({ document: artifactRecords.document }).from(artifactRecords).where(and(eq(artifactRecords.id, artifactId), eq(artifactRecords.ownerId, ownerId))).limit(1);
150
161
  return row?.document ?? null;
@@ -235,18 +246,18 @@ var createDrizzleArtifactStore = (options) => ({
235
246
  })
236
247
  });
237
248
  export {
238
- createDrizzleArtifactStore,
239
- artifactRevisions,
240
- artifactRecords,
241
- artifactIndexingStates,
242
- artifactEvents,
243
- artifactDrizzleSchema,
244
- ArtifactRevisionSelectSchema,
245
- ArtifactRevisionInsertSchema,
246
- ArtifactRecordSelectSchema,
247
- ArtifactRecordInsertSchema,
248
- ArtifactIndexingStateSelectSchema,
249
- ArtifactIndexingStateInsertSchema,
249
+ ArtifactEventInsertSchema,
250
250
  ArtifactEventSelectSchema,
251
- ArtifactEventInsertSchema
251
+ ArtifactIndexingStateInsertSchema,
252
+ ArtifactIndexingStateSelectSchema,
253
+ ArtifactRecordInsertSchema,
254
+ ArtifactRecordSelectSchema,
255
+ ArtifactRevisionInsertSchema,
256
+ ArtifactRevisionSelectSchema,
257
+ artifactDrizzleSchema,
258
+ artifactEvents,
259
+ artifactIndexingStates,
260
+ artifactRecords,
261
+ artifactRevisions,
262
+ createDrizzleArtifactStore
252
263
  };