mindoodb-app-sdk 0.0.71 → 0.0.73
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 +99 -1
- package/dist/{chunk-GTNDGA7P.js → chunk-FKTNDDWB.js} +728 -40
- package/dist/index.d.ts +3 -55
- package/dist/index.js +57 -1
- package/dist/testing/index.d.ts +129 -2
- package/dist/testing/index.js +425 -17
- package/dist/{types-Dff-SyIx.d.ts → types-CbH_R16h.d.ts} +599 -5
- package/package.json +1 -1
|
@@ -66,6 +66,297 @@ function assertValidMindooDBCreateIds(input, methodName = "createDocument") {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// src/inspection.ts
|
|
70
|
+
var MINDOODB_INSPECT_DOCUMENT = "mindoo.inspect.document@1";
|
|
71
|
+
var MINDOODB_INSPECT_SPREADSHEET = "mindoo.inspect.spreadsheet@1";
|
|
72
|
+
var MINDOODB_INSPECT_SLIDES = "mindoo.inspect.slides@1";
|
|
73
|
+
var MINDOODB_APP_INSPECTION_FIELD = "inspection";
|
|
74
|
+
var MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES = 8 * 1024;
|
|
75
|
+
var MINDOODB_APP_INSPECTION_MAX_BYTES = 256 * 1024;
|
|
76
|
+
var MINDOODB_APP_ISSUES_MAX = 100;
|
|
77
|
+
var MindooDBAppEmbedValidationError = class extends Error {
|
|
78
|
+
constructor(issues) {
|
|
79
|
+
const first = issues.find((issue) => issue.severity === "error") ?? issues[0];
|
|
80
|
+
super(first ? first.message : "The document was not saved.");
|
|
81
|
+
this.issues = issues;
|
|
82
|
+
this.name = "MindooDBAppEmbedValidationError";
|
|
83
|
+
}
|
|
84
|
+
issues;
|
|
85
|
+
};
|
|
86
|
+
var SUPPORTS_CAPABILITY = /^[a-z][a-z0-9-]{0,31}$/;
|
|
87
|
+
function mindooDBAppComponentSupports(supports, requirement) {
|
|
88
|
+
const wanted = requirement.trim();
|
|
89
|
+
return (supports ?? []).some((entry) => entry === wanted || !wanted.includes(":") && entry.startsWith(`${wanted}:`));
|
|
90
|
+
}
|
|
91
|
+
function mindooDBAppInspectContracts(supports) {
|
|
92
|
+
return (supports ?? []).filter((entry) => entry.startsWith("inspect:")).map((entry) => entry.slice("inspect:".length));
|
|
93
|
+
}
|
|
94
|
+
function isPlainObject(value) {
|
|
95
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
96
|
+
}
|
|
97
|
+
function normalizeMindooDBAppInspectAnchor(raw) {
|
|
98
|
+
if (!isPlainObject(raw)) {
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
if (raw.kind === "heading" && typeof raw.id === "string" && raw.id && raw.id.length <= 200) {
|
|
102
|
+
return { kind: "heading", id: raw.id };
|
|
103
|
+
}
|
|
104
|
+
if (raw.kind === "cell" && typeof raw.ref === "string" && raw.ref && raw.ref.length <= 200) {
|
|
105
|
+
return { kind: "cell", ref: raw.ref };
|
|
106
|
+
}
|
|
107
|
+
if (raw.kind === "slide" && Number.isInteger(raw.index) && raw.index >= 0) {
|
|
108
|
+
return { kind: "slide", index: raw.index };
|
|
109
|
+
}
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
function normalizeMindooDBAppIssues(raw) {
|
|
113
|
+
if (!Array.isArray(raw)) {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
const issues = [];
|
|
117
|
+
for (const entry of raw) {
|
|
118
|
+
if (issues.length >= MINDOODB_APP_ISSUES_MAX) {
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (!isPlainObject(entry) || typeof entry.message !== "string" || !entry.message.trim()) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const severity = entry.severity === "warning" || entry.severity === "info" ? entry.severity : entry.severity === "error" ? "error" : null;
|
|
125
|
+
if (!severity) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const anchor = normalizeMindooDBAppInspectAnchor(entry.anchor);
|
|
129
|
+
const code = typeof entry.code === "string" && entry.code.trim() ? entry.code.trim().slice(0, 64) : void 0;
|
|
130
|
+
issues.push({
|
|
131
|
+
severity,
|
|
132
|
+
message: entry.message.trim().slice(0, 500),
|
|
133
|
+
...anchor ? { anchor } : {},
|
|
134
|
+
...code ? { code } : {}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return issues;
|
|
138
|
+
}
|
|
139
|
+
function normalizeMindooDBAppInspectRequest(raw) {
|
|
140
|
+
const input = isPlainObject(raw) ? raw : {};
|
|
141
|
+
const strings = (value, max) => Array.isArray(value) ? [...new Set(value.filter((entry) => typeof entry === "string" && !!entry && entry.length <= 200))].slice(0, max) : [];
|
|
142
|
+
const include = strings(input.include, 16);
|
|
143
|
+
const cells = strings(input.cells, 200);
|
|
144
|
+
const maxTextLength = Number(input.maxTextLength);
|
|
145
|
+
return {
|
|
146
|
+
...typeof input.contract === "string" && input.contract ? { contract: input.contract.slice(0, 200) } : {},
|
|
147
|
+
...include.length ? { include } : {},
|
|
148
|
+
...cells.length ? { cells } : {},
|
|
149
|
+
...Number.isFinite(maxTextLength) && maxTextLength > 0 ? { maxTextLength: Math.min(Math.floor(maxTextLength), 5e4) } : {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function normalizeMindooDBAppInspection(raw) {
|
|
153
|
+
let json;
|
|
154
|
+
try {
|
|
155
|
+
json = JSON.stringify(raw);
|
|
156
|
+
} catch {
|
|
157
|
+
throw new Error("An inspection must be plain JSON.");
|
|
158
|
+
}
|
|
159
|
+
if (!json || json.length > MINDOODB_APP_INSPECTION_MAX_BYTES) {
|
|
160
|
+
throw new Error(`An inspection must not be larger than ${MINDOODB_APP_INSPECTION_MAX_BYTES / 1024} KiB.`);
|
|
161
|
+
}
|
|
162
|
+
const value = JSON.parse(json);
|
|
163
|
+
if (!isPlainObject(value) || typeof value.contract !== "string" || !value.contract) {
|
|
164
|
+
throw new Error("An inspection must be an object with a contract.");
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
var SUMMARY_TEXT_STEPS = [500, 200, 0];
|
|
169
|
+
var SUMMARY_LIST_STEPS = [50, 20, 5, 0];
|
|
170
|
+
function shorten(value, textMax, listMax, marks) {
|
|
171
|
+
if (typeof value === "string") {
|
|
172
|
+
if (value.length <= textMax) return value;
|
|
173
|
+
marks.truncated = true;
|
|
174
|
+
return value.slice(0, textMax);
|
|
175
|
+
}
|
|
176
|
+
if (Array.isArray(value)) {
|
|
177
|
+
if (value.length > listMax) marks.truncated = true;
|
|
178
|
+
return value.slice(0, listMax).map((entry) => shorten(entry, Math.min(textMax || 80, 80), listMax, marks));
|
|
179
|
+
}
|
|
180
|
+
if (isPlainObject(value)) {
|
|
181
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, shorten(entry, textMax, listMax, marks)]));
|
|
182
|
+
}
|
|
183
|
+
return value;
|
|
184
|
+
}
|
|
185
|
+
function summarizeMindooDBAppInspection(inspection, maxBytes = MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES) {
|
|
186
|
+
const { cells: _cells, ...rest } = inspection;
|
|
187
|
+
const base = JSON.parse(JSON.stringify(rest));
|
|
188
|
+
for (const textMax of SUMMARY_TEXT_STEPS) {
|
|
189
|
+
for (const listMax of SUMMARY_LIST_STEPS) {
|
|
190
|
+
const marks = { truncated: false };
|
|
191
|
+
const next = shorten(base, textMax, listMax, marks);
|
|
192
|
+
if (textMax === 0 && typeof next.text === "string") delete next.text;
|
|
193
|
+
next.contract = inspection.contract;
|
|
194
|
+
if (typeof inspection.subject === "string") next.subject = inspection.subject.slice(0, 200);
|
|
195
|
+
if (marks.truncated || inspection.truncated) next.truncated = true;
|
|
196
|
+
if (JSON.stringify(next).length <= maxBytes) {
|
|
197
|
+
return next;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return { contract: inspection.contract, truncated: true };
|
|
202
|
+
}
|
|
203
|
+
function mindooDBAppInspectionSummaryValue(inspection) {
|
|
204
|
+
return MindooDBAppValue.atomic(JSON.stringify(summarizeMindooDBAppInspection(inspection)));
|
|
205
|
+
}
|
|
206
|
+
function readMindooDBAppInspectionSummary(root) {
|
|
207
|
+
let value = root?.[MINDOODB_APP_INSPECTION_FIELD];
|
|
208
|
+
if (typeof value === "string") {
|
|
209
|
+
try {
|
|
210
|
+
value = JSON.parse(value);
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return isPlainObject(value) && typeof value.contract === "string" ? value : null;
|
|
216
|
+
}
|
|
217
|
+
function outcomeIssues(rule, outcome) {
|
|
218
|
+
if (!outcome) return [];
|
|
219
|
+
if (typeof outcome === "string") {
|
|
220
|
+
return [{ severity: rule.severity ?? "error", message: outcome, code: rule.code }];
|
|
221
|
+
}
|
|
222
|
+
return (Array.isArray(outcome) ? outcome : [outcome]).map((issue) => ({ code: rule.code, ...issue }));
|
|
223
|
+
}
|
|
224
|
+
function defineDocumentRules(definition) {
|
|
225
|
+
const request = normalizeMindooDBAppInspectRequest(definition);
|
|
226
|
+
function check(inspection) {
|
|
227
|
+
if (!inspection || definition.contract && inspection.contract !== definition.contract) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
const issues = definition.rules.flatMap((rule) => {
|
|
231
|
+
try {
|
|
232
|
+
return outcomeIssues(rule, rule.check(inspection));
|
|
233
|
+
} catch (error) {
|
|
234
|
+
return [
|
|
235
|
+
{
|
|
236
|
+
severity: "warning",
|
|
237
|
+
code: rule.code,
|
|
238
|
+
message: `Check "${rule.code}" failed: ${error instanceof Error ? error.message : String(error)}`
|
|
239
|
+
}
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return normalizeMindooDBAppIssues(issues);
|
|
244
|
+
}
|
|
245
|
+
const rules = {
|
|
246
|
+
request,
|
|
247
|
+
check,
|
|
248
|
+
checkRoot: (root) => check(readMindooDBAppInspectionSummary(root)),
|
|
249
|
+
beforeSave: ({ inspection }) => ({ issues: check(inspection) }),
|
|
250
|
+
attach: (embed) => embed.onBeforeSave(rules.beforeSave, { inspect: request })
|
|
251
|
+
};
|
|
252
|
+
return rules;
|
|
253
|
+
}
|
|
254
|
+
function plural(count, one, many) {
|
|
255
|
+
return `${count} ${count === 1 ? one : many}`;
|
|
256
|
+
}
|
|
257
|
+
var mindooDBAppInspectRules = {
|
|
258
|
+
/** Documents: no placeholder or MERGEFIELD left open. */
|
|
259
|
+
noOpenPlaceholders(severity = "error", message) {
|
|
260
|
+
return {
|
|
261
|
+
code: "open-placeholders",
|
|
262
|
+
severity,
|
|
263
|
+
check: (inspection) => {
|
|
264
|
+
const names = (inspection.placeholders ?? []).map((entry) => entry.name);
|
|
265
|
+
if (!names.length) return null;
|
|
266
|
+
return message?.(names) ?? `${plural(names.length, "placeholder is", "placeholders are")} not filled in: ${names.slice(0, 5).join(", ")}${names.length > 5 ? ", \u2026" : ""}`;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
/** Documents: every comment resolved. */
|
|
271
|
+
noOpenComments(severity = "warning", message) {
|
|
272
|
+
return {
|
|
273
|
+
code: "open-comments",
|
|
274
|
+
severity,
|
|
275
|
+
check: (inspection) => inspection.openComments > 0 ? message?.(inspection.openComments) ?? `${plural(inspection.openComments, "comment is", "comments are")} not resolved.` : null
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
/** Documents: every tracked change accepted or rejected. */
|
|
279
|
+
noOpenTrackedChanges(severity = "warning", message) {
|
|
280
|
+
return {
|
|
281
|
+
code: "open-tracked-changes",
|
|
282
|
+
severity,
|
|
283
|
+
check: (inspection) => inspection.openTrackedChanges > 0 ? message?.(inspection.openTrackedChanges) ?? `${plural(inspection.openTrackedChanges, "tracked change is", "tracked changes are")} not accepted or rejected.` : null
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
/** Spreadsheets: no formula evaluates to an error; one issue per cell. */
|
|
287
|
+
noFormulaErrors(severity = "error") {
|
|
288
|
+
return {
|
|
289
|
+
code: "formula-errors",
|
|
290
|
+
severity,
|
|
291
|
+
check: (inspection) => (inspection.formulaErrors ?? []).map((entry) => ({
|
|
292
|
+
severity,
|
|
293
|
+
message: `${entry.ref}: ${entry.error}`,
|
|
294
|
+
anchor: { kind: "cell", ref: entry.ref }
|
|
295
|
+
}))
|
|
296
|
+
};
|
|
297
|
+
},
|
|
298
|
+
/** Presentations: no layout placeholder left empty; one issue per slide. */
|
|
299
|
+
noEmptySlidePlaceholders(severity = "warning") {
|
|
300
|
+
return {
|
|
301
|
+
code: "empty-placeholders",
|
|
302
|
+
severity,
|
|
303
|
+
check: (inspection) => {
|
|
304
|
+
const bySlide = /* @__PURE__ */ new Map();
|
|
305
|
+
for (const entry of inspection.emptyPlaceholders ?? []) {
|
|
306
|
+
bySlide.set(entry.slide, [...bySlide.get(entry.slide) ?? [], entry.placeholder]);
|
|
307
|
+
}
|
|
308
|
+
return [...bySlide.entries()].map(([slide, names]) => ({
|
|
309
|
+
severity,
|
|
310
|
+
message: `Slide ${slide + 1}: empty ${names.join(", ")}`,
|
|
311
|
+
anchor: { kind: "slide", index: slide }
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
var SUPPORTS_ARGUMENT = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
318
|
+
function isMindooDBAppSupportsEntry(entry, contractPattern) {
|
|
319
|
+
const [capability, argument, ...rest] = entry.split(":");
|
|
320
|
+
if (rest.length || !capability || !SUPPORTS_CAPABILITY.test(capability)) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return argument === void 0 || contractPattern.test(argument) || SUPPORTS_ARGUMENT.test(argument);
|
|
324
|
+
}
|
|
325
|
+
async function performMindooDBAppEmbeddingSave(steps) {
|
|
326
|
+
const validation = await steps.validate();
|
|
327
|
+
if (!validation.ok) {
|
|
328
|
+
if (validation.issues.length && steps.showIssues) {
|
|
329
|
+
try {
|
|
330
|
+
await steps.showIssues(validation.issues);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
console.warn("[mindoodb-app-sdk] Showing issues failed.", error);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
throw new MindooDBAppEmbedValidationError(validation.issues);
|
|
336
|
+
}
|
|
337
|
+
let inspection = null;
|
|
338
|
+
if (steps.provider) {
|
|
339
|
+
try {
|
|
340
|
+
inspection = mindooDBAppInspectionSummaryValue(normalizeMindooDBAppInspection(await steps.provider({})));
|
|
341
|
+
} catch (error) {
|
|
342
|
+
console.warn("[mindoodb-app-sdk] Could not summarize the document.", error);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
await steps.flush({ inspection, issues: validation.issues });
|
|
346
|
+
await steps.saved();
|
|
347
|
+
return validation;
|
|
348
|
+
}
|
|
349
|
+
async function resolveMindooDBAppEmbedValidation(issues, interactive, confirm) {
|
|
350
|
+
if (issues.some((issue) => issue.severity === "error")) {
|
|
351
|
+
return { ok: false, issues };
|
|
352
|
+
}
|
|
353
|
+
const warnings = issues.filter((issue) => issue.severity === "warning");
|
|
354
|
+
if (!warnings.length || !interactive) {
|
|
355
|
+
return { ok: true, issues };
|
|
356
|
+
}
|
|
357
|
+
return { ok: await confirm(warnings) === true, issues };
|
|
358
|
+
}
|
|
359
|
+
|
|
69
360
|
// src/appDefinition.ts
|
|
70
361
|
var MINDOODB_APP_DEFINITION_FORMAT = "mindoodb.haven.app";
|
|
71
362
|
var MINDOODB_APP_DEFINITION_VERSION = 1;
|
|
@@ -96,7 +387,7 @@ var MINDOODB_APP_AGENT_LIMIT_MAX = 300;
|
|
|
96
387
|
var MINDOODB_APP_AGENT_GUIDE_MAX_BYTES = 8 * 1024;
|
|
97
388
|
var MINDOODB_APP_AGENT_TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{0,47}$/;
|
|
98
389
|
var LOGICAL_DATABASE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
99
|
-
function
|
|
390
|
+
function isPlainObject2(value) {
|
|
100
391
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
101
392
|
}
|
|
102
393
|
function readOptionalString(raw, key, errors) {
|
|
@@ -127,7 +418,7 @@ function readStringRecord(raw, key, errors) {
|
|
|
127
418
|
if (value === void 0 || value === null) {
|
|
128
419
|
return void 0;
|
|
129
420
|
}
|
|
130
|
-
if (!
|
|
421
|
+
if (!isPlainObject2(value)) {
|
|
131
422
|
errors.push(`App definition ${key} must be an object of string values.`);
|
|
132
423
|
return void 0;
|
|
133
424
|
}
|
|
@@ -193,7 +484,7 @@ function readDatabases(value, errors) {
|
|
|
193
484
|
const result = [];
|
|
194
485
|
const seen = /* @__PURE__ */ new Set();
|
|
195
486
|
value.forEach((entry, index) => {
|
|
196
|
-
if (!
|
|
487
|
+
if (!isPlainObject2(entry)) {
|
|
197
488
|
errors.push(`App definition database #${index} must be an object.`);
|
|
198
489
|
return;
|
|
199
490
|
}
|
|
@@ -246,7 +537,7 @@ function readLocalizedText(value, label, maxLength, errors) {
|
|
|
246
537
|
}
|
|
247
538
|
return trimmed || void 0;
|
|
248
539
|
}
|
|
249
|
-
if (!
|
|
540
|
+
if (!isPlainObject2(value)) {
|
|
250
541
|
errors.push(`${label} must be a string or an object of per-locale strings.`);
|
|
251
542
|
return void 0;
|
|
252
543
|
}
|
|
@@ -293,7 +584,7 @@ function readAccepts(value, errors) {
|
|
|
293
584
|
const ids = /* @__PURE__ */ new Set();
|
|
294
585
|
value.forEach((entry, index) => {
|
|
295
586
|
const label = `App definition accepts[${index}]`;
|
|
296
|
-
if (!
|
|
587
|
+
if (!isPlainObject2(entry)) {
|
|
297
588
|
errors.push(`${label} must be an object.`);
|
|
298
589
|
return;
|
|
299
590
|
}
|
|
@@ -354,7 +645,7 @@ var COMPONENT_FIELD_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
|
|
|
354
645
|
var COMPONENT_INTENTS = ["create", "edit", "view"];
|
|
355
646
|
var COMPONENT_CREATE_MAX_BYTES = 16 * 1024;
|
|
356
647
|
function readComponentFieldMatch(value, label, errors) {
|
|
357
|
-
if (!
|
|
648
|
+
if (!isPlainObject2(value)) {
|
|
358
649
|
errors.push(`${label} must be an object of field values.`);
|
|
359
650
|
return void 0;
|
|
360
651
|
}
|
|
@@ -377,6 +668,28 @@ var MINDOODB_APP_COMPONENT_CONTRACT_PATTERN = /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]
|
|
|
377
668
|
var COMPONENT_CONTRACTS_MAX = 8;
|
|
378
669
|
var COMPONENT_REFERENCES_MAX = 8;
|
|
379
670
|
var COMPONENT_REFERENCE_SHOW_MAX = 8;
|
|
671
|
+
var COMPONENT_SUPPORTS_MAX = 16;
|
|
672
|
+
function readComponentSupports(value, label, errors) {
|
|
673
|
+
if (value === void 0) {
|
|
674
|
+
return void 0;
|
|
675
|
+
}
|
|
676
|
+
if (!Array.isArray(value) || value.length > COMPONENT_SUPPORTS_MAX) {
|
|
677
|
+
errors.push(`${label} must be an array of at most ${COMPONENT_SUPPORTS_MAX} entries.`);
|
|
678
|
+
return void 0;
|
|
679
|
+
}
|
|
680
|
+
const result = [];
|
|
681
|
+
for (const entry of value) {
|
|
682
|
+
const text = typeof entry === "string" ? entry.trim() : "";
|
|
683
|
+
if (!isMindooDBAppSupportsEntry(text, MINDOODB_APP_COMPONENT_CONTRACT_PATTERN)) {
|
|
684
|
+
errors.push(`${label} entries must look like "validate", "export:pdf" or "inspect:mindoo.inspect.document@1", received ${JSON.stringify(entry)}.`);
|
|
685
|
+
return void 0;
|
|
686
|
+
}
|
|
687
|
+
if (!result.includes(text)) {
|
|
688
|
+
result.push(text);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return result.length ? result : void 0;
|
|
692
|
+
}
|
|
380
693
|
function readComponentContracts(value, label, errors) {
|
|
381
694
|
if (value === void 0) {
|
|
382
695
|
return void 0;
|
|
@@ -387,14 +700,14 @@ function readComponentContracts(value, label, errors) {
|
|
|
387
700
|
}
|
|
388
701
|
const result = [];
|
|
389
702
|
for (const [index, entry] of value.entries()) {
|
|
390
|
-
const contract =
|
|
703
|
+
const contract = isPlainObject2(entry) && typeof entry.contract === "string" ? entry.contract.trim() : "";
|
|
391
704
|
if (!MINDOODB_APP_COMPONENT_CONTRACT_PATTERN.test(contract)) {
|
|
392
705
|
errors.push(`${label}[${index}].contract must look like "mindoo.contacts.company@1".`);
|
|
393
706
|
return void 0;
|
|
394
707
|
}
|
|
395
708
|
let fields;
|
|
396
|
-
if (
|
|
397
|
-
if (!
|
|
709
|
+
if (isPlainObject2(entry) && entry.fields !== void 0) {
|
|
710
|
+
if (!isPlainObject2(entry.fields)) {
|
|
398
711
|
errors.push(`${label}[${index}].fields must map contract fields to document fields.`);
|
|
399
712
|
return void 0;
|
|
400
713
|
}
|
|
@@ -423,7 +736,7 @@ function readComponentReferences(value, label, rootMatch, errors) {
|
|
|
423
736
|
const fieldsSeen = /* @__PURE__ */ new Set();
|
|
424
737
|
for (const [index, entry] of value.entries()) {
|
|
425
738
|
const at = `${label}[${index}]`;
|
|
426
|
-
if (!
|
|
739
|
+
if (!isPlainObject2(entry)) {
|
|
427
740
|
errors.push(`${at} must be an object.`);
|
|
428
741
|
return void 0;
|
|
429
742
|
}
|
|
@@ -472,7 +785,7 @@ function readComponents(value, errors) {
|
|
|
472
785
|
value.forEach((entry, index) => {
|
|
473
786
|
const label = `App definition components[${index}]`;
|
|
474
787
|
const errorCount = errors.length;
|
|
475
|
-
if (!
|
|
788
|
+
if (!isPlainObject2(entry)) {
|
|
476
789
|
errors.push(`${label} must be an object.`);
|
|
477
790
|
return;
|
|
478
791
|
}
|
|
@@ -519,7 +832,7 @@ function readComponents(value, errors) {
|
|
|
519
832
|
}
|
|
520
833
|
let create;
|
|
521
834
|
if (entry.create !== void 0) {
|
|
522
|
-
if (!
|
|
835
|
+
if (!isPlainObject2(entry.create)) {
|
|
523
836
|
errors.push(`${label}.create must be an object of initial field values.`);
|
|
524
837
|
return;
|
|
525
838
|
}
|
|
@@ -548,7 +861,7 @@ function readComponents(value, errors) {
|
|
|
548
861
|
}
|
|
549
862
|
let children;
|
|
550
863
|
if (entry.children !== void 0) {
|
|
551
|
-
if (!
|
|
864
|
+
if (!isPlainObject2(entry.children)) {
|
|
552
865
|
errors.push(`${label}.children must be an object.`);
|
|
553
866
|
return;
|
|
554
867
|
}
|
|
@@ -577,6 +890,7 @@ function readComponents(value, errors) {
|
|
|
577
890
|
}
|
|
578
891
|
const provides = readComponentContracts(entry.provides, `${label}.provides`, errors);
|
|
579
892
|
const references = readComponentReferences(entry.references, `${label}.references`, match, errors);
|
|
893
|
+
const supports = readComponentSupports(entry.supports, `${label}.supports`, errors);
|
|
580
894
|
if (errors.length !== errorCount) {
|
|
581
895
|
return;
|
|
582
896
|
}
|
|
@@ -591,7 +905,8 @@ function readComponents(value, errors) {
|
|
|
591
905
|
...children ? { children } : {},
|
|
592
906
|
...category ? { category } : {},
|
|
593
907
|
...provides ? { provides } : {},
|
|
594
|
-
...references ? { references } : {}
|
|
908
|
+
...references ? { references } : {},
|
|
909
|
+
...supports ? { supports } : {}
|
|
595
910
|
});
|
|
596
911
|
});
|
|
597
912
|
return result.length ? result : void 0;
|
|
@@ -631,7 +946,7 @@ function readListing(value, errors) {
|
|
|
631
946
|
if (value === void 0 || value === null) {
|
|
632
947
|
return void 0;
|
|
633
948
|
}
|
|
634
|
-
if (!
|
|
949
|
+
if (!isPlainObject2(value)) {
|
|
635
950
|
errors.push("App definition listing must be an object.");
|
|
636
951
|
return void 0;
|
|
637
952
|
}
|
|
@@ -671,7 +986,7 @@ function readListing(value, errors) {
|
|
|
671
986
|
value.screenshots.forEach((entry, index) => {
|
|
672
987
|
const label = `App definition listing.screenshots[${index}]`;
|
|
673
988
|
const raw = typeof entry === "string" ? { file: entry } : entry;
|
|
674
|
-
if (!
|
|
989
|
+
if (!isPlainObject2(raw)) {
|
|
675
990
|
errors.push(`${label} must be a path or an object with a file.`);
|
|
676
991
|
return;
|
|
677
992
|
}
|
|
@@ -686,7 +1001,7 @@ function readListing(value, errors) {
|
|
|
686
1001
|
}
|
|
687
1002
|
}
|
|
688
1003
|
if (value.publisher !== void 0 && value.publisher !== null) {
|
|
689
|
-
const publisher =
|
|
1004
|
+
const publisher = isPlainObject2(value.publisher) ? value.publisher : {};
|
|
690
1005
|
const name = typeof publisher.name === "string" ? publisher.name.trim() : "";
|
|
691
1006
|
if (!name) {
|
|
692
1007
|
errors.push("App definition listing.publisher must be an object with a non-empty name.");
|
|
@@ -705,7 +1020,7 @@ var AGENT_CAPABILITY_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,47}$/;
|
|
|
705
1020
|
var AGENT_LOCALE_PATTERN = /^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/;
|
|
706
1021
|
var AGENT_GUIDE_PATH_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9_.\/-]{0,199}\.md$/;
|
|
707
1022
|
function readAgentLocaleText(value, label, maxLength, errors) {
|
|
708
|
-
if (!
|
|
1023
|
+
if (!isPlainObject2(value)) {
|
|
709
1024
|
errors.push(`${label} must be an object of per-locale strings with an "en" entry.`);
|
|
710
1025
|
return void 0;
|
|
711
1026
|
}
|
|
@@ -736,7 +1051,7 @@ function readAgentLocaleList(value, label, maxLength, errors) {
|
|
|
736
1051
|
if (value === void 0) {
|
|
737
1052
|
return void 0;
|
|
738
1053
|
}
|
|
739
|
-
if (!
|
|
1054
|
+
if (!isPlainObject2(value)) {
|
|
740
1055
|
errors.push(`${label} must be an object of per-locale string arrays with an "en" entry.`);
|
|
741
1056
|
return void 0;
|
|
742
1057
|
}
|
|
@@ -777,7 +1092,7 @@ function readAgentCapabilities(value, errors) {
|
|
|
777
1092
|
const ids = /* @__PURE__ */ new Set();
|
|
778
1093
|
for (const [index, entry] of value.entries()) {
|
|
779
1094
|
const at = `${label}[${index}]`;
|
|
780
|
-
if (!
|
|
1095
|
+
if (!isPlainObject2(entry)) {
|
|
781
1096
|
errors.push(`${at} must be an object.`);
|
|
782
1097
|
return void 0;
|
|
783
1098
|
}
|
|
@@ -820,7 +1135,7 @@ function readAgentProfile(value, errors) {
|
|
|
820
1135
|
if (value === void 0 || value === null) {
|
|
821
1136
|
return void 0;
|
|
822
1137
|
}
|
|
823
|
-
if (!
|
|
1138
|
+
if (!isPlainObject2(value)) {
|
|
824
1139
|
errors.push("App definition agent must be an object.");
|
|
825
1140
|
return void 0;
|
|
826
1141
|
}
|
|
@@ -883,7 +1198,7 @@ function resolveMindooDBAppListingAssetUrl(path, originUrl) {
|
|
|
883
1198
|
}
|
|
884
1199
|
function validateMindooDBAppDefinition(raw) {
|
|
885
1200
|
const errors = [];
|
|
886
|
-
if (!
|
|
1201
|
+
if (!isPlainObject2(raw)) {
|
|
887
1202
|
return { definition: null, errors: ["App definition must be a JSON object."] };
|
|
888
1203
|
}
|
|
889
1204
|
if (raw.format !== MINDOODB_APP_DEFINITION_FORMAT) {
|
|
@@ -1397,29 +1712,29 @@ function bindDragSource(element, options, start, follow) {
|
|
|
1397
1712
|
}
|
|
1398
1713
|
|
|
1399
1714
|
// src/client/agentInput.ts
|
|
1400
|
-
function
|
|
1715
|
+
function isPlainObject3(value) {
|
|
1401
1716
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1402
1717
|
}
|
|
1403
1718
|
function isPlaceholder(value) {
|
|
1404
1719
|
if (value === null || value === void 0) return true;
|
|
1405
1720
|
if (typeof value === "string") return value.trim() === "";
|
|
1406
1721
|
if (Array.isArray(value)) return value.length === 0;
|
|
1407
|
-
if (
|
|
1722
|
+
if (isPlainObject3(value)) return Object.keys(value).length === 0;
|
|
1408
1723
|
return false;
|
|
1409
1724
|
}
|
|
1410
1725
|
function normalizeValue(value, schema) {
|
|
1411
|
-
if (!
|
|
1726
|
+
if (!isPlainObject3(schema)) return value;
|
|
1412
1727
|
if (Array.isArray(value)) {
|
|
1413
1728
|
const items = schema.items;
|
|
1414
|
-
return
|
|
1729
|
+
return isPlainObject3(items) ? value.map((item) => normalizeValue(item, items)) : value;
|
|
1415
1730
|
}
|
|
1416
|
-
if (
|
|
1731
|
+
if (isPlainObject3(value) && isPlainObject3(schema.properties)) {
|
|
1417
1732
|
return normalizeObject(value, schema);
|
|
1418
1733
|
}
|
|
1419
1734
|
return value;
|
|
1420
1735
|
}
|
|
1421
1736
|
function normalizeObject(input, schema) {
|
|
1422
|
-
const properties =
|
|
1737
|
+
const properties = isPlainObject3(schema.properties) ? schema.properties : {};
|
|
1423
1738
|
const required = new Set(Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : []);
|
|
1424
1739
|
const result = {};
|
|
1425
1740
|
for (const [key, raw] of Object.entries(input)) {
|
|
@@ -1434,7 +1749,7 @@ function normalizeObject(input, schema) {
|
|
|
1434
1749
|
return result;
|
|
1435
1750
|
}
|
|
1436
1751
|
function normalizeAgentToolInput(input, schema) {
|
|
1437
|
-
return
|
|
1752
|
+
return isPlainObject3(input) ? normalizeObject(input, schema) : input;
|
|
1438
1753
|
}
|
|
1439
1754
|
|
|
1440
1755
|
// src/client/agentTools.ts
|
|
@@ -1538,6 +1853,83 @@ var MindooDBAppAgentApiImpl = class {
|
|
|
1538
1853
|
}
|
|
1539
1854
|
};
|
|
1540
1855
|
|
|
1856
|
+
// src/embedExchange.ts
|
|
1857
|
+
var MINDOODB_APP_EMBED_VARIABLES_MAX = 200;
|
|
1858
|
+
var VARIABLE_KEY = /^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/;
|
|
1859
|
+
function normalizeMindooDBAppEmbedVariables(raw) {
|
|
1860
|
+
if (!Array.isArray(raw)) {
|
|
1861
|
+
return [];
|
|
1862
|
+
}
|
|
1863
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1864
|
+
for (const entry of raw) {
|
|
1865
|
+
if (!entry || typeof entry !== "object") continue;
|
|
1866
|
+
const { key, label, value, group } = entry;
|
|
1867
|
+
if (typeof key !== "string" || !VARIABLE_KEY.test(key)) continue;
|
|
1868
|
+
const text = (input, max) => typeof input === "string" ? input.slice(0, max) : "";
|
|
1869
|
+
byKey.delete(key);
|
|
1870
|
+
byKey.set(key, {
|
|
1871
|
+
key,
|
|
1872
|
+
label: text(label, 120).trim() || key,
|
|
1873
|
+
value: typeof value === "number" || typeof value === "boolean" ? String(value) : text(value, 4e3),
|
|
1874
|
+
...typeof group === "string" && group.trim() ? { group: group.trim().slice(0, 80) } : {}
|
|
1875
|
+
});
|
|
1876
|
+
if (byKey.size >= MINDOODB_APP_EMBED_VARIABLES_MAX) break;
|
|
1877
|
+
}
|
|
1878
|
+
return [...byKey.values()];
|
|
1879
|
+
}
|
|
1880
|
+
function resolveMindooDBAppVariables(text, variables, options = {}) {
|
|
1881
|
+
const values = new Map(variables.map((variable) => [variable.key, variable.value]));
|
|
1882
|
+
return text.replace(/\{\{\s*([A-Za-z_][A-Za-z0-9_.-]{0,63})\s*\}\}/g, (match, key) => {
|
|
1883
|
+
const value = values.get(key);
|
|
1884
|
+
return value === void 0 || !value && !options.keepEmpty ? match : value;
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
var MINDOODB_APP_EMBED_EXPORT_MAX_BYTES = 64 * 1024 * 1024;
|
|
1888
|
+
var EXPORT_TYPES = {
|
|
1889
|
+
pdf: "application/pdf",
|
|
1890
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
1891
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
1892
|
+
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
1893
|
+
png: "image/png",
|
|
1894
|
+
md: "text/markdown",
|
|
1895
|
+
csv: "text/csv"
|
|
1896
|
+
};
|
|
1897
|
+
function mindooDBAppExportMimeType(format) {
|
|
1898
|
+
return EXPORT_TYPES[format] ?? "application/octet-stream";
|
|
1899
|
+
}
|
|
1900
|
+
function normalizeMindooDBAppEmbedExportRequest(raw) {
|
|
1901
|
+
const input = raw && typeof raw === "object" ? raw : {};
|
|
1902
|
+
const format = typeof input.format === "string" ? input.format.trim().toLowerCase() : "";
|
|
1903
|
+
if (!/^[a-z0-9][a-z0-9-]{0,31}$/.test(format)) {
|
|
1904
|
+
throw new Error('An export needs a format such as "pdf" or "png".');
|
|
1905
|
+
}
|
|
1906
|
+
const size = (value) => {
|
|
1907
|
+
const number = Number(value);
|
|
1908
|
+
return Number.isFinite(number) && number > 0 ? Math.min(Math.round(number), 8192) : void 0;
|
|
1909
|
+
};
|
|
1910
|
+
const maxWidth = size(input.maxWidth);
|
|
1911
|
+
const maxHeight = size(input.maxHeight);
|
|
1912
|
+
return { format, ...maxWidth ? { maxWidth } : {}, ...maxHeight ? { maxHeight } : {} };
|
|
1913
|
+
}
|
|
1914
|
+
async function mindooDBAppExportPayload(result, request, baseName = "document") {
|
|
1915
|
+
const blob = result instanceof Blob ? result : null;
|
|
1916
|
+
const data = blob ?? result.data;
|
|
1917
|
+
const bytes = data instanceof Blob ? await data.arrayBuffer() : ArrayBuffer.isView(data) ? data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) : data;
|
|
1918
|
+
if (Object.prototype.toString.call(bytes) !== "[object ArrayBuffer]") {
|
|
1919
|
+
throw new Error("An export must be a Blob, an ArrayBuffer or a Uint8Array.");
|
|
1920
|
+
}
|
|
1921
|
+
if (bytes.byteLength > MINDOODB_APP_EMBED_EXPORT_MAX_BYTES) {
|
|
1922
|
+
throw new Error(`An export must not be larger than ${MINDOODB_APP_EMBED_EXPORT_MAX_BYTES / 1024 / 1024} MiB.`);
|
|
1923
|
+
}
|
|
1924
|
+
const named = blob ? blob.name : result.name;
|
|
1925
|
+
const mimeType = !blob && result.mimeType || (blob?.type ? blob.type : "") || mindooDBAppExportMimeType(request.format);
|
|
1926
|
+
const name = (typeof named === "string" && named.trim() ? named.trim() : `${baseName}.${request.format}`).slice(0, 200);
|
|
1927
|
+
return { data: bytes, name, mimeType };
|
|
1928
|
+
}
|
|
1929
|
+
function mindooDBAppExportFile(payload) {
|
|
1930
|
+
return new File([payload.data], payload.name, { type: payload.mimeType });
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1541
1933
|
// src/directoryPaging.ts
|
|
1542
1934
|
var LIST_USERS_DEFAULT_LIMIT = 50;
|
|
1543
1935
|
var LIST_USERS_MAX_LIMIT = 500;
|
|
@@ -1651,6 +2043,15 @@ import { parseMindooDBFormulaBooleanExpression } from "mindoodb-view-language";
|
|
|
1651
2043
|
function isEmbedEventMessage(message) {
|
|
1652
2044
|
return message.kind === "embed-event";
|
|
1653
2045
|
}
|
|
2046
|
+
function isEmbedRequestMessage(message) {
|
|
2047
|
+
return message.kind === "embed-request";
|
|
2048
|
+
}
|
|
2049
|
+
function isMethodNotFound(error) {
|
|
2050
|
+
return error instanceof Error && error.name === "method-not-found";
|
|
2051
|
+
}
|
|
2052
|
+
function errorMessage(error) {
|
|
2053
|
+
return error instanceof Error ? error.message : String(error);
|
|
2054
|
+
}
|
|
1654
2055
|
function isEmbeddingRequestMessage(message) {
|
|
1655
2056
|
return message.kind === "embedding-request";
|
|
1656
2057
|
}
|
|
@@ -1717,13 +2118,14 @@ function createComponentFrame(container, url, allow) {
|
|
|
1717
2118
|
return frame;
|
|
1718
2119
|
}
|
|
1719
2120
|
var MindooDBAppEmbedImpl = class {
|
|
1720
|
-
constructor(rpc, embedId, componentKey, databaseId, docId, frame, container) {
|
|
2121
|
+
constructor(rpc, embedId, componentKey, databaseId, docId, frame, container, supports = []) {
|
|
1721
2122
|
this.rpc = rpc;
|
|
1722
2123
|
this.embedId = embedId;
|
|
1723
2124
|
this.componentKey = componentKey;
|
|
1724
2125
|
this.databaseId = databaseId;
|
|
1725
2126
|
this.docId = docId;
|
|
1726
2127
|
this.frame = frame;
|
|
2128
|
+
this.supports = supports;
|
|
1727
2129
|
this.closed = new Promise((resolve) => {
|
|
1728
2130
|
this.resolveClosed = resolve;
|
|
1729
2131
|
});
|
|
@@ -1740,6 +2142,7 @@ var MindooDBAppEmbedImpl = class {
|
|
|
1740
2142
|
databaseId;
|
|
1741
2143
|
docId;
|
|
1742
2144
|
frame;
|
|
2145
|
+
supports;
|
|
1743
2146
|
closed;
|
|
1744
2147
|
resolveClosed;
|
|
1745
2148
|
closedEvent = null;
|
|
@@ -1749,6 +2152,8 @@ var MindooDBAppEmbedImpl = class {
|
|
|
1749
2152
|
tracker = null;
|
|
1750
2153
|
toolsState = null;
|
|
1751
2154
|
toolsListeners = /* @__PURE__ */ new Set();
|
|
2155
|
+
beforeSaveHandler = null;
|
|
2156
|
+
savedListeners = /* @__PURE__ */ new Set();
|
|
1752
2157
|
get placement() {
|
|
1753
2158
|
return this.frame ? "frame" : "overlay";
|
|
1754
2159
|
}
|
|
@@ -1831,6 +2236,104 @@ var MindooDBAppEmbedImpl = class {
|
|
|
1831
2236
|
const stopClosed = this.onClosed(() => finish(null));
|
|
1832
2237
|
});
|
|
1833
2238
|
}
|
|
2239
|
+
async inspect(request) {
|
|
2240
|
+
const result = await this.rpc.call("embeds.inspect", {
|
|
2241
|
+
embedId: this.embedId,
|
|
2242
|
+
request: normalizeMindooDBAppInspectRequest(request)
|
|
2243
|
+
});
|
|
2244
|
+
return normalizeMindooDBAppInspection(result);
|
|
2245
|
+
}
|
|
2246
|
+
onBeforeSave(handler, options) {
|
|
2247
|
+
this.beforeSaveHandler = handler;
|
|
2248
|
+
this.announceBeforeSave(true, options?.inspect);
|
|
2249
|
+
return () => {
|
|
2250
|
+
if (this.beforeSaveHandler === handler) {
|
|
2251
|
+
this.beforeSaveHandler = null;
|
|
2252
|
+
this.announceBeforeSave(false);
|
|
2253
|
+
}
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2256
|
+
/** Haven only asks hosts that said they check, and fetches the inspection they want. */
|
|
2257
|
+
announceBeforeSave(enabled, inspect) {
|
|
2258
|
+
if (this.closedEvent) {
|
|
2259
|
+
return;
|
|
2260
|
+
}
|
|
2261
|
+
void this.rpc.call("embeds.setBeforeSave", {
|
|
2262
|
+
embedId: this.embedId,
|
|
2263
|
+
enabled,
|
|
2264
|
+
...enabled ? { inspect: normalizeMindooDBAppInspectRequest(inspect) } : {}
|
|
2265
|
+
}).catch((error) => {
|
|
2266
|
+
if (!isMethodNotFound(error)) {
|
|
2267
|
+
console.warn("[mindoodb-app-sdk] Could not register the save check.", error);
|
|
2268
|
+
}
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
/** Haven asks before the component saves: run the handler, never longer than Haven waits. */
|
|
2272
|
+
async answerBeforeSave(params) {
|
|
2273
|
+
const handler = this.beforeSaveHandler;
|
|
2274
|
+
if (!handler || this.closedEvent) {
|
|
2275
|
+
return { issues: [] };
|
|
2276
|
+
}
|
|
2277
|
+
const result = await handler({
|
|
2278
|
+
embedId: this.embedId,
|
|
2279
|
+
inspection: params?.inspection ?? null,
|
|
2280
|
+
root: params?.root ?? null
|
|
2281
|
+
});
|
|
2282
|
+
return { issues: normalizeMindooDBAppIssues(result?.issues) };
|
|
2283
|
+
}
|
|
2284
|
+
onAfterSave(listener) {
|
|
2285
|
+
this.savedListeners.add(listener);
|
|
2286
|
+
return () => {
|
|
2287
|
+
this.savedListeners.delete(listener);
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
/** The component reported that it saved. */
|
|
2291
|
+
notifySaved() {
|
|
2292
|
+
if (this.closedEvent) {
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
const event = { embedId: this.embedId };
|
|
2296
|
+
this.savedListeners.forEach((listener) => {
|
|
2297
|
+
try {
|
|
2298
|
+
listener(event);
|
|
2299
|
+
} catch (error) {
|
|
2300
|
+
console.error("MindooDB embed saved listener failed.", error);
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
async showIssues(issues) {
|
|
2305
|
+
await this.rpc.call("embeds.showIssues", { embedId: this.embedId, issues: normalizeMindooDBAppIssues(issues) });
|
|
2306
|
+
}
|
|
2307
|
+
async reveal(anchor) {
|
|
2308
|
+
const normalized = normalizeMindooDBAppInspectAnchor(anchor);
|
|
2309
|
+
if (!normalized) {
|
|
2310
|
+
throw new Error("Invalid anchor.");
|
|
2311
|
+
}
|
|
2312
|
+
await this.rpc.call("embeds.reveal", { embedId: this.embedId, anchor: normalized });
|
|
2313
|
+
}
|
|
2314
|
+
async setVariables(variables) {
|
|
2315
|
+
await this.rpc.call("embeds.setVariables", {
|
|
2316
|
+
embedId: this.embedId,
|
|
2317
|
+
variables: normalizeMindooDBAppEmbedVariables(variables)
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2320
|
+
async export(request) {
|
|
2321
|
+
const payload = await this.rpc.call("embeds.export", {
|
|
2322
|
+
embedId: this.embedId,
|
|
2323
|
+
request: normalizeMindooDBAppEmbedExportRequest(request)
|
|
2324
|
+
});
|
|
2325
|
+
if (!payload || Object.prototype.toString.call(payload.data) !== "[object ArrayBuffer]") {
|
|
2326
|
+
throw new Error("The component handed over no file.");
|
|
2327
|
+
}
|
|
2328
|
+
return mindooDBAppExportFile(payload);
|
|
2329
|
+
}
|
|
2330
|
+
async callTool(name, input) {
|
|
2331
|
+
return await this.rpc.call("embeds.callTool", {
|
|
2332
|
+
embedId: this.embedId,
|
|
2333
|
+
name: String(name),
|
|
2334
|
+
input: input === void 0 ? {} : JSON.parse(JSON.stringify(input))
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
1834
2337
|
async setRect(rect) {
|
|
1835
2338
|
if (this.closedEvent) {
|
|
1836
2339
|
return;
|
|
@@ -1885,6 +2388,8 @@ var MindooDBAppEmbedImpl = class {
|
|
|
1885
2388
|
});
|
|
1886
2389
|
this.listeners.clear();
|
|
1887
2390
|
this.dirtyListeners.clear();
|
|
2391
|
+
this.savedListeners.clear();
|
|
2392
|
+
this.beforeSaveHandler = null;
|
|
1888
2393
|
this.toolsState = null;
|
|
1889
2394
|
this.toolsListeners.forEach((listener) => {
|
|
1890
2395
|
try {
|
|
@@ -1904,6 +2409,10 @@ var MindooDBAppEmbedsClient = class {
|
|
|
1904
2409
|
void this.answerRequest(message);
|
|
1905
2410
|
return;
|
|
1906
2411
|
}
|
|
2412
|
+
if (isEmbedRequestMessage(message)) {
|
|
2413
|
+
void this.answerEmbedRequest(message);
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
1907
2416
|
if (!isEmbedEventMessage(message)) {
|
|
1908
2417
|
return;
|
|
1909
2418
|
}
|
|
@@ -1927,6 +2436,10 @@ var MindooDBAppEmbedsClient = class {
|
|
|
1927
2436
|
}
|
|
1928
2437
|
return;
|
|
1929
2438
|
}
|
|
2439
|
+
if (message.event?.type === "saved") {
|
|
2440
|
+
this.open.get(message.event.embedId)?.notifySaved();
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
1930
2443
|
if (message.event?.type !== "closed") {
|
|
1931
2444
|
return;
|
|
1932
2445
|
}
|
|
@@ -1951,10 +2464,17 @@ var MindooDBAppEmbedsClient = class {
|
|
|
1951
2464
|
open: async (input) => {
|
|
1952
2465
|
const { container, rect, ...rest } = input;
|
|
1953
2466
|
const initialRect = container ? containerRect(container) : toRect(rect ?? { left: 0, top: 0, width: 0, height: 0 });
|
|
2467
|
+
const { variables, template, ...plain } = rest;
|
|
1954
2468
|
const response = await this.rpc.call("embeds.open", {
|
|
1955
2469
|
// `frame`: Haven hands back a page for the container instead of laying
|
|
1956
2470
|
// the component over this app. Havens that do not know it ignore it.
|
|
1957
|
-
input: {
|
|
2471
|
+
input: {
|
|
2472
|
+
...plain,
|
|
2473
|
+
rect: initialRect,
|
|
2474
|
+
...container ? { placement: "frame" } : {},
|
|
2475
|
+
...variables ? { variables: normalizeMindooDBAppEmbedVariables(variables) } : {},
|
|
2476
|
+
...template ? { template: { docId: String(template.docId), ...template.databaseId ? { databaseId: String(template.databaseId) } : {} } } : {}
|
|
2477
|
+
}
|
|
1958
2478
|
});
|
|
1959
2479
|
const frame = container && response.frame?.url ? createComponentFrame(container, response.frame.url, response.frame.allow) : null;
|
|
1960
2480
|
const embed = new MindooDBAppEmbedImpl(
|
|
@@ -1964,7 +2484,8 @@ var MindooDBAppEmbedsClient = class {
|
|
|
1964
2484
|
input.databaseId,
|
|
1965
2485
|
input.docId,
|
|
1966
2486
|
frame,
|
|
1967
|
-
container
|
|
2487
|
+
container,
|
|
2488
|
+
Array.isArray(response.supports) ? response.supports.filter((entry) => typeof entry === "string") : []
|
|
1968
2489
|
);
|
|
1969
2490
|
const earlyDirty = this.earlyDirty.get(embed.embedId);
|
|
1970
2491
|
if (earlyDirty !== void 0) {
|
|
@@ -2040,7 +2561,74 @@ var MindooDBAppEmbedsClient = class {
|
|
|
2040
2561
|
this.saveHandler = null;
|
|
2041
2562
|
}
|
|
2042
2563
|
};
|
|
2043
|
-
}
|
|
2564
|
+
},
|
|
2565
|
+
provideInspection: (provider) => {
|
|
2566
|
+
this.inspectionProvider = provider;
|
|
2567
|
+
return () => {
|
|
2568
|
+
if (this.inspectionProvider === provider) {
|
|
2569
|
+
this.inspectionProvider = null;
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
},
|
|
2573
|
+
onShowIssues: (handler) => {
|
|
2574
|
+
this.showIssuesHandler = handler;
|
|
2575
|
+
return () => {
|
|
2576
|
+
if (this.showIssuesHandler === handler) {
|
|
2577
|
+
this.showIssuesHandler = null;
|
|
2578
|
+
}
|
|
2579
|
+
};
|
|
2580
|
+
},
|
|
2581
|
+
getVariables: async () => {
|
|
2582
|
+
if (this.variables) {
|
|
2583
|
+
return this.variables.map((variable) => ({ ...variable }));
|
|
2584
|
+
}
|
|
2585
|
+
try {
|
|
2586
|
+
const result = await this.rpc.call("embedding.getVariables", {});
|
|
2587
|
+
this.variables ??= normalizeMindooDBAppEmbedVariables(result?.variables);
|
|
2588
|
+
} catch (error) {
|
|
2589
|
+
if (!isMethodNotFound(error) && !(error instanceof Error && error.name === "unsupported")) {
|
|
2590
|
+
throw error;
|
|
2591
|
+
}
|
|
2592
|
+
this.variables ??= [];
|
|
2593
|
+
}
|
|
2594
|
+
return this.variables.map((variable) => ({ ...variable }));
|
|
2595
|
+
},
|
|
2596
|
+
onVariablesChange: (listener) => {
|
|
2597
|
+
this.variableListeners.add(listener);
|
|
2598
|
+
return () => {
|
|
2599
|
+
this.variableListeners.delete(listener);
|
|
2600
|
+
};
|
|
2601
|
+
},
|
|
2602
|
+
provideExport: (provider) => {
|
|
2603
|
+
this.exportProvider = provider;
|
|
2604
|
+
return () => {
|
|
2605
|
+
if (this.exportProvider === provider) {
|
|
2606
|
+
this.exportProvider = null;
|
|
2607
|
+
}
|
|
2608
|
+
};
|
|
2609
|
+
},
|
|
2610
|
+
onReveal: (handler) => {
|
|
2611
|
+
this.revealHandler = handler;
|
|
2612
|
+
return () => {
|
|
2613
|
+
if (this.revealHandler === handler) {
|
|
2614
|
+
this.revealHandler = null;
|
|
2615
|
+
}
|
|
2616
|
+
};
|
|
2617
|
+
},
|
|
2618
|
+
validate: async (options) => await this.validate(options),
|
|
2619
|
+
save: async (flush, options) => await performMindooDBAppEmbeddingSave({
|
|
2620
|
+
validate: () => this.validate(options),
|
|
2621
|
+
provider: this.inspectionProvider,
|
|
2622
|
+
showIssues: this.showIssuesHandler,
|
|
2623
|
+
flush,
|
|
2624
|
+
// Only news for the host: a lost message must not fail a save that happened.
|
|
2625
|
+
saved: () => this.rpc.call("embedding.saved", {}).then(
|
|
2626
|
+
() => {
|
|
2627
|
+
},
|
|
2628
|
+
() => {
|
|
2629
|
+
}
|
|
2630
|
+
)
|
|
2631
|
+
})
|
|
2044
2632
|
};
|
|
2045
2633
|
}
|
|
2046
2634
|
rpc;
|
|
@@ -2055,18 +2643,71 @@ var MindooDBAppEmbedsClient = class {
|
|
|
2055
2643
|
stopListening;
|
|
2056
2644
|
/** This app as a component: what to do when its host asks it to save. */
|
|
2057
2645
|
saveHandler = null;
|
|
2058
|
-
|
|
2646
|
+
inspectionProvider = null;
|
|
2647
|
+
showIssuesHandler = null;
|
|
2648
|
+
revealHandler = null;
|
|
2649
|
+
exportProvider = null;
|
|
2650
|
+
/** The host's variables as last pushed; null until known (then asked for on first use). */
|
|
2651
|
+
variables = null;
|
|
2652
|
+
variableListeners = /* @__PURE__ */ new Set();
|
|
2653
|
+
/** `embedding.validate`; ok when Haven cannot check (not embedded, older Haven). */
|
|
2654
|
+
async validate(options) {
|
|
2655
|
+
try {
|
|
2656
|
+
const result = await this.rpc.call("embedding.validate", {
|
|
2657
|
+
interactive: options?.interactive !== false
|
|
2658
|
+
});
|
|
2659
|
+
return {
|
|
2660
|
+
ok: result?.ok !== false,
|
|
2661
|
+
issues: normalizeMindooDBAppIssues(result?.issues),
|
|
2662
|
+
...result?.timedOut ? { timedOut: true } : {}
|
|
2663
|
+
};
|
|
2664
|
+
} catch (error) {
|
|
2665
|
+
if (isMethodNotFound(error) || error instanceof Error && error.name === "unsupported") {
|
|
2666
|
+
return { ok: true, issues: [] };
|
|
2667
|
+
}
|
|
2668
|
+
throw error;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
/** Runs the matching handler and tells Haven how it went; Haven answers the host. */
|
|
2059
2672
|
async answerRequest(message) {
|
|
2060
2673
|
let response;
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
try {
|
|
2674
|
+
try {
|
|
2675
|
+
const params = message.params ?? {};
|
|
2676
|
+
if (message.request === "save" && this.saveHandler) {
|
|
2065
2677
|
await this.saveHandler();
|
|
2066
2678
|
response = { ok: true };
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2679
|
+
} else if (message.request === "inspect" && this.inspectionProvider) {
|
|
2680
|
+
const inspection = await this.inspectionProvider(normalizeMindooDBAppInspectRequest(params.request));
|
|
2681
|
+
response = { ok: true, result: normalizeMindooDBAppInspection(inspection) };
|
|
2682
|
+
} else if (message.request === "showIssues" && this.showIssuesHandler) {
|
|
2683
|
+
await this.showIssuesHandler(normalizeMindooDBAppIssues(params.issues));
|
|
2684
|
+
response = { ok: true };
|
|
2685
|
+
} else if (message.request === "reveal" && this.revealHandler) {
|
|
2686
|
+
const anchor = normalizeMindooDBAppInspectAnchor(params.anchor);
|
|
2687
|
+
if (!anchor) {
|
|
2688
|
+
throw new Error("Invalid anchor.");
|
|
2689
|
+
}
|
|
2690
|
+
await this.revealHandler(anchor);
|
|
2691
|
+
response = { ok: true };
|
|
2692
|
+
} else if (message.request === "variables") {
|
|
2693
|
+
this.variables = normalizeMindooDBAppEmbedVariables(params.variables);
|
|
2694
|
+
const variables = this.variables;
|
|
2695
|
+
this.variableListeners.forEach((listener) => {
|
|
2696
|
+
try {
|
|
2697
|
+
listener(variables.map((variable) => ({ ...variable })));
|
|
2698
|
+
} catch (error) {
|
|
2699
|
+
console.error("MindooDB embedding variables listener failed.", error);
|
|
2700
|
+
}
|
|
2701
|
+
});
|
|
2702
|
+
response = { ok: true };
|
|
2703
|
+
} else if (message.request === "export" && this.exportProvider) {
|
|
2704
|
+
const request = normalizeMindooDBAppEmbedExportRequest(params.request);
|
|
2705
|
+
response = { ok: true, result: await mindooDBAppExportPayload(await this.exportProvider(request), request) };
|
|
2706
|
+
} else {
|
|
2707
|
+
response = { ok: false, error: "unsupported" };
|
|
2069
2708
|
}
|
|
2709
|
+
} catch (error) {
|
|
2710
|
+
response = { ok: false, error: errorMessage(error) };
|
|
2070
2711
|
}
|
|
2071
2712
|
try {
|
|
2072
2713
|
await this.rpc.call("embedding.respond", { requestId: message.requestId, ...response });
|
|
@@ -2074,6 +2715,24 @@ var MindooDBAppEmbedsClient = class {
|
|
|
2074
2715
|
console.warn("[mindoodb-app-sdk] Could not answer the host's request.", error);
|
|
2075
2716
|
}
|
|
2076
2717
|
}
|
|
2718
|
+
/** This app as a host: Haven asks before one of its components saves. */
|
|
2719
|
+
async answerEmbedRequest(message) {
|
|
2720
|
+
let response;
|
|
2721
|
+
const embed = this.open.get(message.embedId);
|
|
2722
|
+
try {
|
|
2723
|
+
response = message.request === "beforeSave" ? { ok: true, result: embed ? await embed.answerBeforeSave(message.params) : { issues: [] } } : { ok: false, error: "unsupported" };
|
|
2724
|
+
} catch (error) {
|
|
2725
|
+
response = {
|
|
2726
|
+
ok: true,
|
|
2727
|
+
result: { issues: [{ severity: "warning", message: `The check failed: ${errorMessage(error)}`, code: "check-failed" }] }
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
try {
|
|
2731
|
+
await this.rpc.call("embeds.respond", { requestId: message.requestId, ...response });
|
|
2732
|
+
} catch (error) {
|
|
2733
|
+
console.warn("[mindoodb-app-sdk] Could not answer Haven's request.", error);
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2077
2736
|
dispose() {
|
|
2078
2737
|
this.stopListening();
|
|
2079
2738
|
}
|
|
@@ -3907,6 +4566,27 @@ export {
|
|
|
3907
4566
|
isValidMindooDBDocumentId,
|
|
3908
4567
|
mindooDBDocumentId,
|
|
3909
4568
|
assertValidMindooDBCreateIds,
|
|
4569
|
+
MINDOODB_INSPECT_DOCUMENT,
|
|
4570
|
+
MINDOODB_INSPECT_SPREADSHEET,
|
|
4571
|
+
MINDOODB_INSPECT_SLIDES,
|
|
4572
|
+
MINDOODB_APP_INSPECTION_FIELD,
|
|
4573
|
+
MINDOODB_APP_INSPECTION_SUMMARY_MAX_BYTES,
|
|
4574
|
+
MINDOODB_APP_INSPECTION_MAX_BYTES,
|
|
4575
|
+
MINDOODB_APP_ISSUES_MAX,
|
|
4576
|
+
MindooDBAppEmbedValidationError,
|
|
4577
|
+
mindooDBAppComponentSupports,
|
|
4578
|
+
mindooDBAppInspectContracts,
|
|
4579
|
+
normalizeMindooDBAppInspectAnchor,
|
|
4580
|
+
normalizeMindooDBAppIssues,
|
|
4581
|
+
normalizeMindooDBAppInspectRequest,
|
|
4582
|
+
normalizeMindooDBAppInspection,
|
|
4583
|
+
summarizeMindooDBAppInspection,
|
|
4584
|
+
mindooDBAppInspectionSummaryValue,
|
|
4585
|
+
readMindooDBAppInspectionSummary,
|
|
4586
|
+
defineDocumentRules,
|
|
4587
|
+
mindooDBAppInspectRules,
|
|
4588
|
+
performMindooDBAppEmbeddingSave,
|
|
4589
|
+
resolveMindooDBAppEmbedValidation,
|
|
3910
4590
|
MINDOODB_APP_DEFINITION_FORMAT,
|
|
3911
4591
|
MINDOODB_APP_DEFINITION_VERSION,
|
|
3912
4592
|
MINDOODB_APP_DEFINITION_FILE_NAME,
|
|
@@ -3952,6 +4632,14 @@ export {
|
|
|
3952
4632
|
bindDragSource,
|
|
3953
4633
|
normalizeAgentToolInput,
|
|
3954
4634
|
MindooDBAppAgentToolError,
|
|
4635
|
+
MINDOODB_APP_EMBED_VARIABLES_MAX,
|
|
4636
|
+
normalizeMindooDBAppEmbedVariables,
|
|
4637
|
+
resolveMindooDBAppVariables,
|
|
4638
|
+
MINDOODB_APP_EMBED_EXPORT_MAX_BYTES,
|
|
4639
|
+
mindooDBAppExportMimeType,
|
|
4640
|
+
normalizeMindooDBAppEmbedExportRequest,
|
|
4641
|
+
mindooDBAppExportPayload,
|
|
4642
|
+
mindooDBAppExportFile,
|
|
3955
4643
|
pageUsers,
|
|
3956
4644
|
DEFAULT_HAVEN_HOST_SHORTCUTS,
|
|
3957
4645
|
matchHostShortcut,
|