@absolutejs/artifacts 0.2.0 → 0.2.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/README.md +40 -0
- package/dist/drizzle.js +24 -13
- package/dist/index.js +253 -12
- package/dist/manifest.js +1 -1
- package/dist/rag.js +2 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/src/manifest.d.ts +9 -0
- package/dist/src/service.d.ts +5 -1
- package/dist/src/store.d.ts +5 -0
- package/dist/src/types.d.ts +81 -1
- package/package.json +1 -1
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
|
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
|
-
|
|
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
|
-
|
|
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
|
};
|
package/dist/index.js
CHANGED
|
@@ -192,6 +192,7 @@ var createArtifactService = (options) => {
|
|
|
192
192
|
const now = () => (options.clock ?? (() => new Date))().toISOString();
|
|
193
193
|
const idFactory = options.idFactory ?? (() => crypto.randomUUID());
|
|
194
194
|
const eventIdFactory = options.eventIdFactory ?? (() => crypto.randomUUID());
|
|
195
|
+
const batchIdFactory = options.batchIdFactory ?? (() => crypto.randomUUID());
|
|
195
196
|
const event = (artifact, type, payload) => ({
|
|
196
197
|
artifactId: artifact.id,
|
|
197
198
|
createdAt: now(),
|
|
@@ -391,6 +392,231 @@ var createArtifactService = (options) => {
|
|
|
391
392
|
throw error;
|
|
392
393
|
}
|
|
393
394
|
},
|
|
395
|
+
stageBatch: async (ownerId, input, stageOptions = {}) => {
|
|
396
|
+
if (input.items.length === 0) {
|
|
397
|
+
throw new ArtifactError("invalid_content", "An artifact batch must contain at least one artifact");
|
|
398
|
+
}
|
|
399
|
+
const keys = input.items.map((item) => item.key.trim());
|
|
400
|
+
if (keys.some((key) => key.length === 0) || new Set(keys).size !== keys.length) {
|
|
401
|
+
throw new ArtifactError("invalid_content", "Artifact batch item keys must be non-empty and unique");
|
|
402
|
+
}
|
|
403
|
+
const bundleId = input.bundleId ?? batchIdFactory();
|
|
404
|
+
const stagedAt = now();
|
|
405
|
+
const sharedEvidence = input.evidence ?? [];
|
|
406
|
+
const staged = [];
|
|
407
|
+
const evidenceJson = (evidence) => evidence.map((reference) => ({
|
|
408
|
+
...reference.capturedAt ? { capturedAt: reference.capturedAt } : {},
|
|
409
|
+
...reference.excerpt ? { excerpt: reference.excerpt } : {},
|
|
410
|
+
...reference.metadata ? { metadata: reference.metadata } : {},
|
|
411
|
+
...reference.sourceId ? { sourceId: reference.sourceId } : {},
|
|
412
|
+
...reference.sourceUrl ? { sourceUrl: reference.sourceUrl } : {}
|
|
413
|
+
}));
|
|
414
|
+
try {
|
|
415
|
+
for (const [index, item] of input.items.entries()) {
|
|
416
|
+
const { assets: assetInputs = [], ...artifactInput } = item.artifact;
|
|
417
|
+
validateAssetInputs(item.artifact.kind, assetInputs);
|
|
418
|
+
const evidence = [...sharedEvidence, ...item.evidence ?? []];
|
|
419
|
+
const provisional = buildRecord(ownerId, {
|
|
420
|
+
...artifactInput,
|
|
421
|
+
metadata: {
|
|
422
|
+
...input.metadata,
|
|
423
|
+
...artifactInput.metadata,
|
|
424
|
+
artifactBatch: {
|
|
425
|
+
bundleId,
|
|
426
|
+
evidence: evidenceJson(evidence),
|
|
427
|
+
itemKey: item.key
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
provenance: {
|
|
431
|
+
...input.provenance,
|
|
432
|
+
...artifactInput.provenance,
|
|
433
|
+
evidence,
|
|
434
|
+
sourceIds: [
|
|
435
|
+
...new Set([
|
|
436
|
+
...input.provenance?.sourceIds ?? [],
|
|
437
|
+
...artifactInput.provenance?.sourceIds ?? [],
|
|
438
|
+
...evidence.flatMap((reference) => reference.sourceId ? [reference.sourceId] : [])
|
|
439
|
+
])
|
|
440
|
+
]
|
|
441
|
+
}
|
|
442
|
+
}, []);
|
|
443
|
+
if (assetInputs.length === 0) {
|
|
444
|
+
staged.push({ evidence, key: item.key, record: provisional });
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const assetStore = requireAssetTransactions();
|
|
448
|
+
const transaction = await assetStore.stage(assetInputs, {
|
|
449
|
+
artifact: provisional,
|
|
450
|
+
idempotencyKey: `artifact-batch:${bundleId}:${index}`
|
|
451
|
+
});
|
|
452
|
+
staged.push({
|
|
453
|
+
evidence,
|
|
454
|
+
key: item.key,
|
|
455
|
+
record: {
|
|
456
|
+
...provisional,
|
|
457
|
+
assets: validateAssets(item.artifact.kind, transaction.references)
|
|
458
|
+
},
|
|
459
|
+
transaction
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
} catch (error) {
|
|
463
|
+
await Promise.allSettled(staged.map((item) => item.transaction?.rollback()));
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
466
|
+
let validationIssues;
|
|
467
|
+
try {
|
|
468
|
+
validationIssues = (await Promise.all((stageOptions.validators ?? []).map((validate) => validate({
|
|
469
|
+
bundleId,
|
|
470
|
+
evidence: sharedEvidence,
|
|
471
|
+
items: staged,
|
|
472
|
+
ownerId
|
|
473
|
+
})))).flat();
|
|
474
|
+
} catch (error) {
|
|
475
|
+
await Promise.allSettled(staged.map((item) => item.transaction?.rollback()));
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
const validation = validationIssues.length === 0 ? { valid: true } : { issues: validationIssues, valid: false };
|
|
479
|
+
let settled;
|
|
480
|
+
const receiptItems = () => staged.map(({ key, record }) => ({
|
|
481
|
+
artifactId: record.id,
|
|
482
|
+
key,
|
|
483
|
+
kind: record.kind,
|
|
484
|
+
revision: record.revision,
|
|
485
|
+
title: record.title
|
|
486
|
+
}));
|
|
487
|
+
const finish = (partial) => {
|
|
488
|
+
settled = {
|
|
489
|
+
bundleId,
|
|
490
|
+
completedAt: now(),
|
|
491
|
+
items: partial.items ?? receiptItems(),
|
|
492
|
+
ownerId,
|
|
493
|
+
stagedAt,
|
|
494
|
+
validation,
|
|
495
|
+
...partial
|
|
496
|
+
};
|
|
497
|
+
return settled;
|
|
498
|
+
};
|
|
499
|
+
const rollbackTransactions = async (candidates = staged) => {
|
|
500
|
+
const failures = [];
|
|
501
|
+
for (const item of candidates) {
|
|
502
|
+
if (!item.transaction)
|
|
503
|
+
continue;
|
|
504
|
+
try {
|
|
505
|
+
await item.transaction.rollback();
|
|
506
|
+
} catch {
|
|
507
|
+
failures.push(item.key);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return failures;
|
|
511
|
+
};
|
|
512
|
+
if (!validation.valid) {
|
|
513
|
+
const failures = await rollbackTransactions();
|
|
514
|
+
finish({
|
|
515
|
+
archivedArtifactIds: [],
|
|
516
|
+
atomic: Boolean(options.store.createBatch),
|
|
517
|
+
error: failures.length === 0 ? "Artifact batch validation failed" : `Artifact batch validation failed; asset rollback failed for: ${failures.join(", ")}`,
|
|
518
|
+
status: failures.length === 0 ? "rolled_back" : "partial_failure"
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
return {
|
|
522
|
+
bundleId,
|
|
523
|
+
commit: async () => {
|
|
524
|
+
if (settled)
|
|
525
|
+
return settled;
|
|
526
|
+
const transactions = staged.flatMap((item) => item.transaction ? [item.transaction] : []);
|
|
527
|
+
const entries = staged.map(({ key, record }) => ({
|
|
528
|
+
events: [
|
|
529
|
+
event(record, "artifact.created", { bundleId, itemKey: key }),
|
|
530
|
+
event(record, "artifact.generated", { bundleId, itemKey: key })
|
|
531
|
+
],
|
|
532
|
+
record
|
|
533
|
+
}));
|
|
534
|
+
if (options.store.createBatch) {
|
|
535
|
+
try {
|
|
536
|
+
for (const transaction of transactions)
|
|
537
|
+
await transaction.commit();
|
|
538
|
+
await options.store.createBatch(entries);
|
|
539
|
+
return finish({
|
|
540
|
+
archivedArtifactIds: [],
|
|
541
|
+
atomic: true,
|
|
542
|
+
status: "committed"
|
|
543
|
+
});
|
|
544
|
+
} catch (error) {
|
|
545
|
+
const failures = await rollbackTransactions();
|
|
546
|
+
return finish({
|
|
547
|
+
archivedArtifactIds: [],
|
|
548
|
+
atomic: true,
|
|
549
|
+
error: error instanceof Error ? error.message : String(error),
|
|
550
|
+
status: failures.length === 0 ? "rolled_back" : "partial_failure"
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if ((input.commitMode ?? "require_atomic") === "require_atomic") {
|
|
555
|
+
const failures = await rollbackTransactions();
|
|
556
|
+
return finish({
|
|
557
|
+
archivedArtifactIds: [],
|
|
558
|
+
atomic: false,
|
|
559
|
+
error: "The configured artifact store does not support atomic batches",
|
|
560
|
+
status: failures.length === 0 ? "rolled_back" : "partial_failure"
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
const created = [];
|
|
564
|
+
try {
|
|
565
|
+
for (const transaction of transactions)
|
|
566
|
+
await transaction.commit();
|
|
567
|
+
for (const [index, entry] of entries.entries()) {
|
|
568
|
+
await options.store.create(entry.record, entry.events);
|
|
569
|
+
created.push(staged[index]);
|
|
570
|
+
}
|
|
571
|
+
return finish({
|
|
572
|
+
archivedArtifactIds: [],
|
|
573
|
+
atomic: false,
|
|
574
|
+
status: "committed"
|
|
575
|
+
});
|
|
576
|
+
} catch (error) {
|
|
577
|
+
const archivedArtifactIds = [];
|
|
578
|
+
const archiveFailures = [];
|
|
579
|
+
for (const item of created) {
|
|
580
|
+
try {
|
|
581
|
+
await service.archive(ownerId, item.record.id);
|
|
582
|
+
archivedArtifactIds.push(item.record.id);
|
|
583
|
+
} catch {
|
|
584
|
+
archiveFailures.push(item.record.id);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
const uncreated = staged.filter((item) => !created.includes(item));
|
|
588
|
+
const rollbackFailures = await rollbackTransactions(uncreated);
|
|
589
|
+
const failed = [...archiveFailures, ...rollbackFailures];
|
|
590
|
+
return finish({
|
|
591
|
+
archivedArtifactIds,
|
|
592
|
+
atomic: false,
|
|
593
|
+
error: error instanceof Error ? error.message : String(error),
|
|
594
|
+
items: receiptItems().map((item) => ({
|
|
595
|
+
...item,
|
|
596
|
+
...archivedArtifactIds.includes(item.artifactId) ? { archived: true } : {}
|
|
597
|
+
})),
|
|
598
|
+
status: failed.length === 0 ? "rolled_back" : "partial_failure"
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
evidence: sharedEvidence,
|
|
603
|
+
items: staged,
|
|
604
|
+
ownerId,
|
|
605
|
+
rollback: async (reason = "Artifact batch rolled back before commit") => {
|
|
606
|
+
if (settled)
|
|
607
|
+
return settled;
|
|
608
|
+
const failures = await rollbackTransactions();
|
|
609
|
+
return finish({
|
|
610
|
+
archivedArtifactIds: [],
|
|
611
|
+
atomic: Boolean(options.store.createBatch),
|
|
612
|
+
error: failures.length === 0 ? reason : `${reason}; asset rollback failed for: ${failures.join(", ")}`,
|
|
613
|
+
status: failures.length === 0 ? "rolled_back" : "partial_failure"
|
|
614
|
+
});
|
|
615
|
+
},
|
|
616
|
+
stagedAt,
|
|
617
|
+
validation
|
|
618
|
+
};
|
|
619
|
+
},
|
|
394
620
|
detach: async (ownerId, artifactId, assetId, expectedRevision) => {
|
|
395
621
|
const current = await get(ownerId, artifactId);
|
|
396
622
|
requireCapability(current, "attach");
|
|
@@ -650,6 +876,21 @@ var createMemoryArtifactStore = (initial = []) => {
|
|
|
650
876
|
for (const event of newEvents)
|
|
651
877
|
events.set(event.id, clone(event));
|
|
652
878
|
},
|
|
879
|
+
createBatch: async (entries) => {
|
|
880
|
+
const ids = entries.map(({ record }) => record.id);
|
|
881
|
+
if (new Set(ids).size !== ids.length) {
|
|
882
|
+
throw new Error("Duplicate artifact id in batch");
|
|
883
|
+
}
|
|
884
|
+
const duplicate = ids.find((id) => records.has(id));
|
|
885
|
+
if (duplicate)
|
|
886
|
+
throw new Error(`Duplicate artifact id: ${duplicate}`);
|
|
887
|
+
for (const { events: newEvents = [], record } of entries) {
|
|
888
|
+
records.set(record.id, clone(record));
|
|
889
|
+
revisions.set(record.id, [clone(record)]);
|
|
890
|
+
for (const event of newEvents)
|
|
891
|
+
events.set(event.id, clone(event));
|
|
892
|
+
}
|
|
893
|
+
},
|
|
653
894
|
get: async (ownerId, artifactId) => {
|
|
654
895
|
const record = records.get(artifactId);
|
|
655
896
|
return record?.ownerId === ownerId ? clone(record) : null;
|
|
@@ -855,17 +1096,17 @@ var createArtifactTools = (options) => ({
|
|
|
855
1096
|
}
|
|
856
1097
|
});
|
|
857
1098
|
export {
|
|
858
|
-
|
|
859
|
-
isJsonValue,
|
|
860
|
-
defineArtifactRegistry,
|
|
861
|
-
createMemoryArtifactStore,
|
|
862
|
-
createMemoryArtifactAssetStore,
|
|
863
|
-
createArtifactTools,
|
|
864
|
-
createArtifactService,
|
|
865
|
-
createArtifactRendererRegistry,
|
|
866
|
-
createArtifactGeneratorRegistry,
|
|
867
|
-
STANDARD_ARTIFACT_KIND_NAMES,
|
|
868
|
-
ArtifactError,
|
|
1099
|
+
ARTIFACT_EVENT_TYPES,
|
|
869
1100
|
ARTIFACT_STATUSES,
|
|
870
|
-
|
|
1101
|
+
ArtifactError,
|
|
1102
|
+
STANDARD_ARTIFACT_KIND_NAMES,
|
|
1103
|
+
createArtifactGeneratorRegistry,
|
|
1104
|
+
createArtifactRendererRegistry,
|
|
1105
|
+
createArtifactService,
|
|
1106
|
+
createArtifactTools,
|
|
1107
|
+
createMemoryArtifactAssetStore,
|
|
1108
|
+
createMemoryArtifactStore,
|
|
1109
|
+
defineArtifactRegistry,
|
|
1110
|
+
isJsonValue,
|
|
1111
|
+
standardArtifactDefinitions
|
|
871
1112
|
};
|
package/dist/manifest.js
CHANGED
package/dist/rag.js
CHANGED
package/dist/src/index.d.ts
CHANGED
|
@@ -13,4 +13,4 @@ export { createArtifactRendererRegistry, type ArtifactRenderer, type ArtifactRen
|
|
|
13
13
|
export { createArtifactService, type ArtifactPublisher, type ArtifactService, type ArtifactServiceOptions, } from "./service";
|
|
14
14
|
export { createMemoryArtifactStore, createMemoryArtifactAssetStore, type ArtifactAssetStore, type ArtifactAssetTransaction, type ArtifactStore, } from "./store";
|
|
15
15
|
export { createArtifactTools, type ArtifactToolDefinition, type ArtifactToolMap, type ArtifactToolOptions, } from "./tools";
|
|
16
|
-
export { ARTIFACT_STATUSES, ARTIFACT_EVENT_TYPES, ArtifactError, isJsonValue, type ArtifactAssetReference, type ArtifactAssetRole, type ArtifactAssetWriteInput, type ArtifactBundleCreateInput, type ArtifactCapability, type ArtifactCreateInput, type ArtifactErrorCode, type ArtifactEvent, type ArtifactEventQuery, type ArtifactEventType, type ArtifactGarbageCollectionResult, type ArtifactIndexingState, type ArtifactIndexingStatus, type ArtifactListQuery, type ArtifactLineageReference, type ArtifactLineageRelation, type ArtifactProvenance, type ArtifactPublication, type ArtifactPublishInput, type ArtifactRecord, type ArtifactRevision, type ArtifactRetentionCandidate, type ArtifactStatus, type ArtifactUpdateInput, type JsonObject, type JsonPrimitive, type JsonValue, } from "./types";
|
|
16
|
+
export { ARTIFACT_STATUSES, ARTIFACT_EVENT_TYPES, ArtifactError, isJsonValue, type ArtifactAssetReference, type ArtifactAssetRole, type ArtifactAssetWriteInput, type ArtifactBatchCommitMode, type ArtifactBatchCompletionReceipt, type ArtifactBatchCreateInput, type ArtifactBatchItemInput, type ArtifactBatchReceiptItem, type ArtifactBatchValidationIssue, type ArtifactBatchValidationResult, type ArtifactBatchValidator, type ArtifactBundleCreateInput, type ArtifactCapability, type ArtifactCreateInput, type ArtifactErrorCode, type ArtifactEvent, type ArtifactEventQuery, type ArtifactEventType, type ArtifactEvidenceReference, type ArtifactGarbageCollectionResult, type ArtifactIndexingState, type ArtifactIndexingStatus, type ArtifactListQuery, type ArtifactLineageReference, type ArtifactLineageRelation, type ArtifactProvenance, type ArtifactPublication, type ArtifactPublishInput, type ArtifactRecord, type ArtifactRevision, type ArtifactRetentionCandidate, type ArtifactStatus, type ArtifactUpdateInput, type JsonObject, type JsonPrimitive, type JsonValue, type StagedArtifactBatch, } from "./types";
|
package/dist/src/manifest.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export declare const manifest: Omit<import("@absolutejs/manifest").PackageManife
|
|
|
9
9
|
}) => Promise<import("./types").ArtifactGarbageCollectionResult>;
|
|
10
10
|
create: (ownerId: string, input: import("./types").ArtifactCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
11
11
|
createBundle: (ownerId: string, input: import("./types").ArtifactBundleCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
12
|
+
stageBatch: (ownerId: string, input: import("./types").ArtifactBatchCreateInput, stageOptions?: {
|
|
13
|
+
validators?: import("./types").ArtifactBatchValidator[];
|
|
14
|
+
}) => Promise<import("./types").StagedArtifactBatch>;
|
|
12
15
|
detach: (ownerId: string, artifactId: string, assetId: string, expectedRevision?: number) => Promise<import("./types").ArtifactRecord>;
|
|
13
16
|
get: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactRecord>;
|
|
14
17
|
getIndexingState: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactIndexingState | null>;
|
|
@@ -44,6 +47,9 @@ export declare const manifest: Omit<import("@absolutejs/manifest").PackageManife
|
|
|
44
47
|
}) => Promise<import("./types").ArtifactGarbageCollectionResult>;
|
|
45
48
|
create: (ownerId: string, input: import("./types").ArtifactCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
46
49
|
createBundle: (ownerId: string, input: import("./types").ArtifactBundleCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
50
|
+
stageBatch: (ownerId: string, input: import("./types").ArtifactBatchCreateInput, stageOptions?: {
|
|
51
|
+
validators?: import("./types").ArtifactBatchValidator[];
|
|
52
|
+
}) => Promise<import("./types").StagedArtifactBatch>;
|
|
47
53
|
detach: (ownerId: string, artifactId: string, assetId: string, expectedRevision?: number) => Promise<import("./types").ArtifactRecord>;
|
|
48
54
|
get: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactRecord>;
|
|
49
55
|
getIndexingState: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactIndexingState | null>;
|
|
@@ -80,6 +86,9 @@ export declare const manifest: Omit<import("@absolutejs/manifest").PackageManife
|
|
|
80
86
|
}) => Promise<import("./types").ArtifactGarbageCollectionResult>;
|
|
81
87
|
create: (ownerId: string, input: import("./types").ArtifactCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
82
88
|
createBundle: (ownerId: string, input: import("./types").ArtifactBundleCreateInput) => Promise<import("./types").ArtifactRecord>;
|
|
89
|
+
stageBatch: (ownerId: string, input: import("./types").ArtifactBatchCreateInput, stageOptions?: {
|
|
90
|
+
validators?: import("./types").ArtifactBatchValidator[];
|
|
91
|
+
}) => Promise<import("./types").StagedArtifactBatch>;
|
|
83
92
|
detach: (ownerId: string, artifactId: string, assetId: string, expectedRevision?: number) => Promise<import("./types").ArtifactRecord>;
|
|
84
93
|
get: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactRecord>;
|
|
85
94
|
getIndexingState: (ownerId: string, artifactId: string) => Promise<import("./types").ArtifactIndexingState | null>;
|
package/dist/src/service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ArtifactKindDefinitions, ArtifactRegistry } from "./registry";
|
|
2
2
|
import type { ArtifactAssetStore, ArtifactStore } from "./store";
|
|
3
|
-
import { type ArtifactAssetReference, type ArtifactAssetWriteInput, type ArtifactBundleCreateInput, type ArtifactCreateInput, type ArtifactEvent, type ArtifactEventQuery, type ArtifactGarbageCollectionResult, type ArtifactIndexingState, type ArtifactIndexingStatus, type ArtifactListQuery, type ArtifactPublishInput, type ArtifactRecord, type ArtifactUpdateInput } from "./types";
|
|
3
|
+
import { type ArtifactAssetReference, type ArtifactAssetWriteInput, type ArtifactBatchCreateInput, type ArtifactBatchValidator, type ArtifactBundleCreateInput, type ArtifactCreateInput, type ArtifactEvent, type ArtifactEventQuery, type ArtifactGarbageCollectionResult, type ArtifactIndexingState, type ArtifactIndexingStatus, type ArtifactListQuery, type ArtifactPublishInput, type ArtifactRecord, type ArtifactUpdateInput, type StagedArtifactBatch } from "./types";
|
|
4
4
|
export type ArtifactPublisher = {
|
|
5
5
|
publish(artifact: ArtifactRecord, options: {
|
|
6
6
|
idempotencyKey: string;
|
|
@@ -16,6 +16,7 @@ export type ArtifactPublisher = {
|
|
|
16
16
|
};
|
|
17
17
|
export type ArtifactServiceOptions<TDefinitions extends ArtifactKindDefinitions = ArtifactKindDefinitions> = {
|
|
18
18
|
assetStore?: ArtifactAssetStore;
|
|
19
|
+
batchIdFactory?: () => string;
|
|
19
20
|
clock?: () => Date;
|
|
20
21
|
eventIdFactory?: () => string;
|
|
21
22
|
idFactory?: () => string;
|
|
@@ -34,6 +35,9 @@ export declare const createArtifactService: <TDefinitions extends ArtifactKindDe
|
|
|
34
35
|
}) => Promise<ArtifactGarbageCollectionResult>;
|
|
35
36
|
create: (ownerId: string, input: ArtifactCreateInput) => Promise<ArtifactRecord>;
|
|
36
37
|
createBundle: (ownerId: string, input: ArtifactBundleCreateInput) => Promise<ArtifactRecord>;
|
|
38
|
+
stageBatch: (ownerId: string, input: ArtifactBatchCreateInput, stageOptions?: {
|
|
39
|
+
validators?: ArtifactBatchValidator[];
|
|
40
|
+
}) => Promise<StagedArtifactBatch>;
|
|
37
41
|
detach: (ownerId: string, artifactId: string, assetId: string, expectedRevision?: number) => Promise<ArtifactRecord>;
|
|
38
42
|
get: (ownerId: string, artifactId: string) => Promise<ArtifactRecord>;
|
|
39
43
|
getIndexingState: (ownerId: string, artifactId: string) => Promise<ArtifactIndexingState | null>;
|
package/dist/src/store.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export type ArtifactAssetStore = {
|
|
|
22
22
|
export type ArtifactStore = {
|
|
23
23
|
/** Persist the current record and its first immutable revision atomically. */
|
|
24
24
|
create(record: ArtifactRecord, events?: ArtifactEvent[]): Promise<void>;
|
|
25
|
+
/** Persist multiple records, first revisions, and events in one transaction. */
|
|
26
|
+
createBatch?(entries: Array<{
|
|
27
|
+
events?: ArtifactEvent[];
|
|
28
|
+
record: ArtifactRecord;
|
|
29
|
+
}>): Promise<void>;
|
|
25
30
|
getIndexingState(ownerId: string, artifactId: string): Promise<ArtifactIndexingState | null>;
|
|
26
31
|
get(ownerId: string, artifactId: string): Promise<ArtifactRecord | null>;
|
|
27
32
|
getRevision(ownerId: string, artifactId: string, revision: number): Promise<ArtifactRevision | null>;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -8,12 +8,20 @@ export declare function isJsonValue(value: unknown): value is JsonValue;
|
|
|
8
8
|
export type ArtifactStatus = (typeof ARTIFACT_STATUSES)[number];
|
|
9
9
|
export type ArtifactCapability = "attach" | "archive" | "edit" | "export" | "preview" | "publish" | "refine";
|
|
10
10
|
export type ArtifactProvenance = {
|
|
11
|
+
evidence?: ArtifactEvidenceReference[];
|
|
11
12
|
lineage?: ArtifactLineageReference[];
|
|
12
13
|
model?: string;
|
|
13
14
|
sourceIds?: string[];
|
|
14
15
|
tool?: string;
|
|
15
16
|
traceId?: string;
|
|
16
17
|
};
|
|
18
|
+
export type ArtifactEvidenceReference = {
|
|
19
|
+
capturedAt?: string;
|
|
20
|
+
excerpt?: string;
|
|
21
|
+
metadata?: JsonObject;
|
|
22
|
+
sourceId?: string;
|
|
23
|
+
sourceUrl?: string;
|
|
24
|
+
};
|
|
17
25
|
export type ArtifactLineageRelation = "derived_from" | "generated_from" | "references" | "replaces";
|
|
18
26
|
export type ArtifactLineageReference = {
|
|
19
27
|
artifactId?: string;
|
|
@@ -122,6 +130,78 @@ export type ArtifactUpdateInput = {
|
|
|
122
130
|
export type ArtifactBundleCreateInput = Omit<ArtifactCreateInput, "assets"> & {
|
|
123
131
|
assets?: ArtifactAssetWriteInput[];
|
|
124
132
|
};
|
|
133
|
+
export type ArtifactBatchItemInput = {
|
|
134
|
+
artifact: ArtifactBundleCreateInput;
|
|
135
|
+
evidence?: ArtifactEvidenceReference[];
|
|
136
|
+
/** Stable caller-defined key used to reconcile a receipt with requested output. */
|
|
137
|
+
key: string;
|
|
138
|
+
};
|
|
139
|
+
export type ArtifactBatchCommitMode = "archive_on_failure" | "require_atomic";
|
|
140
|
+
export type ArtifactBatchCreateInput = {
|
|
141
|
+
bundleId?: string;
|
|
142
|
+
commitMode?: ArtifactBatchCommitMode;
|
|
143
|
+
evidence?: ArtifactEvidenceReference[];
|
|
144
|
+
items: ArtifactBatchItemInput[];
|
|
145
|
+
metadata?: JsonObject;
|
|
146
|
+
provenance?: ArtifactProvenance;
|
|
147
|
+
};
|
|
148
|
+
export type ArtifactBatchValidationIssue = {
|
|
149
|
+
code: string;
|
|
150
|
+
itemKey?: string;
|
|
151
|
+
message: string;
|
|
152
|
+
path?: string;
|
|
153
|
+
};
|
|
154
|
+
export type ArtifactBatchValidationResult = {
|
|
155
|
+
issues?: never;
|
|
156
|
+
valid: true;
|
|
157
|
+
} | {
|
|
158
|
+
issues: ArtifactBatchValidationIssue[];
|
|
159
|
+
valid: false;
|
|
160
|
+
};
|
|
161
|
+
export type ArtifactBatchReceiptItem = {
|
|
162
|
+
artifactId: string;
|
|
163
|
+
archived?: boolean;
|
|
164
|
+
key: string;
|
|
165
|
+
kind: string;
|
|
166
|
+
revision: number;
|
|
167
|
+
title: string;
|
|
168
|
+
};
|
|
169
|
+
export type ArtifactBatchCompletionReceipt = {
|
|
170
|
+
archivedArtifactIds: string[];
|
|
171
|
+
atomic: boolean;
|
|
172
|
+
bundleId: string;
|
|
173
|
+
completedAt: string;
|
|
174
|
+
error?: string;
|
|
175
|
+
items: ArtifactBatchReceiptItem[];
|
|
176
|
+
ownerId: string;
|
|
177
|
+
stagedAt: string;
|
|
178
|
+
status: "committed" | "partial_failure" | "rolled_back";
|
|
179
|
+
validation: ArtifactBatchValidationResult;
|
|
180
|
+
};
|
|
181
|
+
export type ArtifactBatchValidator = (context: {
|
|
182
|
+
bundleId: string;
|
|
183
|
+
evidence: ArtifactEvidenceReference[];
|
|
184
|
+
items: ReadonlyArray<{
|
|
185
|
+
evidence: ArtifactEvidenceReference[];
|
|
186
|
+
key: string;
|
|
187
|
+
record: Readonly<ArtifactRecord>;
|
|
188
|
+
}>;
|
|
189
|
+
ownerId: string;
|
|
190
|
+
}) => ArtifactBatchValidationIssue[] | Promise<ArtifactBatchValidationIssue[]>;
|
|
191
|
+
export type StagedArtifactBatch = {
|
|
192
|
+
bundleId: string;
|
|
193
|
+
commit(): Promise<ArtifactBatchCompletionReceipt>;
|
|
194
|
+
evidence: ArtifactEvidenceReference[];
|
|
195
|
+
items: ReadonlyArray<{
|
|
196
|
+
evidence: ArtifactEvidenceReference[];
|
|
197
|
+
key: string;
|
|
198
|
+
record: Readonly<ArtifactRecord>;
|
|
199
|
+
}>;
|
|
200
|
+
ownerId: string;
|
|
201
|
+
rollback(reason?: string): Promise<ArtifactBatchCompletionReceipt>;
|
|
202
|
+
stagedAt: string;
|
|
203
|
+
validation: ArtifactBatchValidationResult;
|
|
204
|
+
};
|
|
125
205
|
export type ArtifactPublishInput = {
|
|
126
206
|
mode?: "live" | "pinned";
|
|
127
207
|
};
|
|
@@ -133,7 +213,7 @@ export type ArtifactGarbageCollectionResult = {
|
|
|
133
213
|
deleted: ArtifactAssetReference[];
|
|
134
214
|
retained: ArtifactAssetReference[];
|
|
135
215
|
};
|
|
136
|
-
export type ArtifactErrorCode = "asset_store_unavailable" | "asset_transaction_unavailable" | "conflict" | "generator_unavailable" | "invalid_content" | "not_found" | "publisher_unavailable" | "renderer_unavailable" | "unsupported_capability" | "unknown_kind";
|
|
216
|
+
export type ArtifactErrorCode = "asset_store_unavailable" | "asset_transaction_unavailable" | "atomic_batch_unavailable" | "batch_validation_failed" | "conflict" | "generator_unavailable" | "invalid_content" | "not_found" | "publisher_unavailable" | "renderer_unavailable" | "unsupported_capability" | "unknown_kind";
|
|
137
217
|
export declare class ArtifactError extends Error {
|
|
138
218
|
readonly code: ArtifactErrorCode;
|
|
139
219
|
constructor(code: ArtifactErrorCode, message: string);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/artifacts",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Typed, versioned artifacts for AI products — schemas, lifecycle, storage, rendering, publishing, revisions, and agent tools without prescribing a database or host.",
|
|
5
5
|
"author": "Alex Kahn",
|
|
6
6
|
"license": "BUSL-1.1",
|