@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/config.cjs CHANGED
@@ -22,23 +22,16 @@ var config_exports = {};
22
22
  __export(config_exports, {
23
23
  BooleanField: () => BooleanField,
24
24
  ButtonField: () => ButtonField,
25
- DuplicateFormNameError: () => DuplicateFormNameError,
26
- FormOverridesField: () => FormOverridesField,
27
- HoneypotCollisionError: () => HoneypotCollisionError,
28
25
  ImageField: () => ImageField,
29
- InvalidFormFieldError: () => InvalidFormFieldError,
30
- InvalidFormNameError: () => InvalidFormNameError,
31
26
  LinkField: () => LinkField,
32
27
  ListField: () => ListField,
33
28
  NumberField: () => NumberField,
34
29
  ReferenceField: () => ReferenceField,
35
30
  RichTextField: () => RichTextField,
36
31
  SelectField: () => SelectField,
37
- SubmissionsNotReadableError: () => SubmissionsNotReadableError,
38
32
  TextField: () => TextField,
39
33
  VideoField: () => VideoField,
40
34
  defineConfig: () => defineConfig,
41
- defineForm: () => defineForm,
42
35
  withagntcms: () => withagntcms
43
36
  });
44
37
  module.exports = __toCommonJS(config_exports);
@@ -52,7 +45,7 @@ function getDefaultAdapterFactories(requested) {
52
45
  const f = holder()[SLOT];
53
46
  if (f === void 0) {
54
47
  throw new Error(
55
- `[agntcms] defineConfig: cannot fill the default ${requested} adapter because the server-only adapter factories were never registered. Import \`@agntcms/next/server\` (or \`@agntcms/next/handlers\`) before evaluating \`agntcms/config.ts\`, or pass an explicit adapter to \`defineConfig({ contentAdapter, assetAdapter, submissionAdapter })\`.`
48
+ `[agntcms] defineConfig: cannot fill the default ${requested} adapter because the server-only adapter factories were never registered. Import \`@agntcms/next/server\` (or \`@agntcms/next/handlers\`) before evaluating \`agntcms/config.ts\`, or pass an explicit adapter to \`defineConfig({ contentAdapter, assetAdapter })\`.`
56
49
  );
57
50
  }
58
51
  return f;
@@ -67,126 +60,51 @@ function defineConfig(config) {
67
60
  }
68
61
  const contentAdapter = config.contentAdapter ?? getDefaultAdapterFactories("content").content();
69
62
  const assetAdapter = config.assetAdapter ?? getDefaultAdapterFactories("asset").asset();
70
- const submissionAdapter = config.submissionAdapter ?? getDefaultAdapterFactories("submission").submission();
71
63
  return {
72
64
  sections: config.sections,
73
65
  contentAdapter,
74
- assetAdapter,
75
- templates: config.templates ?? [],
76
- forms: config.forms ?? [],
77
- submissionAdapter,
78
- submissionRateLimit: config.submissionRateLimit ?? { perMinute: 5 }
66
+ assetAdapter
79
67
  };
80
68
  }
81
69
 
82
70
  // src/config/withagntcms.ts
83
71
  var DEV_PAGE_EXTENSIONS = ["dev.ts", "dev.tsx", "ts", "tsx", "js", "jsx"];
84
72
  var PROD_PAGE_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
73
+ var CONTENT_TRACE_GLOB = "./content/**/*";
85
74
  function withagntcms(nextConfig) {
86
75
  const isProd = process.env.NODE_ENV === "production";
87
76
  const defaultPageExtensions = isProd ? PROD_PAGE_EXTENSIONS : DEV_PAGE_EXTENSIONS;
88
77
  const userPageExtensions = nextConfig.pageExtensions;
89
78
  const pageExtensions = Array.isArray(userPageExtensions) ? userPageExtensions : [...defaultPageExtensions];
79
+ const userTracingIncludes = isPlainRecordOfStringArrays(
80
+ nextConfig.outputFileTracingIncludes
81
+ ) ? nextConfig.outputFileTracingIncludes : {};
82
+ const outputFileTracingIncludes = mergeTracingIncludes(userTracingIncludes, {
83
+ "/**": [CONTENT_TRACE_GLOB]
84
+ });
90
85
  return {
91
86
  ...nextConfig,
92
- pageExtensions
87
+ pageExtensions,
88
+ outputFileTracingIncludes
93
89
  };
94
90
  }
