@mulmoclaude/core 1.12.0 → 1.14.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/error-recovery.md +110 -1
- package/dist/{calendarGrid-CaS9er8i.cjs → calendarGrid-BQYqOCnF.cjs} +8 -9
- package/dist/{calendarGrid-CaS9er8i.cjs.map → calendarGrid-BQYqOCnF.cjs.map} +1 -1
- package/dist/{calendarGrid-CrGxeCOG.js → calendarGrid-DivcNKkX.js} +8 -9
- package/dist/{calendarGrid-CrGxeCOG.js.map → calendarGrid-DivcNKkX.js.map} +1 -1
- package/dist/collection/core/project.d.ts +11 -0
- package/dist/collection/core/schemaZ.d.ts +4 -4
- package/dist/collection/index.cjs +5 -4
- package/dist/collection/index.js +5 -5
- package/dist/collection/registry/server/index.cjs +3 -3
- package/dist/collection/registry/server/index.cjs.map +1 -1
- package/dist/collection/registry/server/index.js +3 -3
- package/dist/collection/registry/server/index.js.map +1 -1
- package/dist/collection/server/csvQuery.d.ts +7 -2
- package/dist/collection/server/csvStore.d.ts +2 -1
- package/dist/collection/server/index.cjs +3 -3
- package/dist/collection/server/index.js +3 -3
- package/dist/collection-watchers/index.cjs +10 -25
- package/dist/collection-watchers/index.cjs.map +1 -1
- package/dist/collection-watchers/index.js +10 -25
- package/dist/collection-watchers/index.js.map +1 -1
- package/dist/{discovery-NRy3tyUA.cjs → discovery-CRDx6TS4.cjs} +88 -47
- package/dist/discovery-CRDx6TS4.cjs.map +1 -0
- package/dist/{discovery-B4CZvrXR.js → discovery-D6p4ITNR.js} +88 -47
- package/dist/discovery-D6p4ITNR.js.map +1 -0
- package/dist/{dist-pWpC-b04.cjs → dist-CsgSfWwR.cjs} +66 -1
- package/dist/{dist-pWpC-b04.cjs.map → dist-CsgSfWwR.cjs.map} +1 -1
- package/dist/{dist-Cwk0e12G.js → dist-D8zokgGo.js} +25 -2
- package/dist/{dist-Cwk0e12G.js.map → dist-D8zokgGo.js.map} +1 -1
- package/dist/feeds/index.cjs +2 -2
- package/dist/feeds/index.js +2 -2
- package/dist/feeds/server/engine.d.ts +27 -0
- package/dist/feeds/server/index.cjs +97 -26
- package/dist/feeds/server/index.cjs.map +1 -1
- package/dist/feeds/server/index.d.ts +1 -1
- package/dist/feeds/server/index.js +96 -27
- package/dist/feeds/server/index.js.map +1 -1
- package/dist/google/calendar.d.ts +23 -9
- package/dist/google/calendarStateLock.d.ts +23 -0
- package/dist/google/collectionProjection.d.ts +0 -8
- package/dist/google/collectionPush.d.ts +13 -8
- package/dist/google/collectionSync.d.ts +80 -10
- package/dist/google/index.cjs +366 -98
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.d.ts +6 -4
- package/dist/google/index.js +357 -99
- package/dist/google/index.js.map +1 -1
- package/dist/{ingestTypes-D1GQdG8e.cjs → ingestTypes-C7IJSqv4.cjs} +2 -2
- package/dist/{ingestTypes-D1GQdG8e.cjs.map → ingestTypes-C7IJSqv4.cjs.map} +1 -1
- package/dist/{ingestTypes-XReG-li7.js → ingestTypes-DmtDLRmt.js} +2 -2
- package/dist/{ingestTypes-XReG-li7.js.map → ingestTypes-DmtDLRmt.js.map} +1 -1
- package/dist/notifier/index.cjs +1 -1
- package/dist/notifier/index.js +1 -1
- package/dist/notifier/store.d.ts +4 -4
- package/dist/{notifier-BdA5qzhe.js → notifier-Dxh8mEFh.js} +39 -25
- package/dist/notifier-Dxh8mEFh.js.map +1 -0
- package/dist/{notifier-tMsAXyXp.cjs → notifier-Wc4M24Bi.cjs} +39 -25
- package/dist/notifier-Wc4M24Bi.cjs.map +1 -0
- package/dist/plugin-vue/index.cjs +4 -2
- package/dist/plugin-vue/index.cjs.map +1 -1
- package/dist/plugin-vue/index.js +4 -2
- package/dist/plugin-vue/index.js.map +1 -1
- package/dist/project-B0j_Vf_Q.js +33 -0
- package/dist/project-B0j_Vf_Q.js.map +1 -0
- package/dist/project-C1ep9pvo.cjs +44 -0
- package/dist/project-C1ep9pvo.cjs.map +1 -0
- package/dist/{promptSafety-FD8cQn3e.cjs → promptSafety-B52GvaJc.cjs} +99 -85
- package/dist/promptSafety-B52GvaJc.cjs.map +1 -0
- package/dist/{promptSafety-C--op_6a.js → promptSafety-DJgaDjM4.js} +99 -85
- package/dist/promptSafety-DJgaDjM4.js.map +1 -0
- package/dist/remote-host/index.cjs +2 -1
- package/dist/remote-host/index.d.ts +10 -0
- package/dist/remote-host/index.js +2 -2
- package/dist/remote-host/server/index.cjs +2 -2
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +2 -2
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/{remote-host-DkDVxNim.cjs → remote-host-CtQjagPt.cjs} +53 -1
- package/dist/remote-host-CtQjagPt.cjs.map +1 -0
- package/dist/remote-host-Dba4lF3Z.js +82 -0
- package/dist/remote-host-Dba4lF3Z.js.map +1 -0
- package/dist/remote-view/index.cjs +6 -4
- package/dist/remote-view/index.cjs.map +1 -1
- package/dist/remote-view/index.js +6 -4
- package/dist/remote-view/index.js.map +1 -1
- package/dist/scheduler/index.cjs +1 -1
- package/dist/scheduler/index.js +1 -1
- package/dist/{server-DdyIvFhz.js → server-D6EUf3BF.js} +46 -27
- package/dist/server-D6EUf3BF.js.map +1 -0
- package/dist/{server-7U-3DE2e.cjs → server-D7_oRbTJ.cjs} +46 -27
- package/dist/server-D7_oRbTJ.cjs.map +1 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/whisper/index.cjs +2 -6
- package/dist/whisper/index.cjs.map +1 -1
- package/dist/whisper/index.js +2 -6
- package/dist/whisper/index.js.map +1 -1
- package/dist/wiki/index.cjs +2 -2
- package/dist/wiki/index.cjs.map +1 -1
- package/dist/wiki/index.js +2 -2
- package/dist/wiki/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/discovery-B4CZvrXR.js.map +0 -1
- package/dist/discovery-NRy3tyUA.cjs.map +0 -1
- package/dist/notifier-BdA5qzhe.js.map +0 -1
- package/dist/notifier-tMsAXyXp.cjs.map +0 -1
- package/dist/project-BWI5w_BT.cjs +0 -17
- package/dist/project-BWI5w_BT.cjs.map +0 -1
- package/dist/project-bU98ycsy.js +0 -12
- package/dist/project-bU98ycsy.js.map +0 -1
- package/dist/promptSafety-C--op_6a.js.map +0 -1
- package/dist/promptSafety-FD8cQn3e.cjs.map +0 -1
- package/dist/remote-host-D_BRFHcI.js +0 -36
- package/dist/remote-host-D_BRFHcI.js.map +0 -1
- package/dist/remote-host-DkDVxNim.cjs.map +0 -1
- package/dist/server-7U-3DE2e.cjs.map +0 -1
- package/dist/server-DdyIvFhz.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { a as isErrorWithCode, l as isUnknownArray, r as hasNumberProp, s as isRecord } from "./dist-D8zokgGo.js";
|
|
1
2
|
import { t as writeFileAtomic } from "./atomic-DPpdrJzO.js";
|
|
2
|
-
import { A as fieldTextOrNull, C as FEED_SCHEDULES, D as isReadOnlySchema, O as storageKindFor, S as COMPUTED_TYPES, g as SAFE_SLUG_PATTERN, h as SAFE_RECORD_ID_PATTERN, k as fieldText, v as isSafeRecordId, w as INGEST_KINDS, x as AGENT_INGEST_KIND, y as isSafeSlug } from "./calendarGrid-
|
|
3
|
-
import {
|
|
3
|
+
import { A as fieldTextOrNull, C as FEED_SCHEDULES, D as isReadOnlySchema, O as storageKindFor, S as COMPUTED_TYPES, g as SAFE_SLUG_PATTERN, h as SAFE_RECORD_ID_PATTERN, k as fieldText, v as isSafeRecordId, w as INGEST_KINDS, x as AGENT_INGEST_KIND, y as isSafeSlug } from "./calendarGrid-DivcNKkX.js";
|
|
4
|
+
import { n as projectRecordFields } from "./project-B0j_Vf_Q.js";
|
|
4
5
|
import { n as isSafeCustomViewI18nPath, r as isSafeCustomViewPath, t as isSafeActionTemplatePath } from "./templatePath-k_WNbL_Q.js";
|
|
5
6
|
import { realpathSync, watch } from "node:fs";
|
|
6
7
|
import path from "node:path";
|
|
@@ -141,7 +142,7 @@ function realpathClosestAncestor(absPath) {
|
|
|
141
142
|
while (cursor !== path.dirname(cursor)) try {
|
|
142
143
|
return realpathSync(cursor);
|
|
143
144
|
} catch (err) {
|
|
144
|
-
if (err.code === "ENOENT") {
|
|
145
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") {
|
|
145
146
|
cursor = path.dirname(cursor);
|
|
146
147
|
continue;
|
|
147
148
|
}
|
|
@@ -245,8 +246,7 @@ async function isRegularFile(filePath) {
|
|
|
245
246
|
* null when it isn't a JSON object (array / scalar / null). */
|
|
246
247
|
function parseRecordJson(raw) {
|
|
247
248
|
const parsed = JSON.parse(raw);
|
|
248
|
-
|
|
249
|
-
return null;
|
|
249
|
+
return isRecord(parsed) ? parsed : null;
|
|
250
250
|
}
|
|
251
251
|
async function tryReadRecord(filePath) {
|
|
252
252
|
if (!await isRegularFile(filePath)) return null;
|
|
@@ -271,7 +271,7 @@ async function listItems(dataDir, opts = {}) {
|
|
|
271
271
|
try {
|
|
272
272
|
entries = await readdir(dataDir);
|
|
273
273
|
} catch (err) {
|
|
274
|
-
if (err.code === "ENOENT") return [];
|
|
274
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return [];
|
|
275
275
|
throw err;
|
|
276
276
|
}
|
|
277
277
|
const results = [];
|
|
@@ -301,7 +301,7 @@ async function readItem(dataDir, itemId, opts = {}) {
|
|
|
301
301
|
try {
|
|
302
302
|
return parseRecordJson(await readFile(filePath, "utf-8"));
|
|
303
303
|
} catch (err) {
|
|
304
|
-
if (err.code === "ENOENT") return null;
|
|
304
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return null;
|
|
305
305
|
throw err;
|
|
306
306
|
}
|
|
307
307
|
}
|
|
@@ -371,7 +371,7 @@ async function writeItem(dataDir, itemId, item, opts = {}) {
|
|
|
371
371
|
try {
|
|
372
372
|
handle = await open(filePath, "wx");
|
|
373
373
|
} catch (err) {
|
|
374
|
-
if (err.code === "EEXIST") return {
|
|
374
|
+
if (isErrorWithCode(err) && err.code === "EEXIST") return {
|
|
375
375
|
kind: "conflict",
|
|
376
376
|
itemId: safeId
|
|
377
377
|
};
|
|
@@ -417,7 +417,7 @@ async function deleteItem(dataDir, itemId, opts = {}) {
|
|
|
417
417
|
itemId: safeId
|
|
418
418
|
};
|
|
419
419
|
} catch (err) {
|
|
420
|
-
if (err.code === "ENOENT") return {
|
|
420
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return {
|
|
421
421
|
kind: "not-found",
|
|
422
422
|
itemId: safeId
|
|
423
423
|
};
|
|
@@ -595,7 +595,7 @@ function whereFragment(cond) {
|
|
|
595
595
|
}
|
|
596
596
|
if (cond.op === "contains") return {
|
|
597
597
|
sql: `contains(${asText}, ?)`,
|
|
598
|
-
params: [String(cond
|
|
598
|
+
params: [String(scalarValue(cond))]
|
|
599
599
|
};
|
|
600
600
|
const operator = {
|
|
601
601
|
eq: "=",
|
|
@@ -607,9 +607,16 @@ function whereFragment(cond) {
|
|
|
607
607
|
}[cond.op];
|
|
608
608
|
return {
|
|
609
609
|
sql: `${typeof cond.value === "string" && (cond.op === "eq" || cond.op === "ne") ? asText : column} ${operator} ?`,
|
|
610
|
-
params: [cond
|
|
610
|
+
params: [scalarValue(cond)]
|
|
611
611
|
};
|
|
612
612
|
}
|
|
613
|
+
/** `CollectionQueryZ` refines "`in` ⇔ array value", so an array reaching a
|
|
614
|
+
* scalar op means the query was compiled without being validated first —
|
|
615
|
+
* binding it would send an array to a single `?`. */
|
|
616
|
+
function scalarValue(cond) {
|
|
617
|
+
if (Array.isArray(cond.value)) throw new Error(`where condition on '${cond.field}' uses op '${cond.op}', which requires a scalar value, not an array`);
|
|
618
|
+
return cond.value;
|
|
619
|
+
}
|
|
613
620
|
/** Compile a validated query against `fromSql` (a table-function call
|
|
614
621
|
* whose FIRST placeholder is the source path — the executor binds it).
|
|
615
622
|
* Returns the SQL and the where-value parameters that follow the path.
|
|
@@ -831,7 +838,7 @@ async function safeCsvStat(absPath, workspaceRoot) {
|
|
|
831
838
|
try {
|
|
832
839
|
info = await lstat(absPath);
|
|
833
840
|
} catch (err) {
|
|
834
|
-
if (err.code === "ENOENT") return null;
|
|
841
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return null;
|
|
835
842
|
throw err;
|
|
836
843
|
}
|
|
837
844
|
if (!info.isFile()) {
|
|
@@ -1045,7 +1052,7 @@ function projectItemFields(items, fields, primaryKey) {
|
|
|
1045
1052
|
* tests. `limit: 0` is a valid "count only" page. */
|
|
1046
1053
|
function pageFromFullRead(items, opts, primaryKey, truncated) {
|
|
1047
1054
|
const offset = Math.max(0, opts.offset ?? 0);
|
|
1048
|
-
const end = opts.limit === void 0 ?
|
|
1055
|
+
const end = opts.limit === void 0 ? items.length : offset + Math.max(0, opts.limit);
|
|
1049
1056
|
return {
|
|
1050
1057
|
items: projectItemFields(items.slice(offset, end), opts.fields, primaryKey),
|
|
1051
1058
|
total: items.length,
|
|
@@ -1054,14 +1061,23 @@ function pageFromFullRead(items, opts, primaryKey, truncated) {
|
|
|
1054
1061
|
}
|
|
1055
1062
|
//#endregion
|
|
1056
1063
|
//#region src/collection/server/sqliteStore.ts
|
|
1064
|
+
/** A constructor's parameter and return types are not observable at runtime,
|
|
1065
|
+
* so the check stops at "DatabaseSync is constructible" — the only member of
|
|
1066
|
+
* the module this store ever touches. */
|
|
1067
|
+
function isSqliteModule(mod) {
|
|
1068
|
+
return isRecord(mod) && typeof mod.DatabaseSync === "function";
|
|
1069
|
+
}
|
|
1057
1070
|
var sqliteModule = null;
|
|
1071
|
+
/** Drops the memo first so a later call can retry (e.g. tests stubbing the
|
|
1072
|
+
* runtime), then reports why the backend is unusable. */
|
|
1073
|
+
function sqliteUnavailable(reason) {
|
|
1074
|
+
sqliteModule = null;
|
|
1075
|
+
throw new BackendUnavailableError(`sqlite storage needs the node:sqlite module (Node.js >= 22.5) — this runtime cannot load it: ${reason}`);
|
|
1076
|
+
}
|
|
1058
1077
|
/** Lazy-load node:sqlite once. A runtime without it (Node < 22.5) throws a
|
|
1059
1078
|
* clearly-worded error the caller surfaces — never a bare MODULE_NOT_FOUND. */
|
|
1060
1079
|
function loadSqlite() {
|
|
1061
|
-
sqliteModule ??= import("node:sqlite").then((mod) => mod, (err) =>
|
|
1062
|
-
sqliteModule = null;
|
|
1063
|
-
throw new BackendUnavailableError(`sqlite storage needs the node:sqlite module (Node.js >= 22.5) — this runtime cannot load it: ${String(err)}`);
|
|
1064
|
-
});
|
|
1080
|
+
sqliteModule ??= import("node:sqlite").then((mod) => isSqliteModule(mod) ? mod : sqliteUnavailable("the module exposes no DatabaseSync constructor"), (err) => sqliteUnavailable(String(err)));
|
|
1065
1081
|
return sqliteModule;
|
|
1066
1082
|
}
|
|
1067
1083
|
/** The db file's on-disk state. A symlink or non-regular file is refused
|
|
@@ -1073,7 +1089,7 @@ async function dbFileState(absPath) {
|
|
|
1073
1089
|
try {
|
|
1074
1090
|
return (await lstat(absPath)).isFile() ? "file" : "refused";
|
|
1075
1091
|
} catch (err) {
|
|
1076
|
-
if (err.code === "ENOENT") return "missing";
|
|
1092
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return "missing";
|
|
1077
1093
|
throw err;
|
|
1078
1094
|
}
|
|
1079
1095
|
}
|
|
@@ -1125,27 +1141,39 @@ async function withDb(absPath, workspaceRoot, mode, onUnavailable, operation) {
|
|
|
1125
1141
|
handle.database.close();
|
|
1126
1142
|
}
|
|
1127
1143
|
}
|
|
1144
|
+
var SQLITE_CONSTRAINT_PRIMARYKEY = 1555;
|
|
1145
|
+
var SQLITE_CONSTRAINT_UNIQUE = 2067;
|
|
1128
1146
|
/** node:sqlite throws ERR_SQLITE_ERROR with the SQLite extended result
|
|
1129
|
-
* code on `errcode`.
|
|
1130
|
-
*
|
|
1131
|
-
* covers a plain UNIQUE index. Checked structurally (message text kept
|
|
1132
|
-
* only as a fallback for runtimes that don't expose `errcode`). */
|
|
1147
|
+
* code on `errcode`. Checked structurally (message text kept only as a
|
|
1148
|
+
* fallback for runtimes that don't expose `errcode`). */
|
|
1133
1149
|
function isUniqueConstraintError(err) {
|
|
1134
|
-
|
|
1135
|
-
if (errcode !== void 0) return errcode === 1555 || errcode === 2067;
|
|
1150
|
+
if (hasNumberProp(err, "errcode")) return err.errcode === SQLITE_CONSTRAINT_PRIMARYKEY || err.errcode === SQLITE_CONSTRAINT_UNIQUE;
|
|
1136
1151
|
return String(err).includes("UNIQUE constraint");
|
|
1137
1152
|
}
|
|
1138
1153
|
function parseRow(raw) {
|
|
1139
1154
|
if (typeof raw !== "string") return null;
|
|
1140
1155
|
try {
|
|
1141
1156
|
const parsed = JSON.parse(raw);
|
|
1142
|
-
return
|
|
1157
|
+
return isRecord(parsed) ? parsed : null;
|
|
1143
1158
|
} catch {
|
|
1144
1159
|
return null;
|
|
1145
1160
|
}
|
|
1146
1161
|
}
|
|
1162
|
+
/** One column of a result row. node:sqlite types rows as `unknown`, so a
|
|
1163
|
+
* value that is not a row object yields no column at all. */
|
|
1164
|
+
function readColumn(row, column) {
|
|
1165
|
+
return isRecord(row) ? row[column] : void 0;
|
|
1166
|
+
}
|
|
1147
1167
|
function rowsToItems(rows) {
|
|
1148
|
-
return rows.map((row) => parseRow(row
|
|
1168
|
+
return rows.map((row) => parseRow(readColumn(row, "record"))).filter((item) => item !== null);
|
|
1169
|
+
}
|
|
1170
|
+
/** node:sqlite hands back an integer column as `number`, or as `bigint` once
|
|
1171
|
+
* it leaves the safe-integer range — COUNT(*) can be either. */
|
|
1172
|
+
function countRecords(database) {
|
|
1173
|
+
const count = readColumn(database.prepare("SELECT COUNT(*) AS n FROM records").get(), "n");
|
|
1174
|
+
if (typeof count === "number") return count;
|
|
1175
|
+
if (typeof count === "bigint") return Number(count);
|
|
1176
|
+
throw new Error(`sqlite COUNT(*) returned no numeric row count (got ${typeof count})`);
|
|
1149
1177
|
}
|
|
1150
1178
|
async function sqliteList(absPath, workspaceRoot) {
|
|
1151
1179
|
return withDb(absPath, workspaceRoot, "read", () => [], (database) => rowsToItems(database.prepare("SELECT record FROM records ORDER BY id").all()));
|
|
@@ -1157,7 +1185,7 @@ async function sqlitePage(absPath, primaryKey, opts, workspaceRoot) {
|
|
|
1157
1185
|
truncated: false
|
|
1158
1186
|
};
|
|
1159
1187
|
return withDb(absPath, workspaceRoot, "read", () => emptyPage, (database) => {
|
|
1160
|
-
const total =
|
|
1188
|
+
const total = countRecords(database);
|
|
1161
1189
|
const offset = Math.max(0, opts.offset ?? 0);
|
|
1162
1190
|
const limit = opts.limit === void 0 ? -1 : Math.max(0, opts.limit);
|
|
1163
1191
|
return {
|
|
@@ -1171,8 +1199,7 @@ async function sqliteRead(absPath, itemId, workspaceRoot) {
|
|
|
1171
1199
|
const safeId = safeRecordId(itemId);
|
|
1172
1200
|
if (safeId === null) return null;
|
|
1173
1201
|
return withDb(absPath, workspaceRoot, "read", () => null, (database) => {
|
|
1174
|
-
|
|
1175
|
-
return row === void 0 ? null : parseRow(row.record);
|
|
1202
|
+
return parseRow(readColumn(database.prepare("SELECT record FROM records WHERE id = ?").get(safeId), "record"));
|
|
1176
1203
|
});
|
|
1177
1204
|
}
|
|
1178
1205
|
async function sqliteWrite(absPath, itemId, item, opts) {
|
|
@@ -2150,7 +2177,7 @@ var SpawnZ = z.object({
|
|
|
2150
2177
|
* items natively and ignore it — so no kind-specific requirement here. */
|
|
2151
2178
|
var DeclarativeIngestZ = z.object({
|
|
2152
2179
|
kind: z.enum(INGEST_KINDS),
|
|
2153
|
-
url: z.
|
|
2180
|
+
url: z.url(),
|
|
2154
2181
|
schedule: z.enum(FEED_SCHEDULES),
|
|
2155
2182
|
atHour: z.number().int().min(0).max(23).optional(),
|
|
2156
2183
|
itemsAt: z.string().trim().min(1).optional(),
|
|
@@ -2405,23 +2432,38 @@ function ownPrototypeKey(value) {
|
|
|
2405
2432
|
for (const key of PROTOTYPE_KEYS) if (Object.hasOwn(value, key)) return key;
|
|
2406
2433
|
return null;
|
|
2407
2434
|
}
|
|
2435
|
+
/** Own enumerable entries of an object (arrays keyed by index), none for
|
|
2436
|
+
* anything else — the raw input is unvalidated, so `fields` may be junk. */
|
|
2437
|
+
function ownEntries(value) {
|
|
2438
|
+
if (isUnknownArray(value)) return value.map((entry, index) => [String(index), entry]);
|
|
2439
|
+
return isRecord(value) ? Object.entries(value) : [];
|
|
2440
|
+
}
|
|
2441
|
+
/** The name-defining sub-record a raw field spec (`of`) or action (`params`)
|
|
2442
|
+
* carries, or undefined when the holder isn't an object at all. */
|
|
2443
|
+
function nameDefiningSubRecord(holder, key) {
|
|
2444
|
+
return isRecord(holder) ? holder[key] : void 0;
|
|
2445
|
+
}
|
|
2446
|
+
/** Dotted path of the first prototype-sensitive `params` name across both
|
|
2447
|
+
* action lists, or null. */
|
|
2448
|
+
function prototypeActionParamPath(input) {
|
|
2449
|
+
for (const [listName, list] of [["actions", input.actions], ["collectionActions", input.collectionActions]]) for (const action of isUnknownArray(list) ? list : []) {
|
|
2450
|
+
const badParam = ownPrototypeKey(nameDefiningSubRecord(action, "params"));
|
|
2451
|
+
if (badParam !== null) return `${listName}.params.${badParam}`;
|
|
2452
|
+
}
|
|
2453
|
+
return null;
|
|
2454
|
+
}
|
|
2408
2455
|
/** Dotted path of the first prototype-sensitive field name in the raw
|
|
2409
2456
|
* schema input — top-level `fields`, each table field's `of`, and each
|
|
2410
2457
|
* action's `params` (the three records that DEFINE names) — or null. */
|
|
2411
2458
|
function prototypeFieldKeyPath(input) {
|
|
2412
|
-
if (input
|
|
2413
|
-
const
|
|
2414
|
-
const bad = ownPrototypeKey(schema.fields);
|
|
2459
|
+
if (!isRecord(input)) return null;
|
|
2460
|
+
const bad = ownPrototypeKey(input.fields);
|
|
2415
2461
|
if (bad !== null) return `fields.${bad}`;
|
|
2416
|
-
for (const [key, spec] of
|
|
2417
|
-
const badSub = ownPrototypeKey(spec
|
|
2462
|
+
for (const [key, spec] of ownEntries(input.fields)) {
|
|
2463
|
+
const badSub = ownPrototypeKey(nameDefiningSubRecord(spec, "of"));
|
|
2418
2464
|
if (badSub !== null) return `fields.${key}.of.${badSub}`;
|
|
2419
2465
|
}
|
|
2420
|
-
|
|
2421
|
-
const badParam = ownPrototypeKey(action?.params);
|
|
2422
|
-
if (badParam !== null) return `${listName}.params.${badParam}`;
|
|
2423
|
-
}
|
|
2424
|
-
return null;
|
|
2466
|
+
return prototypeActionParamPath(input);
|
|
2425
2467
|
}
|
|
2426
2468
|
var CollectionSchemaZ = z.preprocess((input, ctx) => {
|
|
2427
2469
|
const bad = prototypeFieldKeyPath(input);
|
|
@@ -2437,11 +2479,10 @@ var CollectionSchemaZ = z.preprocess((input, ctx) => {
|
|
|
2437
2479
|
//#endregion
|
|
2438
2480
|
//#region src/collection/server/discovery.ts
|
|
2439
2481
|
function applyFeedSchemaDefaults(parsed, slug) {
|
|
2440
|
-
if (!
|
|
2441
|
-
const
|
|
2442
|
-
const icon = typeof obj.icon === "string" && obj.icon.trim().length > 0 ? obj.icon : "dynamic_feed";
|
|
2482
|
+
if (!isRecord(parsed)) return parsed;
|
|
2483
|
+
const icon = typeof parsed.icon === "string" && parsed.icon.trim().length > 0 ? parsed.icon : "dynamic_feed";
|
|
2443
2484
|
return {
|
|
2444
|
-
...
|
|
2485
|
+
...parsed,
|
|
2445
2486
|
icon,
|
|
2446
2487
|
dataPath: `data/feeds/${slug}`
|
|
2447
2488
|
};
|
|
@@ -2544,7 +2585,7 @@ async function loadOneCollection(skillsRoot, slug, source, workspaceRoot) {
|
|
|
2544
2585
|
if (!(await stat(schemaPath)).isFile()) return null;
|
|
2545
2586
|
raw = await readFile(schemaPath, "utf-8");
|
|
2546
2587
|
} catch (err) {
|
|
2547
|
-
if (err.code !== "ENOENT") log.warn("collections", "failed to read schema.json, skipping", {
|
|
2588
|
+
if (!isErrorWithCode(err) || err.code !== "ENOENT") log.warn("collections", "failed to read schema.json, skipping", {
|
|
2548
2589
|
slug: safeName,
|
|
2549
2590
|
path: schemaPath,
|
|
2550
2591
|
error: String(err)
|
|
@@ -2598,7 +2639,7 @@ async function collectFromDir(skillsRoot, source, workspaceRoot) {
|
|
|
2598
2639
|
try {
|
|
2599
2640
|
entries = await readdir(skillsRoot);
|
|
2600
2641
|
} catch (err) {
|
|
2601
|
-
if (err.code === "ENOENT") return [];
|
|
2642
|
+
if (isErrorWithCode(err) && err.code === "ENOENT") return [];
|
|
2602
2643
|
log.warn("collections", "failed to list skills dir, returning empty", {
|
|
2603
2644
|
root: skillsRoot,
|
|
2604
2645
|
error: String(err)
|
|
@@ -2674,4 +2715,4 @@ function toDetail(collection) {
|
|
|
2674
2715
|
//#endregion
|
|
2675
2716
|
export { skillsStagingDir as $, deleteItem as A, itemFilePath as B, compileCsvQuery as C, MAX_QUERY_ROWS as D, DEFAULT_QUERY_ROWS as E, resolveCreateItemId as F, archiveDir as G, resolveTemplatePath as H, writeItem as I, getWorkspaceRoot as J, collectionsRegistriesConfigPath as K, SCHEMA_FILE as L, isRegularFile as M, listItems as N, BackendUnavailableError as O, readItem as P, setCollectionChangePublisher as Q, isContainedInRoot as R, queryCsv as S, CollectionQueryZ as T, safeRecordId as U, resolveDataDir as V, safeSlugName as W, log as X, isPresetSlug as Y, publishCollectionChange as Z, csvRowToItem as _, toDetail as a, encodeCsvRecordId as b, resolveMutateSet as c, storeFor as d, createForwardingLogger as et, checkpointSqliteDatabase as f, cacheDir as g, MAX_CSV_ROWS as h, resolvePrimaryField as i, generateItemId as j, isBackendUnavailable as k, collectionWritable as l, projectItemFields as m, discoverCollections as n, toSummary as o, pageFromFullRead as p, configureCollectionHost as q, loadCollection as r, CollectionSchemaZ as s, acceptParsedSchema as t, createHostSlot as tt, readOnlyRefusal as u, decodeCsvRecordId as v, compileJsonlQuery as w, normalizeCsvValue as x, dedupeByRecordId as y, isContainedInWorkspace as z };
|
|
2676
2717
|
|
|
2677
|
-
//# sourceMappingURL=discovery-
|
|
2718
|
+
//# sourceMappingURL=discovery-D6p4ITNR.js.map
|