@dyrected/core 2.5.44 → 2.5.46

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/LICENSE.md CHANGED
@@ -4,7 +4,7 @@ Parameters
4
4
 
5
5
  Licensor: Dyrected
6
6
  Licensed Work: Dyrected
7
- Additional Use Grant: Commercial use is permitted as long as it is not used to provide a hosted or managed service that competes with Dyrected.
7
+ Additional Use Grant: Production use and commercial use of the Licensed Work are permitted for your own internal business operations, your own websites and applications, and client websites or applications that you build or deploy on behalf of a client, provided that you do not, without a separate commercial license from the Licensor, (a) provide the Licensed Work as a hosted or managed service to third parties, (b) embed, white-label, sublicense, or otherwise redistribute the Licensed Work as part of a multi-tenant or customer-facing SaaS, platform, or developer service, or (c) enable third parties to create, manage, or operate independent projects, sites, workspaces, or environments using the Licensed Work as a material part of the service you provide.
8
8
  Change Date: 2030-05-18
9
9
  Change License: Apache License 2.0
10
10
 
package/dist/index.cjs CHANGED
@@ -51,7 +51,7 @@ __export(index_exports, {
51
51
  });
52
52
  module.exports = __toCommonJS(index_exports);
53
53
 
54
- // src/types/workflows.js
54
+ // src/types/workflows.ts
55
55
  var LIFECYCLE_EVENT_NAMES = [
56
56
  "revision.created",
57
57
  "workflow.transitioned",
@@ -59,7 +59,7 @@ var LIFECYCLE_EVENT_NAMES = [
59
59
  "entry.unpublished"
60
60
  ];
61
61
 
62
- // src/workflows.js
62
+ // src/workflows.ts
63
63
  var WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
64
64
  var LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
65
65
  function publishingWorkflow() {
@@ -92,18 +92,17 @@ function workflowCapabilities(workflow, user) {
92
92
  const capabilities = new Set(Array.isArray(user?.capabilities) ? user.capabilities : []);
93
93
  const roles = Array.isArray(user?.roles) ? user.roles : [];
94
94
  for (const mapping of workflow.roles ?? []) {
95
- if (roles.includes(mapping.role))
96
- mapping.capabilities.forEach((capability) => capabilities.add(capability));
95
+ if (roles.includes(mapping.role)) mapping.capabilities.forEach((capability) => capabilities.add(capability));
97
96
  }
98
97
  return capabilities;
99
98
  }
100
99
  function canViewWorkflowDraft(workflow, user) {
101
- if (!user)
102
- return false;
100
+ if (!user) return false;
103
101
  const capabilities = workflowCapabilities(workflow, user);
104
- if (capabilities.has("entry.edit"))
105
- return true;
106
- return workflow.transitions.some((transition) => (transition.requiredCapabilities ?? []).some((capability) => capabilities.has(capability)));
102
+ if (capabilities.has("entry.edit")) return true;
103
+ return workflow.transitions.some(
104
+ (transition) => (transition.requiredCapabilities ?? []).some((capability) => capabilities.has(capability))
105
+ );
107
106
  }
108
107
  function availableWorkflowTransitions(workflow, state, user) {
109
108
  const capabilities = workflowCapabilities(workflow, user);
@@ -120,12 +119,10 @@ function initializeWorkflowDocument(data, workflow) {
120
119
  }
121
120
  function materializeWorkflowDocument(doc, workflow, user) {
122
121
  const meta = doc.__workflow;
123
- if (!meta)
124
- return doc;
122
+ if (!meta) return doc;
125
123
  const { __published, __workflow, ...working } = doc;
126
124
  if (!canViewWorkflowDraft(workflow, user)) {
127
- if (!__published || typeof __published !== "object")
128
- return null;
125
+ if (!__published || typeof __published !== "object") return null;
129
126
  return { id: doc.id, ...__published, _workflow: publicMetadata(meta) };
130
127
  }
131
128
  return {
@@ -157,15 +154,13 @@ async function persistEvent(db, event) {
157
154
  }
158
155
  async function dispatchLifecycleEvent(config, event) {
159
156
  const db = config.db;
160
- if (!db || !config.events?.handlers.length)
161
- return;
157
+ if (!db || !config.events?.handlers.length) return;
162
158
  const maxAttempts = config.events.maxAttempts ?? 8;
163
159
  const retryDelayMs = config.events.retryDelayMs ?? 1e3;
164
160
  const attempts = event.attempts + 1;
165
161
  try {
166
162
  await db.update({ collection: LIFECYCLE_EVENTS_COLLECTION, id: event.id, data: { status: "processing", attempts } });
167
- for (const handler of config.events.handlers)
168
- await handler({ ...event, status: "processing", attempts });
163
+ for (const handler of config.events.handlers) await handler({ ...event, status: "processing", attempts });
169
164
  await db.update({
170
165
  collection: LIFECYCLE_EVENTS_COLLECTION,
171
166
  id: event.id,
@@ -186,8 +181,7 @@ async function dispatchLifecycleEvent(config, event) {
186
181
  }
187
182
  }
188
183
  async function dispatchPendingLifecycleEvents(config, limit = 50) {
189
- if (!config.db || !config.events?.handlers.length)
190
- return 0;
184
+ if (!config.db || !config.events?.handlers.length) return 0;
191
185
  const maxAttempts = config.events.maxAttempts ?? 8;
192
186
  const result = await config.db.find({
193
187
  collection: LIFECYCLE_EVENTS_COLLECTION,
@@ -196,17 +190,17 @@ async function dispatchPendingLifecycleEvents(config, limit = 50) {
196
190
  limit
197
191
  });
198
192
  const now = Date.now();
199
- const due = result.docs.filter((doc) => Number(doc.attempts ?? 0) < maxAttempts && (!doc.nextAttemptAt || new Date(doc.nextAttemptAt).getTime() <= now));
200
- for (const event of due)
201
- await dispatchLifecycleEvent(config, event);
193
+ const due = result.docs.filter(
194
+ (doc) => Number(doc.attempts ?? 0) < maxAttempts && (!doc.nextAttemptAt || new Date(doc.nextAttemptAt).getTime() <= now)
195
+ );
196
+ for (const event of due) await dispatchLifecycleEvent(config, event);
202
197
  return due.length;
203
198
  }
204
199
  async function saveWorkflowDraft(args) {
205
200
  const { config, collection, id, originalDoc, data, user } = args;
206
201
  const db = config.db;
207
202
  const workflow = collection.workflow;
208
- if (!db.transaction)
209
- throw new Error(`The configured database adapter does not support workflow transactions.`);
203
+ if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
210
204
  const previous = originalDoc.__workflow;
211
205
  const event = createLifecycleEvent({
212
206
  name: "revision.created",
@@ -231,8 +225,7 @@ async function saveWorkflowDraft(args) {
231
225
  async function createWorkflowDocument(args) {
232
226
  const { config, collection, data, user } = args;
233
227
  const db = config.db;
234
- if (!db.transaction)
235
- throw new Error(`The configured database adapter does not support workflow transactions.`);
228
+ if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
236
229
  let event;
237
230
  const doc = await db.transaction(async (tx) => {
238
231
  const created = await tx.create({ collection: collection.slug, data });
@@ -253,14 +246,11 @@ async function transitionWorkflow(args) {
253
246
  const { config, collection, id, transitionName, expectedRevision, comment, user, req } = args;
254
247
  const db = config.db;
255
248
  const workflow = collection.workflow;
256
- if (!db.transaction)
257
- throw new Error(`The configured database adapter does not support workflow transactions.`);
249
+ if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
258
250
  const original = await db.findOne({ collection: collection.slug, id });
259
- if (!original)
260
- throw Object.assign(new Error("Not Found"), { statusCode: 404 });
251
+ if (!original) throw Object.assign(new Error("Not Found"), { statusCode: 404 });
261
252
  const meta = original.__workflow;
262
- if (!meta)
263
- throw Object.assign(new Error("Entry has no workflow metadata"), { statusCode: 409 });
253
+ if (!meta) throw Object.assign(new Error("Entry has no workflow metadata"), { statusCode: 409 });
264
254
  if (expectedRevision !== void 0 && expectedRevision !== meta.revision) {
265
255
  throw Object.assign(new Error("This entry changed since it was loaded. Refresh before transitioning it."), { statusCode: 409 });
266
256
  }
@@ -276,8 +266,7 @@ async function transitionWorkflow(args) {
276
266
  throw Object.assign(new Error(`A comment is required for "${transition.label}".`), { statusCode: 400 });
277
267
  }
278
268
  const hookContext = { transition, from: meta.state, to: transition.to, doc: original, user, comment, req, db };
279
- for (const hook of workflow.hooks?.beforeTransition ?? [])
280
- await hook(hookContext);
269
+ for (const hook of workflow.hooks?.beforeTransition ?? []) await hook(hookContext);
281
270
  const events = [createLifecycleEvent({
282
271
  name: "workflow.transitioned",
283
272
  collection: collection.slug,
@@ -293,8 +282,7 @@ async function transitionWorkflow(args) {
293
282
  }
294
283
  const updated = await db.transaction(async (tx) => {
295
284
  const locked = await tx.findOne({ collection: collection.slug, id });
296
- if (!locked)
297
- throw Object.assign(new Error("Not Found"), { statusCode: 404 });
285
+ if (!locked) throw Object.assign(new Error("Not Found"), { statusCode: 404 });
298
286
  const lockedMeta = locked.__workflow;
299
287
  if (lockedMeta.revision !== meta.revision || lockedMeta.state !== meta.state || expectedRevision !== void 0 && lockedMeta.revision !== expectedRevision) {
300
288
  throw Object.assign(new Error("This entry changed since it was loaded. Refresh before transitioning it."), { statusCode: 409 });
@@ -308,24 +296,20 @@ async function transitionWorkflow(args) {
308
296
  ...transition.unpublish ? { publishedRevision: void 0, publishedAt: void 0, publishedBy: void 0 } : {}
309
297
  };
310
298
  const data = { __workflow: nextMeta };
311
- if (targetState.published)
312
- data.__published = working;
313
- if (transition.unpublish)
314
- data.__published = null;
299
+ if (targetState.published) data.__published = working;
300
+ if (transition.unpublish) data.__published = null;
315
301
  const next = await tx.update({ collection: collection.slug, id, data });
316
302
  await tx.create({
317
303
  collection: WORKFLOW_HISTORY_COLLECTION,
318
304
  data: { collection: collection.slug, documentId: id, transition: transition.name, from: lockedMeta.state, to: transition.to, revision: lockedMeta.revision, comment: comment ?? null, actorId: user?.sub ?? null, createdAt: now }
319
305
  });
320
- for (const event of events)
321
- await persistEvent(tx, event);
306
+ for (const event of events) await persistEvent(tx, event);
322
307
  if (collection.audit) {
323
308
  await tx.create({ collection: "__audit", data: { collection: collection.slug, documentId: id, operation: "workflow.transition", user: user?.sub ?? null, timestamp: now, changes: JSON.stringify({ transition: transition.name, from: lockedMeta.state, to: transition.to, revision: lockedMeta.revision }) } });
324
309
  }
325
310
  return next;
326
311
  });
327
- for (const event of events)
328
- void dispatchLifecycleEvent(config, event);
312
+ for (const event of events) void dispatchLifecycleEvent(config, event);
329
313
  for (const hook of workflow.hooks?.afterTransition ?? []) {
330
314
  try {
331
315
  await hook({ ...hookContext, doc: updated, event: events[0] });
@@ -336,7 +320,7 @@ async function transitionWorkflow(args) {
336
320
  return updated;
337
321
  }
338
322
 
339
- // src/utils/admin-auth.js
323
+ // src/utils/admin-auth.ts
340
324
  function getAdminAuthCollection(config) {
341
325
  const requestedSlug = config.adminAuth?.collectionSlug;
342
326
  if (requestedSlug) {
@@ -360,12 +344,11 @@ function getPublicAdminAuthConfig(adminAuth) {
360
344
  }
361
345
  function humanizeProviderName(id, type) {
362
346
  const cleaned = id.replace(/[-_]+/g, " ").trim();
363
- if (!cleaned)
364
- return type.toUpperCase();
347
+ if (!cleaned) return type.toUpperCase();
365
348
  return cleaned.replace(/\b\w/g, (char) => char.toUpperCase());
366
349
  }
367
350
 
368
- // src/utils/config.js
351
+ // src/utils/config.ts
369
352
  var AUDIT_COLLECTION_SLUG = "__audit";
370
353
  var SYSTEM_FIELDS = [
371
354
  {
@@ -579,8 +562,7 @@ function normalizeConfig(config) {
579
562
  });
580
563
  const hasAuditCollection = normalizedCollections.some((col) => col.slug === AUDIT_COLLECTION_SLUG);
581
564
  const systemCollections = [];
582
- if (needsAudit && !hasAuditCollection)
583
- systemCollections.push(AUDIT_COLLECTION);
565
+ if (needsAudit && !hasAuditCollection) systemCollections.push(AUDIT_COLLECTION);
584
566
  if (needsWorkflow && !normalizedCollections.some((col) => col.slug === WORKFLOW_HISTORY_COLLECTION)) {
585
567
  systemCollections.push(WORKFLOW_HISTORY_COLLECTION_CONFIG);
586
568
  }
@@ -594,7 +576,7 @@ function normalizeConfig(config) {
594
576
  };
595
577
  }
596
578
 
597
- // src/utils/parse-where.js
579
+ // src/utils/parse-where.ts
598
580
  function assertNever(op, context) {
599
581
  throw new Error(`[dyrected/core] Unhandled where operator "${op}" in ${context}`);
600
582
  }
@@ -630,8 +612,7 @@ function parseSqlWhere(where, getJsonField, placeholder = "?") {
630
612
  return `${c} != ${next()}`;
631
613
  case "in": {
632
614
  const vals = Array.isArray(operand) ? operand : [operand];
633
- if (vals.length === 0)
634
- return "1=0";
615
+ if (vals.length === 0) return "1=0";
635
616
  const placeholders = vals.map((v) => {
636
617
  params.push(v);
637
618
  return next();
@@ -640,8 +621,7 @@ function parseSqlWhere(where, getJsonField, placeholder = "?") {
640
621
  }
641
622
  case "not_in": {
642
623
  const vals = Array.isArray(operand) ? operand : [operand];
643
- if (vals.length === 0)
644
- return "1=1";
624
+ if (vals.length === 0) return "1=1";
645
625
  const placeholders = vals.map((v) => {
646
626
  params.push(v);
647
627
  return next();
@@ -747,26 +727,22 @@ function parseMongoWhere(where) {
747
727
  conditions.push(buildOperator(field, value));
748
728
  }
749
729
  }
750
- if (conditions.length === 0)
751
- return {};
752
- if (conditions.length === 1)
753
- return conditions[0];
730
+ if (conditions.length === 0) return {};
731
+ if (conditions.length === 1) return conditions[0];
754
732
  return { $and: conditions };
755
733
  }
756
734
  return buildClause(where);
757
735
  }
758
736
 
759
- // src/utils/parse-sort.js
737
+ // src/utils/parse-sort.ts
760
738
  var SORT_FIELD_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)(?:\s+(ASC|DESC))?$/i;
761
739
  function parseSort(sort, fallback = { field: "createdAt", direction: "DESC" }) {
762
- if (!sort)
763
- return [fallback];
740
+ if (!sort) return [fallback];
764
741
  const clauses = sort.split(",").map((part) => part.trim()).filter(Boolean).map((part) => {
765
742
  const descByPrefix = part.startsWith("-");
766
743
  const withoutPrefix = descByPrefix ? part.slice(1).trim() : part;
767
744
  const match = withoutPrefix.match(SORT_FIELD_PATTERN);
768
- if (!match)
769
- return null;
745
+ if (!match) return null;
770
746
  return {
771
747
  field: match[1],
772
748
  direction: descByPrefix || match[2]?.toUpperCase() === "DESC" ? "DESC" : "ASC"
@@ -775,7 +751,7 @@ function parseSort(sort, fallback = { field: "createdAt", direction: "DESC" }) {
775
751
  return clauses.length > 0 ? clauses : [fallback];
776
752
  }
777
753
 
778
- // src/utils/hooks.js
754
+ // src/utils/hooks.ts
779
755
  async function runCollectionHooks(hooks, args, options = {}) {
780
756
  if (!hooks || hooks.length === 0) {
781
757
  return args.data ?? args.doc ?? void 0;
@@ -802,12 +778,10 @@ async function runCollectionHooks(hooks, args, options = {}) {
802
778
  return currentPayload;
803
779
  }
804
780
  async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
805
- if (!data || typeof data !== "object")
806
- return data;
781
+ if (!data || typeof data !== "object") return data;
807
782
  const result = { ...data };
808
783
  for (const field of fields) {
809
- if (!field.name)
810
- continue;
784
+ if (!field.name) continue;
811
785
  const value = result[field.name];
812
786
  const origValue = originalDoc?.[field.name];
813
787
  let updatedValue = value;
@@ -827,13 +801,21 @@ async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
827
801
  }
828
802
  if (updatedValue !== void 0 && updatedValue !== null) {
829
803
  if (field.type === "object" && field.fields) {
830
- result[field.name] = await executeFieldBeforeChange(field.fields, updatedValue, origValue, user, db);
804
+ result[field.name] = await executeFieldBeforeChange(
805
+ field.fields,
806
+ updatedValue,
807
+ origValue,
808
+ user,
809
+ db
810
+ );
831
811
  } else if (field.type === "array" && field.fields && Array.isArray(updatedValue)) {
832
812
  const arrayResult = [];
833
813
  for (let i = 0; i < updatedValue.length; i++) {
834
814
  const item = updatedValue[i];
835
815
  const origItem = Array.isArray(origValue) ? origValue[i] : null;
836
- arrayResult.push(await executeFieldBeforeChange(field.fields, item, origItem, user, db));
816
+ arrayResult.push(
817
+ await executeFieldBeforeChange(field.fields, item, origItem, user, db)
818
+ );
837
819
  }
838
820
  result[field.name] = arrayResult;
839
821
  } else if (field.type === "blocks" && field.blocks && Array.isArray(updatedValue)) {
@@ -841,9 +823,19 @@ async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
841
823
  for (let i = 0; i < updatedValue.length; i++) {
842
824
  const blockData = updatedValue[i];
843
825
  const origBlock = Array.isArray(origValue) ? origValue[i] : null;
844
- const blockConfig = field.blocks.find((b) => b.slug === blockData.blockType);
826
+ const blockConfig = field.blocks.find(
827
+ (b) => b.slug === blockData.blockType
828
+ );
845
829
  if (blockConfig) {
846
- blocksResult.push(await executeFieldBeforeChange(blockConfig.fields, blockData, origBlock, user, db));
830
+ blocksResult.push(
831
+ await executeFieldBeforeChange(
832
+ blockConfig.fields,
833
+ blockData,
834
+ origBlock,
835
+ user,
836
+ db
837
+ )
838
+ );
847
839
  } else {
848
840
  blocksResult.push(blockData);
849
841
  }
@@ -855,12 +847,10 @@ async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
855
847
  return result;
856
848
  }
857
849
  async function executeFieldAfterRead(fields, doc, user, db) {
858
- if (!doc || typeof doc !== "object")
859
- return doc;
850
+ if (!doc || typeof doc !== "object") return doc;
860
851
  const result = { ...doc };
861
852
  for (const field of fields) {
862
- if (!field.name)
863
- continue;
853
+ if (!field.name) continue;
864
854
  const value = result[field.name];
865
855
  let updatedValue = value;
866
856
  if (field.hooks?.afterRead) {
@@ -878,20 +868,41 @@ async function executeFieldAfterRead(fields, doc, user, db) {
878
868
  }
879
869
  if (updatedValue !== void 0 && updatedValue !== null) {
880
870
  if (field.type === "object" && field.fields) {
881
- result[field.name] = await executeFieldAfterRead(field.fields, updatedValue, user, db);
871
+ result[field.name] = await executeFieldAfterRead(
872
+ field.fields,
873
+ updatedValue,
874
+ user,
875
+ db
876
+ );
882
877
  } else if (field.type === "array" && field.fields && Array.isArray(updatedValue)) {
883
878
  const arrayResult = [];
884
879
  for (const item of updatedValue) {
885
- arrayResult.push(await executeFieldAfterRead(field.fields, item, user, db));
880
+ arrayResult.push(
881
+ await executeFieldAfterRead(
882
+ field.fields,
883
+ item,
884
+ user,
885
+ db
886
+ )
887
+ );
886
888
  }
887
889
  result[field.name] = arrayResult;
888
890
  } else if (field.type === "blocks" && field.blocks && Array.isArray(updatedValue)) {
889
891
  const blocksResult = [];
890
892
  for (const blockData of updatedValue) {
891
893
  const typedBlock = blockData;
892
- const blockConfig = field.blocks.find((b) => b.slug === typedBlock.blockType);
894
+ const blockConfig = field.blocks.find(
895
+ (b) => b.slug === typedBlock.blockType
896
+ );
893
897
  if (blockConfig) {
894
- blocksResult.push(await executeFieldAfterRead(blockConfig.fields, typedBlock, user, db));
898
+ blocksResult.push(
899
+ await executeFieldAfterRead(
900
+ blockConfig.fields,
901
+ typedBlock,
902
+ user,
903
+ db
904
+ )
905
+ );
895
906
  } else {
896
907
  blocksResult.push(blockData);
897
908
  }
@@ -903,7 +914,7 @@ async function executeFieldAfterRead(fields, doc, user, db) {
903
914
  return result;
904
915
  }
905
916
 
906
- // src/utils/openapi.js
917
+ // src/utils/openapi.ts
907
918
  function generateOpenApi(config) {
908
919
  const spec = {
909
920
  openapi: "3.0.0",
@@ -1612,8 +1623,7 @@ function fieldsToProperties(fields) {
1612
1623
  required.push(...nested.required);
1613
1624
  continue;
1614
1625
  }
1615
- if (!field.name)
1616
- continue;
1626
+ if (!field.name) continue;
1617
1627
  props[field.name] = fieldToSchema(field);
1618
1628
  if (field.required) {
1619
1629
  required.push(field.name);
@@ -1725,8 +1735,7 @@ function fieldToSchema(field) {
1725
1735
  default:
1726
1736
  schema = { type: "string" };
1727
1737
  }
1728
- if (field.label)
1729
- schema.description = field.label;
1738
+ if (field.label) schema.description = field.label;
1730
1739
  return schema;
1731
1740
  }
1732
1741
 
package/dist/index.js CHANGED
@@ -20,9 +20,9 @@ import {
20
20
  saveWorkflowDraft,
21
21
  transitionWorkflow,
22
22
  workflowCapabilities
23
- } from "./chunk-44O2LDPT.js";
23
+ } from "./chunk-FCXE5CVC.js";
24
24
 
25
- // src/types/workflows.js
25
+ // src/types/workflows.ts
26
26
  var LIFECYCLE_EVENT_NAMES = [
27
27
  "revision.created",
28
28
  "workflow.transitioned",
@@ -30,7 +30,7 @@ var LIFECYCLE_EVENT_NAMES = [
30
30
  "entry.unpublished"
31
31
  ];
32
32
 
33
- // src/utils/parse-where.js
33
+ // src/utils/parse-where.ts
34
34
  function assertNever(op, context) {
35
35
  throw new Error(`[dyrected/core] Unhandled where operator "${op}" in ${context}`);
36
36
  }
@@ -66,8 +66,7 @@ function parseSqlWhere(where, getJsonField, placeholder = "?") {
66
66
  return `${c} != ${next()}`;
67
67
  case "in": {
68
68
  const vals = Array.isArray(operand) ? operand : [operand];
69
- if (vals.length === 0)
70
- return "1=0";
69
+ if (vals.length === 0) return "1=0";
71
70
  const placeholders = vals.map((v) => {
72
71
  params.push(v);
73
72
  return next();
@@ -76,8 +75,7 @@ function parseSqlWhere(where, getJsonField, placeholder = "?") {
76
75
  }
77
76
  case "not_in": {
78
77
  const vals = Array.isArray(operand) ? operand : [operand];
79
- if (vals.length === 0)
80
- return "1=1";
78
+ if (vals.length === 0) return "1=1";
81
79
  const placeholders = vals.map((v) => {
82
80
  params.push(v);
83
81
  return next();
@@ -183,26 +181,22 @@ function parseMongoWhere(where) {
183
181
  conditions.push(buildOperator(field, value));
184
182
  }
185
183
  }
186
- if (conditions.length === 0)
187
- return {};
188
- if (conditions.length === 1)
189
- return conditions[0];
184
+ if (conditions.length === 0) return {};
185
+ if (conditions.length === 1) return conditions[0];
190
186
  return { $and: conditions };
191
187
  }
192
188
  return buildClause(where);
193
189
  }
194
190
 
195
- // src/utils/parse-sort.js
191
+ // src/utils/parse-sort.ts
196
192
  var SORT_FIELD_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*)(?:\s+(ASC|DESC))?$/i;
197
193
  function parseSort(sort, fallback = { field: "createdAt", direction: "DESC" }) {
198
- if (!sort)
199
- return [fallback];
194
+ if (!sort) return [fallback];
200
195
  const clauses = sort.split(",").map((part) => part.trim()).filter(Boolean).map((part) => {
201
196
  const descByPrefix = part.startsWith("-");
202
197
  const withoutPrefix = descByPrefix ? part.slice(1).trim() : part;
203
198
  const match = withoutPrefix.match(SORT_FIELD_PATTERN);
204
- if (!match)
205
- return null;
199
+ if (!match) return null;
206
200
  return {
207
201
  field: match[1],
208
202
  direction: descByPrefix || match[2]?.toUpperCase() === "DESC" ? "DESC" : "ASC"