95
-
96
- // src/domain/form.ts
97
- var FORM_FORBIDDEN_KINDS = /* @__PURE__ */ new Set([
98
- "image",
99
- "video",
100
- "reference",
101
- "list",
102
- // `formOverrides` is a section-only descriptor (it overrides another
103
- // form schema instance). Putting it inside a form would mean a form's
104
- // payload could carry overrides for itself or another form — a
105
- // recursive shape with no ergonomic editor UI. Section-only by design.
106
- "formOverrides",
107
- // `button` is a section-only descriptor: a styled CTA with an
108
- // optional link. Public-form payloads collect user input — a button
109
- // value is authored content, not a submitted answer. Section-only
110
- // by design (mirrors `formOverrides`).
111
- "button"
112
- ]);
113
- var SubmissionsNotReadableError = class extends Error {
114
- constructor(message = "submission adapter does not support reading") {
115
- super(message);
116
- this.name = "SubmissionsNotReadableError";
117
- }
118
- };
119
-
120
- // src/forms/defineForm.ts
121
- var InvalidFormFieldError = class extends Error {
122
- formName;
123
- fieldName;
124
- fieldKind;
125
- constructor(formName, fieldName, fieldKind) {
126
- super(
127
- `Form "${formName}": field "${fieldName}" uses kind "${fieldKind}", which is not allowed in a form schema in v1. Allowed kinds: text, richText, number, boolean, select, link. Forbidden kinds: image, reference, list, formOverrides. See ARCHITECTURE.md \xA76.5.`
128
- );
129
- this.name = "InvalidFormFieldError";
130
- this.formName = formName;
131
- this.fieldName = fieldName;
132
- this.fieldKind = fieldKind;
133
- }
134
- };
135
- var HoneypotCollisionError = class extends Error {
136
- formName;
137
- fieldName;
138
- reason;
139
- constructor(formName, fieldName, reason = "collision") {
140
- super(
141
- reason === "empty" ? `Form "${formName}": honeypot name must be a non-empty string.` : `Form "${formName}": honeypot name "${fieldName}" collides with a real field. Choose a honeypot name that does not appear in the schema.`
142
- );
143
- this.name = "HoneypotCollisionError";
144
- this.formName = formName;
145
- this.fieldName = fieldName;
146
- this.reason = reason;
147
- }
148
- };
149
- var InvalidFormNameError = class extends Error {
150
- constructor(name) {
151
- super(
152
- `Invalid form name ${JSON.stringify(name)}. Use letters, digits, hyphen, and underscore only (no path separators).`
153
- );
154
- this.name = "InvalidFormNameError";
91
+ function isPlainRecordOfStringArrays(value) {
92
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
93
+ for (const v of Object.values(value)) {
94
+ if (!Array.isArray(v)) return false;
95
+ if (!v.every((item) => typeof item === "string")) return false;
155
96
  }
156
- };
157
- var FORM_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
158
- function defineForm(input) {
159
- if (typeof input.name !== "string" || !FORM_NAME_PATTERN.test(input.name)) {
160
- throw new InvalidFormNameError(input.name);
161
- }
162
- for (const [fieldName, descriptor] of Object.entries(input.schema)) {
163
- const kind = descriptor.kind;
164
- if (FORM_FORBIDDEN_KINDS.has(kind)) {
165
- throw new InvalidFormFieldError(input.name, fieldName, kind);
166
- }
167
- }
168
- if (input.honeypot !== void 0) {
169
- if (typeof input.honeypot !== "string" || input.honeypot === "") {
170
- throw new HoneypotCollisionError(input.name, input.honeypot, "empty");
171
- }
172
- if (Object.prototype.hasOwnProperty.call(input.schema, input.honeypot)) {
173
- throw new HoneypotCollisionError(input.name, input.honeypot, "collision");
174
- }
175
- }
176
- return input.honeypot !== void 0 ? { name: input.name, schema: input.schema, honeypot: input.honeypot } : { name: input.name, schema: input.schema };
97
+ return true;
177
98
  }
178
-
179
- // src/forms/registry.ts
180
- var DuplicateFormNameError = class extends Error {
181
- formName;
182
- constructor(name) {
183
- super(
184
- `Form name "${name}" is registered more than once. Form names must be unique within a config.`
185
- );
186
- this.name = "DuplicateFormNameError";
187
- this.formName = name;
99
+ function mergeTracingIncludes(user, framework) {
100
+ const result = {};
101
+ const keys = /* @__PURE__ */ new Set([...Object.keys(user), ...Object.keys(framework)]);
102
+ for (const key of keys) {
103
+ const merged = [...user[key] ?? [], ...framework[key] ?? []];
104
+ result[key] = Array.from(new Set(merged));
188
105
  }
189
- };
106
+ return result;
107
+ }
190
108
 
191
109
  // src/domain/fields.ts
192
110
  var TextField = { kind: "text" };
@@ -214,33 +132,19 @@ var ListField = (itemSchema, opts) => ({
214
132
  ...opts?.max !== void 0 ? { max: opts.max } : {},
215
133
  ...opts?.default !== void 0 ? { default: opts.default } : {}
216
134
  });
217
-
218
- // src/domain/formOverrides.ts
219
- var FormOverridesField = (formName, opts) => ({
220
- kind: "formOverrides",
221
- formName,
222
- ...opts?.default !== void 0 ? { default: opts.default } : {}
223
- });
224
135
  // Annotate the CommonJS export names for ESM import in node:
225
136
  0 && (module.exports = {
226
137
  BooleanField,
227
138
  ButtonField,
228
- DuplicateFormNameError,
229
- FormOverridesField,
230
- HoneypotCollisionError,
231
139
  ImageField,
232
- InvalidFormFieldError,
233
- InvalidFormNameError,
234
140
  LinkField,
235
141
  ListField,
236
142
  NumberField,
237
143
  ReferenceField,
238
144
  RichTextField,
239
145
  SelectField,
240
- SubmissionsNotReadableError,
241
146
  TextField,
242
147
  VideoField,
243
148
  defineConfig,
244
- defineForm,
245
149
  withagntcms
246
150
  });
package/dist/config.d.cts CHANGED
@@ -1,36 +1,8 @@
1
- import { A as AnyFormDefinition, o as SubmissionStorageAdapter } from './form-BqY0H1V5.cjs';
2
- export { j as BooleanField, B as ButtonField, b as FormDefinition, p as FormFieldDescriptor, q as FormFieldOverride, n as FormFieldOverrides, r as FormOverridesField, m as FormOverridesFieldDescriptor, a as FormSchema, I as ImageField, L as LinkField, l as ListField, N as NumberField, f as ReferenceField, R as RichTextField, k as SelectField, s as Submission, t as SubmissionAdapterInfo, u as SubmissionSummary, v as SubmissionsNotReadableError, T as TextField, V as VideoField } from './form-BqY0H1V5.cjs';
3
- import { A as AnySectionDefinition } from './defineSection-9qQ5ulAH.cjs';
4
- import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-Cyt9upqW.cjs';
5
- export { D as DefineFormInput, H as HoneypotCollisionError, I as InvalidFormFieldError, a as InvalidFormNameError, d as defineForm } from './defineForm-CJ8KZC93.cjs';
6
- export { D as DuplicateFormNameError } from './registry-CraTTwT7.cjs';
1
+ import { A as AnySectionDefinition } from './defineSection-ByG5uwiR.cjs';
2
+ import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-B3oNeLdj.cjs';
3
+ export { g as BooleanField, B as ButtonField, I as ImageField, L as LinkField, i as ListField, N as NumberField, c as ReferenceField, R as RichTextField, h as SelectField, T as TextField, V as VideoField } from './page-DXF0_SrY.cjs';
7
4
  import './global-CV23g5Bn.cjs';
8
5
 
9
- /**
10
- * A named preset that pre-fills sections when creating a new page.
11
- *
12
- * Templates are a config-level concept only — after creation, the page is a
13
- * normal page with no template constraints. The `sectionTypes` array
14
- * references section names from the registered `sections` list; unknown
15
- * names are silently skipped at list time.
16
- */
17
- interface PageTemplate {
18
- readonly name: string;
19
- readonly description?: string;
20
- /** Ordered list of section type names to pre-fill. */
21
- readonly sectionTypes: readonly string[];
22
- }
23
- /**
24
- * Submission rate-limit configuration knob (ARCHITECTURE.md §6.5).
25
- *
26
- * Single field on purpose — multiplexing perWindow/windowMs/strategy into
27
- * a struct here would invite YAGNI bikeshedding. The window is fixed at
28
- * 60 seconds in v1; only the per-window count is user-tunable.
29
- */
30
- interface SubmissionRateLimit {
31
- /** Max submissions per minute per (IP, form) pair. Default: 5. */
32
- readonly perMinute: number;
33
- }
34
6
  /**
35
7
  * User-facing configuration shape passed to `defineConfig`.
36
8
  *
@@ -45,25 +17,6 @@ interface AgentCmsConfig {
45
17
  readonly contentAdapter?: ContentStorageAdapter;
46
18
  /** Asset storage adapter. Defaults to FS adapter with standard paths. */
47
19
  readonly assetAdapter?: AssetStorageAdapter;
48
- /** Page creation templates. Optional — defaults to [] (blank pages only). */
49
- readonly templates?: readonly PageTemplate[];
50
- /**
51
- * Registered form definitions (ARCHITECTURE.md §6.5). Optional — when
52
- * omitted, no forms are registered and the submit handler returns 404
53
- * for every form name.
54
- */
55
- readonly forms?: readonly AnyFormDefinition[];
56
- /**
57
- * Submission storage adapter. Defaults to the FS adapter rooted at
58
- * `<projectRoot>/content/submissions`. Use `createWebhookSubmissionAdapter`
59
- * (or a custom implementation) to send submissions to an external service.
60
- */
61
- readonly submissionAdapter?: SubmissionStorageAdapter;
62
- /**
63
- * Rate-limit knob for the submit endpoint. Defaults to `{ perMinute: 5 }`.
64
- * The window is always 60 seconds in v1 — only the count is user-tunable.
65
- */
66
- readonly submissionRateLimit?: SubmissionRateLimit;
67
20
  }
68
21
  /**
69
22
  * Fully-resolved configuration with all defaults filled in.
@@ -74,14 +27,6 @@ interface ResolvedConfig {
74
27
  readonly sections: readonly AnySectionDefinition[];
75
28
  readonly contentAdapter: ContentStorageAdapter;
76
29
  readonly assetAdapter: AssetStorageAdapter;
77
- /** Page creation templates. Always present (defaults to []). */
78
- readonly templates: readonly PageTemplate[];
79
- /** Registered forms. Always present (defaults to []). */
80
- readonly forms: readonly AnyFormDefinition[];
81
- /** Submission storage adapter. Always present. */
82
- readonly submissionAdapter: SubmissionStorageAdapter;
83
- /** Resolved rate-limit knob. Always present. */
84
- readonly submissionRateLimit: SubmissionRateLimit;
85
30
  }
86
31
  /**
87
32
  * Resolve a user config into a fully-populated config with defaults.
@@ -96,6 +41,7 @@ interface ResolvedConfig {
96
41
  */
97
42
  declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
98
43
 
44
+ type TracingIncludes = Record<string, string[]>;
99
45
  /**
100
46
  * Wrap a Next.js configuration object for agntcms.
101
47
  *
@@ -111,6 +57,7 @@ declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
111
57
  */
112
58
  declare function withagntcms<T extends Record<string, unknown>>(nextConfig: T): T & {
113
59
  pageExtensions: string[];
60
+ outputFileTracingIncludes: TracingIncludes;
114
61
  };
115
62
 
116
- export { type AgentCmsConfig, AnyFormDefinition, type PageTemplate, type ResolvedConfig, type SubmissionRateLimit, SubmissionStorageAdapter, defineConfig, withagntcms };
63
+ export { type AgentCmsConfig, type ResolvedConfig, defineConfig, withagntcms };
package/dist/config.d.ts CHANGED
@@ -1,36 +1,8 @@
1
- import { A as AnyFormDefinition, o as SubmissionStorageAdapter } from './form-BqY0H1V5.js';
2
- export { j as BooleanField, B as ButtonField, b as FormDefinition, p as FormFieldDescriptor, q as FormFieldOverride, n as FormFieldOverrides, r as FormOverridesField, m as FormOverridesFieldDescriptor, a as FormSchema, I as ImageField, L as LinkField, l as ListField, N as NumberField, f as ReferenceField, R as RichTextField, k as SelectField, s as Submission, t as SubmissionAdapterInfo, u as SubmissionSummary, v as SubmissionsNotReadableError, T as TextField, V as VideoField } from './form-BqY0H1V5.js';
3
- import { A as AnySectionDefinition } from './defineSection-Kr0pWqMY.js';
4
- import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-P8OCigDG.js';
5
- export { D as DefineFormInput, H as HoneypotCollisionError, I as InvalidFormFieldError, a as InvalidFormNameError, d as defineForm } from './defineForm-Bp9vzW56.js';
6
- export { D as DuplicateFormNameError } from './registry-DMujGqt0.js';
1
+ import { A as AnySectionDefinition } from './defineSection-ChkZCQyQ.js';
2
+ import { C as ContentStorageAdapter, A as AssetStorageAdapter } from './assets-DHumg-X7.js';
3
+ export { g as BooleanField, B as ButtonField, I as ImageField, L as LinkField, i as ListField, N as NumberField, c as ReferenceField, R as RichTextField, h as SelectField, T as TextField, V as VideoField } from './page-DXF0_SrY.js';
7
4
  import './global-CV23g5Bn.js';
8
5
 
9
- /**
10
- * A named preset that pre-fills sections when creating a new page.
11
- *
12
- * Templates are a config-level concept only — after creation, the page is a
13
- * normal page with no template constraints. The `sectionTypes` array
14
- * references section names from the registered `sections` list; unknown
15
- * names are silently skipped at list time.
16
- */
17
- interface PageTemplate {
18
- readonly name: string;
19
- readonly description?: string;
20
- /** Ordered list of section type names to pre-fill. */
21
- readonly sectionTypes: readonly string[];
22
- }
23
- /**
24
- * Submission rate-limit configuration knob (ARCHITECTURE.md §6.5).
25
- *
26
- * Single field on purpose — multiplexing perWindow/windowMs/strategy into
27
- * a struct here would invite YAGNI bikeshedding. The window is fixed at
28
- * 60 seconds in v1; only the per-window count is user-tunable.
29
- */
30
- interface SubmissionRateLimit {
31
- /** Max submissions per minute per (IP, form) pair. Default: 5. */
32
- readonly perMinute: number;
33
- }
34
6
  /**
35
7
  * User-facing configuration shape passed to `defineConfig`.
36
8
  *
@@ -45,25 +17,6 @@ interface AgentCmsConfig {
45
17
  readonly contentAdapter?: ContentStorageAdapter;
46
18
  /** Asset storage adapter. Defaults to FS adapter with standard paths. */
47
19
  readonly assetAdapter?: AssetStorageAdapter;
48
- /** Page creation templates. Optional — defaults to [] (blank pages only). */
49
- readonly templates?: readonly PageTemplate[];
50
- /**
51
- * Registered form definitions (ARCHITECTURE.md §6.5). Optional — when
52
- * omitted, no forms are registered and the submit handler returns 404
53
- * for every form name.
54
- */
55
- readonly forms?: readonly AnyFormDefinition[];
56
- /**
57
- * Submission storage adapter. Defaults to the FS adapter rooted at
58
- * `<projectRoot>/content/submissions`. Use `createWebhookSubmissionAdapter`
59
- * (or a custom implementation) to send submissions to an external service.
60
- */
61
- readonly submissionAdapter?: SubmissionStorageAdapter;
62
- /**
63
- * Rate-limit knob for the submit endpoint. Defaults to `{ perMinute: 5 }`.
64
- * The window is always 60 seconds in v1 — only the count is user-tunable.
65
- */
66
- readonly submissionRateLimit?: SubmissionRateLimit;
67
20
  }
