@dyrected/core 2.5.61 → 2.5.62
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/app-config-BcuZIpvL.d.cts +1951 -0
- package/dist/app-config-BcuZIpvL.d.ts +1951 -0
- package/dist/app-config-Bm9-2Am6.d.cts +1875 -0
- package/dist/app-config-Bm9-2Am6.d.ts +1875 -0
- package/dist/app-config-CJAGGPrk.d.cts +1900 -0
- package/dist/app-config-CJAGGPrk.d.ts +1900 -0
- package/dist/app-config-CiEDJm0e.d.cts +1912 -0
- package/dist/app-config-CiEDJm0e.d.ts +1912 -0
- package/dist/app-config-DCDh8Gbx.d.cts +1926 -0
- package/dist/app-config-DCDh8Gbx.d.ts +1926 -0
- package/dist/app-config-Dv5XACR4.d.cts +2065 -0
- package/dist/app-config-Dv5XACR4.d.ts +2065 -0
- package/dist/app-config-_kkj71CB.d.cts +2010 -0
- package/dist/app-config-_kkj71CB.d.ts +2010 -0
- package/dist/app-config-tITj_0sn.d.cts +1926 -0
- package/dist/app-config-tITj_0sn.d.ts +1926 -0
- package/dist/chunk-57FNM42D.js +2392 -0
- package/dist/chunk-BAMX7YUC.js +1815 -0
- package/dist/chunk-BQV3QW3Y.js +2588 -0
- package/dist/chunk-EH3MJGB5.js +2571 -0
- package/dist/chunk-M3HKRN7E.js +1665 -0
- package/dist/chunk-MQZH7RQC.js +1667 -0
- package/dist/chunk-VCYYBN5J.js +1873 -0
- package/dist/chunk-WVD7PORQ.js +1672 -0
- package/dist/chunk-XZLIBQSO.js +2397 -0
- package/dist/index.cjs +336 -39
- package/dist/index.d.cts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.js +3 -1
- package/dist/server.cjs +2934 -708
- package/dist/server.d.cts +124 -12
- package/dist/server.d.ts +124 -12
- package/dist/server.js +2059 -697
- package/package.json +10 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -46,6 +56,7 @@ __export(index_exports, {
|
|
|
46
56
|
defineMultiSelectField: () => defineMultiSelectField,
|
|
47
57
|
defineNumberField: () => defineNumberField,
|
|
48
58
|
defineObjectField: () => defineObjectField,
|
|
59
|
+
definePublishingWorkflow: () => definePublishingWorkflow,
|
|
49
60
|
defineRadioField: () => defineRadioField,
|
|
50
61
|
defineRelationshipField: () => defineRelationshipField,
|
|
51
62
|
defineRichTextField: () => defineRichTextField,
|
|
@@ -88,10 +99,47 @@ var LIFECYCLE_EVENT_NAMES = [
|
|
|
88
99
|
"entry.unpublished"
|
|
89
100
|
];
|
|
90
101
|
|
|
102
|
+
// src/auth/token.ts
|
|
103
|
+
var import_jose = require("jose");
|
|
104
|
+
var import_node_util = require("util");
|
|
105
|
+
|
|
106
|
+
// src/auth/sessions.ts
|
|
107
|
+
var AUTH_SESSIONS_COLLECTION = "__auth_sessions";
|
|
108
|
+
|
|
109
|
+
// src/observability.ts
|
|
110
|
+
var import_api = require("@opentelemetry/api");
|
|
111
|
+
var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
112
|
+
var import_exporter_prometheus = require("@opentelemetry/exporter-prometheus");
|
|
113
|
+
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
114
|
+
var import_resources = require("@opentelemetry/resources");
|
|
115
|
+
var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
116
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
117
|
+
var import_pino = __toESM(require("pino"), 1);
|
|
118
|
+
var import_pino_pretty = __toESM(require("pino-pretty"), 1);
|
|
119
|
+
var import_node_stream = require("stream");
|
|
120
|
+
var runtimeByConfig = /* @__PURE__ */ new WeakMap();
|
|
121
|
+
var fallbackLogger = (0, import_pino.default)({
|
|
122
|
+
name: "dyrected",
|
|
123
|
+
enabled: process.env.DISABLE_LOGGING !== "true",
|
|
124
|
+
timestamp: import_pino.stdTimeFunctions.isoTime
|
|
125
|
+
});
|
|
126
|
+
function getObservabilityRuntime(config) {
|
|
127
|
+
if (!config || typeof config !== "object") return void 0;
|
|
128
|
+
return runtimeByConfig.get(config);
|
|
129
|
+
}
|
|
130
|
+
function getConfigLogger(config, component) {
|
|
131
|
+
const base = config?.logger && !("options" in config.logger) ? config.logger : fallbackLogger;
|
|
132
|
+
return base.child({ component });
|
|
133
|
+
}
|
|
134
|
+
|
|
91
135
|
// src/workflows.ts
|
|
92
136
|
var WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
|
|
93
137
|
var LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
|
|
94
|
-
|
|
138
|
+
var EDITOR_CAPABILITIES = ["entry.edit", "entry.submit"];
|
|
139
|
+
var PUBLISHER_CAPABILITIES = ["entry.edit", "entry.submit", "entry.publish", "entry.unpublish"];
|
|
140
|
+
function definePublishingWorkflow(options = {}) {
|
|
141
|
+
const editors = options.editors ?? ["editor"];
|
|
142
|
+
const publishers = options.publishers ?? ["publisher", "admin"];
|
|
95
143
|
return {
|
|
96
144
|
initialState: "draft",
|
|
97
145
|
draftState: "draft",
|
|
@@ -107,12 +155,14 @@ function publishingWorkflow() {
|
|
|
107
155
|
{ name: "unpublish", label: "Unpublish", from: "published", to: "draft", requiredCapabilities: ["entry.unpublish"], unpublish: true }
|
|
108
156
|
],
|
|
109
157
|
roles: [
|
|
110
|
-
{ role
|
|
111
|
-
{ role
|
|
112
|
-
{ role: "admin", capabilities: ["entry.edit", "entry.submit", "entry.publish", "entry.unpublish"] }
|
|
158
|
+
...editors.map((role) => ({ role, capabilities: [...EDITOR_CAPABILITIES] })),
|
|
159
|
+
...publishers.map((role) => ({ role, capabilities: [...PUBLISHER_CAPABILITIES] }))
|
|
113
160
|
]
|
|
114
161
|
};
|
|
115
162
|
}
|
|
163
|
+
function publishingWorkflow() {
|
|
164
|
+
return definePublishingWorkflow();
|
|
165
|
+
}
|
|
116
166
|
function simplePublishingWorkflow() {
|
|
117
167
|
return {
|
|
118
168
|
initialState: "draft",
|
|
@@ -125,6 +175,9 @@ function simplePublishingWorkflow() {
|
|
|
125
175
|
{ name: "publish", label: "Publish", from: "draft", to: "published" },
|
|
126
176
|
{ name: "unpublish", label: "Unpublish", from: "published", to: "draft", unpublish: true }
|
|
127
177
|
]
|
|
178
|
+
// Intentionally no `roles`: this lightweight workflow (synthesized from
|
|
179
|
+
// `drafts: true`) does no capability-based gating. Draft visibility for a
|
|
180
|
+
// no-roles workflow is handled in `canViewWorkflowDraft`.
|
|
128
181
|
};
|
|
129
182
|
}
|
|
130
183
|
function publicMetadata(meta) {
|
|
@@ -143,9 +196,13 @@ function canViewWorkflowDraft(workflow, user) {
|
|
|
143
196
|
if (!user) return false;
|
|
144
197
|
const capabilities = workflowCapabilities(workflow, user);
|
|
145
198
|
if (capabilities.has("entry.edit")) return true;
|
|
146
|
-
|
|
199
|
+
if (workflow.transitions.some(
|
|
147
200
|
(transition) => (transition.requiredCapabilities ?? []).some((capability) => capabilities.has(capability))
|
|
148
|
-
)
|
|
201
|
+
)) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
if (!workflow.roles || workflow.roles.length === 0) return true;
|
|
205
|
+
return false;
|
|
149
206
|
}
|
|
150
207
|
function availableWorkflowTransitions(workflow, state, user) {
|
|
151
208
|
const capabilities = workflowCapabilities(workflow, user);
|
|
@@ -371,7 +428,17 @@ async function transitionWorkflow(args) {
|
|
|
371
428
|
try {
|
|
372
429
|
await hook({ ...hookContext, doc: updated, event: events[0] });
|
|
373
430
|
} catch (error) {
|
|
374
|
-
|
|
431
|
+
getObservabilityRuntime(config)?.recordWorkflowHookFailure({
|
|
432
|
+
collection: collection.slug,
|
|
433
|
+
transition: transition.name
|
|
434
|
+
});
|
|
435
|
+
getConfigLogger(config, "workflow").error({
|
|
436
|
+
err: error,
|
|
437
|
+
msg: "afterTransition hook failed",
|
|
438
|
+
collection: collection.slug,
|
|
439
|
+
transition: transition.name,
|
|
440
|
+
documentId: id
|
|
441
|
+
});
|
|
375
442
|
}
|
|
376
443
|
}
|
|
377
444
|
return updated;
|
|
@@ -412,6 +479,98 @@ function humanizeProviderName(id, type) {
|
|
|
412
479
|
return cleaned.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
413
480
|
}
|
|
414
481
|
|
|
482
|
+
// src/utils/block-references.ts
|
|
483
|
+
function mergeUniqueBlocks(blocks) {
|
|
484
|
+
const seen = /* @__PURE__ */ new Map();
|
|
485
|
+
for (const block of blocks) {
|
|
486
|
+
const existing = seen.get(block.slug);
|
|
487
|
+
if (existing && existing !== block) {
|
|
488
|
+
throw new Error(
|
|
489
|
+
`Duplicate block slug "${block.slug}" found in the reusable block registry. Block slugs must be unique.`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
if (!existing) seen.set(block.slug, block);
|
|
493
|
+
}
|
|
494
|
+
return Array.from(seen.values());
|
|
495
|
+
}
|
|
496
|
+
function buildRegistry(blocks) {
|
|
497
|
+
return new Map(blocks.map((block) => [block.slug, block]));
|
|
498
|
+
}
|
|
499
|
+
function resolveField(field, registry, blockCache) {
|
|
500
|
+
const next = { ...field };
|
|
501
|
+
if (next.fields) {
|
|
502
|
+
next.fields = next.fields.map(
|
|
503
|
+
(child) => resolveField(child, registry, blockCache)
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
if (next.type !== "blocks") return next;
|
|
507
|
+
const hasInlineBlocks = Array.isArray(next.blocks) && next.blocks.length > 0;
|
|
508
|
+
const hasReferences = Array.isArray(next.blockReferences) && next.blockReferences.length > 0;
|
|
509
|
+
if (hasInlineBlocks && hasReferences) {
|
|
510
|
+
throw new Error(
|
|
511
|
+
`Blocks field "${next.name ?? "(unnamed)"}" cannot define both "blocks" and "blockReferences". Use one or the other.`
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
if (hasReferences) {
|
|
515
|
+
next.blocks = next.blockReferences.map((slug) => {
|
|
516
|
+
const block = registry.get(slug);
|
|
517
|
+
if (!block) {
|
|
518
|
+
throw new Error(
|
|
519
|
+
`Unknown block reference "${slug}" on blocks field "${next.name ?? "(unnamed)"}". Add it to defineConfig({ blocks: [...] }).`
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
return resolveBlock(block, registry, blockCache);
|
|
523
|
+
});
|
|
524
|
+
return next;
|
|
525
|
+
}
|
|
526
|
+
if (hasInlineBlocks) {
|
|
527
|
+
next.blocks = next.blocks.map(
|
|
528
|
+
(block) => resolveBlock(block, registry, blockCache)
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
return next;
|
|
532
|
+
}
|
|
533
|
+
function resolveBlock(block, registry, blockCache) {
|
|
534
|
+
const cached = blockCache.get(block);
|
|
535
|
+
if (cached) return cached;
|
|
536
|
+
const resolved = {
|
|
537
|
+
...block,
|
|
538
|
+
fields: []
|
|
539
|
+
};
|
|
540
|
+
blockCache.set(block, resolved);
|
|
541
|
+
resolved.fields = block.fields.map(
|
|
542
|
+
(field) => resolveField(field, registry, blockCache)
|
|
543
|
+
);
|
|
544
|
+
return resolved;
|
|
545
|
+
}
|
|
546
|
+
function resolveFields(fields, registry, blockCache) {
|
|
547
|
+
return fields.map((field) => resolveField(field, registry, blockCache));
|
|
548
|
+
}
|
|
549
|
+
function normalizeSchemaFragment(fragment) {
|
|
550
|
+
const reusableBlocks = mergeUniqueBlocks(fragment.blocks ?? []);
|
|
551
|
+
const registry = buildRegistry(reusableBlocks);
|
|
552
|
+
const blockCache = /* @__PURE__ */ new WeakMap();
|
|
553
|
+
const resolvedBlocks = reusableBlocks.map(
|
|
554
|
+
(block) => resolveBlock(block, registry, blockCache)
|
|
555
|
+
);
|
|
556
|
+
const resolvedCollections = (fragment.collections ?? []).map(
|
|
557
|
+
(collection) => ({
|
|
558
|
+
...collection,
|
|
559
|
+
fields: resolveFields(collection.fields ?? [], registry, blockCache)
|
|
560
|
+
})
|
|
561
|
+
);
|
|
562
|
+
const resolvedGlobals = (fragment.globals ?? []).map((global) => ({
|
|
563
|
+
...global,
|
|
564
|
+
fields: resolveFields(global.fields ?? [], registry, blockCache)
|
|
565
|
+
}));
|
|
566
|
+
return {
|
|
567
|
+
...fragment,
|
|
568
|
+
...fragment.blocks ? { blocks: resolvedBlocks } : {},
|
|
569
|
+
...fragment.collections ? { collections: resolvedCollections } : {},
|
|
570
|
+
...fragment.globals ? { globals: resolvedGlobals } : {}
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
415
574
|
// src/utils/config.ts
|
|
416
575
|
var AUDIT_COLLECTION_SLUG = "__audit";
|
|
417
576
|
var SYSTEM_FIELDS = [
|
|
@@ -446,12 +605,23 @@ var AUDIT_COLLECTION = {
|
|
|
446
605
|
fields: [
|
|
447
606
|
{ name: "collection", type: "text", label: "Collection", required: true },
|
|
448
607
|
{ name: "documentId", type: "text", label: "Document ID" },
|
|
449
|
-
{
|
|
608
|
+
{
|
|
609
|
+
name: "operation",
|
|
610
|
+
type: "select",
|
|
611
|
+
label: "Operation",
|
|
612
|
+
options: ["create", "update", "delete"],
|
|
613
|
+
required: true
|
|
614
|
+
},
|
|
450
615
|
{ name: "user", type: "text", label: "User ID" },
|
|
451
616
|
{ name: "timestamp", type: "date", label: "Timestamp", required: true },
|
|
452
617
|
{ name: "changes", type: "json", label: "Changes" }
|
|
453
618
|
],
|
|
454
|
-
access: {
|
|
619
|
+
access: {
|
|
620
|
+
read: () => false,
|
|
621
|
+
create: () => false,
|
|
622
|
+
update: () => false,
|
|
623
|
+
delete: () => false
|
|
624
|
+
},
|
|
455
625
|
admin: { hidden: true }
|
|
456
626
|
};
|
|
457
627
|
var WORKFLOW_HISTORY_COLLECTION_CONFIG = {
|
|
@@ -468,7 +638,12 @@ var WORKFLOW_HISTORY_COLLECTION_CONFIG = {
|
|
|
468
638
|
{ name: "actorId", type: "text" },
|
|
469
639
|
{ name: "createdAt", type: "date", required: true }
|
|
470
640
|
],
|
|
471
|
-
access: {
|
|
641
|
+
access: {
|
|
642
|
+
read: ({ user }) => !!user,
|
|
643
|
+
create: () => false,
|
|
644
|
+
update: () => false,
|
|
645
|
+
delete: () => false
|
|
646
|
+
},
|
|
472
647
|
admin: { hidden: true }
|
|
473
648
|
};
|
|
474
649
|
var LIFECYCLE_EVENTS_COLLECTION_CONFIG = {
|
|
@@ -482,22 +657,56 @@ var LIFECYCLE_EVENTS_COLLECTION_CONFIG = {
|
|
|
482
657
|
{ name: "actorId", type: "text" },
|
|
483
658
|
{ name: "payload", type: "json", required: true },
|
|
484
659
|
{ name: "attempts", type: "number", required: true },
|
|
485
|
-
{
|
|
660
|
+
{
|
|
661
|
+
name: "status",
|
|
662
|
+
type: "select",
|
|
663
|
+
options: ["pending", "processing", "delivered", "failed"],
|
|
664
|
+
required: true
|
|
665
|
+
},
|
|
486
666
|
{ name: "nextAttemptAt", type: "date" },
|
|
487
667
|
{ name: "deliveredAt", type: "date" },
|
|
488
668
|
{ name: "lastError", type: "textarea" }
|
|
489
669
|
],
|
|
490
|
-
access: {
|
|
670
|
+
access: {
|
|
671
|
+
read: ({ user }) => !!user?.roles?.includes("admin"),
|
|
672
|
+
create: () => false,
|
|
673
|
+
update: () => false,
|
|
674
|
+
delete: () => false
|
|
675
|
+
},
|
|
676
|
+
admin: { hidden: true }
|
|
677
|
+
};
|
|
678
|
+
var AUTH_SESSIONS_COLLECTION_CONFIG = {
|
|
679
|
+
slug: AUTH_SESSIONS_COLLECTION,
|
|
680
|
+
labels: { singular: "Auth session", plural: "Auth sessions" },
|
|
681
|
+
fields: [
|
|
682
|
+
{ name: "userId", type: "text", required: true },
|
|
683
|
+
{ name: "email", type: "email", required: true },
|
|
684
|
+
{ name: "collection", type: "text", required: true },
|
|
685
|
+
{ name: "authSource", type: "text" },
|
|
686
|
+
{ name: "providerId", type: "text" },
|
|
687
|
+
{ name: "lastIp", type: "text" },
|
|
688
|
+
{ name: "lastSeenAt", type: "date" },
|
|
689
|
+
{ name: "expiresAt", type: "date" },
|
|
690
|
+
{ name: "revokedAt", type: "date" }
|
|
691
|
+
],
|
|
692
|
+
access: {
|
|
693
|
+
read: () => false,
|
|
694
|
+
create: () => false,
|
|
695
|
+
update: () => false,
|
|
696
|
+
delete: () => false
|
|
697
|
+
},
|
|
491
698
|
admin: { hidden: true }
|
|
492
699
|
};
|
|
493
700
|
function normalizeConfig(config) {
|
|
494
|
-
const
|
|
495
|
-
const
|
|
701
|
+
const schemaAwareConfig = normalizeSchemaFragment(config);
|
|
702
|
+
const collections = schemaAwareConfig?.collections || [];
|
|
703
|
+
const globals = schemaAwareConfig?.globals || [];
|
|
496
704
|
const needsAudit = collections.some((col) => col.audit);
|
|
497
705
|
const needsWorkflow = collections.some((col) => col.workflow || col.drafts);
|
|
706
|
+
const needsAuthSessions = collections.some((col) => !!col.auth);
|
|
498
707
|
const adminAuthCollectionSlug = getAdminAuthCollection({
|
|
499
708
|
collections,
|
|
500
|
-
adminAuth:
|
|
709
|
+
adminAuth: schemaAwareConfig.adminAuth
|
|
501
710
|
})?.slug;
|
|
502
711
|
const normalizedCollections = collections.map((col) => {
|
|
503
712
|
let fields = col.fields || [];
|
|
@@ -594,7 +803,7 @@ function normalizeConfig(config) {
|
|
|
594
803
|
return field;
|
|
595
804
|
});
|
|
596
805
|
}
|
|
597
|
-
if (adminAuthCollectionSlug && col.slug === adminAuthCollectionSlug &&
|
|
806
|
+
if (adminAuthCollectionSlug && col.slug === adminAuthCollectionSlug && schemaAwareConfig.adminAuth?.mode === "external") {
|
|
598
807
|
const externalAdminFields = [
|
|
599
808
|
{
|
|
600
809
|
name: "authProvider",
|
|
@@ -628,7 +837,9 @@ function normalizeConfig(config) {
|
|
|
628
837
|
}
|
|
629
838
|
}
|
|
630
839
|
const updatedFieldNames = new Set(fields.map((f) => f.name));
|
|
631
|
-
const fieldsToInject = SYSTEM_FIELDS.filter(
|
|
840
|
+
const fieldsToInject = SYSTEM_FIELDS.filter(
|
|
841
|
+
(f) => !updatedFieldNames.has(f.name)
|
|
842
|
+
);
|
|
632
843
|
const workflow = col.workflow || (col.drafts ? simplePublishingWorkflow() : void 0);
|
|
633
844
|
return {
|
|
634
845
|
...col,
|
|
@@ -636,17 +847,27 @@ function normalizeConfig(config) {
|
|
|
636
847
|
fields: [...fields, ...fieldsToInject]
|
|
637
848
|
};
|
|
638
849
|
});
|
|
639
|
-
const hasAuditCollection = normalizedCollections.some(
|
|
850
|
+
const hasAuditCollection = normalizedCollections.some(
|
|
851
|
+
(col) => col.slug === AUDIT_COLLECTION_SLUG
|
|
852
|
+
);
|
|
640
853
|
const systemCollections = [];
|
|
641
|
-
if (needsAudit && !hasAuditCollection)
|
|
642
|
-
|
|
854
|
+
if (needsAudit && !hasAuditCollection)
|
|
855
|
+
systemCollections.push(AUDIT_COLLECTION);
|
|
856
|
+
if (needsWorkflow && !normalizedCollections.some(
|
|
857
|
+
(col) => col.slug === WORKFLOW_HISTORY_COLLECTION
|
|
858
|
+
)) {
|
|
643
859
|
systemCollections.push(WORKFLOW_HISTORY_COLLECTION_CONFIG);
|
|
644
860
|
}
|
|
645
|
-
if (needsWorkflow && !normalizedCollections.some(
|
|
861
|
+
if (needsWorkflow && !normalizedCollections.some(
|
|
862
|
+
(col) => col.slug === LIFECYCLE_EVENTS_COLLECTION
|
|
863
|
+
)) {
|
|
646
864
|
systemCollections.push(LIFECYCLE_EVENTS_COLLECTION_CONFIG);
|
|
647
865
|
}
|
|
866
|
+
if (needsAuthSessions && !normalizedCollections.some((col) => col.slug === AUTH_SESSIONS_COLLECTION)) {
|
|
867
|
+
systemCollections.push(AUTH_SESSIONS_COLLECTION_CONFIG);
|
|
868
|
+
}
|
|
648
869
|
return {
|
|
649
|
-
...
|
|
870
|
+
...schemaAwareConfig,
|
|
650
871
|
collections: [...normalizedCollections, ...systemCollections],
|
|
651
872
|
globals
|
|
652
873
|
};
|
|
@@ -872,7 +1093,10 @@ async function runCollectionHooks(hooks, args, options = {}) {
|
|
|
872
1093
|
}
|
|
873
1094
|
} catch (err) {
|
|
874
1095
|
if (options.isolated) {
|
|
875
|
-
|
|
1096
|
+
getConfigLogger(void 0, "hooks").error({
|
|
1097
|
+
err,
|
|
1098
|
+
msg: "Side-effect hook failed after a successful write"
|
|
1099
|
+
});
|
|
876
1100
|
} else {
|
|
877
1101
|
throw err;
|
|
878
1102
|
}
|
|
@@ -917,7 +1141,13 @@ async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
|
|
|
917
1141
|
const item = updatedValue[i];
|
|
918
1142
|
const origItem = Array.isArray(origValue) ? origValue[i] : null;
|
|
919
1143
|
arrayResult.push(
|
|
920
|
-
await executeFieldBeforeChange(
|
|
1144
|
+
await executeFieldBeforeChange(
|
|
1145
|
+
field.fields,
|
|
1146
|
+
item,
|
|
1147
|
+
origItem,
|
|
1148
|
+
user,
|
|
1149
|
+
db
|
|
1150
|
+
)
|
|
921
1151
|
);
|
|
922
1152
|
}
|
|
923
1153
|
result[field.name] = arrayResult;
|
|
@@ -1058,7 +1288,15 @@ function generateOpenApi(config) {
|
|
|
1058
1288
|
},
|
|
1059
1289
|
WorkflowHistoryEntry: {
|
|
1060
1290
|
type: "object",
|
|
1061
|
-
required: [
|
|
1291
|
+
required: [
|
|
1292
|
+
"collection",
|
|
1293
|
+
"documentId",
|
|
1294
|
+
"transition",
|
|
1295
|
+
"from",
|
|
1296
|
+
"to",
|
|
1297
|
+
"revision",
|
|
1298
|
+
"createdAt"
|
|
1299
|
+
],
|
|
1062
1300
|
properties: {
|
|
1063
1301
|
id: { type: "string" },
|
|
1064
1302
|
collection: { type: "string" },
|
|
@@ -1083,7 +1321,11 @@ function generateOpenApi(config) {
|
|
|
1083
1321
|
user: { type: "string", nullable: true },
|
|
1084
1322
|
timestamp: { type: "string", format: "date-time" },
|
|
1085
1323
|
changes: {
|
|
1086
|
-
oneOf: [
|
|
1324
|
+
oneOf: [
|
|
1325
|
+
{ type: "string" },
|
|
1326
|
+
{ type: "object", additionalProperties: true },
|
|
1327
|
+
{ type: "null" }
|
|
1328
|
+
]
|
|
1087
1329
|
}
|
|
1088
1330
|
}
|
|
1089
1331
|
},
|
|
@@ -1175,13 +1417,17 @@ function generateOpenApi(config) {
|
|
|
1175
1417
|
get: {
|
|
1176
1418
|
tags: ["Preferences"],
|
|
1177
1419
|
summary: "Get an authenticated user preference",
|
|
1178
|
-
parameters: [
|
|
1420
|
+
parameters: [
|
|
1421
|
+
{ name: "key", in: "path", required: true, schema: { type: "string" } }
|
|
1422
|
+
],
|
|
1179
1423
|
responses: { 200: { description: "Preference value" } }
|
|
1180
1424
|
},
|
|
1181
1425
|
put: {
|
|
1182
1426
|
tags: ["Preferences"],
|
|
1183
1427
|
summary: "Set an authenticated user preference",
|
|
1184
|
-
parameters: [
|
|
1428
|
+
parameters: [
|
|
1429
|
+
{ name: "key", in: "path", required: true, schema: { type: "string" } }
|
|
1430
|
+
],
|
|
1185
1431
|
requestBody: {
|
|
1186
1432
|
required: true,
|
|
1187
1433
|
content: { "application/json": { schema: { type: "object" } } }
|
|
@@ -1217,10 +1463,23 @@ function generateOpenApi(config) {
|
|
|
1217
1463
|
tags: ["Audit"],
|
|
1218
1464
|
summary: "Get audit entries across all readable audited collections",
|
|
1219
1465
|
parameters: [
|
|
1220
|
-
{
|
|
1466
|
+
{
|
|
1467
|
+
name: "limit",
|
|
1468
|
+
in: "query",
|
|
1469
|
+
schema: { type: "integer", default: 50, maximum: 100 }
|
|
1470
|
+
},
|
|
1221
1471
|
{ name: "page", in: "query", schema: { type: "integer", default: 1 } },
|
|
1222
|
-
{
|
|
1223
|
-
|
|
1472
|
+
{
|
|
1473
|
+
name: "where",
|
|
1474
|
+
in: "query",
|
|
1475
|
+
schema: { type: "string" },
|
|
1476
|
+
description: "JSON filter"
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
name: "sort",
|
|
1480
|
+
in: "query",
|
|
1481
|
+
schema: { type: "string", default: "-timestamp" }
|
|
1482
|
+
}
|
|
1224
1483
|
],
|
|
1225
1484
|
responses: {
|
|
1226
1485
|
200: {
|
|
@@ -1425,10 +1684,27 @@ function generateOpenApi(config) {
|
|
|
1425
1684
|
tags: [collectionTag],
|
|
1426
1685
|
summary: `Get ${labels.singular} audit entries`,
|
|
1427
1686
|
parameters: [
|
|
1428
|
-
{
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1687
|
+
{
|
|
1688
|
+
name: "limit",
|
|
1689
|
+
in: "query",
|
|
1690
|
+
schema: { type: "integer", default: 50, maximum: 100 }
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
name: "page",
|
|
1694
|
+
in: "query",
|
|
1695
|
+
schema: { type: "integer", default: 1 }
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
name: "where",
|
|
1699
|
+
in: "query",
|
|
1700
|
+
schema: { type: "string" },
|
|
1701
|
+
description: "JSON filter"
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
name: "sort",
|
|
1705
|
+
in: "query",
|
|
1706
|
+
schema: { type: "string", default: "-timestamp" }
|
|
1707
|
+
}
|
|
1432
1708
|
],
|
|
1433
1709
|
responses: {
|
|
1434
1710
|
200: {
|
|
@@ -1554,6 +1830,15 @@ function generateOpenApi(config) {
|
|
|
1554
1830
|
post: {
|
|
1555
1831
|
tags: [collectionTag],
|
|
1556
1832
|
summary: `Log out of ${labels.plural}`,
|
|
1833
|
+
parameters: [
|
|
1834
|
+
{
|
|
1835
|
+
name: "allSessions",
|
|
1836
|
+
in: "query",
|
|
1837
|
+
required: false,
|
|
1838
|
+
schema: { type: "boolean" },
|
|
1839
|
+
description: "Revoke every active session for this account instead of only the current one."
|
|
1840
|
+
}
|
|
1841
|
+
],
|
|
1557
1842
|
responses: { 200: { description: "Logged out" } }
|
|
1558
1843
|
}
|
|
1559
1844
|
};
|
|
@@ -1579,7 +1864,11 @@ function generateOpenApi(config) {
|
|
|
1579
1864
|
post: {
|
|
1580
1865
|
tags: [collectionTag],
|
|
1581
1866
|
summary: "Refresh an authentication token",
|
|
1582
|
-
responses: {
|
|
1867
|
+
responses: {
|
|
1868
|
+
200: {
|
|
1869
|
+
description: "Refreshed token for the current active session"
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1583
1872
|
}
|
|
1584
1873
|
};
|
|
1585
1874
|
spec.paths[`${path}/forgot-password`] = {
|
|
@@ -1610,7 +1899,11 @@ function generateOpenApi(config) {
|
|
|
1610
1899
|
schema: { type: "string" }
|
|
1611
1900
|
}
|
|
1612
1901
|
],
|
|
1613
|
-
responses: {
|
|
1902
|
+
responses: {
|
|
1903
|
+
200: {
|
|
1904
|
+
description: "Password changed and active sessions revoked"
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1614
1907
|
}
|
|
1615
1908
|
};
|
|
1616
1909
|
}
|
|
@@ -1819,7 +2112,7 @@ function fieldsToProperties(fields) {
|
|
|
1819
2112
|
return { properties: props, required };
|
|
1820
2113
|
}
|
|
1821
2114
|
function fieldToSchema(field) {
|
|
1822
|
-
let schema
|
|
2115
|
+
let schema;
|
|
1823
2116
|
switch (field.type) {
|
|
1824
2117
|
case "text":
|
|
1825
2118
|
case "textarea":
|
|
@@ -1828,7 +2121,10 @@ function fieldToSchema(field) {
|
|
|
1828
2121
|
break;
|
|
1829
2122
|
case "url":
|
|
1830
2123
|
schema = {
|
|
1831
|
-
oneOf: [
|
|
2124
|
+
oneOf: [
|
|
2125
|
+
{ type: "string" },
|
|
2126
|
+
{ type: "object", additionalProperties: true }
|
|
2127
|
+
]
|
|
1832
2128
|
};
|
|
1833
2129
|
break;
|
|
1834
2130
|
case "icon":
|
|
@@ -1998,6 +2294,7 @@ function defineTab(args) {
|
|
|
1998
2294
|
defineMultiSelectField,
|
|
1999
2295
|
defineNumberField,
|
|
2000
2296
|
defineObjectField,
|
|
2297
|
+
definePublishingWorkflow,
|
|
2001
2298
|
defineRadioField,
|
|
2002
2299
|
defineRelationshipField,
|
|
2003
2300
|
defineRichTextField,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, e as ArrayField, f as BlocksField, g as BooleanField, h as
|
|
2
|
-
export {
|
|
1
|
+
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, e as ArrayField, f as BlocksField, g as BooleanField, h as AuthConfig, i as DateField, j as DateTimeField, E as EmailField, G as GlobalConfig, I as IconField, k as ImageField, J as JoinField, l as JsonField, M as MultiSelectField, N as NumberField, O as ObjectField, R as RadioField, m as RelationshipField, n as RichTextField, o as RowField, S as SelectField, T as TextField, p as TextareaField, q as TimeField, U as UrlField } from './app-config-Dv5XACR4.cjs';
|
|
2
|
+
export { r as AccessFunction, s as AccessFunctionArgs, t as AccessPolicyResolver, u as AccessResult, v as AccessRule, w as AdminAuthAccessResolution, x as AdminAuthClaimMapping, y as AdminAuthMember, z as AdminAuthProvider, K as AdminAuthProviderMembersConfig, Q as AdminAuthProvisioningMode, V as AdminAuthResolveAccessArgs, X as AdminAuthResolvedIdentity, Y as AdminConfig, Z as AdminDashboardComponentSlots, _ as AdminIconName, $ as BaseAdminAuthProvider, a0 as BaseFieldAdmin, a1 as BlockVariant, a2 as BooleanFieldAdmin, a3 as BooleanFormat, a4 as CharacterLimitFieldAdmin, a5 as CharacterLimitFieldConfig, a6 as CollectionAfterChangeHook, a7 as CollectionAfterDeleteHook, a8 as CollectionAfterReadHook, a9 as CollectionAfterTransitionHook, aa as CollectionBeforeChangeHook, ab as CollectionBeforeDeleteHook, ac as CollectionBeforeReadHook, ad as CollectionBeforeTransitionHook, ae as CollectionListComponentSlots, af as CustomAdminAuthProvider, ag as DatabaseAdapter, ah as DateFieldAdmin, ai as DateFormat, aj as DisplayTone, ak as DynamicOptionItem, al as DynamicOptionsConfig, am as DynamicOptionsResolver, an as DynamicOptionsResolverArgs, ao as DyrectedLoggerConfig, ap as DyrectedObservabilityConfig, aq as EmailFieldAdmin, ar as FieldAdminHooks, as as FieldAdminOnChangeHook, at as FieldAdminOnChangeHookArgs, au as FieldAdminOptionsHook, av as FieldAdminOptionsHookArgs, aw as FieldAdminOptionsHookResult, ax as FieldAfterReadHook, ay as FieldAfterReadHookArgs, az as FieldBase, aA as FieldBeforeChangeHook, aB as FieldBeforeChangeHookArgs, aC as FieldHook, aD as FieldHooks, aE as FieldType, aF as FileData, aG as GlobalAfterChangeHook, aH as GlobalAfterReadHook, aI as GlobalBeforeChangeHook, aJ as GlobalBeforeReadHook, aK as HeadingLevel, aL as HookFunction, aM as IconFieldAdmin, aN as ImageService, aO as JsonFieldAdmin, aP as JsonFormat, aQ as LIFECYCLE_EVENT_NAMES, aR as LifecycleEventHandler, aS as LinkFormat, aT as MultiSelectFieldAdmin, aU as NamedAccessPolicy, aV as NumberFieldAdmin, aW as NumberFormat, aX as NumberLimitFieldAdmin, aY as NumberLimitFieldConfig, aZ as OIDCAdminAuthProvider, a_ as OptionFormat, a$ as PaginatedResult, b0 as PublicAdminAuthProvider, b1 as RadioFieldAdmin, b2 as RateLimitConfig, b3 as ReadonlyDatabaseAdapter, b4 as RichTextFeature, b5 as RichTextFieldConfig, b6 as SelectFieldAdmin, b7 as StorageAdapter, b8 as TextFieldAdmin, b9 as TextFormat, ba as TextareaFieldAdmin, bb as TrustProxyConfig, bc as TypedField, bd as UploadConfig, be as UrlFieldAdmin, bf as UrlLinkValue, bg as WordLimitFieldAdmin, bh as WordLimitFieldConfig, bi as WorkflowMetadata, bj as WorkflowRole, bk as WorkflowState, bl as WorkflowTransitionContext } from './app-config-Dv5XACR4.cjs';
|
|
3
3
|
import 'lucide-react';
|
|
4
|
+
import 'pino';
|
|
4
5
|
|
|
5
6
|
type Prettify<T> = {
|
|
6
7
|
[K in keyof T]: T[K];
|
|
@@ -241,6 +242,35 @@ declare function generateOpenApi(config: DyrectedConfig): any;
|
|
|
241
242
|
|
|
242
243
|
declare const WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
|
|
243
244
|
declare const LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
|
|
245
|
+
/**
|
|
246
|
+
* Role mapping for {@link definePublishingWorkflow}. Map your app's own role
|
|
247
|
+
* values onto the publishing workflow's two capability tiers.
|
|
248
|
+
*/
|
|
249
|
+
interface PublishingWorkflowOptions {
|
|
250
|
+
/** Role values allowed to edit and submit for review. Defaults to `["editor"]`. */
|
|
251
|
+
editors?: string[];
|
|
252
|
+
/** Role values allowed to also publish and unpublish. Defaults to `["publisher", "admin"]`. */
|
|
253
|
+
publishers?: string[];
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Build a `draft → in review → published` editorial workflow, mapping your own
|
|
257
|
+
* role values onto its capability tiers. Reach for this instead of
|
|
258
|
+
* {@link publishingWorkflow} when your roles aren't named
|
|
259
|
+
* `editor`/`publisher`/`admin`.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* workflow: definePublishingWorkflow({
|
|
263
|
+
* editors: ["writer"],
|
|
264
|
+
* publishers: ["managing-editor", "admin"],
|
|
265
|
+
* })
|
|
266
|
+
*/
|
|
267
|
+
declare function definePublishingWorkflow(options?: PublishingWorkflowOptions): WorkflowConfig;
|
|
268
|
+
/**
|
|
269
|
+
* The default `draft → in review → published` editorial workflow, using the
|
|
270
|
+
* conventional role names `editor`, `publisher`, and `admin`. Shorthand for
|
|
271
|
+
* `definePublishingWorkflow()` — use {@link definePublishingWorkflow} to map
|
|
272
|
+
* your own role names onto its capability tiers.
|
|
273
|
+
*/
|
|
244
274
|
declare function publishingWorkflow(): WorkflowConfig;
|
|
245
275
|
declare function simplePublishingWorkflow(): WorkflowConfig;
|
|
246
276
|
declare function workflowCapabilities(workflow: WorkflowConfig, user?: AuthenticatedUser): Set<string>;
|
|
@@ -326,7 +356,7 @@ declare function defineCollection<const TFields extends Field[]>(config: Omit<Co
|
|
|
326
356
|
id: string;
|
|
327
357
|
} & InferDocShape<TFields> & SystemDocFields & AuthDocFields>>, "fields" | "auth"> & {
|
|
328
358
|
fields: TFields;
|
|
329
|
-
auth: true;
|
|
359
|
+
auth: true | AuthConfig;
|
|
330
360
|
}): CollectionConfig<Prettify<{
|
|
331
361
|
id: string;
|
|
332
362
|
} & InferDocShape<TFields> & SystemDocFields & AuthDocFields>>;
|
|
@@ -539,4 +569,4 @@ declare function defineTab<const T extends readonly Field[]>(args: {
|
|
|
539
569
|
fields: T;
|
|
540
570
|
}): T;
|
|
541
571
|
|
|
542
|
-
export { AdminAuthConfig, ArrayField, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, BlocksField, BooleanField, CollectionConfig, DateField, DateTimeField, DyrectedConfig, EmailField, Field, GlobalConfig, HookRequestContext, IconField, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, MultiSelectField, NumberField, ObjectField, type Prettify, PublicAdminAuthConfig, RadioField, RelationshipField, RichTextField, RowField, SelectField, type SortClause, type SortDirection, type SqlSortDialect, type SqlWhereResult, type SystemDocFields, TextField, TextareaField, TimeField, type UploadDocFields, UrlField, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMultiSelectField, defineNumberField, defineObjectField, defineRadioField, defineRelationshipField, defineRichTextField, defineRowField, defineSelectField, defineTab, defineTextField, defineTextareaField, defineTimeField, defineUrlField, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, numericFieldNames, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, resolveAdminAuthCollection, runCollectionHooks, saveWorkflowDraft, simplePublishingWorkflow, transitionWorkflow, workflowCapabilities };
|
|
572
|
+
export { AdminAuthConfig, ArrayField, AuthConfig, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, BlocksField, BooleanField, CollectionConfig, DateField, DateTimeField, DyrectedConfig, EmailField, Field, GlobalConfig, HookRequestContext, IconField, ImageField, type InferDocShape, JoinField, JsonField, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, MultiSelectField, NumberField, ObjectField, type Prettify, PublicAdminAuthConfig, type PublishingWorkflowOptions, RadioField, RelationshipField, RichTextField, RowField, SelectField, type SortClause, type SortDirection, type SqlSortDialect, type SqlWhereResult, type SystemDocFields, TextField, TextareaField, TimeField, type UploadDocFields, UrlField, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, buildSqlOrderBy, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineArrayField, defineBlock, defineBlocksField, defineBooleanField, defineCollection, defineConfig, defineDateField, defineDateTimeField, defineEmailField, defineField, defineGlobal, defineIconField, defineImageField, defineJoinField, defineJsonField, defineMultiSelectField, defineNumberField, defineObjectField, definePublishingWorkflow, defineRadioField, defineRelationshipField, defineRichTextField, defineRowField, defineSelectField, defineTab, defineTextField, defineTextareaField, defineTimeField, defineUrlField, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, numericFieldNames, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, resolveAdminAuthCollection, runCollectionHooks, saveWorkflowDraft, simplePublishingWorkflow, transitionWorkflow, workflowCapabilities };
|