ampless 1.0.0-alpha.23 → 1.0.0-alpha.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -615,7 +615,33 @@ interface PluginJsonField extends PluginFieldBase<unknown> {
615
615
  placeholder?: string;
616
616
  rows?: number;
617
617
  }
618
- type PluginSettingField = PluginTextField | PluginTextareaField | PluginBooleanField | PluginNumberField | PluginSelectField | PluginUrlField | PluginCodeField | PluginJsonField;
618
+ /**
619
+ * Sub-fields allowed inside a `PluginRepeatableField`. Restricted to
620
+ * the scalar-shape field types so the v1 admin editor can render each
621
+ * cell with the existing `renderScalarInput` seam. Code / json /
622
+ * repeatable are excluded — code is rarely useful per-item, json
623
+ * recurses into "json inside json" UX that we explicitly want to
624
+ * avoid, and nested repeatable is deferred.
625
+ */
626
+ type PluginRepeatableSubField = PluginTextField | PluginTextareaField | PluginBooleanField | PluginNumberField | PluginSelectField | PluginUrlField;
627
+ interface PluginRepeatableField extends PluginFieldBase<ReadonlyArray<Readonly<Record<string, unknown>>>> {
628
+ type: 'repeatable';
629
+ /** Shape of each item — every item is a flat object keyed by sub-field `key`. */
630
+ fields: ReadonlyArray<PluginRepeatableSubField>;
631
+ /** Hard cap on item count (default 50). Exceeding rejects the whole field. */
632
+ maxItems?: number;
633
+ /** Minimum item count (default 0). Below rejects the whole field. */
634
+ minItems?: number;
635
+ /** Label for the "+ Add item" button in the admin editor. */
636
+ addLabel?: LocalizedString;
637
+ /**
638
+ * Sub-field key used as the per-item heading in the admin editor
639
+ * (e.g. `'id'` so categories[0] reads "analytics" not "Item 1").
640
+ * Falls back to "Item N" when absent or empty.
641
+ */
642
+ itemLabelKey?: string;
643
+ }
644
+ type PluginSettingField = PluginTextField | PluginTextareaField | PluginBooleanField | PluginNumberField | PluginSelectField | PluginUrlField | PluginCodeField | PluginJsonField | PluginRepeatableField;
619
645
  /**
620
646
  * Static manifest declared in a plugin package's `package.json` under
621
647
  * the `amplessPlugin` key. The plugin package must also expose
@@ -1186,7 +1212,7 @@ declare function isValidPluginKey(key: string): boolean;
1186
1212
  * `boolean`, `json` stores the decoded value (object / array /
1187
1213
  * primitive — never the source string), etc.
1188
1214
  */
1189
- declare function validatePluginSettingValue(field: PluginSettingField, raw: unknown): unknown | null;
1215
+ declare function validatePluginSettingValue(field: PluginSettingField, raw: unknown, mode?: 'strict' | 'lenient'): unknown | null;
1190
1216
  /**
1191
1217
  * Merge stored values on top of manifest defaults for one plugin
1192
1218
  * instance. Both sides are validated through `validatePluginSettingValue`
package/dist/index.js CHANGED
@@ -239,7 +239,7 @@ var PLUGIN_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
239
239
  function isValidPluginKey(key) {
240
240
  return typeof key === "string" && PLUGIN_KEY_PATTERN.test(key);
241
241
  }
242
- function validatePluginSettingValue(field, raw) {
242
+ function validatePluginSettingValue(field, raw, mode = "lenient") {
243
243
  if (raw === void 0) return null;
244
244
  switch (field.type) {
245
245
  case "text":
@@ -318,6 +318,60 @@ function validatePluginSettingValue(field, raw) {
318
318
  if (typeof raw === "string") return null;
319
319
  return raw;
320
320
  }
321
+ case "repeatable": {
322
+ if (!Array.isArray(raw)) return null;
323
+ const maxItems = typeof field.maxItems === "number" ? field.maxItems : 50;
324
+ const minItems = typeof field.minItems === "number" ? field.minItems : 0;
325
+ if (raw.length > maxItems) return null;
326
+ if (raw.length < minItems) return null;
327
+ const subFieldMap = /* @__PURE__ */ new Map();
328
+ for (const sf of field.fields) {
329
+ subFieldMap.set(sf.key, sf);
330
+ }
331
+ const validatedItems = [];
332
+ for (const item of raw) {
333
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
334
+ if (mode === "strict") return null;
335
+ continue;
336
+ }
337
+ const rawItem = item;
338
+ let itemValid = true;
339
+ const validatedItem = {};
340
+ for (const sf of field.fields) {
341
+ const rawSubVal = Object.prototype.hasOwnProperty.call(rawItem, sf.key) ? rawItem[sf.key] : void 0;
342
+ if (rawSubVal === void 0) {
343
+ if (sf.required) {
344
+ if (mode === "strict") return null;
345
+ itemValid = false;
346
+ break;
347
+ }
348
+ if (sf.default !== void 0) {
349
+ const validatedDefault = validatePluginSettingValue(sf, sf.default, mode);
350
+ if (validatedDefault !== null) {
351
+ validatedItem[sf.key] = validatedDefault;
352
+ }
353
+ }
354
+ continue;
355
+ }
356
+ const validatedSubVal = validatePluginSettingValue(sf, rawSubVal, mode);
357
+ if (validatedSubVal === null) {
358
+ if (sf.required) {
359
+ if (mode === "strict") return null;
360
+ itemValid = false;
361
+ break;
362
+ }
363
+ continue;
364
+ }
365
+ validatedItem[sf.key] = validatedSubVal;
366
+ }
367
+ if (!itemValid) {
368
+ continue;
369
+ }
370
+ validatedItems.push(validatedItem);
371
+ }
372
+ if (validatedItems.length < minItems) return null;
373
+ return validatedItems;
374
+ }
321
375
  }
322
376
  }
323
377
  function resolvePluginSettings(manifest, stored) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ampless",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.24",
4
4
  "description": "Serverless CMS for AWS Amplify",
5
5
  "license": "MIT",
6
6
  "type": "module",