68
21
  /**
69
22
  * Fully-resolved configuration with all defaults filled in.
@@ -74,14 +27,6 @@ interface ResolvedConfig {
74
27
  readonly sections: readonly AnySectionDefinition[];
75
28
  readonly contentAdapter: ContentStorageAdapter;
76
29
  readonly assetAdapter: AssetStorageAdapter;
77
- /** Page creation templates. Always present (defaults to []). */
78
- readonly templates: readonly PageTemplate[];
79
- /** Registered forms. Always present (defaults to []). */
80
- readonly forms: readonly AnyFormDefinition[];
81
- /** Submission storage adapter. Always present. */
82
- readonly submissionAdapter: SubmissionStorageAdapter;
83
- /** Resolved rate-limit knob. Always present. */
84
- readonly submissionRateLimit: SubmissionRateLimit;
85
30
  }
86
31
  /**
87
32
  * Resolve a user config into a fully-populated config with defaults.
@@ -96,6 +41,7 @@ interface ResolvedConfig {
96
41
  */
97
42
  declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
98
43
 
44
+ type TracingIncludes = Record<string, string[]>;
99
45
  /**
100
46
  * Wrap a Next.js configuration object for agntcms.
101
47
  *
@@ -111,6 +57,7 @@ declare function defineConfig(config: AgentCmsConfig): ResolvedConfig;
111
57
  */
