@jini-ai/cms 0.3.10 → 0.4.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/CHANGELOG.md +59 -0
- package/README.md +47 -19
- package/dist/content-types/agent-tools.d.ts +3 -56
- package/dist/content-types/agent-tools.js +22 -6
- package/dist/content-types/cleanup.d.ts +18 -13
- package/dist/content-types/cleanup.js +16 -11
- package/dist/content-types/errors.d.ts +57 -24
- package/dist/content-types/errors.js +56 -39
- package/dist/content-types/field-defs.d.ts +8 -4
- package/dist/content-types/field-defs.js +19 -14
- package/dist/content-types/index-provisioning.d.ts +61 -47
- package/dist/content-types/index-provisioning.js +90 -66
- package/dist/content-types/index.d.ts +4 -3
- package/dist/content-types/lifecycle-dispatch.d.ts +11 -5
- package/dist/content-types/lifecycle-dispatch.js +5 -4
- package/dist/content-types/lifecycle.d.ts +23 -18
- package/dist/content-types/lifecycle.js +71 -64
- package/dist/content-types/repo.memory.d.ts +5 -4
- package/dist/content-types/repo.memory.js +3 -2
- package/dist/content-types/tool-registrations.d.ts +6 -8
- package/dist/content-types/tool-registrations.js +24 -28
- package/dist/content-types/types.d.ts +17 -13
- package/dist/content-types/types.js +11 -5
- package/dist/content-types/write-service.d.ts +20 -22
- package/dist/content-types/write-service.js +78 -75
- package/dist/core/authorization.d.ts +15 -0
- package/dist/core/authorization.js +2 -0
- package/dist/core/commands/change-set.d.ts +15 -7
- package/dist/core/commands/command.d.ts +45 -26
- package/dist/core/commands/command.js +73 -63
- package/dist/core/entity-liveness.d.ts +11 -7
- package/dist/core/entity-liveness.js +5 -4
- package/dist/core/index.d.ts +12 -5
- package/dist/core/index.js +10 -4
- package/dist/core/ports.d.ts +25 -24
- package/dist/core/ports.js +1 -0
- package/dist/core/tools/args.d.ts +49 -0
- package/dist/core/tools/args.js +46 -0
- package/dist/core/tools/index.d.ts +3 -0
- package/dist/core/tools/index.js +3 -0
- package/dist/entries/agent-tools.d.ts +1 -73
- package/dist/entries/agent-tools.js +19 -13
- package/dist/entries/errors.d.ts +28 -14
- package/dist/entries/errors.js +17 -11
- package/dist/entries/field-validation.d.ts +5 -3
- package/dist/entries/field-validation.js +7 -5
- package/dist/entries/index.d.ts +2 -2
- package/dist/entries/lifecycle-dispatch.d.ts +5 -2
- package/dist/entries/lifecycle-dispatch.js +2 -1
- package/dist/entries/list.d.ts +4 -2
- package/dist/entries/list.js +4 -3
- package/dist/entries/repo.memory.d.ts +12 -10
- package/dist/entries/repo.memory.js +11 -10
- package/dist/entries/tool-registrations.d.ts +6 -8
- package/dist/entries/tool-registrations.js +42 -41
- package/dist/entries/types.d.ts +0 -7
- package/dist/entries/write-service.d.ts +28 -29
- package/dist/entries/write-service.js +114 -105
- package/dist/http/settings/cms-adapter.d.ts +20 -0
- package/dist/http/settings/cms-adapter.js +124 -0
- package/dist/http/settings/contracts.d.ts +135 -0
- package/dist/http/settings/contracts.js +2 -0
- package/dist/http/settings/http.d.ts +10 -0
- package/dist/http/settings/http.js +211 -0
- package/dist/http/settings/index.d.ts +5 -0
- package/dist/http/settings/index.js +4 -0
- package/dist/http/settings/shared.d.ts +68 -0
- package/dist/http/settings/shared.js +54 -0
- package/dist/http/settings/stream.d.ts +24 -0
- package/dist/http/settings/stream.js +147 -0
- package/dist/media/agent-tools.d.ts +1 -66
- package/dist/media/agent-tools.js +5 -1
- package/dist/media/blob-gc-lock.d.ts +6 -2
- package/dist/media/blob-gc-lock.js +4 -2
- package/dist/media/blob-gc.d.ts +64 -51
- package/dist/media/blob-gc.js +62 -52
- package/dist/media/blob-key.d.ts +1 -1
- package/dist/media/content-type-sniffer.d.ts +3 -1
- package/dist/media/content-type-sniffer.js +1 -1
- package/dist/media/html-attributes.d.ts +9 -5
- package/dist/media/html-attributes.js +8 -6
- package/dist/media/image-transformer.js +1 -1
- package/dist/media/image-transformer.sharp.d.ts +6 -0
- package/dist/media/image-transformer.sharp.js +12 -6
- package/dist/media/import/fetch-image.d.ts +24 -0
- package/dist/media/import/fetch-image.js +137 -0
- package/dist/media/import/index.d.ts +3 -0
- package/dist/media/import/index.js +3 -0
- package/dist/media/import/ports.d.ts +38 -0
- package/dist/media/index.d.ts +7 -1
- package/dist/media/index.js +1 -0
- package/dist/media/media-service.d.ts +14 -10
- package/dist/media/media-service.js +57 -52
- package/dist/media/ports.d.ts +3 -2
- package/dist/media/rendition-service.d.ts +3 -3
- package/dist/media/rendition-service.js +38 -37
- package/dist/media/repo.memory.d.ts +18 -7
- package/dist/media/repo.memory.js +12 -6
- package/dist/media/tool-registrations.d.ts +16 -15
- package/dist/media/tool-registrations.js +84 -72
- package/dist/media/transform-lock.d.ts +22 -12
- package/dist/media/transform-lock.js +14 -13
- package/dist/media/transform-registry.d.ts +3 -3
- package/dist/media/transform-registry.js +19 -18
- package/dist/media/transform-types.d.ts +8 -3
- package/dist/media/transform-types.js +10 -5
- package/dist/media/types.d.ts +21 -4
- package/dist/media/types.js +15 -2
- package/dist/navigation/agent-tools.d.ts +1 -80
- package/dist/navigation/agent-tools.js +15 -3
- package/dist/navigation/contracts.d.ts +1 -1
- package/dist/navigation/index.d.ts +2 -2
- package/dist/navigation/menu-service.d.ts +57 -40
- package/dist/navigation/menu-service.js +80 -69
- package/dist/navigation/ports.d.ts +1 -1
- package/dist/navigation/read-model.d.ts +3 -1
- package/dist/navigation/read-model.js +2 -2
- package/dist/navigation/reconcile.d.ts +2 -2
- package/dist/navigation/reconcile.js +2 -1
- package/dist/navigation/repo.memory.d.ts +7 -3
- package/dist/navigation/repo.memory.js +4 -2
- package/dist/navigation/resolver.d.ts +4 -1
- package/dist/navigation/resolver.js +1 -1
- package/dist/navigation/tool-registrations.d.ts +6 -8
- package/dist/navigation/tool-registrations.js +44 -42
- package/dist/navigation/types.d.ts +1 -1
- package/dist/presentation/presentation.d.ts +11 -3
- package/dist/presentation/presentation.js +13 -6
- package/dist/presentation/repo.memory.d.ts +6 -2
- package/dist/presentation/repo.memory.js +3 -2
- package/dist/settings/agent-tools.d.ts +2 -75
- package/dist/settings/agent-tools.js +49 -45
- package/dist/settings/agent-value-write-tools.d.ts +22 -0
- package/dist/settings/agent-value-write-tools.js +154 -0
- package/dist/settings/agent-writable-preferences.js +8 -20
- package/dist/settings/agent-write-denylist.d.ts +19 -0
- package/dist/settings/agent-write-denylist.js +15 -0
- package/dist/settings/change-feed.d.ts +11 -2
- package/dist/settings/change-feed.js +4 -4
- package/dist/settings/definitions-dispatch.d.ts +8 -3
- package/dist/settings/definitions-dispatch.js +5 -5
- package/dist/settings/dictionaries/index.d.ts +5 -2
- package/dist/settings/dictionaries/index.js +2 -2
- package/dist/settings/dictionaries/settings-dialog.ar.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.bn.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.de.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.es.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.fa.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.fr.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.hi.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.hu.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.id.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.it.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.ja.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.ko.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.pl.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.ru.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.th.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.tr.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.uk.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.ur.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js +0 -1
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js +0 -1
- package/dist/settings/ensure-definitions.d.ts +5 -5
- package/dist/settings/errors.d.ts +7 -1
- package/dist/settings/errors.js +7 -1
- package/dist/settings/index.d.ts +4 -1
- package/dist/settings/index.js +1 -0
- package/dist/settings/ports.d.ts +6 -5
- package/dist/settings/principal-lookup.d.ts +9 -0
- package/dist/settings/principal-lookup.js +2 -0
- package/dist/settings/purge-service.d.ts +5 -4
- package/dist/settings/purge-service.js +3 -2
- package/dist/settings/settings.d.ts +22 -7
- package/dist/settings/settings.js +47 -26
- package/dist/settings/tool-registrations.d.ts +25 -32
- package/dist/settings/tool-registrations.js +66 -56
- package/dist/settings/types.d.ts +1 -1
- package/dist/settings/ui-tab-definitions.d.ts +1 -1
- package/dist/settings/write-service.d.ts +32 -26
- package/dist/settings/write-service.js +26 -20
- package/dist/taxonomy/agent-tools.d.ts +1 -66
- package/dist/taxonomy/agent-tools.js +25 -15
- package/dist/taxonomy/content-lookup.js +1 -1
- package/dist/taxonomy/index.d.ts +2 -2
- package/dist/taxonomy/merge-term.d.ts +7 -4
- package/dist/taxonomy/merge-term.js +7 -5
- package/dist/taxonomy/repo.memory.d.ts +42 -19
- package/dist/taxonomy/repo.memory.js +14 -12
- package/dist/taxonomy/validation-chain.d.ts +39 -18
- package/dist/taxonomy/validation-chain.js +35 -25
- package/dist/taxonomy/write-service.d.ts +106 -45
- package/dist/taxonomy/write-service.js +221 -179
- package/dist/trash/adapters/record-store.d.ts +52 -0
- package/dist/trash/adapters/record-store.js +36 -0
- package/dist/trash/cursor.d.ts +20 -0
- package/dist/trash/cursor.js +36 -0
- package/dist/trash/follow-ups.d.ts +76 -0
- package/dist/trash/follow-ups.js +46 -0
- package/dist/trash/index.d.ts +8 -0
- package/dist/trash/index.js +8 -0
- package/dist/trash/ports.d.ts +308 -0
- package/dist/trash/ports.js +2 -0
- package/dist/trash/repo.memory.d.ts +50 -0
- package/dist/trash/repo.memory.js +114 -0
- package/dist/trash/sweeper.d.ts +77 -0
- package/dist/trash/sweeper.js +127 -0
- package/dist/trash/write-service.d.ts +100 -0
- package/dist/trash/write-service.js +242 -0
- package/dist/workspace/agent-tools.d.ts +1 -59
- package/dist/workspace/agent-tools.js +27 -12
- package/dist/workspace/create.d.ts +31 -6
- package/dist/workspace/create.js +18 -5
- package/dist/workspace/delete.d.ts +18 -13
- package/dist/workspace/delete.js +20 -12
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/repo.memory.d.ts +19 -4
- package/dist/workspace/repo.memory.js +26 -4
- package/dist/workspace/tool-registrations.d.ts +2 -2
- package/dist/workspace/tool-registrations.js +13 -13
- package/dist/workspace/update.d.ts +6 -5
- package/dist/workspace/update.js +9 -8
- package/package.json +44 -38
- package/dist/identity/admin-crud-service.d.ts +0 -280
- package/dist/identity/admin-crud-service.js +0 -468
- package/dist/identity/agent-tool-input.d.ts +0 -58
- package/dist/identity/agent-tool-input.js +0 -126
- package/dist/identity/agent-tools.d.ts +0 -101
- package/dist/identity/agent-tools.js +0 -290
- package/dist/identity/auth-service.d.ts +0 -118
- package/dist/identity/auth-service.js +0 -170
- package/dist/identity/authorize.d.ts +0 -90
- package/dist/identity/authorize.js +0 -94
- package/dist/identity/grant-service.d.ts +0 -198
- package/dist/identity/grant-service.js +0 -361
- package/dist/identity/hasher.d.ts +0 -39
- package/dist/identity/hasher.js +0 -39
- package/dist/identity/index.d.ts +0 -62
- package/dist/identity/index.js +0 -54
- package/dist/identity/password-policy.d.ts +0 -57
- package/dist/identity/password-policy.js +0 -66
- package/dist/identity/permission-migrations.d.ts +0 -86
- package/dist/identity/permission-migrations.js +0 -67
- package/dist/identity/permissions.d.ts +0 -35
- package/dist/identity/permissions.js +0 -603
- package/dist/identity/ports.d.ts +0 -201
- package/dist/identity/repo.memory.d.ts +0 -164
- package/dist/identity/repo.memory.js +0 -224
- package/dist/identity/seed.d.ts +0 -54
- package/dist/identity/seed.js +0 -429
- package/dist/identity/tool-registrations.d.ts +0 -50
- package/dist/identity/tool-registrations.js +0 -419
- package/dist/identity/types.d.ts +0 -185
- package/dist/identity/types.js +0 -64
- package/dist/identity/username.d.ts +0 -12
- package/dist/identity/username.js +0 -14
- /package/dist/{identity → media/import}/ports.js +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { buildDomainRegistrations, indexCatalogById, requireInputRecord, requireString,
|
|
1
|
+
import { buildDomainRegistrations, indexCatalogById, requireInputRecord, requireString, withSchemaOnRejection } from "@jini-ai/core";
|
|
2
|
+
import { adaptLegacyAuthorize, requireToolPermission } from "../core/tools/index.js";
|
|
2
3
|
import { mediaAgentToolCatalog } from "./agent-tools.js";
|
|
3
4
|
import { listMedia, MediaValidationError, rollbackUploadedMedia, trashMedia, updateMediaMetadata, uploadMedia } from "./media-service.js";
|
|
4
|
-
const CATALOG_BY_ID = indexCatalogById(mediaAgentToolCatalog);
|
|
5
|
+
const CATALOG_BY_ID = indexCatalogById({ catalog: mediaAgentToolCatalog });
|
|
5
6
|
/**
|
|
6
7
|
* This wiring layer's OWN risk classification, authored from what each handler below actually
|
|
7
8
|
* calls. See `DerivedRiskByToolId` in the kit for why it is independent of the catalog's own
|
|
@@ -19,7 +20,7 @@ export const mediaDerivedRisk = new Map([
|
|
|
19
20
|
["media_trash_asset", "mutates-durable-state"],
|
|
20
21
|
]);
|
|
21
22
|
/** The only Media rejection worth decorating with the published schema — a shape problem a different input would fix. */
|
|
22
|
-
function isMediaShapeRejection(error) {
|
|
23
|
+
function isMediaShapeRejection({ error }) {
|
|
23
24
|
return error instanceof MediaValidationError;
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
@@ -53,10 +54,21 @@ function toMediaToolView(record) {
|
|
|
53
54
|
* responsibility — see `MediaToolDeps.resolvePublicUrls`'s own doc).
|
|
54
55
|
*/
|
|
55
56
|
async function toMediaToolViewsWithPublicUrls(routeDeps, records) {
|
|
56
|
-
const urls = routeDeps.resolvePublicUrls ? await routeDeps.resolvePublicUrls(records) : new Map();
|
|
57
|
+
const urls = routeDeps.resolvePublicUrls ? await routeDeps.resolvePublicUrls({ assets: records }) : new Map();
|
|
57
58
|
return records.map((record) => ({ ...toMediaToolView(record), publicUrl: urls.get(record.id) ?? null }));
|
|
58
59
|
}
|
|
59
|
-
export function buildMediaRegistrations(
|
|
60
|
+
export function buildMediaRegistrations(required, optional = {}) {
|
|
61
|
+
const routeDeps = {
|
|
62
|
+
authorize: required.authorize,
|
|
63
|
+
workspaceId: required.workspaceId,
|
|
64
|
+
clock: required.clock,
|
|
65
|
+
idGen: required.idGen,
|
|
66
|
+
mediaRepo: required.mediaRepo,
|
|
67
|
+
assetBlobRepo: required.assetBlobRepo,
|
|
68
|
+
assetRenditionRepo: required.assetRenditionRepo,
|
|
69
|
+
blobStore: required.blobStore,
|
|
70
|
+
...optional,
|
|
71
|
+
};
|
|
60
72
|
const mediaWriteDeps = () => ({
|
|
61
73
|
clock: routeDeps.clock,
|
|
62
74
|
idGen: routeDeps.idGen,
|
|
@@ -67,84 +79,84 @@ export function buildMediaRegistrations(routeDeps) {
|
|
|
67
79
|
});
|
|
68
80
|
const handlers = {
|
|
69
81
|
media_list_assets: async (ctx) => {
|
|
70
|
-
await requireToolPermission(routeDeps,
|
|
82
|
+
await requireToolPermission({ authorize: adaptLegacyAuthorize({ authorize: routeDeps.authorize }), workspaceId: routeDeps.workspaceId, principalId: ctx.principal.id, permission: "media.read" }, { entityType: "media" });
|
|
71
83
|
const { media } = await listMedia({ deps: { mediaRepo: routeDeps.mediaRepo }, input: { workspaceId: routeDeps.workspaceId } });
|
|
72
84
|
return { media: await toMediaToolViewsWithPublicUrls(routeDeps, media) };
|
|
73
85
|
},
|
|
74
86
|
media_upload_asset: async (ctx) => {
|
|
75
|
-
const input = requireInputRecord(ctx.input);
|
|
76
|
-
await requireToolPermission(routeDeps,
|
|
77
|
-
return withSchemaOnRejection({ toolId: "media_upload_asset", catalog: CATALOG_BY_ID, isShapeRejection: isMediaShapeRejection
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
bytes = new Uint8Array(Buffer.from(dataBase64, "base64"));
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
throw new Error("'dataBase64' is not valid base64");
|
|
85
|
-
}
|
|
86
|
-
const { media } = await uploadMedia({
|
|
87
|
-
deps: mediaWriteDeps(),
|
|
88
|
-
input: {
|
|
89
|
-
workspaceId: routeDeps.workspaceId,
|
|
90
|
-
bytes,
|
|
91
|
-
filename: requireString(input, "filename"),
|
|
92
|
-
contentType: requireString(input, "contentType"),
|
|
93
|
-
alt: typeof input.alt === "string" ? input.alt : undefined,
|
|
94
|
-
caption: typeof input.caption === "string" ? input.caption : undefined,
|
|
95
|
-
credit: typeof input.credit === "string" ? input.credit : undefined,
|
|
96
|
-
createdByPrincipal: ctx.principal.id,
|
|
97
|
-
},
|
|
98
|
-
}, { maxUploadBytes: routeDeps.maxUploadBytes });
|
|
99
|
-
if (routeDeps.recordUploadContentType) {
|
|
87
|
+
const input = requireInputRecord({ input: ctx.input });
|
|
88
|
+
await requireToolPermission({ authorize: adaptLegacyAuthorize({ authorize: routeDeps.authorize }), workspaceId: routeDeps.workspaceId, principalId: ctx.principal.id, permission: "media.upload" }, { entityType: "media" });
|
|
89
|
+
return withSchemaOnRejection({ toolId: "media_upload_asset", catalog: CATALOG_BY_ID, isShapeRejection: isMediaShapeRejection, fn: async () => {
|
|
90
|
+
const dataBase64 = requireString({ input, key: "dataBase64" });
|
|
91
|
+
let bytes;
|
|
100
92
|
try {
|
|
101
|
-
|
|
93
|
+
bytes = new Uint8Array(Buffer.from(dataBase64, "base64"));
|
|
102
94
|
}
|
|
103
|
-
catch
|
|
104
|
-
|
|
105
|
-
// when the caller is about to see this whole upload as failed (the fix for that gap —
|
|
106
|
-
// see rollbackUploadedMedia's own doc). The original hook error is rethrown unchanged.
|
|
107
|
-
await rollbackUploadedMedia({
|
|
108
|
-
deps: {
|
|
109
|
-
mediaRepo: routeDeps.mediaRepo,
|
|
110
|
-
blobRepo: routeDeps.assetBlobRepo,
|
|
111
|
-
renditionRepo: routeDeps.assetRenditionRepo,
|
|
112
|
-
clock: routeDeps.clock,
|
|
113
|
-
},
|
|
114
|
-
input: { workspaceId: routeDeps.workspaceId, media },
|
|
115
|
-
});
|
|
116
|
-
throw err;
|
|
95
|
+
catch {
|
|
96
|
+
throw new Error("'dataBase64' is not valid base64");
|
|
117
97
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
98
|
+
const { media } = await uploadMedia({
|
|
99
|
+
deps: mediaWriteDeps(),
|
|
100
|
+
input: {
|
|
101
|
+
workspaceId: routeDeps.workspaceId,
|
|
102
|
+
bytes,
|
|
103
|
+
filename: requireString({ input, key: "filename" }),
|
|
104
|
+
contentType: requireString({ input, key: "contentType" }),
|
|
105
|
+
alt: typeof input.alt === "string" ? input.alt : undefined,
|
|
106
|
+
caption: typeof input.caption === "string" ? input.caption : undefined,
|
|
107
|
+
credit: typeof input.credit === "string" ? input.credit : undefined,
|
|
108
|
+
createdByPrincipal: ctx.principal.id,
|
|
109
|
+
},
|
|
110
|
+
}, { maxUploadBytes: routeDeps.maxUploadBytes });
|
|
111
|
+
if (routeDeps.recordUploadContentType) {
|
|
112
|
+
try {
|
|
113
|
+
await routeDeps.recordUploadContentType({ media, bytes });
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// The blob/media/rendition rows uploadMedia() just wrote must not survive as orphans
|
|
117
|
+
// when the caller is about to see this whole upload as failed (the fix for that gap —
|
|
118
|
+
// see rollbackUploadedMedia's own doc). The original hook error is rethrown unchanged.
|
|
119
|
+
await rollbackUploadedMedia({
|
|
120
|
+
deps: {
|
|
121
|
+
mediaRepo: routeDeps.mediaRepo,
|
|
122
|
+
blobRepo: routeDeps.assetBlobRepo,
|
|
123
|
+
renditionRepo: routeDeps.assetRenditionRepo,
|
|
124
|
+
clock: routeDeps.clock,
|
|
125
|
+
},
|
|
126
|
+
input: { workspaceId: routeDeps.workspaceId, media },
|
|
127
|
+
});
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const [view] = await toMediaToolViewsWithPublicUrls(routeDeps, [media]);
|
|
132
|
+
return { media: view };
|
|
133
|
+
} });
|
|
122
134
|
},
|
|
123
135
|
media_update_metadata: async (ctx) => {
|
|
124
|
-
const input = requireInputRecord(ctx.input);
|
|
125
|
-
const mediaId = requireString(input, "mediaId");
|
|
126
|
-
await requireToolPermission(routeDeps,
|
|
127
|
-
return withSchemaOnRejection({ toolId: "media_update_metadata", catalog: CATALOG_BY_ID, isShapeRejection: isMediaShapeRejection
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
const input = requireInputRecord({ input: ctx.input });
|
|
137
|
+
const mediaId = requireString({ input, key: "mediaId" });
|
|
138
|
+
await requireToolPermission({ authorize: adaptLegacyAuthorize({ authorize: routeDeps.authorize }), workspaceId: routeDeps.workspaceId, principalId: ctx.principal.id, permission: "media.update" }, { entityType: "media", entityId: mediaId });
|
|
139
|
+
return withSchemaOnRejection({ toolId: "media_update_metadata", catalog: CATALOG_BY_ID, isShapeRejection: isMediaShapeRejection, fn: async () => {
|
|
140
|
+
const { media } = await updateMediaMetadata({
|
|
141
|
+
deps: { clock: routeDeps.clock, mediaRepo: routeDeps.mediaRepo },
|
|
142
|
+
input: {
|
|
143
|
+
workspaceId: routeDeps.workspaceId,
|
|
144
|
+
id: mediaId,
|
|
145
|
+
title: typeof input.title === "string" ? input.title : undefined,
|
|
146
|
+
alt: typeof input.alt === "string" ? input.alt : undefined,
|
|
147
|
+
caption: typeof input.caption === "string" ? input.caption : undefined,
|
|
148
|
+
credit: typeof input.credit === "string" ? input.credit : undefined,
|
|
149
|
+
slug: typeof input.slug === "string" ? input.slug : undefined,
|
|
150
|
+
cssClass: typeof input.cssClass === "string" ? input.cssClass : undefined,
|
|
151
|
+
htmlAttributes: typeof input.htmlAttributes === "string" ? input.htmlAttributes : undefined,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
return { media: toMediaToolView(media) };
|
|
155
|
+
} });
|
|
144
156
|
},
|
|
145
157
|
media_trash_asset: async (ctx) => {
|
|
146
|
-
const mediaId = requireString(requireInputRecord(ctx.input), "mediaId");
|
|
147
|
-
await requireToolPermission(routeDeps,
|
|
158
|
+
const mediaId = requireString({ input: requireInputRecord({ input: ctx.input }), key: "mediaId" });
|
|
159
|
+
await requireToolPermission({ authorize: adaptLegacyAuthorize({ authorize: routeDeps.authorize }), workspaceId: routeDeps.workspaceId, principalId: ctx.principal.id, permission: "media.delete" }, { entityType: "media", entityId: mediaId });
|
|
148
160
|
const { media } = await trashMedia({
|
|
149
161
|
deps: { clock: routeDeps.clock, mediaRepo: routeDeps.mediaRepo },
|
|
150
162
|
input: { workspaceId: routeDeps.workspaceId, id: mediaId },
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Generic in-process keyed mutex factory, extracted from
|
|
3
|
-
* `blob-gc-lock.ts`'s `withSha256Lock` shape (
|
|
3
|
+
* `blob-gc-lock.ts`'s `withSha256Lock` shape (
|
|
4
4
|
* "Serialization" clause) so the same FIFO-per-key critical-section pattern
|
|
5
5
|
* can back two independent lock namespaces this domain needs:
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* - `withTransformRegistryLock` — serializes `registerTransform`'s
|
|
8
|
+
* read-max-version-then-insert-next-version sequence per `(workspaceId,
|
|
9
|
+
* name)`, so two concurrent registrations of the same name can't both
|
|
10
|
+
* read the same "current max" and mint a colliding version.
|
|
11
|
+
* - `withRenditionLock` — serializes lazy rendition generation per
|
|
12
|
+
* `(sha256, transformName, version)` ("single-flight"), so two
|
|
13
|
+
* concurrent requests for the same not-yet-generated rendition never run
|
|
14
|
+
* the image transformer twice.
|
|
15
15
|
*
|
|
16
16
|
* `blob-gc-lock.ts` itself is untouched — this is a separate module, not a
|
|
17
17
|
* modification of that file's exports (its shape is deliberately mirrored
|
|
18
18
|
* here, not imported, so `blob-gc-lock.ts`'s own signature stays untouched).
|
|
19
|
+
* See docs/decisions/DR-004-journaled-blob-gc.md.
|
|
19
20
|
*/
|
|
20
21
|
/**
|
|
21
22
|
* Creates one independent keyed-lock namespace: calls sharing the same `key`
|
|
@@ -28,9 +29,18 @@
|
|
|
28
29
|
* by the number of other calls currently queued for the same key.
|
|
29
30
|
* @overallScore 100
|
|
30
31
|
*/
|
|
31
|
-
export declare function createKeyedLock(
|
|
32
|
+
export declare function createKeyedLock(_required: Record<string, never>, _optional?: Record<string, never>): <T>(required: {
|
|
33
|
+
key: string;
|
|
34
|
+
criticalSection: () => Promise<T>;
|
|
35
|
+
}, optional?: Record<string, never>) => Promise<T>;
|
|
32
36
|
/** Keyed on `${workspaceId}:${name}` — see file header. */
|
|
33
|
-
export declare const withTransformRegistryLock: <T>(
|
|
37
|
+
export declare const withTransformRegistryLock: <T>(required: {
|
|
38
|
+
key: string;
|
|
39
|
+
criticalSection: () => Promise<T>;
|
|
40
|
+
}, optional?: Record<string, never>) => Promise<T>;
|
|
34
41
|
/** Keyed on `${sha256}:${transformName}:${version}` — see file header. */
|
|
35
|
-
export declare const withRenditionLock: <T>(
|
|
42
|
+
export declare const withRenditionLock: <T>(required: {
|
|
43
|
+
key: string;
|
|
44
|
+
criticalSection: () => Promise<T>;
|
|
45
|
+
}, optional?: Record<string, never>) => Promise<T>;
|
|
36
46
|
//# sourceMappingURL=transform-lock.d.ts.map
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Generic in-process keyed mutex factory, extracted from
|
|
3
|
-
* `blob-gc-lock.ts`'s `withSha256Lock` shape (
|
|
3
|
+
* `blob-gc-lock.ts`'s `withSha256Lock` shape (
|
|
4
4
|
* "Serialization" clause) so the same FIFO-per-key critical-section pattern
|
|
5
5
|
* can back two independent lock namespaces this domain needs:
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* - `withTransformRegistryLock` — serializes `registerTransform`'s
|
|
8
|
+
* read-max-version-then-insert-next-version sequence per `(workspaceId,
|
|
9
|
+
* name)`, so two concurrent registrations of the same name can't both
|
|
10
|
+
* read the same "current max" and mint a colliding version.
|
|
11
|
+
* - `withRenditionLock` — serializes lazy rendition generation per
|
|
12
|
+
* `(sha256, transformName, version)` ("single-flight"), so two
|
|
13
|
+
* concurrent requests for the same not-yet-generated rendition never run
|
|
14
|
+
* the image transformer twice.
|
|
15
15
|
*
|
|
16
16
|
* `blob-gc-lock.ts` itself is untouched — this is a separate module, not a
|
|
17
17
|
* modification of that file's exports (its shape is deliberately mirrored
|
|
18
18
|
* here, not imported, so `blob-gc-lock.ts`'s own signature stays untouched).
|
|
19
|
+
* See docs/decisions/DR-004-journaled-blob-gc.md.
|
|
19
20
|
*/
|
|
20
21
|
/**
|
|
21
22
|
* Creates one independent keyed-lock namespace: calls sharing the same `key`
|
|
@@ -28,9 +29,9 @@
|
|
|
28
29
|
* by the number of other calls currently queued for the same key.
|
|
29
30
|
* @overallScore 100
|
|
30
31
|
*/
|
|
31
|
-
export function createKeyedLock() {
|
|
32
|
+
export function createKeyedLock(_required, _optional = {}) {
|
|
32
33
|
const lockTails = new Map();
|
|
33
|
-
return function withLock(key, criticalSection) {
|
|
34
|
+
return function withLock({ key, criticalSection }, _optional = {}) {
|
|
34
35
|
const priorTail = lockTails.get(key) ?? Promise.resolve();
|
|
35
36
|
const run = priorTail.then(criticalSection, criticalSection);
|
|
36
37
|
const settledTail = run.then(() => undefined, () => undefined);
|
|
@@ -44,7 +45,7 @@ export function createKeyedLock() {
|
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
/** Keyed on `${workspaceId}:${name}` — see file header. */
|
|
47
|
-
export const withTransformRegistryLock = createKeyedLock();
|
|
48
|
+
export const withTransformRegistryLock = createKeyedLock({});
|
|
48
49
|
/** Keyed on `${sha256}:${transformName}:${version}` — see file header. */
|
|
49
|
-
export const withRenditionLock = createKeyedLock();
|
|
50
|
+
export const withRenditionLock = createKeyedLock({});
|
|
50
51
|
//# sourceMappingURL=transform-lock.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Mirrors `media-service.ts`'s shape: plain async functions taking
|
|
7
7
|
* `{ deps, input }` (+ optional `options`), typed domain errors.
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { Clock, IdGenerator, UUID } from "@jini-ai/core/primitives";
|
|
10
10
|
import type { TransformDefinitionRepoPort } from "./ports.js";
|
|
11
11
|
import { TransformValidationError, type TransformDefinitionRecord, type TransformParams } from "./transform-types.js";
|
|
12
12
|
export { TransformValidationError };
|
|
@@ -18,8 +18,8 @@ export interface RegisterTransformInput {
|
|
|
18
18
|
owner: string;
|
|
19
19
|
}
|
|
20
20
|
export interface RegisterTransformDeps {
|
|
21
|
-
clock:
|
|
22
|
-
idGen:
|
|
21
|
+
clock: Clock;
|
|
22
|
+
idGen: IdGenerator;
|
|
23
23
|
transformRepo: TransformDefinitionRepoPort;
|
|
24
24
|
}
|
|
25
25
|
export interface RegisterTransformRequired {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nowIso as kernelNowIso } from "@jini-ai/core/primitives";
|
|
1
2
|
import { assertValidTransformParams, TransformValidationError } from "./transform-types.js";
|
|
2
3
|
import { withTransformRegistryLock } from "./transform-lock.js";
|
|
3
4
|
export { TransformValidationError };
|
|
@@ -21,26 +22,26 @@ export async function registerTransform(required, _optional = {}) {
|
|
|
21
22
|
const { deps, input } = required;
|
|
22
23
|
const name = input.name.trim();
|
|
23
24
|
if (!name)
|
|
24
|
-
throw new TransformValidationError("transform name is required");
|
|
25
|
+
throw new TransformValidationError({ message: "transform name is required" });
|
|
25
26
|
const owner = input.owner.trim();
|
|
26
27
|
if (!owner)
|
|
27
|
-
throw new TransformValidationError("owner is required");
|
|
28
|
-
assertValidTransformParams(input.params);
|
|
29
|
-
return withTransformRegistryLock(`${input.workspaceId}:${name}`, async () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
throw new TransformValidationError({ message: "owner is required" });
|
|
29
|
+
assertValidTransformParams({ format: input.params.format }, { width: input.params.width, height: input.params.height, fit: input.params.fit });
|
|
30
|
+
return withTransformRegistryLock({ key: `${input.workspaceId}:${name}`, criticalSection: async () => {
|
|
31
|
+
const existingVersions = await deps.transformRepo.listByName({ workspaceId: input.workspaceId, name });
|
|
32
|
+
const currentMaxVersion = existingVersions.reduce((max, row) => Math.max(max, row.version), 0);
|
|
33
|
+
const definition = {
|
|
34
|
+
id: deps.idGen.newId(),
|
|
35
|
+
workspaceId: input.workspaceId,
|
|
36
|
+
name,
|
|
37
|
+
version: currentMaxVersion + 1,
|
|
38
|
+
params: input.params,
|
|
39
|
+
owner,
|
|
40
|
+
createdAt: kernelNowIso({ clock: deps.clock }),
|
|
41
|
+
};
|
|
42
|
+
await deps.transformRepo.insert(definition);
|
|
43
|
+
return { definition };
|
|
44
|
+
} });
|
|
44
45
|
}
|
|
45
46
|
/**
|
|
46
47
|
* Returns the highest-`version` row registered for `name`, or `null` if
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* solves the identical "who registered this, extensibly" problem for the
|
|
22
22
|
* permission catalog.
|
|
23
23
|
*/
|
|
24
|
-
import type { ISODateTime, UUID } from "
|
|
24
|
+
import type { ISODateTime, UUID } from "@jini-ai/core/primitives";
|
|
25
25
|
/** Resize behavior, mirrors `sharp`'s `fit` vocabulary (a deliberately small subset). */
|
|
26
26
|
export type TransformFit = "cover" | "contain" | "fill" | "inside" | "outside";
|
|
27
27
|
/**
|
|
@@ -60,12 +60,17 @@ export interface TransformDefinitionRecord {
|
|
|
60
60
|
createdAt: ISODateTime;
|
|
61
61
|
}
|
|
62
62
|
export declare class TransformValidationError extends Error {
|
|
63
|
+
constructor({ message }: {
|
|
64
|
+
message: string;
|
|
65
|
+
}, optionalArgs?: ErrorOptions);
|
|
63
66
|
}
|
|
64
67
|
/**
|
|
65
68
|
* @complexity O(1).
|
|
66
69
|
* @overallScore 100
|
|
67
70
|
*/
|
|
68
|
-
export declare function mimeForTransformFormat(
|
|
71
|
+
export declare function mimeForTransformFormat(requiredArgs: {
|
|
72
|
+
format: TransformFormat;
|
|
73
|
+
}, optionalArgs?: Record<string, never>): string;
|
|
69
74
|
/** Upper bound on a requested resize dimension — an output-side resource-use guard (not the
|
|
70
75
|
* full pixel-bomb ingest cap, which polices upload input; this polices the transform
|
|
71
76
|
* definition itself so a registered definition can't ask the image transformer to allocate an
|
|
@@ -78,5 +83,5 @@ export declare const MAX_TRANSFORM_DIMENSION_PX = 8000;
|
|
|
78
83
|
* @complexity O(1).
|
|
79
84
|
* @overallScore 100
|
|
80
85
|
*/
|
|
81
|
-
export declare function assertValidTransformParams(
|
|
86
|
+
export declare function assertValidTransformParams(required: Pick<TransformParams, "format">, optional?: Omit<TransformParams, "format">): void;
|
|
82
87
|
//# sourceMappingURL=transform-types.d.ts.map
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export class TransformValidationError extends Error {
|
|
2
|
+
constructor({ message }, optionalArgs = {}) {
|
|
3
|
+
super(message, optionalArgs);
|
|
4
|
+
}
|
|
2
5
|
}
|
|
3
6
|
/** Maps a {@link TransformFormat} to the MIME type served on the rendition response. */
|
|
4
7
|
const MIME_BY_TRANSFORM_FORMAT = {
|
|
@@ -11,7 +14,8 @@ const MIME_BY_TRANSFORM_FORMAT = {
|
|
|
11
14
|
* @complexity O(1).
|
|
12
15
|
* @overallScore 100
|
|
13
16
|
*/
|
|
14
|
-
export function mimeForTransformFormat(
|
|
17
|
+
export function mimeForTransformFormat(requiredArgs, optionalArgs = {}) {
|
|
18
|
+
const { format } = requiredArgs;
|
|
15
19
|
return MIME_BY_TRANSFORM_FORMAT[format];
|
|
16
20
|
}
|
|
17
21
|
/** Upper bound on a requested resize dimension — an output-side resource-use guard (not the
|
|
@@ -26,9 +30,10 @@ export const MAX_TRANSFORM_DIMENSION_PX = 8000;
|
|
|
26
30
|
* @complexity O(1).
|
|
27
31
|
* @overallScore 100
|
|
28
32
|
*/
|
|
29
|
-
export function assertValidTransformParams(
|
|
33
|
+
export function assertValidTransformParams(required, optional = {}) {
|
|
34
|
+
const params = { format: required.format, ...optional };
|
|
30
35
|
if (!params.format || !(params.format in MIME_BY_TRANSFORM_FORMAT)) {
|
|
31
|
-
throw new TransformValidationError(`transform params.format must be one of ${Object.keys(MIME_BY_TRANSFORM_FORMAT).join(", ")}`);
|
|
36
|
+
throw new TransformValidationError({ message: `transform params.format must be one of ${Object.keys(MIME_BY_TRANSFORM_FORMAT).join(", ")}` });
|
|
32
37
|
}
|
|
33
38
|
for (const [key, value] of [
|
|
34
39
|
["width", params.width],
|
|
@@ -37,11 +42,11 @@ export function assertValidTransformParams(params) {
|
|
|
37
42
|
if (value === undefined)
|
|
38
43
|
continue;
|
|
39
44
|
if (!Number.isInteger(value) || value < 1 || value > MAX_TRANSFORM_DIMENSION_PX) {
|
|
40
|
-
throw new TransformValidationError(`transform params.${key} must be an integer between 1 and ${MAX_TRANSFORM_DIMENSION_PX}`);
|
|
45
|
+
throw new TransformValidationError({ message: `transform params.${key} must be an integer between 1 and ${MAX_TRANSFORM_DIMENSION_PX}` });
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
if (params.fit !== undefined && !(params.width && params.height)) {
|
|
44
|
-
throw new TransformValidationError("transform params.fit requires both width and height");
|
|
49
|
+
throw new TransformValidationError({ message: "transform params.fit requires both width and height" });
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
//# sourceMappingURL=transform-types.js.map
|
package/dist/media/types.d.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* the original design describes — they were always meant to be core-owned tables
|
|
23
23
|
* independent of the entries model, so no scope adjustment was needed there.
|
|
24
24
|
*/
|
|
25
|
-
import type { ISODateTime, UUID } from "
|
|
25
|
+
import type { ISODateTime, UUID } from "@jini-ai/core/primitives";
|
|
26
26
|
/** Deletion ladder status (mirrored from `navigation`'s menu ladder). */
|
|
27
27
|
export type MediaStatus = "active" | "trashed";
|
|
28
28
|
/**
|
|
@@ -91,13 +91,14 @@ export interface MediaRecord {
|
|
|
91
91
|
htmlAttributes: string | null;
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
|
-
* Blob-GC lifecycle status (
|
|
94
|
+
* Blob-GC lifecycle status ( two-phase journaled protocol,
|
|
95
95
|
* implemented in `blob-gc.ts`). `active` — has at least one live reference as
|
|
96
96
|
* of the last check (or has never been checked). `tombstoned` — the
|
|
97
97
|
* tombstone-pass found it unreferenced and is waiting out `gc_grace` before
|
|
98
98
|
* the delete-pass may remove the row; a dedup upload observing `tombstoned`
|
|
99
99
|
* resurrects it back to `active` in the same locked section instead of
|
|
100
100
|
* writing a duplicate blob.
|
|
101
|
+
* See docs/decisions/DR-004-journaled-blob-gc.md.
|
|
101
102
|
*/
|
|
102
103
|
export type AssetBlobStatus = "active" | "tombstoned";
|
|
103
104
|
/**
|
|
@@ -119,7 +120,7 @@ export interface AssetBlobRecord {
|
|
|
119
120
|
tombstonedAt?: ISODateTime | undefined;
|
|
120
121
|
}
|
|
121
122
|
/**
|
|
122
|
-
* `blob_gc_journal` sidecar (
|
|
123
|
+
* `blob_gc_journal` sidecar ( two-phase protocol,
|
|
123
124
|
* `blob-gc.ts`): written by the delete-pass in the same locked step as the
|
|
124
125
|
* `asset_blobs` row deletion, drained by the unlink-pass. This is what makes
|
|
125
126
|
* the unlink crash-safe/retriable instead of "delete row, hope the unlink
|
|
@@ -128,6 +129,7 @@ export interface AssetBlobRecord {
|
|
|
128
129
|
* in-memory table like every other `media` repo in this pass — it does not
|
|
129
130
|
* survive a process restart; see `repo.memory.ts` file header for the
|
|
130
131
|
* standing disclosed precedent.)
|
|
132
|
+
* See docs/decisions/DR-004-journaled-blob-gc.md.
|
|
131
133
|
*/
|
|
132
134
|
export interface BlobGcJournalEntry {
|
|
133
135
|
id: UUID;
|
|
@@ -152,16 +154,28 @@ export interface AssetRenditionRecord {
|
|
|
152
154
|
createdAt: ISODateTime;
|
|
153
155
|
}
|
|
154
156
|
export declare class MediaNotFoundError extends Error {
|
|
157
|
+
constructor({ message }: {
|
|
158
|
+
message: string;
|
|
159
|
+
}, optionalArgs?: ErrorOptions);
|
|
155
160
|
}
|
|
156
161
|
export declare class MediaValidationError extends Error {
|
|
162
|
+
constructor({ message }: {
|
|
163
|
+
message: string;
|
|
164
|
+
}, optionalArgs?: ErrorOptions);
|
|
157
165
|
}
|
|
158
166
|
export declare class MediaConflictError extends Error {
|
|
167
|
+
constructor({ message }: {
|
|
168
|
+
message: string;
|
|
169
|
+
}, optionalArgs?: ErrorOptions);
|
|
159
170
|
}
|
|
160
171
|
/**
|
|
161
172
|
* The write-once source guard rejected an attempt to change an
|
|
162
173
|
* already-set `source.sha256` ("settable-once-from-absent").
|
|
163
174
|
*/
|
|
164
175
|
export declare class MediaSourceImmutableError extends MediaValidationError {
|
|
176
|
+
constructor({ message }: {
|
|
177
|
+
message: string;
|
|
178
|
+
}, optionalArgs?: ErrorOptions);
|
|
165
179
|
}
|
|
166
180
|
/**
|
|
167
181
|
* The 409-style purge rejection (deletion ladder, mirrors
|
|
@@ -171,6 +185,9 @@ export declare class MediaSourceImmutableError extends MediaValidationError {
|
|
|
171
185
|
*/
|
|
172
186
|
export declare class MediaStillReferencedError extends MediaConflictError {
|
|
173
187
|
readonly referencing: readonly string[];
|
|
174
|
-
constructor(
|
|
188
|
+
constructor(requiredArgs: {
|
|
189
|
+
message: string;
|
|
190
|
+
referencing: readonly string[];
|
|
191
|
+
}, optionalArgs?: Record<string, never>);
|
|
175
192
|
}
|
|
176
193
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/media/types.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
export class MediaNotFoundError extends Error {
|
|
2
|
+
constructor({ message }, optionalArgs = {}) {
|
|
3
|
+
super(message, optionalArgs);
|
|
4
|
+
}
|
|
2
5
|
}
|
|
3
6
|
export class MediaValidationError extends Error {
|
|
7
|
+
constructor({ message }, optionalArgs = {}) {
|
|
8
|
+
super(message, optionalArgs);
|
|
9
|
+
}
|
|
4
10
|
}
|
|
5
11
|
export class MediaConflictError extends Error {
|
|
12
|
+
constructor({ message }, optionalArgs = {}) {
|
|
13
|
+
super(message, optionalArgs);
|
|
14
|
+
}
|
|
6
15
|
}
|
|
7
16
|
/**
|
|
8
17
|
* The write-once source guard rejected an attempt to change an
|
|
9
18
|
* already-set `source.sha256` ("settable-once-from-absent").
|
|
10
19
|
*/
|
|
11
20
|
export class MediaSourceImmutableError extends MediaValidationError {
|
|
21
|
+
constructor({ message }, optionalArgs = {}) {
|
|
22
|
+
super({ message }, optionalArgs);
|
|
23
|
+
}
|
|
12
24
|
}
|
|
13
25
|
/**
|
|
14
26
|
* The 409-style purge rejection (deletion ladder, mirrors
|
|
@@ -18,8 +30,9 @@ export class MediaSourceImmutableError extends MediaValidationError {
|
|
|
18
30
|
*/
|
|
19
31
|
export class MediaStillReferencedError extends MediaConflictError {
|
|
20
32
|
referencing;
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
33
|
+
constructor(requiredArgs, optionalArgs = {}) {
|
|
34
|
+
const { message, referencing } = requiredArgs;
|
|
35
|
+
super({ message: message });
|
|
23
36
|
this.referencing = referencing;
|
|
24
37
|
}
|
|
25
38
|
}
|