@mulmoclaude/core 4.1.1 → 4.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/assets/helps/collection-skills.md +17 -6
- package/assets/helps/error-recovery.md +53 -0
- package/dist/collection/core/calendarGrid.d.ts +2 -2
- package/dist/collection/core/serverTime.d.ts +93 -0
- package/dist/collection/index.cjs +9 -2
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.js +3 -3
- package/dist/collection/registry/server/index.cjs +2 -2
- package/dist/collection/registry/server/index.js +2 -2
- package/dist/collection/server/index.cjs +4 -3
- package/dist/collection/server/index.js +4 -4
- package/dist/collection/server/manageTool.d.ts +24 -0
- package/dist/collection-watchers/index.cjs +4 -4
- package/dist/collection-watchers/index.js +4 -4
- package/dist/{discovery-B9EESjHP.cjs → discovery-Dl9nRa-m.cjs} +38 -20
- package/dist/discovery-Dl9nRa-m.cjs.map +1 -0
- package/dist/{discovery-D88x2DmW.js → discovery-P64fgtuD.js} +38 -20
- package/dist/discovery-P64fgtuD.js.map +1 -0
- package/dist/feeds/index.cjs +2 -2
- package/dist/feeds/index.js +2 -2
- package/dist/feeds/server/index.cjs +4 -4
- package/dist/feeds/server/index.js +4 -4
- package/dist/google/index.cjs +2 -2
- package/dist/google/index.js +2 -2
- package/dist/{ingestTypes-B312BwXg.js → ingestTypes-CIy1lHjf.js} +2 -2
- package/dist/{ingestTypes-B312BwXg.js.map → ingestTypes-CIy1lHjf.js.map} +1 -1
- package/dist/{ingestTypes-B4XfrUoq.cjs → ingestTypes-CaX7_s-K.cjs} +2 -2
- package/dist/{ingestTypes-B4XfrUoq.cjs.map → ingestTypes-CaX7_s-K.cjs.map} +1 -1
- package/dist/{itemId-DfTm08jm.js → itemId-BY2YPBkT.js} +200 -6
- package/dist/itemId-BY2YPBkT.js.map +1 -0
- package/dist/{itemId-Dzrr3vs5.cjs → itemId-CEQdK01z.cjs} +241 -5
- package/dist/itemId-CEQdK01z.cjs.map +1 -0
- package/dist/{promptSafety-CJ-sC1pX.js → promptSafety-Bp780ezk.js} +2 -2
- package/dist/{promptSafety-CJ-sC1pX.js.map → promptSafety-Bp780ezk.js.map} +1 -1
- package/dist/{promptSafety-CuczAN9d.cjs → promptSafety-C0BWDsfT.cjs} +2 -2
- package/dist/{promptSafety-CuczAN9d.cjs.map → promptSafety-C0BWDsfT.cjs.map} +1 -1
- package/dist/{server-L12n8We3.js → server-BvXO49Vj.js} +87 -17
- package/dist/server-BvXO49Vj.js.map +1 -0
- package/dist/{server-meS6kjBN.cjs → server-CF1qllGV.cjs} +92 -16
- package/dist/server-CF1qllGV.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/discovery-B9EESjHP.cjs.map +0 -1
- package/dist/discovery-D88x2DmW.js.map +0 -1
- package/dist/itemId-DfTm08jm.js.map +0 -1
- package/dist/itemId-Dzrr3vs5.cjs.map +0 -1
- package/dist/server-L12n8We3.js.map +0 -1
- package/dist/server-meS6kjBN.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as isErrorWithCode, l as isUnknownArray, r as hasNumberProp, s as isRecord } from "./dist-D8zokgGo.js";
|
|
2
2
|
import { n as writeFileAtomic, t as canonicalRoot } from "./root-BMroU_mB.js";
|
|
3
|
-
import {
|
|
3
|
+
import { B as COMPUTED_TYPES, G as isReadOnlySchema, H as INGEST_KINDS, I as isSafeRecordId, J as fieldTextOrNull, K as storageKindFor, L as isSafeSlug, M as sharedCollectionKey, N as SAFE_RECORD_ID_PATTERN, O as isValidCollectionName, P as SAFE_SLUG_PATTERN, V as FEED_SCHEDULES, _ as decodeRecordTimes, k as localCollectionKeyOf, q as fieldText, t as newItemId, y as encodeRecordTimes, z as AGENT_INGEST_KIND } from "./itemId-BY2YPBkT.js";
|
|
4
4
|
import { n as projectRecordFields } from "./project-B0j_Vf_Q.js";
|
|
5
5
|
import { n as backoffDelayMs, r as classifyListenerError } from "./listen-D5av7GzB.js";
|
|
6
6
|
import { n as isSafeCustomViewI18nPath, r as isSafeCustomViewPath, t as isSafeActionTemplatePath } from "./templatePath-k_WNbL_Q.js";
|
|
@@ -8,6 +8,7 @@ import { readFileSync, realpathSync, watch } from "node:fs";
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { createHash, randomBytes } from "node:crypto";
|
|
10
10
|
import { lstat, mkdir, open, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
11
|
+
import { Timestamp } from "firebase/firestore";
|
|
11
12
|
import { tmpdir } from "node:os";
|
|
12
13
|
import iconv from "iconv-lite";
|
|
13
14
|
import { z } from "zod";
|
|
@@ -473,10 +474,10 @@ async function guarded(key, email, run) {
|
|
|
473
474
|
* It also removes the reason a submit path would have had to accept the
|
|
474
475
|
* primary key as a `createField` at all — a submission that cannot name its
|
|
475
476
|
* own id is exactly right when the id is the thing being assigned. */
|
|
476
|
-
function toItem(data, docId,
|
|
477
|
+
function toItem(data, docId, schema) {
|
|
477
478
|
return isRecord(data) ? {
|
|
478
|
-
...data,
|
|
479
|
-
[primaryKey]: docId
|
|
479
|
+
...decodeRecordTimes(data, schema),
|
|
480
|
+
[schema.primaryKey]: docId
|
|
480
481
|
} : null;
|
|
481
482
|
}
|
|
482
483
|
/** Record ids are validated with the SAME helper every other backend uses.
|
|
@@ -488,26 +489,26 @@ function withSafeId(itemId, onInvalid, run) {
|
|
|
488
489
|
if (safeId === null) return onInvalid();
|
|
489
490
|
return run(safeId, requireHandle());
|
|
490
491
|
}
|
|
491
|
-
async function firestoreList(key,
|
|
492
|
+
async function firestoreList(key, schema) {
|
|
492
493
|
const { docs, email } = requireHandle();
|
|
493
|
-
return (await guarded(key, email, () => docs.list(sharedItemsPath(key)))).map((entry) => toItem(entry.data, entry.id,
|
|
494
|
+
return (await guarded(key, email, () => docs.list(sharedItemsPath(key)))).map((entry) => toItem(entry.data, entry.id, schema)).filter((item) => item !== null);
|
|
494
495
|
}
|
|
495
496
|
/** Paging is emulated over a full ordered read rather than pushed into
|
|
496
497
|
* Firestore: `offset` has no server-side form there (the cursor API needs the
|
|
497
498
|
* preceding document, which a stateless offset/limit call doesn't have), and
|
|
498
499
|
* `total` needs the full count anyway. Hence `nativePaging: false` — the
|
|
499
500
|
* capability is honest about the cost. */
|
|
500
|
-
async function firestorePage(key,
|
|
501
|
-
const items = await firestoreList(key,
|
|
501
|
+
async function firestorePage(key, schema, opts) {
|
|
502
|
+
const items = await firestoreList(key, schema);
|
|
502
503
|
const offset = Math.max(0, opts.offset ?? 0);
|
|
503
504
|
return {
|
|
504
|
-
items: projectItemFields(opts.limit === void 0 ? items.slice(offset) : items.slice(offset, offset + Math.max(0, opts.limit)), opts.fields, primaryKey),
|
|
505
|
+
items: projectItemFields(opts.limit === void 0 ? items.slice(offset) : items.slice(offset, offset + Math.max(0, opts.limit)), opts.fields, schema.primaryKey),
|
|
505
506
|
total: items.length,
|
|
506
507
|
truncated: false
|
|
507
508
|
};
|
|
508
509
|
}
|
|
509
|
-
async function firestoreRead(key, itemId,
|
|
510
|
-
return withSafeId(itemId, () => Promise.resolve(null), async (safeId, { docs, email }) => toItem(await guarded(key, email, () => docs.get(sharedItemsPath(key), safeId)), safeId,
|
|
510
|
+
async function firestoreRead(key, itemId, schema) {
|
|
511
|
+
return withSafeId(itemId, () => Promise.resolve(null), async (safeId, { docs, email }) => toItem(await guarded(key, email, () => docs.get(sharedItemsPath(key), safeId)), safeId, schema));
|
|
511
512
|
}
|
|
512
513
|
/** Publish the "records changed" ping for a shared collection.
|
|
513
514
|
*
|
|
@@ -522,18 +523,35 @@ function publishShared(key, ids, operation) {
|
|
|
522
523
|
op: operation
|
|
523
524
|
}, key.aid));
|
|
524
525
|
}
|
|
525
|
-
|
|
526
|
+
/** The write half of the decode above, and it is not optional.
|
|
527
|
+
*
|
|
528
|
+
* A record is read, edited and written back WHOLE — `putItems`' upsert
|
|
529
|
+
* replaces the document — so a decoded stamp would return to Firestore as a
|
|
530
|
+
* string. The rules freeze that field by comparing `diff().affectedKeys()`, so
|
|
531
|
+
* that write is refused and so is every later one: the record becomes
|
|
532
|
+
* permanently unupdatable. Dropping the key instead does not help, because a
|
|
533
|
+
* removed key is an affected key too.
|
|
534
|
+
*
|
|
535
|
+
* Only a `datetime` field carrying the exact canonical form is converted, and
|
|
536
|
+
* that form is only ever produced by the decode — so the pair is closed over
|
|
537
|
+
* its own output and cannot re-type a value somebody else wrote. */
|
|
538
|
+
async function firestoreWrite(key, itemId, item, schema, opts) {
|
|
526
539
|
return withSafeId(itemId, () => Promise.resolve({
|
|
527
540
|
kind: "invalid-id",
|
|
528
541
|
itemId
|
|
529
542
|
}), async (safeId, { docs, email }) => {
|
|
530
543
|
const collectionPath = sharedItemsPath(key);
|
|
544
|
+
const asTimestamp = (parts) => new Timestamp(parts.seconds, parts.nanoseconds);
|
|
531
545
|
if (opts.refuseOverwrite) {
|
|
532
|
-
if (!await guarded(key, email, () => docs.create(collectionPath, safeId, item))) return {
|
|
546
|
+
if (!await guarded(key, email, () => docs.create(collectionPath, safeId, encodeRecordTimes(item, null, asTimestamp)))) return {
|
|
533
547
|
kind: "conflict",
|
|
534
548
|
itemId: safeId
|
|
535
549
|
};
|
|
536
|
-
} else
|
|
550
|
+
} else {
|
|
551
|
+
const previous = await guarded(key, email, () => docs.get(collectionPath, safeId));
|
|
552
|
+
const stored = encodeRecordTimes(item, isRecord(previous) ? previous : null, asTimestamp);
|
|
553
|
+
await guarded(key, email, () => docs.set(collectionPath, safeId, stored));
|
|
554
|
+
}
|
|
537
555
|
if (opts.slug) publishShared(key, [safeId], "upsert");
|
|
538
556
|
return {
|
|
539
557
|
kind: "ok",
|
|
@@ -666,7 +684,7 @@ function armSharedWatch(key, onChange) {
|
|
|
666
684
|
/** The store factory registered for `storage.type === "firestore"`.
|
|
667
685
|
* Synchronous and connection-agnostic by contract — see the header. */
|
|
668
686
|
function firestoreStoreFor(collection, opts) {
|
|
669
|
-
const {
|
|
687
|
+
const { schema } = collection;
|
|
670
688
|
const ioOpts = {
|
|
671
689
|
...opts,
|
|
672
690
|
slug: opts.slug ?? collection.slug
|
|
@@ -677,10 +695,10 @@ function firestoreStoreFor(collection, opts) {
|
|
|
677
695
|
nativeQuery: false,
|
|
678
696
|
nativePaging: false
|
|
679
697
|
},
|
|
680
|
-
list: async () => firestoreList(keyOf(collection),
|
|
681
|
-
page: async (pageOpts = {}) => firestorePage(keyOf(collection),
|
|
682
|
-
read: async (itemId) => firestoreRead(keyOf(collection), itemId,
|
|
683
|
-
write: async (itemId, item, writeOpts = {}) => firestoreWrite(keyOf(collection), itemId, item, {
|
|
698
|
+
list: async () => firestoreList(keyOf(collection), schema),
|
|
699
|
+
page: async (pageOpts = {}) => firestorePage(keyOf(collection), schema, pageOpts),
|
|
700
|
+
read: async (itemId) => firestoreRead(keyOf(collection), itemId, schema),
|
|
701
|
+
write: async (itemId, item, writeOpts = {}) => firestoreWrite(keyOf(collection), itemId, item, schema, {
|
|
684
702
|
...ioOpts,
|
|
685
703
|
refuseOverwrite: writeOpts.refuseOverwrite
|
|
686
704
|
}),
|
|
@@ -3315,4 +3333,4 @@ function toDetail(collection) {
|
|
|
3315
3333
|
//#endregion
|
|
3316
3334
|
export { collectionsRegistriesConfigPath as $, readItem as A, SCHEMA_FILE as B, CollectionQueryZ as C, generateItemId as D, deleteItem as E, loadAppManifest as F, safeRecordId as G, itemFilePath as H, parseAppManifest as I, isBackendUnavailable as J, safeSlugName as K, sharedItemsPath as L, writeItem as M, APP_MANIFEST_FILE as N, isRegularFile as O, appManifestReason as P, collectionChangePayload as Q, pageFromFullRead as R, compileJsonlQuery as S, MAX_QUERY_ROWS as T, resolveDataDir as U, isContainedInRoot as V, resolveTemplatePath as W, archiveDir as X, COLLECTION_ROOT_REQUIRED as Y, collectionChangeKey as Z, dedupeByRecordId as _, createHostSlot as _t, toDetail as a, localCollectionKey as at, queryCsv as b, resolveMutateSet as c, projectSkillsDir as ct, storeFor as d, setFirestoreAccessor as dt, configureCollectionHost as et, checkpointSqliteDatabase as f, setSharedCollectionsSupport as ft, decodeCsvRecordId as g, createForwardingLogger as gt, csvRowToItem as h, stagingSkillDir as ht, resolvePrimaryField as i, isPresetSlug as it, resolveCreateItemId as j, listItems as k, collectionWritable as l, publishCollectionChange as lt, cacheDir as m, skillsStagingDir as mt, discoverCollections as n, getWorkspaceRoot as nt, toSummary as o, log as ot, MAX_CSV_ROWS as p, sharedCollectionChangePayload as pt, BackendUnavailableError as q, loadCollection as r, hostSupportsSharedCollections as rt, CollectionSchemaZ as s, peekWorkspaceRoot as st, acceptParsedSchema as t, firestoreHandle as tt, readOnlyRefusal as u, setCollectionChangePublisher as ut, encodeCsvRecordId as v, DEFAULT_QUERY_ROWS as w, compileCsvQuery as x, normalizeCsvValue as y, projectItemFields as z };
|
|
3317
3335
|
|
|
3318
|
-
//# sourceMappingURL=discovery-
|
|
3336
|
+
//# sourceMappingURL=discovery-P64fgtuD.js.map
|