112
58
  declare function withagntcms<T extends Record<string, unknown>>(nextConfig: T): T & {
113
59
  pageExtensions: string[];
60
+ outputFileTracingIncludes: TracingIncludes;
114
61
  };
115
62
 
116
- export { type AgentCmsConfig, AnyFormDefinition, type PageTemplate, type ResolvedConfig, type SubmissionRateLimit, SubmissionStorageAdapter, defineConfig, withagntcms };
63
+ export { type AgentCmsConfig, type ResolvedConfig, defineConfig, withagntcms };
package/dist/config.mjs CHANGED
@@ -7,7 +7,7 @@ function getDefaultAdapterFactories(requested) {
7
7
  const f = holder()[SLOT];
8
8
  if (f === void 0) {
9
9
  throw new Error(
10
- `[agntcms] defineConfig: cannot fill the default ${requested} adapter because the server-only adapter factories were never registered. Import \`@agntcms/next/server\` (or \`@agntcms/next/handlers\`) before evaluating \`agntcms/config.ts\`, or pass an explicit adapter to \`defineConfig({ contentAdapter, assetAdapter, submissionAdapter })\`.`
10
+ `[agntcms] defineConfig: cannot fill the default ${requested} adapter because the server-only adapter factories were never registered. Import \`@agntcms/next/server\` (or \`@agntcms/next/handlers\`) before evaluating \`agntcms/config.ts\`, or pass an explicit adapter to \`defineConfig({ contentAdapter, assetAdapter })\`.`
11
11
  );
12
12
  }
13
13
  return f;
@@ -22,126 +22,51 @@ function defineConfig(config) {
22
22
  }
23
23
  const contentAdapter = config.contentAdapter ?? getDefaultAdapterFactories("content").content();
24
24
  const assetAdapter = config.assetAdapter ?? getDefaultAdapterFactories("asset").asset();
25
- const submissionAdapter = config.submissionAdapter ?? getDefaultAdapterFactories("submission").submission();
26
25
  return {
27
26
  sections: config.sections,
28
27
  contentAdapter,
29
- assetAdapter,
30
- templates: config.templates ?? [],
31
- forms: config.forms ?? [],
32
- submissionAdapter,
33
- submissionRateLimit: config.submissionRateLimit ?? { perMinute: 5 }
28
+ assetAdapter
34
29
  };
35
30
  }
