@odla-ai/brand 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +72 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +72 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -289,24 +289,6 @@ var BrandReviewStateChangedError = class extends BrandConflictError {
|
|
|
289
289
|
}
|
|
290
290
|
};
|
|
291
291
|
|
|
292
|
-
// src/deps.ts
|
|
293
|
-
async function defaultFetchBytes(url) {
|
|
294
|
-
const res = await fetch(url);
|
|
295
|
-
if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);
|
|
296
|
-
return {
|
|
297
|
-
bytes: new Uint8Array(await res.arrayBuffer()),
|
|
298
|
-
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
function resolveDeps(deps) {
|
|
302
|
-
return {
|
|
303
|
-
db: deps.db,
|
|
304
|
-
now: deps.now ?? Date.now,
|
|
305
|
-
newId: deps.newId ?? (() => crypto.randomUUID()),
|
|
306
|
-
fetchBytes: deps.fetchBytes ?? defaultFetchBytes
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
|
|
310
292
|
// src/schema.ts
|
|
311
293
|
var a = (type, o = {}) => ({
|
|
312
294
|
type,
|
|
@@ -493,6 +475,70 @@ var BRAND_SCHEMA = {
|
|
|
493
475
|
}
|
|
494
476
|
};
|
|
495
477
|
|
|
478
|
+
// src/read-shape.ts
|
|
479
|
+
var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
480
|
+
var DATE_FIELDS = /* @__PURE__ */ new Map();
|
|
481
|
+
for (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))
|
|
482
|
+
DATE_FIELDS.set(
|
|
483
|
+
ns,
|
|
484
|
+
new Set(
|
|
485
|
+
Object.entries(entity.attrs).filter(([, attr]) => attr.type === "date").map(([label]) => label)
|
|
486
|
+
)
|
|
487
|
+
);
|
|
488
|
+
function rowAsWritten(ns, row) {
|
|
489
|
+
const dates = DATE_FIELDS.get(ns);
|
|
490
|
+
if (!dates?.size || !record(row)) return row;
|
|
491
|
+
let changed = false;
|
|
492
|
+
const out = { ...row };
|
|
493
|
+
for (const field of dates) {
|
|
494
|
+
const value = out[field];
|
|
495
|
+
if (typeof value !== "string") continue;
|
|
496
|
+
const parsed = Date.parse(value);
|
|
497
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) continue;
|
|
498
|
+
out[field] = parsed;
|
|
499
|
+
changed = true;
|
|
500
|
+
}
|
|
501
|
+
return changed ? out : row;
|
|
502
|
+
}
|
|
503
|
+
function receiptAsWritten(row) {
|
|
504
|
+
return rowAsWritten(BRAND_NS.approvalReceipt, row);
|
|
505
|
+
}
|
|
506
|
+
function proposalAsWritten(row) {
|
|
507
|
+
return rowAsWritten(BRAND_NS.proposal, row);
|
|
508
|
+
}
|
|
509
|
+
function resultAsWritten(result) {
|
|
510
|
+
const out = { ...result };
|
|
511
|
+
for (const [ns, rows] of Object.entries(out)) {
|
|
512
|
+
if (Array.isArray(rows)) out[ns] = rows.map((row) => rowAsWritten(ns, row));
|
|
513
|
+
}
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// src/deps.ts
|
|
518
|
+
async function defaultFetchBytes(url) {
|
|
519
|
+
const res = await fetch(url);
|
|
520
|
+
if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);
|
|
521
|
+
return {
|
|
522
|
+
bytes: new Uint8Array(await res.arrayBuffer()),
|
|
523
|
+
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function readingAsWritten(db) {
|
|
527
|
+
return {
|
|
528
|
+
query: async (q) => resultAsWritten(await db.query(q)),
|
|
529
|
+
transact: (ops, opts) => db.transact(ops, opts),
|
|
530
|
+
storage: db.storage
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function resolveDeps(deps) {
|
|
534
|
+
return {
|
|
535
|
+
db: readingAsWritten(deps.db),
|
|
536
|
+
now: deps.now ?? Date.now,
|
|
537
|
+
newId: deps.newId ?? (() => crypto.randomUUID()),
|
|
538
|
+
fetchBytes: deps.fetchBytes ?? defaultFetchBytes
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
496
542
|
// src/rules.ts
|
|
497
543
|
var CURRENT_BOOK_MEMBER = "ref('book.memberIds').exists(members, auth.id in members)";
|
|
498
544
|
var BRAND_RULES = {
|
|
@@ -693,38 +739,6 @@ function assertAnalysis(value) {
|
|
|
693
739
|
};
|
|
694
740
|
}
|
|
695
741
|
|
|
696
|
-
// src/read-shape.ts
|
|
697
|
-
var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
698
|
-
var DATE_FIELDS = /* @__PURE__ */ new Map();
|
|
699
|
-
for (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))
|
|
700
|
-
DATE_FIELDS.set(
|
|
701
|
-
ns,
|
|
702
|
-
new Set(
|
|
703
|
-
Object.entries(entity.attrs).filter(([, attr]) => attr.type === "date").map(([label]) => label)
|
|
704
|
-
)
|
|
705
|
-
);
|
|
706
|
-
function rowAsWritten(ns, row) {
|
|
707
|
-
const dates = DATE_FIELDS.get(ns);
|
|
708
|
-
if (!dates?.size || !record(row)) return row;
|
|
709
|
-
let changed = false;
|
|
710
|
-
const out = { ...row };
|
|
711
|
-
for (const field of dates) {
|
|
712
|
-
const value = out[field];
|
|
713
|
-
if (typeof value !== "string") continue;
|
|
714
|
-
const parsed = Date.parse(value);
|
|
715
|
-
if (!Number.isSafeInteger(parsed) || parsed < 0) continue;
|
|
716
|
-
out[field] = parsed;
|
|
717
|
-
changed = true;
|
|
718
|
-
}
|
|
719
|
-
return changed ? out : row;
|
|
720
|
-
}
|
|
721
|
-
function receiptAsWritten(row) {
|
|
722
|
-
return rowAsWritten(BRAND_NS.approvalReceipt, row);
|
|
723
|
-
}
|
|
724
|
-
function proposalAsWritten(row) {
|
|
725
|
-
return rowAsWritten(BRAND_NS.proposal, row);
|
|
726
|
-
}
|
|
727
|
-
|
|
728
742
|
// src/review-json.ts
|
|
729
743
|
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
730
744
|
function isBoundedBrandJson(root, limits = {}) {
|
|
@@ -4029,7 +4043,8 @@ async function handleDesignPreview(ctx, req, bookId, assetId) {
|
|
|
4029
4043
|
const asset = await linkedAsset(ctx, book, assetId);
|
|
4030
4044
|
if (asset.kind !== DESIGN_ASSET_KIND) throw new BrandNotFoundError(`design ${assetId}`);
|
|
4031
4045
|
const signed = await ctx.db.storage.sign(asset.path, SIGNED_READ_TTL_SECONDS);
|
|
4032
|
-
const
|
|
4046
|
+
const fetchPrivateAsset = ctx.fetchPrivateAsset;
|
|
4047
|
+
const fetched = await fetchPrivateAsset(signed, {
|
|
4033
4048
|
headers: { accept: "text/html" },
|
|
4034
4049
|
redirect: "manual",
|
|
4035
4050
|
signal: req.signal
|
|
@@ -4914,7 +4929,8 @@ async function handleBrandDiscussionAsset(ctx, req, target) {
|
|
|
4914
4929
|
await ctx.db.storage.sign(before.path, SIGN_TTL_SECONDS)
|
|
4915
4930
|
);
|
|
4916
4931
|
if (!signed) throw new BrandInputError("private asset signing failed");
|
|
4917
|
-
const
|
|
4932
|
+
const fetchPrivateAsset = ctx.fetchPrivateAsset;
|
|
4933
|
+
const response = await fetchPrivateAsset(signed, {
|
|
4918
4934
|
headers: { accept: contentType },
|
|
4919
4935
|
redirect: "manual",
|
|
4920
4936
|
signal: req.signal
|
|
@@ -5151,7 +5167,10 @@ function createBrandRoutes(options) {
|
|
|
5151
5167
|
newId: options.newId ?? (() => crypto.randomUUID()),
|
|
5152
5168
|
maxUploadBytes: options.maxUploadBytes ?? 8 * 1024 * 1024,
|
|
5153
5169
|
discussionBasePath: options.discussionBasePath ?? "/",
|
|
5154
|
-
|
|
5170
|
+
// Bound: this is stored on the context and invoked from route handlers,
|
|
5171
|
+
// where a property call would set the receiver to that context and
|
|
5172
|
+
// Cloudflare's fetch refuses a foreign receiver ("Illegal invocation").
|
|
5173
|
+
fetchPrivateAsset: options.fetchPrivateAsset ?? globalThis.fetch.bind(globalThis),
|
|
5155
5174
|
previewFrameAncestors: options.previewFrameAncestors ?? ["'self'"]
|
|
5156
5175
|
};
|
|
5157
5176
|
return async (req) => {
|