@odla-ai/chapter 0.47.0 → 0.47.2
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.map +1 -1
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js.map +1 -1
- package/dist/worker/index.cjs +124 -42
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.js +121 -33
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/worker/index.js
CHANGED
|
@@ -6087,7 +6087,13 @@ var handleAdminNetworkPush = async (req, url, env, ctx) => {
|
|
|
6087
6087
|
};
|
|
6088
6088
|
|
|
6089
6089
|
// src/worker-routes-network-records-follower.ts
|
|
6090
|
-
import {
|
|
6090
|
+
import {
|
|
6091
|
+
CRM_NS as CRM_NS2,
|
|
6092
|
+
CrmInputError,
|
|
6093
|
+
getRecord as getRecord4,
|
|
6094
|
+
setStage as setStage2,
|
|
6095
|
+
updateRecord as updateRecord3
|
|
6096
|
+
} from "@odla-ai/crm";
|
|
6091
6097
|
import { verifyFederatedRequest as verifyFederatedRequest6 } from "@odla-ai/db";
|
|
6092
6098
|
|
|
6093
6099
|
// src/worker-routes-network-records-common.ts
|
|
@@ -6095,9 +6101,39 @@ var IDENTIFIER = /^[a-z][a-zA-Z0-9_]*$/;
|
|
|
6095
6101
|
var MAX_PAGE = 50;
|
|
6096
6102
|
var MAX_OFFSET = 1e4;
|
|
6097
6103
|
var MAX_SEARCH = 200;
|
|
6104
|
+
var MAX_STAGE = 100;
|
|
6098
6105
|
var MAX_BODY = 32768;
|
|
6099
6106
|
var RECORD_ID = /^[a-zA-Z0-9][a-zA-Z0-9:_-]{0,191}$/;
|
|
6100
6107
|
var MUTATION_ID2 = /^[a-zA-Z0-9][a-zA-Z0-9:._-]{7,127}$/;
|
|
6108
|
+
var NETWORK_RECORD_SORTS = [
|
|
6109
|
+
{ id: "updated_desc", label: "Recently updated" },
|
|
6110
|
+
{ id: "updated_asc", label: "Least recently updated" },
|
|
6111
|
+
{ id: "name_asc", label: "Name A\u2013Z" },
|
|
6112
|
+
{ id: "name_desc", label: "Name Z\u2013A" }
|
|
6113
|
+
];
|
|
6114
|
+
var NETWORK_RECORD_SORT_COLUMNS = {
|
|
6115
|
+
updated_desc: { field: "updatedAt", dir: "desc" },
|
|
6116
|
+
updated_asc: { field: "updatedAt", dir: "asc" },
|
|
6117
|
+
name_asc: { field: "name", dir: "asc" },
|
|
6118
|
+
name_desc: { field: "name", dir: "desc" }
|
|
6119
|
+
};
|
|
6120
|
+
function networkRecordWindow(params) {
|
|
6121
|
+
const limit = integer(params.get("limit"), 25, 1, MAX_PAGE);
|
|
6122
|
+
const offset = integer(params.get("offset"), 0, 0, MAX_OFFSET);
|
|
6123
|
+
const search = (params.get("search") ?? "").trim();
|
|
6124
|
+
const stage = (params.get("stage") ?? "").trim();
|
|
6125
|
+
const requestedSort = (params.get("sort") ?? "updated_desc").trim();
|
|
6126
|
+
const sortId = NETWORK_RECORD_SORTS.some((candidate) => candidate.id === requestedSort) ? requestedSort : null;
|
|
6127
|
+
if (limit == null || offset == null || search.length > MAX_SEARCH || stage.length > 0 && (stage.length > MAX_STAGE || /[\u0000-\u001f\u007f]/.test(stage)) || !sortId) return null;
|
|
6128
|
+
return {
|
|
6129
|
+
limit,
|
|
6130
|
+
offset,
|
|
6131
|
+
...search ? { search } : {},
|
|
6132
|
+
...stage ? { stage } : {},
|
|
6133
|
+
sortId,
|
|
6134
|
+
sort: NETWORK_RECORD_SORT_COLUMNS[sortId]
|
|
6135
|
+
};
|
|
6136
|
+
}
|
|
6101
6137
|
function bodyTooLarge(body) {
|
|
6102
6138
|
return new TextEncoder().encode(body).byteLength > MAX_BODY;
|
|
6103
6139
|
}
|
|
@@ -6152,6 +6188,45 @@ function restrictedRecord(record4, target) {
|
|
|
6152
6188
|
return { ...record4, ...edit ? { edit } : { edit: void 0 } };
|
|
6153
6189
|
}
|
|
6154
6190
|
|
|
6191
|
+
// src/worker-routes-network-records-search.ts
|
|
6192
|
+
import { CRM_NS, rowToRecord } from "@odla-ai/crm";
|
|
6193
|
+
var MAX_SAFE_LIKE_BYTES = 50;
|
|
6194
|
+
function safePrefix(value) {
|
|
6195
|
+
const prefixed = `${value}%`;
|
|
6196
|
+
return value.includes("%") || value.includes("_") || new TextEncoder().encode(prefixed).byteLength > MAX_SAFE_LIKE_BYTES ? value : { $like: prefixed };
|
|
6197
|
+
}
|
|
6198
|
+
async function listReaderRecords(db, type, allowed2, emailField, window) {
|
|
6199
|
+
const clauses = [
|
|
6200
|
+
{ type },
|
|
6201
|
+
{ archived: false },
|
|
6202
|
+
...window.stage ? [{ stage: window.stage }] : []
|
|
6203
|
+
];
|
|
6204
|
+
if (window.search) {
|
|
6205
|
+
const visible = [{ name: safePrefix(window.search) }];
|
|
6206
|
+
if (emailField && allowed2.includes(emailField)) {
|
|
6207
|
+
visible.push({ primaryEmail: safePrefix(window.search.toLowerCase()) });
|
|
6208
|
+
}
|
|
6209
|
+
clauses.push({ or: visible });
|
|
6210
|
+
}
|
|
6211
|
+
const where = { and: clauses };
|
|
6212
|
+
const crmDb = db;
|
|
6213
|
+
const [result, aggregate] = await Promise.all([
|
|
6214
|
+
crmDb.query({
|
|
6215
|
+
[CRM_NS.record]: { $: {
|
|
6216
|
+
where,
|
|
6217
|
+
order: { [window.sort.field]: window.sort.dir },
|
|
6218
|
+
limit: window.limit,
|
|
6219
|
+
offset: window.offset
|
|
6220
|
+
} }
|
|
6221
|
+
}),
|
|
6222
|
+
crmDb.aggregate(CRM_NS.record, { count: true }, { where })
|
|
6223
|
+
]);
|
|
6224
|
+
return {
|
|
6225
|
+
records: (result[CRM_NS.record] ?? []).map(rowToRecord),
|
|
6226
|
+
total: aggregate.count ?? 0
|
|
6227
|
+
};
|
|
6228
|
+
}
|
|
6229
|
+
|
|
6155
6230
|
// src/worker-routes-network-records-follower.ts
|
|
6156
6231
|
var NETWORK_MUTATION_META = "chapterNetworkMutation";
|
|
6157
6232
|
function mutationFingerprint(input) {
|
|
@@ -6178,9 +6253,9 @@ function mutationError(error) {
|
|
|
6178
6253
|
}
|
|
6179
6254
|
async function priorMutation(db, id) {
|
|
6180
6255
|
const result = await db.query({
|
|
6181
|
-
[
|
|
6256
|
+
[CRM_NS2.activity]: { $: { where: { id }, limit: 1 } }
|
|
6182
6257
|
});
|
|
6183
|
-
const row = (result[
|
|
6258
|
+
const row = (result[CRM_NS2.activity] ?? [])[0];
|
|
6184
6259
|
const meta = row?.meta;
|
|
6185
6260
|
const receipt = meta?.[NETWORK_MUTATION_META];
|
|
6186
6261
|
return typeof receipt?.fingerprint === "string" ? { fingerprint: receipt.fingerprint } : null;
|
|
@@ -6300,21 +6375,19 @@ var handleNetworkRecords = async (req, url, env, ctx) => {
|
|
|
6300
6375
|
const type = url.searchParams.get("type") ?? "";
|
|
6301
6376
|
const allowed2 = reader.fields[type];
|
|
6302
6377
|
if (!IDENTIFIER.test(type) || !allowed2) return json({ error: "record type is not shared with this reader" }, 403);
|
|
6303
|
-
const
|
|
6304
|
-
|
|
6305
|
-
const
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
sort: { field: "updatedAt", dir: "desc" }
|
|
6317
|
-
}
|
|
6378
|
+
const window = networkRecordWindow(url.searchParams);
|
|
6379
|
+
if (!window) return json({ error: "invalid record query parameters" }, 400);
|
|
6380
|
+
const typeDef = ctx.chapter.crm.type(type);
|
|
6381
|
+
const stages = typeDef.pipeline?.stages ?? [];
|
|
6382
|
+
if (window.stage && !stages.some((stage) => stage.id === window.stage)) {
|
|
6383
|
+
return json({ error: "stage is not defined for this record type" }, 400);
|
|
6384
|
+
}
|
|
6385
|
+
const page = await listReaderRecords(
|
|
6386
|
+
db,
|
|
6387
|
+
type,
|
|
6388
|
+
allowed2,
|
|
6389
|
+
typeDef.emailField,
|
|
6390
|
+
window
|
|
6318
6391
|
);
|
|
6319
6392
|
const response = {
|
|
6320
6393
|
version: 1,
|
|
@@ -6322,8 +6395,16 @@ var handleNetworkRecords = async (req, url, env, ctx) => {
|
|
|
6322
6395
|
type,
|
|
6323
6396
|
records: page.records.map((record4) => readerRecord(record4, reader, ctx.chapter.crm)),
|
|
6324
6397
|
total: page.total,
|
|
6325
|
-
limit:
|
|
6326
|
-
offset:
|
|
6398
|
+
limit: window.limit,
|
|
6399
|
+
offset: window.offset,
|
|
6400
|
+
filters: {
|
|
6401
|
+
stages: stages.map((stage) => ({ id: stage.id, label: stage.label ?? stage.id })),
|
|
6402
|
+
sorts: [...NETWORK_RECORD_SORTS]
|
|
6403
|
+
},
|
|
6404
|
+
appliedQuery: {
|
|
6405
|
+
...window.stage ? { stage: window.stage } : {},
|
|
6406
|
+
sort: window.sortId
|
|
6407
|
+
}
|
|
6327
6408
|
};
|
|
6328
6409
|
return json(response);
|
|
6329
6410
|
};
|
|
@@ -6356,7 +6437,8 @@ async function readTargetRecords(db, env, ctx, target, query) {
|
|
|
6356
6437
|
const upstream = body && "error" in body && typeof body.error === "string" ? body.error : void 0;
|
|
6357
6438
|
return {
|
|
6358
6439
|
ok: false,
|
|
6359
|
-
error: upstream ?? (response.ok ? "invalid follower record response" : `follower returned ${response.status}`)
|
|
6440
|
+
error: upstream ?? (response.ok ? "invalid follower record response" : `follower returned ${response.status}`),
|
|
6441
|
+
...response.status === 400 ? { status: 400 } : {}
|
|
6360
6442
|
};
|
|
6361
6443
|
}
|
|
6362
6444
|
return {
|
|
@@ -6447,16 +6529,22 @@ var handleAdminNetworkRecords = async (req, url, env, ctx) => {
|
|
|
6447
6529
|
const type = url.searchParams.get("type") ?? "";
|
|
6448
6530
|
const target = targetFor2(ctx, targetId);
|
|
6449
6531
|
if (!target || !IDENTIFIER.test(type)) return json({ error: "configured targetId and record type are required" }, 400);
|
|
6450
|
-
const
|
|
6451
|
-
|
|
6452
|
-
const
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6532
|
+
const window = networkRecordWindow(url.searchParams);
|
|
6533
|
+
if (!window) return json({ error: "invalid record query parameters" }, 400);
|
|
6534
|
+
const query = new URLSearchParams({
|
|
6535
|
+
type,
|
|
6536
|
+
limit: String(window.limit),
|
|
6537
|
+
offset: String(window.offset),
|
|
6538
|
+
sort: window.sortId
|
|
6539
|
+
});
|
|
6540
|
+
if (window.search) query.set("search", window.search);
|
|
6541
|
+
if (window.stage) query.set("stage", window.stage);
|
|
6458
6542
|
const result = await readTargetRecords(got.db, env, ctx, target, query);
|
|
6459
|
-
|
|
6543
|
+
if (!result.ok) return json({ error: result.error }, result.status ?? 502);
|
|
6544
|
+
if ((window.stage || url.searchParams.has("sort")) && (!result.page.appliedQuery || result.page.appliedQuery.sort !== window.sortId || result.page.appliedQuery.stage !== window.stage)) {
|
|
6545
|
+
return json({ error: "follower did not apply the requested record query" }, 502);
|
|
6546
|
+
}
|
|
6547
|
+
return json(result.page);
|
|
6460
6548
|
};
|
|
6461
6549
|
|
|
6462
6550
|
// src/worker-routes-network-notes.ts
|
|
@@ -6546,7 +6634,7 @@ var handleAdminNetworkNotes = async (req, url, env, ctx) => {
|
|
|
6546
6634
|
// src/worker-routes-network-shared-notes.ts
|
|
6547
6635
|
import {
|
|
6548
6636
|
addActivity,
|
|
6549
|
-
CRM_NS as
|
|
6637
|
+
CRM_NS as CRM_NS3,
|
|
6550
6638
|
getRecord as getRecord5
|
|
6551
6639
|
} from "@odla-ai/crm";
|
|
6552
6640
|
import { signFederatedRequest as signFederatedRequest5, verifyFederatedRequest as verifyFederatedRequest7 } from "@odla-ai/db";
|
|
@@ -6578,7 +6666,7 @@ function sharedNote(activity, sourceId) {
|
|
|
6578
6666
|
}
|
|
6579
6667
|
async function listSharedNotes(db, sourceId, recordId) {
|
|
6580
6668
|
const result = await db.query({
|
|
6581
|
-
[
|
|
6669
|
+
[CRM_NS3.activity]: {
|
|
6582
6670
|
$: {
|
|
6583
6671
|
where: {
|
|
6584
6672
|
and: [
|
|
@@ -6591,7 +6679,7 @@ async function listSharedNotes(db, sourceId, recordId) {
|
|
|
6591
6679
|
}
|
|
6592
6680
|
}
|
|
6593
6681
|
});
|
|
6594
|
-
return (result[
|
|
6682
|
+
return (result[CRM_NS3.activity] ?? []).flatMap((activity) => {
|
|
6595
6683
|
const note = sharedNote(activity, sourceId);
|
|
6596
6684
|
return note ? [note] : [];
|
|
6597
6685
|
});
|