36
31
 
37
32
  // src/config/withagntcms.ts
38
33
  var DEV_PAGE_EXTENSIONS = ["dev.ts", "dev.tsx", "ts", "tsx", "js", "jsx"];
39
34
  var PROD_PAGE_EXTENSIONS = ["ts", "tsx", "js", "jsx"];
35
+ var CONTENT_TRACE_GLOB = "./content/**/*";
40
36
  function withagntcms(nextConfig) {
41
37
  const isProd = process.env.NODE_ENV === "production";
42
38
  const defaultPageExtensions = isProd ? PROD_PAGE_EXTENSIONS : DEV_PAGE_EXTENSIONS;
43
39
  const userPageExtensions = nextConfig.pageExtensions;
44
40
  const pageExtensions = Array.isArray(userPageExtensions) ? userPageExtensions : [...defaultPageExtensions];
41
+ const userTracingIncludes = isPlainRecordOfStringArrays(
42
+ nextConfig.outputFileTracingIncludes
43
+ ) ? nextConfig.outputFileTracingIncludes : {};
44
+ const outputFileTracingIncludes = mergeTracingIncludes(userTracingIncludes, {
45
+ "/**": [CONTENT_TRACE_GLOB]
46
+ });
45
47
  return {
46
48
  ...nextConfig,
47
- pageExtensions
49
+ pageExtensions,
50
+ outputFileTracingIncludes
48
51
  };
49
52
  }
