@agntcms/next 0.3.1 → 0.3.4
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/{assets-Cyt9upqW.d.cts → assets-B3oNeLdj.d.cts} +1 -1
- package/dist/{assets-P8OCigDG.d.ts → assets-DHumg-X7.d.ts} +1 -1
- package/dist/client.cjs +2831 -4747
- package/dist/client.d.cts +11 -153
- package/dist/client.d.ts +11 -153
- package/dist/client.mjs +4750 -6675
- package/dist/config.cjs +25 -121
- package/dist/config.d.cts +6 -59
- package/dist/config.d.ts +6 -59
- package/dist/config.mjs +25 -114
- package/dist/{defineSection-Kr0pWqMY.d.ts → defineSection-ByG5uwiR.d.cts} +5 -24
- package/dist/{defineSection-9qQ5ulAH.d.cts → defineSection-ChkZCQyQ.d.ts} +5 -24
- package/dist/{rateLimit-CXptRM_K.d.ts → getContent-DAgAn095.d.ts} +3 -132
- package/dist/{rateLimit-CiROGTLE.d.cts → getContent-yK-sARoc.d.cts} +3 -132
- package/dist/handlers.cjs +19 -382
- package/dist/handlers.d.cts +4 -73
- package/dist/handlers.d.ts +4 -73
- package/dist/handlers.mjs +19 -377
- package/dist/index.cjs +1 -109
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.mjs +1 -103
- package/dist/{form-BqY0H1V5.d.cts → page-DXF0_SrY.d.cts} +3 -293
- package/dist/{form-BqY0H1V5.d.ts → page-DXF0_SrY.d.ts} +3 -293
- package/dist/server.cjs +15 -635
- package/dist/server.d.cts +8 -75
- package/dist/server.d.ts +8 -75
- package/dist/server.mjs +11 -618
- package/package.json +1 -1
- package/dist/defineForm-Bp9vzW56.d.ts +0 -71
- package/dist/defineForm-CJ8KZC93.d.cts +0 -71
- package/dist/registry-CraTTwT7.d.cts +0 -29
- package/dist/registry-DMujGqt0.d.ts +0 -29
package/dist/handlers.cjs
CHANGED
|
@@ -35,17 +35,12 @@ __export(handlers_exports, {
|
|
|
35
35
|
createAssetsHandler: () => createAssetsHandler,
|
|
36
36
|
createDraftHandler: () => createDraftHandler,
|
|
37
37
|
createEventsHandler: () => createEventsHandler,
|
|
38
|
-
createFormsDeleteHandler: () => createFormsDeleteHandler,
|
|
39
|
-
createFormsListHandler: () => createFormsListHandler,
|
|
40
|
-
createFormsReadHandler: () => createFormsReadHandler,
|
|
41
38
|
createGlobalHandler: () => createGlobalHandler,
|
|
42
39
|
createMcpHandler: () => createMcpHandler,
|
|
43
40
|
createPageHandler: () => createPageHandler,
|
|
44
41
|
createPreviewHandler: () => createPreviewHandler,
|
|
45
42
|
createPreviewTokenStore: () => createPreviewTokenStore,
|
|
46
|
-
createSubmitFormHandler: () => createSubmitFormHandler,
|
|
47
43
|
createTaskStore: () => createTaskStore,
|
|
48
|
-
createTemplateHandler: () => createTemplateHandler,
|
|
49
44
|
createagntcmsRouteHandler: () => createagntcmsRouteHandler
|
|
50
45
|
});
|
|
51
46
|
module.exports = __toCommonJS(handlers_exports);
|
|
@@ -234,14 +229,6 @@ function assertValidPage(page) {
|
|
|
234
229
|
assertValidPageMeta(obj);
|
|
235
230
|
}
|
|
236
231
|
|
|
237
|
-
// src/domain/form.ts
|
|
238
|
-
var SubmissionsNotReadableError = class extends Error {
|
|
239
|
-
constructor(message = "submission adapter does not support reading") {
|
|
240
|
-
super(message);
|
|
241
|
-
this.name = "SubmissionsNotReadableError";
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
232
|
// src/storage/fs/content.ts
|
|
246
233
|
var SLUG_PATTERN = /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/;
|
|
247
234
|
var assertValidSlug = (slug) => {
|
|
@@ -302,7 +289,7 @@ var createFsContentAdapter = (options) => {
|
|
|
302
289
|
throw err;
|
|
303
290
|
}
|
|
304
291
|
};
|
|
305
|
-
const
|
|
292
|
+
const listJsonFiles = async (dir) => {
|
|
306
293
|
let entries;
|
|
307
294
|
try {
|
|
308
295
|
entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
@@ -316,7 +303,7 @@ var createFsContentAdapter = (options) => {
|
|
|
316
303
|
results.push(entry.name);
|
|
317
304
|
} else if (entry.isDirectory()) {
|
|
318
305
|
const subDir = path3.join(dir, entry.name);
|
|
319
|
-
const subFiles = await
|
|
306
|
+
const subFiles = await listJsonFiles(subDir);
|
|
320
307
|
for (const sub of subFiles) {
|
|
321
308
|
results.push(`${entry.name}/${sub}`);
|
|
322
309
|
}
|
|
@@ -355,7 +342,7 @@ var createFsContentAdapter = (options) => {
|
|
|
355
342
|
await writeAtomic(filePath, JSON.stringify(page, null, 2));
|
|
356
343
|
};
|
|
357
344
|
const listDrafts = async () => {
|
|
358
|
-
const files = await
|
|
345
|
+
const files = await listJsonFiles(draftsDir);
|
|
359
346
|
const results = [];
|
|
360
347
|
for (const relPath of files) {
|
|
361
348
|
const slug = relPath.slice(0, -".json".length);
|
|
@@ -365,7 +352,7 @@ var createFsContentAdapter = (options) => {
|
|
|
365
352
|
return results;
|
|
366
353
|
};
|
|
367
354
|
const listPages = async () => {
|
|
368
|
-
const files = await
|
|
355
|
+
const files = await listJsonFiles(pagesDir);
|
|
369
356
|
const results = [];
|
|
370
357
|
for (const relPath of files) {
|
|
371
358
|
const slug = relPath.slice(0, -".json".length);
|
|
@@ -375,7 +362,7 @@ var createFsContentAdapter = (options) => {
|
|
|
375
362
|
return results;
|
|
376
363
|
};
|
|
377
364
|
const listPageSummaries = async () => {
|
|
378
|
-
const files = await
|
|
365
|
+
const files = await listJsonFiles(pagesDir);
|
|
379
366
|
const results = [];
|
|
380
367
|
for (const relPath of files) {
|
|
381
368
|
const slug = relPath.slice(0, -".json".length);
|
|
@@ -673,151 +660,6 @@ var createFsContentAdapter = (options) => {
|
|
|
673
660
|
};
|
|
674
661
|
};
|
|
675
662
|
|
|
676
|
-
// src/storage/fs/submissions.ts
|
|
677
|
-
var import_node_crypto2 = require("crypto");
|
|
678
|
-
var fs4 = __toESM(require("fs/promises"), 1);
|
|
679
|
-
var path4 = __toESM(require("path"), 1);
|
|
680
|
-
var DEFAULT_MAX_LIST = 500;
|
|
681
|
-
var FORM_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
682
|
-
var parseSubmission = (raw) => {
|
|
683
|
-
let parsed;
|
|
684
|
-
try {
|
|
685
|
-
parsed = JSON.parse(raw);
|
|
686
|
-
} catch {
|
|
687
|
-
return null;
|
|
688
|
-
}
|
|
689
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
690
|
-
return null;
|
|
691
|
-
}
|
|
692
|
-
const obj = parsed;
|
|
693
|
-
if (typeof obj["formName"] !== "string") return null;
|
|
694
|
-
if (typeof obj["id"] !== "string") return null;
|
|
695
|
-
if (typeof obj["submittedAt"] !== "string") return null;
|
|
696
|
-
if (obj["payload"] === null || typeof obj["payload"] !== "object" || Array.isArray(obj["payload"])) {
|
|
697
|
-
return null;
|
|
698
|
-
}
|
|
699
|
-
return {
|
|
700
|
-
formName: obj["formName"],
|
|
701
|
-
id: obj["id"],
|
|
702
|
-
submittedAt: obj["submittedAt"],
|
|
703
|
-
payload: obj["payload"]
|
|
704
|
-
};
|
|
705
|
-
};
|
|
706
|
-
var assertValidFormName = (name) => {
|
|
707
|
-
if (typeof name !== "string" || !FORM_NAME_PATTERN.test(name)) {
|
|
708
|
-
throw new Error(`invalid form name: ${JSON.stringify(name)}`);
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
var submissionFilename = (submittedAt, id) => {
|
|
712
|
-
const ts = submittedAt.replace(/:/g, "-");
|
|
713
|
-
return `${ts}-${id}.json`;
|
|
714
|
-
};
|
|
715
|
-
var listJsonFiles = async (dir) => {
|
|
716
|
-
let entries;
|
|
717
|
-
try {
|
|
718
|
-
entries = await fs4.readdir(dir, { withFileTypes: true });
|
|
719
|
-
} catch (err) {
|
|
720
|
-
if (isEnoent(err)) return [];
|
|
721
|
-
throw err;
|
|
722
|
-
}
|
|
723
|
-
const results = [];
|
|
724
|
-
for (const entry of entries) {
|
|
725
|
-
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
726
|
-
results.push(entry.name);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
return results;
|
|
730
|
-
};
|
|
731
|
-
var createFsSubmissionAdapter = (options) => {
|
|
732
|
-
const { submissionsRoot } = options;
|
|
733
|
-
if (!path4.isAbsolute(submissionsRoot)) {
|
|
734
|
-
throw new Error(
|
|
735
|
-
`submissionsRoot must be an absolute path, got: ${JSON.stringify(submissionsRoot)}`
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
const maxList = options.maxList ?? DEFAULT_MAX_LIST;
|
|
739
|
-
if (!Number.isFinite(maxList) || maxList <= 0 || !Number.isInteger(maxList)) {
|
|
740
|
-
throw new Error(
|
|
741
|
-
`maxList must be a positive integer, got: ${maxList}`
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
const rootResolved = path4.resolve(submissionsRoot);
|
|
745
|
-
const rootWithSep = rootResolved.endsWith(path4.sep) ? rootResolved : rootResolved + path4.sep;
|
|
746
|
-
const formDir = (formName) => {
|
|
747
|
-
assertValidFormName(formName);
|
|
748
|
-
const dir = path4.resolve(rootResolved, formName);
|
|
749
|
-
if (!dir.startsWith(rootWithSep)) {
|
|
750
|
-
throw new Error(`form name escapes submissions root: ${JSON.stringify(formName)}`);
|
|
751
|
-
}
|
|
752
|
-
return dir;
|
|
753
|
-
};
|
|
754
|
-
const cryptoSuffix = () => (0, import_node_crypto2.randomUUID)();
|
|
755
|
-
const store = async (submission) => {
|
|
756
|
-
const dir = formDir(submission.formName);
|
|
757
|
-
const filename = submissionFilename(submission.submittedAt, submission.id);
|
|
758
|
-
if (filename.includes("/") || filename.includes("\\")) {
|
|
759
|
-
throw new Error(`submission id contains path separator: ${JSON.stringify(submission.id)}`);
|
|
760
|
-
}
|
|
761
|
-
const target = path4.join(dir, filename);
|
|
762
|
-
await writeAtomic(target, JSON.stringify(submission, null, 2), cryptoSuffix);
|
|
763
|
-
};
|
|
764
|
-
const list = async (formName) => {
|
|
765
|
-
const dir = formDir(formName);
|
|
766
|
-
const files = await listJsonFiles(dir);
|
|
767
|
-
const summaries = [];
|
|
768
|
-
for (const filename of files) {
|
|
769
|
-
const stem = filename.slice(0, -".json".length);
|
|
770
|
-
const lastDash = stem.lastIndexOf("-");
|
|
771
|
-
if (lastDash < 0) continue;
|
|
772
|
-
const tsRaw = stem.slice(0, lastDash);
|
|
773
|
-
const id = stem.slice(lastDash + 1);
|
|
774
|
-
if (id === "") continue;
|
|
775
|
-
const tIndex = tsRaw.indexOf("T");
|
|
776
|
-
if (tIndex < 0) continue;
|
|
777
|
-
const datePart = tsRaw.slice(0, tIndex);
|
|
778
|
-
const timePart = tsRaw.slice(tIndex + 1).replace(/-/g, ":");
|
|
779
|
-
const submittedAt = `${datePart}T${timePart}`;
|
|
780
|
-
summaries.push({ id, submittedAt });
|
|
781
|
-
}
|
|
782
|
-
summaries.sort((a, b) => {
|
|
783
|
-
if (a.submittedAt !== b.submittedAt) {
|
|
784
|
-
return a.submittedAt < b.submittedAt ? 1 : -1;
|
|
785
|
-
}
|
|
786
|
-
if (a.id !== b.id) {
|
|
787
|
-
return a.id < b.id ? 1 : -1;
|
|
788
|
-
}
|
|
789
|
-
return 0;
|
|
790
|
-
});
|
|
791
|
-
return summaries.length > maxList ? summaries.slice(0, maxList) : summaries;
|
|
792
|
-
};
|
|
793
|
-
const read = async (formName, id) => {
|
|
794
|
-
if (id.includes("/") || id.includes("\\") || id.includes("..")) {
|
|
795
|
-
return null;
|
|
796
|
-
}
|
|
797
|
-
const dir = formDir(formName);
|
|
798
|
-
let entries;
|
|
799
|
-
try {
|
|
800
|
-
entries = (await fs4.readdir(dir)).filter((n) => n.endsWith(".json"));
|
|
801
|
-
} catch (err) {
|
|
802
|
-
if (isEnoent(err)) return null;
|
|
803
|
-
throw err;
|
|
804
|
-
}
|
|
805
|
-
const suffix = `-${id}.json`;
|
|
806
|
-
const found = entries.find((n) => n.endsWith(suffix));
|
|
807
|
-
if (!found) return null;
|
|
808
|
-
const target = path4.join(dir, found);
|
|
809
|
-
let raw;
|
|
810
|
-
try {
|
|
811
|
-
raw = await fs4.readFile(target, { encoding: "utf8" });
|
|
812
|
-
} catch (err) {
|
|
813
|
-
if (isEnoent(err)) return null;
|
|
814
|
-
throw err;
|
|
815
|
-
}
|
|
816
|
-
return parseSubmission(raw);
|
|
817
|
-
};
|
|
818
|
-
return { info: { kind: "fs" }, store, list, read };
|
|
819
|
-
};
|
|
820
|
-
|
|
821
663
|
// src/config/defaults-registry.ts
|
|
822
664
|
var SLOT = /* @__PURE__ */ Symbol.for("@agntcms/next/default-adapter-factories");
|
|
823
665
|
function holder() {
|
|
@@ -828,31 +670,24 @@ function registerDefaultAdapterFactories(factories) {
|
|
|
828
670
|
}
|
|
829
671
|
|
|
830
672
|
// src/config/defaults.ts
|
|
831
|
-
var
|
|
673
|
+
var path4 = __toESM(require("path"), 1);
|
|
832
674
|
function createDefaultContentAdapter(options) {
|
|
833
675
|
const root = options?.projectRoot ?? process.cwd();
|
|
834
676
|
return createFsContentAdapter({
|
|
835
|
-
contentRoot:
|
|
677
|
+
contentRoot: path4.resolve(root, "content")
|
|
836
678
|
});
|
|
837
679
|
}
|
|
838
680
|
function createDefaultAssetAdapter(options) {
|
|
839
681
|
const root = options?.projectRoot ?? process.cwd();
|
|
840
682
|
return createFsAssetAdapter({
|
|
841
|
-
assetsRoot:
|
|
683
|
+
assetsRoot: path4.resolve(root, "public/assets"),
|
|
842
684
|
publicUrlBase: "/assets"
|
|
843
685
|
});
|
|
844
686
|
}
|
|
845
|
-
function createDefaultSubmissionAdapter(options) {
|
|
846
|
-
const root = options?.projectRoot ?? process.cwd();
|
|
847
|
-
return createFsSubmissionAdapter({
|
|
848
|
-
submissionsRoot: path5.resolve(root, "content/submissions")
|
|
849
|
-
});
|
|
850
|
-
}
|
|
851
687
|
function installDefaultAdapterFactories() {
|
|
852
688
|
const factories = {
|
|
853
689
|
content: createDefaultContentAdapter,
|
|
854
|
-
asset: createDefaultAssetAdapter
|
|
855
|
-
submission: createDefaultSubmissionAdapter
|
|
690
|
+
asset: createDefaultAssetAdapter
|
|
856
691
|
};
|
|
857
692
|
registerDefaultAdapterFactories(factories);
|
|
858
693
|
}
|
|
@@ -1653,11 +1488,11 @@ var createTaskStore = () => {
|
|
|
1653
1488
|
if (entries.has(task.id)) {
|
|
1654
1489
|
throw new Error(`duplicate task id: ${task.id}`);
|
|
1655
1490
|
}
|
|
1656
|
-
return new Promise((
|
|
1491
|
+
return new Promise((resolve5, reject) => {
|
|
1657
1492
|
const entry = {
|
|
1658
1493
|
state: "pending",
|
|
1659
1494
|
task,
|
|
1660
|
-
resolve:
|
|
1495
|
+
resolve: resolve5,
|
|
1661
1496
|
reject,
|
|
1662
1497
|
listeners: /* @__PURE__ */ new Set()
|
|
1663
1498
|
};
|
|
@@ -1721,7 +1556,7 @@ var createTaskStore = () => {
|
|
|
1721
1556
|
};
|
|
1722
1557
|
|
|
1723
1558
|
// src/preview-tokens/store.ts
|
|
1724
|
-
var
|
|
1559
|
+
var import_node_crypto2 = require("crypto");
|
|
1725
1560
|
var DEFAULT_TTL_MS = 6e5;
|
|
1726
1561
|
var createPreviewTokenStore = (options) => {
|
|
1727
1562
|
const ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
|
|
@@ -1736,7 +1571,7 @@ var createPreviewTokenStore = (options) => {
|
|
|
1736
1571
|
const issue = (slug) => {
|
|
1737
1572
|
const now = Date.now();
|
|
1738
1573
|
sweep(now);
|
|
1739
|
-
const token = (0,
|
|
1574
|
+
const token = (0, import_node_crypto2.randomUUID)();
|
|
1740
1575
|
const entry = { slug, createdAt: now };
|
|
1741
1576
|
entries.set(token, entry);
|
|
1742
1577
|
return { token, slug, createdAt: now };
|
|
@@ -1757,7 +1592,7 @@ var createPreviewTokenStore = (options) => {
|
|
|
1757
1592
|
};
|
|
1758
1593
|
|
|
1759
1594
|
// src/handlers/page/page-handler.ts
|
|
1760
|
-
var
|
|
1595
|
+
var import_node_crypto3 = require("crypto");
|
|
1761
1596
|
var SLUG_PATTERN2 = /^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/;
|
|
1762
1597
|
var reservedSlugResponse = (slug, error) => {
|
|
1763
1598
|
const violation = getReservedPageSlugViolation(slug);
|
|
@@ -1766,7 +1601,7 @@ var reservedSlugResponse = (slug, error) => {
|
|
|
1766
1601
|
};
|
|
1767
1602
|
var cloneSection = (section) => {
|
|
1768
1603
|
const fresh = {
|
|
1769
|
-
id: `sec_${(0,
|
|
1604
|
+
id: `sec_${(0, import_node_crypto3.randomUUID)()}`,
|
|
1770
1605
|
type: section.type,
|
|
1771
1606
|
data: section.data,
|
|
1772
1607
|
...section.globalRef !== void 0 ? { globalRef: section.globalRef } : {}
|
|
@@ -2318,191 +2153,6 @@ function createGlobalHandler(deps) {
|
|
|
2318
2153
|
return { list, read, save, delete: deleteHandler, listHistory, rollback };
|
|
2319
2154
|
}
|
|
2320
2155
|
|
|
2321
|
-
// src/handlers/template/template-handler.ts
|
|
2322
|
-
function createTemplateHandler(deps) {
|
|
2323
|
-
const { sectionDefaults, templates } = deps;
|
|
2324
|
-
const list = async (_req) => {
|
|
2325
|
-
const resolved = [];
|
|
2326
|
-
for (const template of templates) {
|
|
2327
|
-
const sections = [];
|
|
2328
|
-
for (const typeName of template.sectionTypes) {
|
|
2329
|
-
const defaults = sectionDefaults.get(typeName);
|
|
2330
|
-
if (!defaults) {
|
|
2331
|
-
console.warn(
|
|
2332
|
-
`[agntcms] Template "${template.name}": section type "${typeName}" not found in registered sections, skipping.`
|
|
2333
|
-
);
|
|
2334
|
-
continue;
|
|
2335
|
-
}
|
|
2336
|
-
sections.push({ type: typeName, data: defaults });
|
|
2337
|
-
}
|
|
2338
|
-
resolved.push({
|
|
2339
|
-
name: template.name,
|
|
2340
|
-
...template.description !== void 0 ? { description: template.description } : {},
|
|
2341
|
-
sections
|
|
2342
|
-
});
|
|
2343
|
-
}
|
|
2344
|
-
return jsonResponse({ templates: resolved }, 200);
|
|
2345
|
-
};
|
|
2346
|
-
return { list };
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
// src/handlers/forms/submit-handler.ts
|
|
2350
|
-
var extractIp = (req) => {
|
|
2351
|
-
const xff = req.headers.get("x-forwarded-for");
|
|
2352
|
-
if (xff) {
|
|
2353
|
-
const first = xff.split(",")[0]?.trim();
|
|
2354
|
-
if (first && first.length > 0) return first;
|
|
2355
|
-
}
|
|
2356
|
-
const xri = req.headers.get("x-real-ip");
|
|
2357
|
-
if (xri && xri.trim().length > 0) return xri.trim();
|
|
2358
|
-
return "unknown";
|
|
2359
|
-
};
|
|
2360
|
-
function createSubmitFormHandler(deps) {
|
|
2361
|
-
const { runtime, rateLimit } = deps;
|
|
2362
|
-
return async function handle(req) {
|
|
2363
|
-
let body;
|
|
2364
|
-
try {
|
|
2365
|
-
body = await req.json();
|
|
2366
|
-
} catch {
|
|
2367
|
-
return jsonResponse({ ok: false, error: "invalid_json" }, 400);
|
|
2368
|
-
}
|
|
2369
|
-
if (body === null || typeof body !== "object") {
|
|
2370
|
-
return jsonResponse({ ok: false, error: "invalid_body" }, 400);
|
|
2371
|
-
}
|
|
2372
|
-
const obj = body;
|
|
2373
|
-
if (typeof obj["formName"] !== "string" || obj["formName"] === "") {
|
|
2374
|
-
return jsonResponse({ ok: false, error: "missing_form_name" }, 400);
|
|
2375
|
-
}
|
|
2376
|
-
const payload = obj["payload"];
|
|
2377
|
-
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
2378
|
-
return jsonResponse({ ok: false, error: "invalid_payload" }, 400);
|
|
2379
|
-
}
|
|
2380
|
-
const formName = obj["formName"];
|
|
2381
|
-
const ip = extractIp(req);
|
|
2382
|
-
const rl = rateLimit.check(ip, formName);
|
|
2383
|
-
if (!rl.allowed) {
|
|
2384
|
-
return jsonResponse({ ok: false, error: "rate_limit" }, 429, {
|
|
2385
|
-
// Inform polite clients when they may retry. Spec-compliant for 429.
|
|
2386
|
-
"Retry-After": Math.max(1, Math.ceil((rl.resetAt - Date.now()) / 1e3)).toString()
|
|
2387
|
-
});
|
|
2388
|
-
}
|
|
2389
|
-
let result;
|
|
2390
|
-
try {
|
|
2391
|
-
result = await runtime.submitForm({
|
|
2392
|
-
formName,
|
|
2393
|
-
payload
|
|
2394
|
-
});
|
|
2395
|
-
} catch (err) {
|
|
2396
|
-
void safeErrorMessage(err);
|
|
2397
|
-
return jsonResponse({ ok: false, error: "storage_unavailable" }, 502);
|
|
2398
|
-
}
|
|
2399
|
-
if (!result.ok) {
|
|
2400
|
-
switch (result.error) {
|
|
2401
|
-
case "unknown_form":
|
|
2402
|
-
return jsonResponse({ ok: false, error: "unknown_form" }, 404);
|
|
2403
|
-
case "validation_failed":
|
|
2404
|
-
return jsonResponse(
|
|
2405
|
-
{ ok: false, error: "validation_failed", errors: result.errors },
|
|
2406
|
-
400
|
|
2407
|
-
);
|
|
2408
|
-
default: {
|
|
2409
|
-
const _exhaustive = result;
|
|
2410
|
-
void _exhaustive;
|
|
2411
|
-
return jsonResponse({ ok: false, error: "internal_error" }, 500);
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
if (!result.stored) {
|
|
2416
|
-
return jsonResponse({ ok: true, stored: false }, 200);
|
|
2417
|
-
}
|
|
2418
|
-
return jsonResponse({ ok: true, stored: true, id: result.id }, 200);
|
|
2419
|
-
};
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
// src/handlers/forms/list-handler.ts
|
|
2423
|
-
function createFormsListHandler(deps) {
|
|
2424
|
-
const adapter = deps.adapter ?? { kind: "fs" };
|
|
2425
|
-
return async function handle(_req) {
|
|
2426
|
-
try {
|
|
2427
|
-
const forms = deps.forms.map((f) => {
|
|
2428
|
-
const schema = {};
|
|
2429
|
-
for (const [name, descriptor] of Object.entries(f.schema)) {
|
|
2430
|
-
schema[name] = descriptor;
|
|
2431
|
-
}
|
|
2432
|
-
return { name: f.name, schema };
|
|
2433
|
-
});
|
|
2434
|
-
return jsonResponse({ forms, adapter }, 200);
|
|
2435
|
-
} catch (err) {
|
|
2436
|
-
console.error("[agntcms] list_forms_failed:", err);
|
|
2437
|
-
return jsonResponse({ error: "list_forms_failed", message: "internal error" }, 500);
|
|
2438
|
-
}
|
|
2439
|
-
};
|
|
2440
|
-
}
|
|
2441
|
-
|
|
2442
|
-
// src/handlers/forms/read-handler.ts
|
|
2443
|
-
var FORM_NAME_PATTERN2 = /^[a-zA-Z0-9_-]+$/;
|
|
2444
|
-
var ID_PATTERN = /^[0-9A-HJKMNPQRSTVWXYZ]{16}$/;
|
|
2445
|
-
function createFormsReadHandler(deps) {
|
|
2446
|
-
return async function handle(req) {
|
|
2447
|
-
const url = new URL(req.url);
|
|
2448
|
-
const form = url.searchParams.get("form");
|
|
2449
|
-
const id = url.searchParams.get("id");
|
|
2450
|
-
if (!form) return jsonResponse({ error: "missing_form" }, 400);
|
|
2451
|
-
if (!FORM_NAME_PATTERN2.test(form)) {
|
|
2452
|
-
return jsonResponse({ error: "invalid_form" }, 400);
|
|
2453
|
-
}
|
|
2454
|
-
if (!deps.knownForms.has(form)) {
|
|
2455
|
-
return jsonResponse({ error: "unknown_form" }, 404);
|
|
2456
|
-
}
|
|
2457
|
-
if (id !== null) {
|
|
2458
|
-
if (!ID_PATTERN.test(id)) {
|
|
2459
|
-
return jsonResponse({ error: "invalid_id" }, 400);
|
|
2460
|
-
}
|
|
2461
|
-
try {
|
|
2462
|
-
const sub = await deps.submissionAdapter.read(form, id);
|
|
2463
|
-
if (!sub) return jsonResponse({ error: "not_found" }, 404);
|
|
2464
|
-
return jsonResponse({ submission: sub }, 200);
|
|
2465
|
-
} catch (err) {
|
|
2466
|
-
if (err instanceof SubmissionsNotReadableError) {
|
|
2467
|
-
return jsonResponse(
|
|
2468
|
-
{ error: "not_supported", message: err.message },
|
|
2469
|
-
501
|
|
2470
|
-
);
|
|
2471
|
-
}
|
|
2472
|
-
console.error("[agntcms] read_failed:", err);
|
|
2473
|
-
return jsonResponse({ error: "read_failed", message: "internal error" }, 500);
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
try {
|
|
2477
|
-
const summaries = await deps.submissionAdapter.list(form);
|
|
2478
|
-
return jsonResponse({ submissions: summaries }, 200);
|
|
2479
|
-
} catch (err) {
|
|
2480
|
-
if (err instanceof SubmissionsNotReadableError) {
|
|
2481
|
-
return jsonResponse(
|
|
2482
|
-
{ error: "not_supported", message: err.message },
|
|
2483
|
-
501
|
|
2484
|
-
);
|
|
2485
|
-
}
|
|
2486
|
-
console.error("[agntcms] list_failed:", err);
|
|
2487
|
-
return jsonResponse({ error: "list_failed", message: "internal error" }, 500);
|
|
2488
|
-
}
|
|
2489
|
-
};
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
// src/handlers/forms/delete-handler.ts
|
|
2493
|
-
function createFormsDeleteHandler() {
|
|
2494
|
-
return async function handle(_req) {
|
|
2495
|
-
return jsonResponse(
|
|
2496
|
-
{
|
|
2497
|
-
ok: false,
|
|
2498
|
-
error: "not_implemented",
|
|
2499
|
-
message: "Submission delete is reserved but not implemented in v1. See ARCHITECTURE.md \xA76.5 / \xA712."
|
|
2500
|
-
},
|
|
2501
|
-
501
|
|
2502
|
-
);
|
|
2503
|
-
};
|
|
2504
|
-
}
|
|
2505
|
-
|
|
2506
2156
|
// src/handlers/dispatcher.ts
|
|
2507
2157
|
function buildRouteTable(h) {
|
|
2508
2158
|
const table = /* @__PURE__ */ new Map();
|
|
@@ -2532,10 +2182,6 @@ function buildRouteTable(h) {
|
|
|
2532
2182
|
table.set("preview/enter", { POST: async (req) => h.preview.enter(req), GET: async (req) => h.preview.enterWithToken(req) });
|
|
2533
2183
|
table.set("preview/exit", { POST: async (req) => h.preview.exit(req) });
|
|
2534
2184
|
table.set("preview/issue", { POST: h.preview.issueToken });
|
|
2535
|
-
table.set("template/list", { GET: h.template.list });
|
|
2536
|
-
table.set("forms/list", { GET: h.formsList });
|
|
2537
|
-
table.set("forms/read", { GET: h.formsRead });
|
|
2538
|
-
table.set("forms/delete", { POST: h.formsDelete });
|
|
2539
2185
|
return table;
|
|
2540
2186
|
}
|
|
2541
2187
|
function createagntcmsRouteHandler(opts) {
|
|
@@ -2549,19 +2195,15 @@ function createagntcmsRouteHandler(opts) {
|
|
|
2549
2195
|
// factory branches on `deps?.tokenStore` and `deps?.cookieName`).
|
|
2550
2196
|
preview: createPreviewHandler(opts.preview),
|
|
2551
2197
|
events: createEventsHandler(opts.events),
|
|
2552
|
-
mcp: createMcpHandler(opts.mcp)
|
|
2553
|
-
template: createTemplateHandler(opts.template),
|
|
2554
|
-
formsList: createFormsListHandler(opts.formsList),
|
|
2555
|
-
formsRead: createFormsReadHandler(opts.formsRead),
|
|
2556
|
-
formsDelete: createFormsDeleteHandler()
|
|
2198
|
+
mcp: createMcpHandler(opts.mcp)
|
|
2557
2199
|
};
|
|
2558
2200
|
const table = buildRouteTable(handlers);
|
|
2559
2201
|
const dispatch = async (method, req, ctx) => {
|
|
2560
|
-
const { path:
|
|
2561
|
-
if (!
|
|
2202
|
+
const { path: path5 } = await ctx.params;
|
|
2203
|
+
if (!path5 || path5.length === 0) {
|
|
2562
2204
|
return new Response(null, { status: 404 });
|
|
2563
2205
|
}
|
|
2564
|
-
const key =
|
|
2206
|
+
const key = path5.join("/");
|
|
2565
2207
|
const entry = table.get(key);
|
|
2566
2208
|
if (!entry) {
|
|
2567
2209
|
return new Response(null, { status: 404 });
|
|
@@ -2590,16 +2232,11 @@ installDefaultAdapterFactories();
|
|
|
2590
2232
|
createAssetsHandler,
|
|
2591
2233
|
createDraftHandler,
|
|
2592
2234
|
createEventsHandler,
|
|
2593
|
-
createFormsDeleteHandler,
|
|
2594
|
-
createFormsListHandler,
|
|
2595
|
-
createFormsReadHandler,
|
|
2596
2235
|
createGlobalHandler,
|
|
2597
2236
|
createMcpHandler,
|
|
2598
2237
|
createPageHandler,
|
|
2599
2238
|
createPreviewHandler,
|
|
2600
2239
|
createPreviewTokenStore,
|
|
2601
|
-
createSubmitFormHandler,
|
|
2602
2240
|
createTaskStore,
|
|
2603
|
-
createTemplateHandler,
|
|
2604
2241
|
createagntcmsRouteHandler
|
|
2605
2242
|
});
|
package/dist/handlers.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-B3oNeLdj.cjs';
|
|
2
|
+
import { R as Runtime } from './getContent-yK-sARoc.cjs';
|
|
3
|
+
import './page-DXF0_SrY.cjs';
|
|
4
4
|
import './global-CV23g5Bn.cjs';
|
|
5
5
|
|
|
6
6
|
type TaskId = string;
|
|
@@ -261,72 +261,6 @@ interface GlobalHandler {
|
|
|
261
261
|
}
|
|
262
262
|
declare function createGlobalHandler(deps: GlobalHandlerDeps): GlobalHandler;
|
|
263
263
|
|
|
264
|
-
/**
|
|
265
|
-
* Template definition shape matching `PageTemplate` from config.
|
|
266
|
-
* Redeclared here as a structural type so the handler does not import
|
|
267
|
-
* from config/ (invariant 1).
|
|
268
|
-
*/
|
|
269
|
-
interface TemplateDef {
|
|
270
|
-
readonly name: string;
|
|
271
|
-
readonly description?: string;
|
|
272
|
-
readonly sectionTypes: readonly string[];
|
|
273
|
-
}
|
|
274
|
-
interface TemplateHandlerDeps {
|
|
275
|
-
/**
|
|
276
|
-
* Pre-resolved map: section type name -> default data for that section.
|
|
277
|
-
* Built by the wiring layer from the registered `AnySectionDefinition[]`.
|
|
278
|
-
*/
|
|
279
|
-
readonly sectionDefaults: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
|
|
280
|
-
/** The template definitions from config. */
|
|
281
|
-
readonly templates: readonly TemplateDef[];
|
|
282
|
-
}
|
|
283
|
-
interface TemplateHandler {
|
|
284
|
-
/** GET /api/agntcms/template/list */
|
|
285
|
-
readonly list: (req: Request) => Promise<Response>;
|
|
286
|
-
}
|
|
287
|
-
declare function createTemplateHandler(deps: TemplateHandlerDeps): TemplateHandler;
|
|
288
|
-
|
|
289
|
-
interface SubmitHandlerDeps {
|
|
290
|
-
readonly runtime: Runtime;
|
|
291
|
-
readonly rateLimit: RateLimit;
|
|
292
|
-
}
|
|
293
|
-
declare function createSubmitFormHandler(deps: SubmitHandlerDeps): (req: Request) => Promise<Response>;
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Adapter info surfaced to the AdminModal. Two shapes:
|
|
297
|
-
* - `{ kind: 'fs' }` — local FS submissions; readable.
|
|
298
|
-
* - `{ kind: 'webhook', host }` — webhook adapter; not locally readable.
|
|
299
|
-
*/
|
|
300
|
-
type FormsListAdapterInfo = {
|
|
301
|
-
readonly kind: 'fs';
|
|
302
|
-
} | {
|
|
303
|
-
readonly kind: 'webhook';
|
|
304
|
-
readonly host: string;
|
|
305
|
-
};
|
|
306
|
-
interface FormsListHandlerDeps {
|
|
307
|
-
/** Registered form definitions (from `defineConfig({ forms: [...] })`). */
|
|
308
|
-
readonly forms: ReadonlyArray<AnyFormDefinition>;
|
|
309
|
-
/**
|
|
310
|
-
* Optional adapter descriptor. When omitted, the handler reports
|
|
311
|
-
* `{ kind: 'fs' }` — the v1 default adapter (ARCHITECTURE.md §6.5).
|
|
312
|
-
* Frozen routes that wire a webhook adapter pass `{ kind: 'webhook',
|
|
313
|
-
* host: '<host>' }` here; the host is computed once at handler-construction
|
|
314
|
-
* time from the configured webhook URL.
|
|
315
|
-
*/
|
|
316
|
-
readonly adapter?: FormsListAdapterInfo;
|
|
317
|
-
}
|
|
318
|
-
/** Forms list handler. */
|
|
319
|
-
declare function createFormsListHandler(deps: FormsListHandlerDeps): (_req: Request) => Promise<Response>;
|
|
320
|
-
|
|
321
|
-
interface FormsReadHandlerDeps {
|
|
322
|
-
readonly submissionAdapter: SubmissionStorageAdapter;
|
|
323
|
-
/** Registered form names — used to 404 unknown forms before hitting the adapter. */
|
|
324
|
-
readonly knownForms: ReadonlySet<string>;
|
|
325
|
-
}
|
|
326
|
-
declare function createFormsReadHandler(deps: FormsReadHandlerDeps): (req: Request) => Promise<Response>;
|
|
327
|
-
|
|
328
|
-
declare function createFormsDeleteHandler(): (_req: Request) => Promise<Response>;
|
|
329
|
-
|
|
330
264
|
/**
|
|
331
265
|
* Dependencies for every endpoint the dispatcher serves. Grouped by
|
|
332
266
|
* underlying handler factory so the template wiring mirrors the v0.2
|
|
@@ -346,9 +280,6 @@ interface agntcmsRouteHandlerOptions {
|
|
|
346
280
|
readonly preview?: PreviewHandlerDeps;
|
|
347
281
|
readonly events: EventsHandlerDeps;
|
|
348
282
|
readonly mcp: McpHandlerDeps;
|
|
349
|
-
readonly template: TemplateHandlerDeps;
|
|
350
|
-
readonly formsList: FormsListHandlerDeps;
|
|
351
|
-
readonly formsRead: FormsReadHandlerDeps;
|
|
352
283
|
}
|
|
353
284
|
/** HTTP methods the dispatcher routes. */
|
|
354
285
|
type DispatcherMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
@@ -391,4 +322,4 @@ interface agntcmsRouteHandler {
|
|
|
391
322
|
*/
|
|
392
323
|
declare function createagntcmsRouteHandler(opts: agntcmsRouteHandlerOptions): agntcmsRouteHandler;
|
|
393
324
|
|
|
394
|
-
export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DispatcherMethod, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type
|
|
325
|
+
export { type AgentBridge, type AgentBridgeStatus, AgentUnreachableError, type AssetsHandler, type AssetsHandlerDeps, type CreateAgentBridgeOptions, type DispatcherMethod, type DraftHandler, type DraftHandlerDeps, type EventsHandler, type EventsHandlerDeps, type GlobalHandler, type GlobalHandlerDeps, type McpHandler, type McpHandlerDeps, type PageHandler, type PageHandlerDeps, type PreviewHandler, type PreviewHandlerDeps, type PreviewToken, type PreviewTokenStore, type PreviewTokenStoreOptions, type Task, type TaskEvent, type TaskId, type TaskSnapshot, type TaskState, type TaskStore, type agntcmsRouteContext, type agntcmsRouteHandler, type agntcmsRouteHandlerOptions, createAgentBridge, createAssetsHandler, createDraftHandler, createEventsHandler, createGlobalHandler, createMcpHandler, createPageHandler, createPreviewHandler, createPreviewTokenStore, createTaskStore, createagntcmsRouteHandler };
|