50
-
51
- // src/domain/form.ts
52
- var FORM_FORBIDDEN_KINDS = /* @__PURE__ */ new Set([
53
- "image",
54
- "video",
55
- "reference",
56
- "list",
57
- // `formOverrides` is a section-only descriptor (it overrides another
58
- // form schema instance). Putting it inside a form would mean a form's
59
- // payload could carry overrides for itself or another form — a
60
- // recursive shape with no ergonomic editor UI. Section-only by design.
61
- "formOverrides",
62
- // `button` is a section-only descriptor: a styled CTA with an
63
- // optional link. Public-form payloads collect user input — a button
64
- // value is authored content, not a submitted answer. Section-only
65
- // by design (mirrors `formOverrides`).
66
- "button"
67
- ]);
68
- var SubmissionsNotReadableError = class extends Error {
69
- constructor(message = "submission adapter does not support reading") {
70
- super(message);
71
- this.name = "SubmissionsNotReadableError";
72
- }
73
- };
74
-
75
- // src/forms/defineForm.ts
76
- var InvalidFormFieldError = class extends Error {
77
- formName;
78
- fieldName;
79
- fieldKind;
80
- constructor(formName, fieldName, fieldKind) {
81
- super(
82
- `Form "${formName}": field "${fieldName}" uses kind "${fieldKind}", which is not allowed in a form schema in v1. Allowed kinds: text, richText, number, boolean, select, link. Forbidden kinds: image, reference, list, formOverrides. See ARCHITECTURE.md \xA76.5.`
83
- );
84
- this.name = "InvalidFormFieldError";
85
- this.formName = formName;
86
- this.fieldName = fieldName;
87
- this.fieldKind = fieldKind;
88
- }
89
- };
90
- var HoneypotCollisionError = class extends Error {
91
- formName;
92
- fieldName;
93
- reason;
94
- constructor(formName, fieldName, reason = "collision") {
95
- super(
96
- reason === "empty" ? `Form "${formName}": honeypot name must be a non-empty string.` : `Form "${formName}": honeypot name "${fieldName}" collides with a real field. Choose a honeypot name that does not appear in the schema.`
97
- );
98
- this.name = "HoneypotCollisionError";
99
- this.formName = formName;
100
- this.fieldName = fieldName;
101
- this.reason = reason;
102
- }
103
- };
104
- var InvalidFormNameError = class extends Error {
105
- constructor(name) {
106
- super(
107
- `Invalid form name ${JSON.stringify(name)}. Use letters, digits, hyphen, and underscore only (no path separators).`
108
- );
109
- this.name = "InvalidFormNameError";
53
+ function isPlainRecordOfStringArrays(value) {
54
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
55
+ for (const v of Object.values(value)) {
56
+ if (!Array.isArray(v)) return false;
57
+ if (!v.every((item) => typeof item === "string")) return false;
110
58
  }
111
- };
112
- var FORM_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
113
- function defineForm(input) {
114
- if (typeof input.name !== "string" || !FORM_NAME_PATTERN.test(input.name)) {
115
- throw new InvalidFormNameError(input.name);
116
- }
117
- for (const [fieldName, descriptor] of Object.entries(input.schema)) {
118
- const kind = descriptor.kind;
119
- if (FORM_FORBIDDEN_KINDS.has(kind)) {
120
- throw new InvalidFormFieldError(input.name, fieldName, kind);
121
- }
122
- }
123
- if (input.honeypot !== void 0) {
124
- if (typeof input.honeypot !== "string" || input.honeypot === "") {
125
- throw new HoneypotCollisionError(input.name, input.honeypot, "empty");
126
- }
127
- if (Object.prototype.hasOwnProperty.call(input.schema, input.honeypot)) {
128
- throw new HoneypotCollisionError(input.name, input.honeypot, "collision");
129
- }
130
- }
131
- return input.honeypot !== void 0 ? { name: input.name, schema: input.schema, honeypot: input.honeypot } : { name: input.name, schema: input.schema };
59
+ return true;
132
60
  }
133
-
134
- // src/forms/registry.ts
135
- var DuplicateFormNameError = class extends Error {
136
- formName;
137
- constructor(name) {
138
- super(
139
- `Form name "${name}" is registered more than once. Form names must be unique within a config.`
140
- );
141
- this.name = "DuplicateFormNameError";
142
- this.formName = name;
61
+ function mergeTracingIncludes(user, framework) {
62
+ const result = {};
63
+ const keys = /* @__PURE__ */ new Set([...Object.keys(user), ...Object.keys(framework)]);
64
+ for (const key of keys) {
65
+ const merged = [...user[key] ?? [], ...framework[key] ?? []];
66
+ result[key] = Array.from(new Set(merged));
143
67
  }
144
- };
68
+ return result;
69
+ }
145
70
 
146
71
  // src/domain/fields.ts
147
72
  var TextField = { kind: "text" };
@@ -169,32 +94,18 @@ var ListField = (itemSchema, opts) => ({
169
94
  ...opts?.max !== void 0 ? { max: opts.max } : {},
170
95
  ...opts?.default !== void 0 ? { default: opts.default } : {}
171
96
  });
172
-
173
- // src/domain/formOverrides.ts
174
- var FormOverridesField = (formName, opts) => ({
175
- kind: "formOverrides",
176
- formName,
177
- ...opts?.default !== void 0 ? { default: opts.default } : {}
178
- });
179
97
  export {
180
98
  BooleanField,
181
99
  ButtonField,
182
- DuplicateFormNameError,
183
- FormOverridesField,
184
- HoneypotCollisionError,
185
100
  ImageField,
186
- InvalidFormFieldError,
187
- InvalidFormNameError,
188
101
  LinkField,
189
102
  ListField,
190
103
  NumberField,
191
104
  ReferenceField,
192
105
  RichTextField,
193
106
  SelectField,
194
- SubmissionsNotReadableError,
195
107
  TextField,
196
108
  VideoField,
197
109
  defineConfig,
198
- defineForm,
199
110
  withagntcms
200
111
  };