@rsc-kit/press 0.30.50 → 0.30.52

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.
Files changed (61) hide show
  1. package/README.md +3 -2
  2. package/dist/admin/actions.js +6 -3
  3. package/dist/admin/actions.js.map +1 -1
  4. package/dist/admin/panel.js +28 -9
  5. package/dist/admin/panel.js.map +1 -1
  6. package/dist/admin/theme.d.ts +10 -1
  7. package/dist/admin/theme.js.map +1 -1
  8. package/dist/admin/url.d.ts +12 -0
  9. package/dist/admin/url.js +18 -0
  10. package/dist/admin/url.js.map +1 -1
  11. package/dist/conditions.d.ts +32 -0
  12. package/dist/conditions.js +25 -0
  13. package/dist/conditions.js.map +1 -0
  14. package/dist/forms/actions.d.ts +6 -5
  15. package/dist/forms/actions.js +13 -8
  16. package/dist/forms/actions.js.map +1 -1
  17. package/dist/forms/blueprint.d.ts +99 -0
  18. package/dist/forms/blueprint.js +141 -0
  19. package/dist/forms/blueprint.js.map +1 -0
  20. package/dist/forms/brand.d.ts +26 -0
  21. package/dist/forms/brand.js +9 -0
  22. package/dist/forms/brand.js.map +1 -0
  23. package/dist/forms/host.d.ts +12 -2
  24. package/dist/forms/host.js +16 -6
  25. package/dist/forms/host.js.map +1 -1
  26. package/dist/forms/index.d.ts +3 -3
  27. package/dist/forms/index.js +1 -1
  28. package/dist/forms/index.js.map +1 -1
  29. package/dist/forms/registry.d.ts +6 -1
  30. package/dist/forms/registry.js +1 -1
  31. package/dist/forms/registry.js.map +1 -1
  32. package/dist/forms/theme.d.ts +10 -7
  33. package/dist/forms/theme.js.map +1 -1
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/installable.js +8 -3
  38. package/dist/installable.js.map +1 -1
  39. package/dist/resource.d.ts +77 -6
  40. package/dist/resource.js +137 -18
  41. package/dist/resource.js.map +1 -1
  42. package/dist/shadcn/blueprint-form.d.ts +8 -0
  43. package/dist/shadcn/{public-form.js → blueprint-form.js} +7 -6
  44. package/dist/shadcn/blueprint-form.js.map +1 -0
  45. package/dist/shadcn/data-table.d.ts +1 -1
  46. package/dist/shadcn/data-table.js +5 -4
  47. package/dist/shadcn/data-table.js.map +1 -1
  48. package/dist/shadcn/fields.d.ts +11 -1
  49. package/dist/shadcn/fields.js +72 -10
  50. package/dist/shadcn/fields.js.map +1 -1
  51. package/dist/shadcn/index.d.ts +1 -1
  52. package/dist/shadcn/index.js +3 -3
  53. package/dist/shadcn/index.js.map +1 -1
  54. package/dist/shadcn/resource-form.js +3 -2
  55. package/dist/shadcn/resource-form.js.map +1 -1
  56. package/package.json +2 -2
  57. package/dist/forms/form.d.ts +0 -61
  58. package/dist/forms/form.js +0 -66
  59. package/dist/forms/form.js.map +0 -1
  60. package/dist/shadcn/public-form.d.ts +0 -8
  61. package/dist/shadcn/public-form.js.map +0 -1
@@ -2,9 +2,14 @@ import type { Field, FormSchema } from '../resource.js';
2
2
  export interface FormHandle {
3
3
  name: string;
4
4
  schema: FormSchema;
5
+ editSchema: FormSchema;
5
6
  fields: Field[];
6
- handle: (values: Record<string, unknown>) => void | Promise<void>;
7
+ editFields: Field[];
8
+ create: ((values: Record<string, unknown>) => Promise<unknown>) | null;
9
+ update: ((values: Record<string, unknown>, key: string) => Promise<unknown>) | null;
7
10
  redirect: string | null;
11
+ /** Whether a filled bot trap drops the submission. */
12
+ honeypot: boolean;
8
13
  }
9
14
  export declare function registerForm(form: FormHandle): void;
10
15
  export declare function formNamed(name: string): FormHandle;
@@ -11,7 +11,7 @@ export function registerForm(form) {
11
11
  export function formNamed(name) {
12
12
  const form = forms.get(name);
13
13
  if (!form)
14
- throw new Error(`[forms] no form named ${name}; defineForm({ name: ${JSON.stringify(name)} }) has not run`);
14
+ throw new Error(`[forms] no form named ${name}; defineBlueprint({ name: ${JSON.stringify(name)} }) has not run`);
15
15
  return form;
16
16
  }
17
17
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/forms/registry.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;AAC9C,MAAM,KAAK,GAA4B,CAAE,UAAsC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,EAAE,CAA4B,CAAA;AAE9H,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAE5B,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,wBAAwB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAEtH,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import type { Field, FormSchema } from '../resource.js'\n\nexport interface FormHandle {\n name: string\n schema: FormSchema\n fields: Field[]\n handle: (values: Record<string, unknown>) => void | Promise<void>\n redirect: string | null\n}\n\n/**\n * Forms by name. An action receives a name, not a form - only what can be\n * serialised crosses to the browser and back - so the form is looked up here.\n * On globalThis because a dev server can evaluate this module more than once.\n */\nconst KEY = Symbol.for('@rsc-kit/press.forms')\nconst forms: Map<string, FormHandle> = ((globalThis as Record<symbol, unknown>)[KEY] ??= new Map()) as Map<string, FormHandle>\n\nexport function registerForm(form: FormHandle): void {\n forms.set(form.name, form)\n}\n\nexport function formNamed(name: string): FormHandle {\n const form = forms.get(name)\n\n if (!form) throw new Error(`[forms] no form named ${name}; defineForm({ name: ${JSON.stringify(name)} }) has not run`)\n\n return form\n}\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/forms/registry.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;AAC9C,MAAM,KAAK,GAA4B,CAAE,UAAsC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,EAAE,CAA4B,CAAA;AAE9H,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAE5B,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,6BAA6B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAE3H,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import type { Field, FormSchema } from '../resource.js'\n\nexport interface FormHandle {\n name: string\n schema: FormSchema\n editSchema: FormSchema\n fields: Field[]\n editFields: Field[]\n create: ((values: Record<string, unknown>) => Promise<unknown>) | null\n update: ((values: Record<string, unknown>, key: string) => Promise<unknown>) | null\n redirect: string | null\n /** Whether a filled bot trap drops the submission. */\n honeypot: boolean\n}\n\n/**\n * Forms by name. An action receives a name, not a form - only what can be\n * serialised crosses to the browser and back - so the form is looked up here.\n * On globalThis because a dev server can evaluate this module more than once.\n */\nconst KEY = Symbol.for('@rsc-kit/press.forms')\nconst forms: Map<string, FormHandle> = ((globalThis as Record<symbol, unknown>)[KEY] ??= new Map()) as Map<string, FormHandle>\n\nexport function registerForm(form: FormHandle): void {\n forms.set(form.name, form)\n}\n\nexport function formNamed(name: string): FormHandle {\n const form = forms.get(name)\n\n if (!form) throw new Error(`[forms] no form named ${name}; defineBlueprint({ name: ${JSON.stringify(name)} }) has not run`)\n\n return form\n}\n"]}
@@ -1,19 +1,21 @@
1
1
  import type { ComponentType } from 'react';
2
2
  import type { Field } from '../resource.js';
3
3
  /**
4
- * What a theme draws for a public form. As with a panel, every prop is data,
5
- * a bound server action or a string - never a component - so the form may be
6
- * a client component, and it is: it shows the browser's checks and the
4
+ * What a theme draws for a blueprint's form. As with a panel, every prop is
5
+ * data, a bound server action or a string - never a component - so the form
6
+ * may be a client component, and it is: it shows the browser's checks and the
7
7
  * server's refusals under their fields.
8
8
  */
9
9
  export interface FormsTheme {
10
- PublicForm: ComponentType<PublicFormProps>;
10
+ BlueprintForm: ComponentType<FormProps>;
11
11
  }
12
- export interface PublicFormProps {
12
+ export interface FormProps {
13
13
  /** Checks and sends the form. A refusal is a 422 whose messages belong under their fields. */
14
14
  action: (form: FormData) => Promise<unknown>;
15
15
  fields: Field[];
16
- /** The submit button's words: Send message. */
16
+ /** What each field starts as: the record being edited, or nothing. */
17
+ values: Record<string, unknown>;
18
+ /** The submit button's words: Send message, Save. */
17
19
  submit: string;
18
20
  /**
19
21
  * What the visitor reads once it is sent, in place of the form. Absent when
@@ -24,6 +26,7 @@ export interface PublicFormProps {
24
26
  * The name of a field people never see and bots fill in. The theme renders
25
27
  * it hidden from sight, from screen readers and from the tab order, with
26
28
  * autocomplete off; a submission with it filled is thanked and dropped.
29
+ * Absent for a blueprint that turned it off.
27
30
  */
28
- honeypot: string;
31
+ honeypot?: string;
29
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/forms/theme.ts"],"names":[],"mappings":"","sourcesContent":["import type { ComponentType } from 'react'\nimport type { Field } from '../resource.js'\n\n/**\n * What a theme draws for a public form. As with a panel, every prop is data,\n * a bound server action or a string - never a component - so the form may be\n * a client component, and it is: it shows the browser's checks and the\n * server's refusals under their fields.\n */\nexport interface FormsTheme {\n PublicForm: ComponentType<PublicFormProps>\n}\n\nexport interface PublicFormProps {\n /** Checks and sends the form. A refusal is a 422 whose messages belong under their fields. */\n action: (form: FormData) => Promise<unknown>\n fields: Field[]\n /** The submit button's words: Send message. */\n submit: string\n /**\n * What the visitor reads once it is sent, in place of the form. Absent when\n * the form redirects instead.\n */\n done?: string\n /**\n * The name of a field people never see and bots fill in. The theme renders\n * it hidden from sight, from screen readers and from the tab order, with\n * autocomplete off; a submission with it filled is thanked and dropped.\n */\n honeypot: string\n}\n"]}
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/forms/theme.ts"],"names":[],"mappings":"","sourcesContent":["import type { ComponentType } from 'react'\nimport type { Field } from '../resource.js'\n\n/**\n * What a theme draws for a blueprint's form. As with a panel, every prop is\n * data, a bound server action or a string - never a component - so the form\n * may be a client component, and it is: it shows the browser's checks and the\n * server's refusals under their fields.\n */\nexport interface FormsTheme {\n BlueprintForm: ComponentType<FormProps>\n}\n\nexport interface FormProps {\n /** Checks and sends the form. A refusal is a 422 whose messages belong under their fields. */\n action: (form: FormData) => Promise<unknown>\n fields: Field[]\n /** What each field starts as: the record being edited, or nothing. */\n values: Record<string, unknown>\n /** The submit button's words: Send message, Save. */\n submit: string\n /**\n * What the visitor reads once it is sent, in place of the form. Absent when\n * the form redirects instead.\n */\n done?: string\n /**\n * The name of a field people never see and bots fill in. The theme renders\n * it hidden from sight, from screen readers and from the tab order, with\n * autocomplete off; a submission with it filled is thanked and dropped.\n * Absent for a blueprint that turned it off.\n */\n honeypot?: string\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { defineResource, fieldsOf, humanize, parse, valuesFrom } from './resource.js';
2
- export type { BulkAction, Column, ColumnBuilder, Columns, DataSource, BlockSpec, Field, FieldType, Filter, FieldOverride, FormSchema, Format, ListQuery, Option, Parsed, ParseOptions, Resource, ResourceDefinition, SourceContext, TableMode, ValuesOf, Tenant, } from './resource.js';
2
+ export { shown, slugify } from './conditions.js';
3
+ export type { Derivation, Visibility } from './conditions.js';
4
+ export type { BulkAction, Column, ColumnBuilder, Columns, DataSource, BlockSpec, Field, FieldType, Filter, FieldOverride, FormSchema, Format, ListPage, ListQuery, Option, Parsed, ParseOptions, Resource, ResourceDefinition, SourceContext, TableMode, ValuesOf, Tenant, } from './resource.js';
3
5
  export { IMAGE_TYPES } from './uploads.js';
4
6
  export type { Storage, StorageContext } from './uploads.js';
5
7
  export { Blocks, defineBlock } from './blocks.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { defineResource, fieldsOf, humanize, parse, valuesFrom } from './resource.js';
2
+ export { shown, slugify } from './conditions.js';
2
3
  export { IMAGE_TYPES } from './uploads.js';
3
4
  export { Blocks, defineBlock } from './blocks.js';
4
5
  export { memorySource } from './memory.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAyBrF,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA","sourcesContent":["export { defineResource, fieldsOf, humanize, parse, valuesFrom } from './resource.js'\nexport type {\n BulkAction,\n Column,\n ColumnBuilder,\n Columns,\n DataSource,\n BlockSpec,\n Field,\n FieldType,\n Filter,\n FieldOverride,\n FormSchema,\n Format,\n ListQuery,\n Option,\n Parsed,\n ParseOptions,\n Resource,\n ResourceDefinition,\n SourceContext,\n TableMode,\n ValuesOf,\n Tenant,\n} from './resource.js'\nexport { IMAGE_TYPES } from './uploads.js'\nexport type { Storage, StorageContext } from './uploads.js'\nexport { Blocks, defineBlock } from './blocks.js'\nexport type { Block, BlockDefinition, BlockValue } from './blocks.js'\nexport { memorySource } from './memory.js'\nexport { perTenant } from './tenant.js'\nexport { definePlugin } from './plugin.js'\nexport type { PanelPlugin, RecordChange, Widget } from './plugin.js'\nexport { memoryInstallations, manifestProblems, publicHttps } from './installable.js'\nexport type { Installation, Installations, Installs, ManifestColumn, ManifestProperty, ManifestResource, PluginManifest, PluginRequest } from './installable.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACrF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AA2BhD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA","sourcesContent":["export { defineResource, fieldsOf, humanize, parse, valuesFrom } from './resource.js'\nexport { shown, slugify } from './conditions.js'\nexport type { Derivation, Visibility } from './conditions.js'\nexport type {\n BulkAction,\n Column,\n ColumnBuilder,\n Columns,\n DataSource,\n BlockSpec,\n Field,\n FieldType,\n Filter,\n FieldOverride,\n FormSchema,\n Format,\n ListPage,\n ListQuery,\n Option,\n Parsed,\n ParseOptions,\n Resource,\n ResourceDefinition,\n SourceContext,\n TableMode,\n ValuesOf,\n Tenant,\n} from './resource.js'\nexport { IMAGE_TYPES } from './uploads.js'\nexport type { Storage, StorageContext } from './uploads.js'\nexport { Blocks, defineBlock } from './blocks.js'\nexport type { Block, BlockDefinition, BlockValue } from './blocks.js'\nexport { memorySource } from './memory.js'\nexport { perTenant } from './tenant.js'\nexport { definePlugin } from './plugin.js'\nexport type { PanelPlugin, RecordChange, Widget } from './plugin.js'\nexport { memoryInstallations, manifestProblems, publicHttps } from './installable.js'\nexport type { Installation, Installations, Installs, ManifestColumn, ManifestProperty, ManifestResource, PluginManifest, PluginRequest } from './installable.js'\n"]}
@@ -345,10 +345,15 @@ function remoteSource(installation, resource, allow) {
345
345
  return {
346
346
  async list(query, context) {
347
347
  const answer = await call({ type: 'list', resource, query }, context);
348
- if (!isObject(answer) || !Array.isArray(answer.rows) || typeof answer.total !== 'number') {
349
- throw new Error(`[admin] the plugin ${plugin} answered a list without { rows, total }`);
348
+ const cursor = (value) => typeof value === 'string' || value === null || value === undefined;
349
+ const paged = isObject(answer) && 'next' in answer && cursor(answer.next) && cursor(answer.prev);
350
+ if (!isObject(answer) || !Array.isArray(answer.rows) || (typeof answer.total !== 'number' && !paged)) {
351
+ throw new Error(`[admin] the plugin ${plugin} answered a list without { rows, total } or { rows, next }`);
350
352
  }
351
- return { rows: answer.rows.map((value) => row(value, plugin)), total: answer.total };
353
+ const rows = answer.rows.map((value) => row(value, plugin));
354
+ return paged
355
+ ? { rows, next: answer.next ?? null, prev: answer.prev ?? null }
356
+ : { rows, total: answer.total };
352
357
  },
353
358
  async find(id, context) {
354
359
  const answer = await call({ type: 'find', resource, id }, context);
@@ -1 +1 @@
1
- {"version":3,"file":"installable.js","sourceRoot":"","sources":["../src/installable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAsGvD,8FAA8F;AAC9F,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;AAEzD,sFAAsF;AACtF,MAAM,UAAU,mBAAmB,CAAC,IAAI,GAAG,SAAS;IAClD,MAAM,GAAG,GAAG,CAAE,UAAsC,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,EAAE,CAA6C,CAAA;IACvH,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAA0B,CAAA;IAE/D,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAEnB,MAAM,EAAE,GAAG,CAAC,MAAqB,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAA;IAEtD,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACzD,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QAC/G,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAChI,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CACzB,KAAK,IAAI,CAAC,GAAG,CACX,EAAE,CAAC,MAAM,CAAC,EACV,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CACxH;KACJ,CAAA;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,IAAI,GAAG,2BAA2B,CAAA;AACxC,MAAM,GAAG,GAAG,+BAA+B,CAAA;AAC3C,MAAM,OAAO,GAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;AAC/E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AAE1C,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAE3I,SAAS,IAAI,CAAC,KAAc,EAAE,GAAW;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,CAAA;AAChF,CAAC;AAED,qIAAqI;AACrI,SAAS,IAAI,CAAC,KAAa,EAAE,KAA8B,EAAE,IAAc,EAAE,QAAkB;IAC7F,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,mBAAmB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAChI,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAiB,EAAE,WAAmB,EAAE,IAAc;IACrF,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,mCAAmC,CAAC,CAAA;IAErE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;IAE9H,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAA;IAC3I,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAA;IACtF,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;IAChI,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAElH,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,CAAA;QAEhE,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM;YAAE,QAAQ,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAA;IAC5H,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;IACtE,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,IAAI,CAAC,MAAM;QAAE,QAAQ,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;SAC3E,CAAC;QACJ,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAE1F,IAAI,CAAC,KAAK;gBAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAA;iBAC/E,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,4CAA4C,CAAC,CAAA;;gBAC1G,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;IAE/E,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAClE,QAAQ,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAA;QAE7C,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC7H,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAEjF,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,aAAa,KAAK,GAAG,CAAA;QAEnC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAA;YACxC,SAAQ;QACV,CAAC;QAED,IAAI,CACF,KAAK,EACL,QAAQ,EACR,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC,EACxI,QAAQ,CACT,CAAA;QAED,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;QAEjG,IAAI,CAAC,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,6CAA6C,CAAC,CAAA;aAC1E,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,IAAI,qBAAqB,CAAC,CAAA;aACvF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,kDAAkD,IAAI,EAAE,CAAC,CAAA;aACxG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,kCAAkC,IAAI,EAAE,CAAC,CAAA;QAErG,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAU,EAAE,CAAC;YAChE,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,GAAG,sBAAsB,CAAC,CAAA;QACjJ,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAA;QAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA;QAEjH,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YAC/F,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,qDAAqD,CAAC,CAAA;YAC5E,SAAQ;QACV,CAAC;QAED,IAAI,CAAC,GAAG,KAAK,OAAO,EAAE,IAA+B,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;QAEpG,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAE1C,IAAI,IAAI,IAAK,IAA+B,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACpE,MAAM,QAAQ,GAAI,IAA+B,CAAC,QAAQ,CAAA;YAE1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAC,EAAE,CAAC;gBAChG,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,2CAA2C,CAAC,CAAA;YACpE,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,EAAE,GAAG,GAAG,KAAK,oBAAoB,KAAK,EAAE,CAAA;YAE9C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAA;YAC9D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAA;gBACrC,SAAQ;YACV,CAAC;YAED,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;YAEvJ,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAc,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,2CAA2C,CAAC,CAAA;YAClJ,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAgB,CAAC,EAAE,CAAC;gBACrH,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,6CAA6C,CAAC,CAAA;YACnE,CAAC;YACD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtJ,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAA;YAChD,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,CAAU,EAAE,CAAC;gBAC9E,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,QAAQ;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,YAAY,CAAC,CAAA;YACrH,CAAC;YACD,sEAAsE;YACtE,oEAAoE;YACpE,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,kCAAkC,CAAC,CAAA;YAC1H,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBAChH,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,sDAAsD,CAAC,CAAA;YACnH,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,QAAQ,CAAC,GAAG,CAAC,CAAA;QAE/G,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAA;QAC5G,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,8CAA8C,CAAC,CAAA;QAEnG,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;QAEzE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,6BAA6B,CAAC,CAAA;aAC5G,CAAC;YACJ,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC7C,MAAM,MAAM,GAAG,GAAG,KAAK,YAAY,EAAE,GAAG,CAAA;gBAExC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,iBAAiB,CAAC,CAAA;oBACzC,SAAQ;gBACV,CAAC;gBAED,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAA;gBAEhG,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,oBAAoB,CAAC,CAAA;gBACzG,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,+BAA+B,CAAC,CAAA;gBAClH,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAwB,CAAC;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAC/I,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;oBAC1G,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,cAAc,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,sDAAsD,CAAC,CAAA;gBACrH,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;YAEvE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAE,UAAU,CAAC,MAAM,CAAkC,EAAE,IAAI;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAA;YAC1K,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAK,QAAQ,CAAC,OAAkB,IAAI,CAAC,IAAK,QAAQ,CAAC,OAAkB,IAAI,GAAG,CAAC,EAAE,CAAC;YACxJ,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAA;QAC7C,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,yBAAyB,CAAC,CAAA;QAC7I,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,0BAA0B,CAAC,CAAA;QAEhI,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA;YAEjF,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,oCAAoC,CAAC,CAAA;iBAC3F,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,6CAA6C,CAAC,CAAA;iBAC1H,CAAC;gBACJ,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;wBAC3I,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,0DAA0D,CAAC,CAAA;oBACnF,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;QAEtE,IAAI,CAAC,MAAM;YAAE,QAAQ,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAA;aACzD,CAAC;YACJ,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;oBAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAA;YACnJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,QAAwB,EAAE,OAAqC;IACxF,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QAEnE,OAAO,YAAY,QAAQ,qEAAqE,CAAA;IAClG,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,+EAA+E;AAE/E,4GAA4G;AAC5G,MAAM,UAAU,WAAW,CAAC,GAAQ;IAClC,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE3C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAEjD,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9H,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAE7D,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,CAAA;AACjC,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;AAEpC,wGAAwG;AACxG,KAAK,UAAU,OAAO,CAAC,QAAkB,EAAE,KAAa;IACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAA;IAEpE,IAAI,QAAQ,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,gBAAgB,KAAK,EAAE,CAAC,CAAA;IAE/F,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAElC,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,QAAQ,CAAC,CAAA;IAErF,OAAO,IAAI,CAAA;AACb,CAAC;AAED,uHAAuH;AACvH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,KAA4B,EAAE,IAAc;IACnG,IAAI,GAAQ,CAAA;IAEZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAE1F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAEtJ,IAAI,CAAC,QAAQ,EAAE,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAElH,IAAI,QAAiB,CAAA;IAErB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAA;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAC9C,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAE3D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAE9F,MAAM,OAAO,GAAG,QAA0B,CAAA;IAE1C,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AACtE,CAAC;AAED,wGAAwG;AACxG,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAwB;IACrD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAEvH,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC9E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,QAAwB;IAC3E,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAA;AAC1I,CAAC;AAcD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,YAA0B,EAC1B,IAAgB,EAChB,OAAsB,EACtB,KAA4B,EAC5B,OAAO,GAAG,MAAM;IAEhB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACxD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAA;IAEvC,uEAAuE;IACvE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,kCAAkC,CAAC,CAAA;IAEnG,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9H,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QACrC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,CAAC,MAAM,aAAa,CAAC,YAAY,CAAC,EAAE,EAAE,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE;QACjJ,IAAI;QACJ,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;KACrC,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IAExC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;IACpD,IAAI,IAAI,GAAY,IAAI,CAAA;IAExB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,aAAa,QAAQ,CAAC,MAAM,kCAAkC,CAAC,CAAA;IAC3G,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAG,EAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAC5H,CAAA;QAED,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,aAAa,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAE3F,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,KAAc,EAAE,MAAc,EAA2B,EAAE;IACtE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,uCAAuC,CAAC,CAAA;IAE1G,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,mDAAmD;AACnD,SAAS,YAAY,CAAC,YAA0B,EAAE,QAAgB,EAAE,KAA4B;IAC9F,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAA;IACzC,MAAM,IAAI,GAAG,CAAC,IAAgB,EAAE,OAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAEzG,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO;YACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAA;YAErE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACzF,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,0CAA0C,CAAC,CAAA;YACzF,CAAC;YAED,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAA;QACtF,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO;YACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;YAElE,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC7G,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO;YAC1B,OAAO,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,CAA6B,EAAE,MAAM,CAAC,CAAC,GAA8B,CAAA;QAC5I,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO;YAC9B,OAAO,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,CAA6B,EAAE,MAAM,CAAC,CAAC,GAA8B,CAAA;QAChJ,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO;YACtB,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;QACvD,CAAC;KACF,CAAA;AACH,CAAC;AAED,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAA8B;IAC3D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;IAE7C,MAAM,QAAQ,GAAG,CAAC,KAAc,EAA0F,EAAE;QAC1H,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,CAAA;QAEtF,MAAM,GAAG,GAA4B,EAAE,CAAA;QACvC,MAAM,MAAM,GAA0C,EAAE,CAAA;QAExD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;YACzB,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAExE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBAC1D,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,UAAU,CAAC,CAAA;gBACvE,SAAQ;YACV,CAAC;YAED,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAChC,IAAI,OAAO,KAAK,KAAK,SAAS;oBAAE,IAAI,CAAC,wBAAwB,CAAC,CAAA;;oBACzD,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;gBACtB,SAAQ;YACV,CAAC;YAED,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9D,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAEhE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,IAAI,CAAC,mBAAmB,CAAC,CAAA;qBAClD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;oBAAE,IAAI,CAAC,yBAAyB,CAAC,CAAA;qBAC7F,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,GAAG,QAAQ,CAAC,OAAO;oBAAE,IAAI,CAAC,YAAY,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;qBACrG,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,GAAG,QAAQ,CAAC,OAAO;oBAAE,IAAI,CAAC,WAAW,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;;oBACpG,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA;gBACvB,SAAQ;YACV,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;YAE5B,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,IAAI,CAAC,UAAU,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;iBAC3F,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS;gBAAE,IAAI,CAAC,YAAY,QAAQ,CAAC,SAAS,aAAa,CAAC,CAAA;iBAC7H,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS;gBAAE,IAAI,CAAC,WAAW,QAAQ,CAAC,SAAS,aAAa,CAAC,CAAA;;gBAC5H,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA;QACzB,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAA;IACxD,CAAC,CAAA;IAED,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC,WAAW,CAC5B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3G,IAAI;YACJ,EAAE,GAAG,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;SACxE,CAAC,CACH;KACF,CAAA;IAED,OAAO;QACL,WAAW,EAAE;YACX,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,uBAAuB;YAC/B,QAAQ;YACR,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE;SACtD;KACuB,CAAA;AAC5B,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,YAA0B,EAAE,KAA4B;IAClF,OAAO,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACvD,cAAc,EAA2B,CAAC;QACxC,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,EAAE,SAAS,CAAC,GAAG;QAClB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,MAAM,EAAE,YAAY,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC;QACzD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACb,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAEpH,IAAI,MAAM,CAAC,KAAK;gBAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC3C,IAAI,MAAM,CAAC,QAAQ;gBAAE,KAAK,CAAC,QAAQ,EAAE,CAAA;YACrC,IAAI,MAAM,CAAC,UAAU;gBAAE,KAAK,CAAC,UAAU,EAAE,CAAA;YAEzC,OAAO,KAAK,CAAA;QACd,CAAC,CAAC;QACJ,IAAI,EAAE,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC;QACpC,MAAM,EAAE,MAAM,CAAC,WAAW,CACxB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE;YACrE,MAAM,QAAQ,GAAG;gBACf,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtE,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9D,CAAA;YAED,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACnE,CAAC,CAAC,CACH;QACD,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,WAAW,EAAE,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1D,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,EAAE,KAAK,EAAE,IAA+B,EAAE,OAAsB,EAAE,EAAE;gBACrE,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,YAAY,EACZ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EACvH,OAAO,EACP,KAAK,CACN,CAAA;gBAED,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YAC1G,CAAC;SACF,CAAC,CAAC;KACJ,CAAC,CACH,CAAA;AACH,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,WAAW,CAAC,YAA0B,EAAE,MAAoB;IAC1E,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAA;AACzE,CAAC","sourcesContent":["/**\n * Plugins installed while the panel runs, with no rebuild: a manifest that\n * says what the plugin adds, and an endpoint of its own that answers for it.\n *\n * Nothing a plugin wrote runs here. Its resources are drawn by the panel's\n * own components from data, its rows arrive as JSON and are shown as text,\n * and every call to it is signed with a secret made at install and scoped to\n * the tenant that installed it. What it may see of the app's own records is\n * what its scopes say, granted by a person who read them on the review page:\n *\n * read:products told when a product changes, and which product one of\n * its own records points to\n *\n * A build-time plugin (definePlugin) is code, trusted like the app's own.\n * This is the other kind: installed by a person, trusted with what they\n * granted and nothing more. design/installable-admin-plugins.md has the\n * reasoning and what is left out.\n */\nimport { ActionValidationError } from '@rsc-kit/core/action'\nimport type { RecordChange } from './plugin.js'\nimport { defineResource } from './resource.js'\nimport type { DataSource, Format, FormSchema, ListQuery, Resource, SourceContext, Tenant } from './resource.js'\nimport { newSecret, signedHeaders } from './signing.js'\n\n/** A plugin, as it describes itself at its manifest url. */\nexport interface PluginManifest {\n /** Lowercase letters, digits and dashes; unique within a tenant. */\n name: string\n label: string\n description?: string\n version?: string\n /** Where the panel POSTs every call. Same origin as the manifest. */\n endpoint: string\n /** What it may see of the app's own resources: read:<resource>. */\n scopes: string[]\n resources: ManifestResource[]\n /** Resources whose changes it is told about: its own, or ones it may read. */\n events?: string[]\n}\n\nexport type ManifestFormat = Exclude<Format, 'relation'>\n\nexport interface ManifestColumn {\n key: string\n label?: string\n format?: ManifestFormat\n /** Shown by that resource's title: one of the plugin's own, or one it may read. */\n relation?: string\n sortable?: boolean\n searchable?: boolean\n}\n\n/** The JSON Schema a manifest's form is written in: flat, one level, scalar fields. */\nexport interface ManifestProperty {\n type: 'string' | 'number' | 'integer' | 'boolean'\n format?: 'email' | 'date' | 'date-time' | 'textarea'\n enum?: string[]\n minLength?: number\n maxLength?: number\n minimum?: number\n maximum?: number\n /** For the browser's pattern attribute only: the plugin checks it, not the panel. */\n pattern?: string\n title?: string\n description?: string\n /** A belongsTo, drawn as a select of that resource's rows. */\n relation?: string\n}\n\nexport interface ManifestResource {\n name: string\n label?: string\n singular?: string\n key: string\n title: string\n description?: string\n columns: ManifestColumn[]\n form: { type: 'object'; properties: Record<string, ManifestProperty>; required?: string[] }\n filters?: string[]\n perPage?: number\n mode?: 'server' | 'client'\n readOnly?: boolean\n bulkActions?: { name: string; label: string; done?: string; destructive?: boolean }[]\n}\n\n/** One plugin installed for one tenant. The secret signs every call to it. */\nexport interface Installation {\n /** Random; the plugin finds this installation's secret by it. */\n id: string\n manifestUrl: string\n manifest: PluginManifest\n secret: string\n /** Until someone confirms they copied the secret into the plugin, the plugins page shows it. */\n secretSeen: boolean\n installedAt: string\n}\n\n/**\n * Where installations are kept: the app's database, in a real app. Each call\n * names the tenant, and a store answers for that tenant alone - one team's\n * installs never reach another's panel. Keep `secret` encrypted at rest.\n */\nexport interface Installations {\n list(tenant: Tenant | null): Promise<Installation[]>\n add(tenant: Tenant | null, installation: Installation): Promise<void>\n remove(tenant: Tenant | null, id: string): Promise<void>\n /** The secret was copied into the plugin; stop showing it. */\n seen(tenant: Tenant | null, id: string): Promise<void>\n}\n\nexport interface Installs {\n store: Installations\n /**\n * Whether the panel may call this url: a manifest's, and so its endpoint's.\n * By default https to a public host name - not localhost, not an address.\n * The panel's server makes the request, so a url that reaches your own\n * network is the thing to refuse; allow what your plugins are, and in\n * development, localhost.\n */\n allow?: (url: URL) => boolean\n /** Who may install and uninstall. The panel's authorize by default; an owner, usually. */\n manage?: () => boolean | Promise<boolean>\n}\n\n/** Keyed by the tenant; on globalThis because a dev server can evaluate this module twice. */\nconst MEMORY = Symbol.for('@rsc-kit/press.installations')\n\n/** Installations in memory: for a demo, a test, a single process. Gone on restart. */\nexport function memoryInstallations(name = 'default'): Installations {\n const all = ((globalThis as Record<symbol, unknown>)[MEMORY] ??= new Map()) as Map<string, Map<string, Installation[]>>\n const kept = all.get(name) ?? new Map<string, Installation[]>()\n\n all.set(name, kept)\n\n const of = (tenant: Tenant | null) => tenant?.id ?? ''\n\n return {\n list: async (tenant) => [...(kept.get(of(tenant)) ?? [])],\n add: async (tenant, installation) => void kept.set(of(tenant), [...(kept.get(of(tenant)) ?? []), installation]),\n remove: async (tenant, id) => void kept.set(of(tenant), (kept.get(of(tenant)) ?? []).filter((candidate) => candidate.id !== id)),\n seen: async (tenant, id) =>\n void kept.set(\n of(tenant),\n (kept.get(of(tenant)) ?? []).map((candidate) => (candidate.id === id ? { ...candidate, secretSeen: true } : candidate)),\n ),\n }\n}\n\n// ---------------------------------------------------------------- the manifest\n\nconst NAME = /^[a-z0-9][a-z0-9-]{0,39}$/\nconst KEY = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/\nconst FORMATS: ManifestFormat[] = ['text', 'money', 'badge', 'boolean', 'date']\n/** The panel's own url segments under its path, which no resource may take. */\nexport const RESERVED = ['plugins', 'new']\n\nconst isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\n\nfunction text(value: unknown, max: number): value is string {\n return typeof value === 'string' && value.trim() !== '' && value.length <= max\n}\n\n/** Keys a manifest object may have. One it does not know is refused: a newer field read as nothing could be a permission ignored. */\nfunction only(where: string, value: Record<string, unknown>, keys: string[], problems: string[]) {\n for (const key of Object.keys(value)) if (!keys.includes(key)) problems.push(`${where}: unknown field ${JSON.stringify(key)}`)\n}\n\n/**\n * Every problem with a manifest, or none. Checked when it is reviewed, when it\n * is installed, and on every request after - the app's resources can change\n * under an installed plugin, and one that no longer fits is left out.\n */\nexport function manifestProblems(manifest: unknown, manifestUrl: string, host: string[]): string[] {\n const problems: string[] = []\n\n if (!isObject(manifest)) return ['the manifest is not a JSON object']\n\n only('manifest', manifest, ['name', 'label', 'description', 'version', 'endpoint', 'scopes', 'resources', 'events'], problems)\n\n if (typeof manifest.name !== 'string' || !NAME.test(manifest.name)) problems.push('name: lowercase letters, digits and dashes, at most 40')\n if (!text(manifest.label, 60)) problems.push('label: required, at most 60 characters')\n if (manifest.description !== undefined && !text(manifest.description, 300)) problems.push('description: at most 300 characters')\n if (manifest.version !== undefined && !text(manifest.version, 30)) problems.push('version: at most 30 characters')\n\n try {\n const endpoint = new URL(String(manifest.endpoint), manifestUrl)\n\n if (endpoint.origin !== new URL(manifestUrl).origin) problems.push('endpoint: must be on the same origin as the manifest')\n } catch {\n problems.push('endpoint: not a url')\n }\n\n const scopes = Array.isArray(manifest.scopes) ? manifest.scopes : null\n const readable: string[] = []\n\n if (!scopes) problems.push('scopes: a list, empty if it reads nothing of yours')\n else {\n for (const scope of scopes) {\n const match = typeof scope === 'string' ? /^read:([a-z0-9][a-z0-9-]*)$/.exec(scope) : null\n\n if (!match) problems.push(`scopes: ${JSON.stringify(scope)} is not read:<resource>`)\n else if (!host.includes(match[1]!)) problems.push(`scopes: ${scope} names a resource this panel does not have`)\n else readable.push(match[1]!)\n }\n }\n\n const resources = Array.isArray(manifest.resources) ? manifest.resources : null\n\n if (!resources || resources.length === 0 || resources.length > 20) {\n problems.push('resources: a list of 1 to 20')\n\n return problems\n }\n\n const own = resources.flatMap((resource) => (isObject(resource) && typeof resource.name === 'string' ? [resource.name] : []))\n const reachable = (name: string) => own.includes(name) || readable.includes(name)\n\n for (const [index, resource] of resources.entries()) {\n const where = `resources[${index}]`\n\n if (!isObject(resource)) {\n problems.push(`${where}: not an object`)\n continue\n }\n\n only(\n where,\n resource,\n ['name', 'label', 'singular', 'key', 'title', 'description', 'columns', 'form', 'filters', 'perPage', 'mode', 'readOnly', 'bulkActions'],\n problems,\n )\n\n const name = typeof resource.name === 'string' && NAME.test(resource.name) ? resource.name : null\n\n if (!name) problems.push(`${where}.name: lowercase letters, digits and dashes`)\n else if (RESERVED.includes(name)) problems.push(`${where}.name: ${name} is the panel's own`)\n else if (host.includes(name)) problems.push(`${where}.name: this panel already has a resource named ${name}`)\n else if (own.indexOf(name) !== index) problems.push(`${where}.name: two resources are named ${name}`)\n\n for (const key of ['label', 'singular', 'description'] as const) {\n if (resource[key] !== undefined && !text(resource[key], key === 'description' ? 300 : 60)) problems.push(`${where}.${key}: too long, or empty`)\n }\n\n const form = resource.form\n const properties = isObject(form) && form.type === 'object' && isObject(form.properties) ? form.properties : null\n\n if (!properties || Object.keys(properties).length === 0 || Object.keys(properties).length > 50) {\n problems.push(`${where}.form: a JSON Schema object with 1 to 50 properties`)\n continue\n }\n\n only(`${where}.form`, form as Record<string, unknown>, ['type', 'properties', 'required'], problems)\n\n const fieldNames = Object.keys(properties)\n\n if (form && (form as { required?: unknown }).required !== undefined) {\n const required = (form as { required?: unknown }).required\n\n if (!Array.isArray(required) || required.some((field) => !fieldNames.includes(field as string))) {\n problems.push(`${where}.form.required: names that are properties`)\n }\n }\n\n for (const [field, property] of Object.entries(properties)) {\n const at = `${where}.form.properties.${field}`\n\n if (!KEY.test(field)) problems.push(`${at}: not a field name`)\n if (!isObject(property)) {\n problems.push(`${at}: not an object`)\n continue\n }\n\n only(at, property, ['type', 'format', 'enum', 'minLength', 'maxLength', 'minimum', 'maximum', 'pattern', 'title', 'description', 'relation'], problems)\n\n if (!['string', 'number', 'integer', 'boolean'].includes(property.type as string)) problems.push(`${at}.type: string, number, integer or boolean`)\n if (property.format !== undefined && !['email', 'date', 'date-time', 'textarea'].includes(property.format as string)) {\n problems.push(`${at}.format: email, date, date-time or textarea`)\n }\n if (property.enum !== undefined && (!Array.isArray(property.enum) || property.enum.length === 0 || property.enum.some((option) => !text(option, 60)))) {\n problems.push(`${at}.enum: a list of strings`)\n }\n for (const bound of ['minLength', 'maxLength', 'minimum', 'maximum'] as const) {\n if (property[bound] !== undefined && typeof property[bound] !== 'number') problems.push(`${at}.${bound}: a number`)\n }\n // Only the browser runs it - a pattern run on the server is a regular\n // expression a stranger wrote, and one can be made to take minutes.\n if (property.pattern !== undefined && !text(property.pattern, 200)) problems.push(`${at}.pattern: at most 200 characters`)\n if (property.relation !== undefined && !(typeof property.relation === 'string' && reachable(property.relation))) {\n problems.push(`${at}.relation: ${String(property.relation)} is neither its own resource nor one its scopes read`)\n }\n }\n\n const fieldOf = (key: unknown) => typeof key === 'string' && (fieldNames.includes(key) || key === resource.key)\n\n if (typeof resource.key !== 'string' || !KEY.test(resource.key)) problems.push(`${where}.key: a field name`)\n if (!fieldOf(resource.title)) problems.push(`${where}.title: one of the form's fields, or the key`)\n\n const columns = Array.isArray(resource.columns) ? resource.columns : null\n\n if (!columns || columns.length === 0 || columns.length > 30) problems.push(`${where}.columns: a list of 1 to 30`)\n else {\n for (const [at, column] of columns.entries()) {\n const where2 = `${where}.columns[${at}]`\n\n if (!isObject(column)) {\n problems.push(`${where2}: not an object`)\n continue\n }\n\n only(where2, column, ['key', 'label', 'format', 'relation', 'sortable', 'searchable'], problems)\n\n if (typeof column.key !== 'string' || !KEY.test(column.key)) problems.push(`${where2}.key: a field name`)\n if (column.label !== undefined && !text(column.label, 60)) problems.push(`${where2}.label: at most 60 characters`)\n if (column.format !== undefined && !FORMATS.includes(column.format as ManifestFormat)) problems.push(`${where2}.format: ${FORMATS.join(', ')}`)\n if (column.relation !== undefined && !(typeof column.relation === 'string' && reachable(column.relation))) {\n problems.push(`${where2}.relation: ${String(column.relation)} is neither its own resource nor one its scopes read`)\n }\n }\n }\n\n if (resource.filters !== undefined) {\n const filters = Array.isArray(resource.filters) ? resource.filters : []\n\n for (const filter of filters) {\n if (typeof filter !== 'string' || !(properties[filter] as ManifestProperty | undefined)?.enum) problems.push(`${where}.filters: ${String(filter)} is not an enum field`)\n }\n }\n\n if (resource.perPage !== undefined && !(Number.isInteger(resource.perPage) && (resource.perPage as number) >= 1 && (resource.perPage as number) <= 100)) {\n problems.push(`${where}.perPage: 1 to 100`)\n }\n if (resource.mode !== undefined && resource.mode !== 'server' && resource.mode !== 'client') problems.push(`${where}.mode: server or client`)\n if (resource.readOnly !== undefined && typeof resource.readOnly !== 'boolean') problems.push(`${where}.readOnly: true or false`)\n\n if (resource.bulkActions !== undefined) {\n const actions = Array.isArray(resource.bulkActions) ? resource.bulkActions : null\n\n if (!actions || actions.length > 10) problems.push(`${where}.bulkActions: a list of at most 10`)\n else if (resource.readOnly === true && actions.length > 0) problems.push(`${where}.bulkActions: a read-only resource has none`)\n else {\n for (const action of actions) {\n if (!isObject(action) || typeof action.name !== 'string' || !NAME.test(action.name) || action.name === 'delete' || !text(action.label, 40)) {\n problems.push(`${where}.bulkActions: each needs a name (not delete) and a label`)\n }\n }\n }\n }\n }\n\n if (manifest.events !== undefined) {\n const events = Array.isArray(manifest.events) ? manifest.events : null\n\n if (!events) problems.push('events: a list of resource names')\n else {\n for (const event of events) {\n if (typeof event !== 'string' || !reachable(event)) problems.push(`events: ${String(event)} is neither its own resource nor one its scopes read`)\n }\n }\n }\n\n return problems\n}\n\n/** The scopes, as the person installing reads them. */\nexport function scopeWords(manifest: PluginManifest, labelOf: (resource: string) => string): string[] {\n return manifest.scopes.map((scope) => {\n const resource = labelOf(scope.slice('read:'.length)).toLowerCase()\n\n return `See your ${resource}: be told when one changes, and which one its own records point to.`\n })\n}\n\n// ---------------------------------------------------------- reaching a plugin\n\n/** Https to a name: not localhost, and not an address, which is how a private network is reached by url. */\nexport function publicHttps(url: URL): boolean {\n if (url.protocol !== 'https:') return false\n\n const host = url.hostname.replace(/^\\[|\\]$/g, '')\n\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local') || host.endsWith('.internal')) return false\n if (/^[\\d.]+$/.test(host) || host.includes(':')) return false\n\n return true\n}\n\nconst MANIFEST_BYTES = 256 * 1024\nconst ANSWER_BYTES = 5 * 1024 * 1024\n\n/** A response's body, up to a limit: a plugin that answers with gigabytes is a plugin that is wrong. */\nasync function bounded(response: Response, limit: number): Promise<string> {\n const declared = Number(response.headers.get('content-length') ?? 0)\n\n if (declared > limit) throw new Error(`[admin] the answer is ${declared} bytes, over ${limit}`)\n\n const body = await response.text()\n\n if (body.length > limit) throw new Error(`[admin] the answer is over ${limit} bytes`)\n\n return body\n}\n\n/** A manifest, fetched and checked. Redirects are refused: a url allowed once must not lead somewhere that was not. */\nexport async function fetchManifest(manifestUrl: string, allow: (url: URL) => boolean, host: string[]): Promise<PluginManifest> {\n let url: URL\n\n try {\n url = new URL(manifestUrl)\n } catch {\n throw new Error('That is not a url.')\n }\n\n if (!allow(url)) throw new Error('This panel does not install plugins from that address.')\n\n const response = await fetch(url, { headers: { accept: 'application/json' }, redirect: 'error', signal: AbortSignal.timeout(5000) }).catch(() => null)\n\n if (!response?.ok) throw new Error(`The manifest could not be fetched${response ? ` (${response.status})` : ''}.`)\n\n let manifest: unknown\n\n try {\n manifest = JSON.parse(await bounded(response, MANIFEST_BYTES))\n } catch {\n throw new Error('The manifest is not JSON.')\n }\n\n const problems = manifestProblems(manifest, url.href, host)\n\n if (problems.length > 0) throw new Error(`The manifest has problems: ${problems.join('; ')}.`)\n\n const checked = manifest as PluginManifest\n\n return { ...checked, endpoint: new URL(checked.endpoint, url).href }\n}\n\n/** A stable digest of a manifest: what was reviewed is what is installed, or the install is refused. */\nexport async function digestOf(manifest: PluginManifest): Promise<string> {\n const bytes = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(JSON.stringify(manifest))))\n\n return [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nexport function newInstallation(manifestUrl: string, manifest: PluginManifest): Installation {\n return { id: crypto.randomUUID(), manifestUrl, manifest, secret: newSecret(), secretSeen: false, installedAt: new Date().toISOString() }\n}\n\n/** What a plugin's endpoint is sent. `tenant` is the installation's, never one the browser named. */\nexport type PluginCall =\n | { type: 'list'; resource: string; query: ListQuery }\n | { type: 'find'; resource: string; id: string }\n | { type: 'create'; resource: string; values: Record<string, unknown> }\n | { type: 'update'; resource: string; id: string; values: Record<string, unknown> }\n | { type: 'delete'; resource: string; id: string }\n | { type: 'bulk'; resource: string; action: string; ids: string[] }\n | { type: 'change'; change: RecordChange }\n\nexport type PluginRequest = PluginCall & { tenant: Tenant | null }\n\n/**\n * One signed call. A 404 is null; a 422 with `{ errors: { field: [message] } }`\n * is the form's field errors, exactly as Laravel's are; anything else that is\n * not a 2xx is a failure with the plugin's name on it.\n */\nexport async function callPlugin(\n installation: Installation,\n call: PluginCall,\n context: SourceContext,\n allow: (url: URL) => boolean,\n timeout = 10_000,\n): Promise<unknown> {\n const endpoint = new URL(installation.manifest.endpoint)\n const name = installation.manifest.name\n\n // Checked again on every call: the rule can tighten after the install.\n if (!allow(endpoint)) throw new Error(`[admin] the plugin ${name}'s endpoint is no longer allowed`)\n\n const body = JSON.stringify({ ...call, tenant: context.tenant ? { id: context.tenant.id, name: context.tenant.name } : null })\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json', ...(await signedHeaders(installation.id, installation.secret, body)) },\n body,\n redirect: 'error',\n signal: AbortSignal.timeout(timeout),\n })\n\n if (response.status === 404) return null\n\n const answer = await bounded(response, ANSWER_BYTES)\n let json: unknown = null\n\n try {\n json = answer === '' ? null : JSON.parse(answer)\n } catch {\n throw new Error(`[admin] the plugin ${name} answered ${response.status} with something that is not JSON`)\n }\n\n if (response.status === 422 && isObject(json) && isObject(json.errors)) {\n const errors = Object.fromEntries(\n Object.entries(json.errors).map(([field, messages]) => [field, ([] as unknown[]).concat(messages).map(String).slice(0, 5)]),\n )\n\n throw new ActionValidationError(errors)\n }\n\n if (!response.ok) throw new Error(`[admin] the plugin ${name} answered ${response.status}`)\n\n return json\n}\n\nconst row = (value: unknown, plugin: string): Record<string, unknown> => {\n if (!isObject(value)) throw new Error(`[admin] the plugin ${plugin} answered a row that is not an object`)\n\n return value\n}\n\n/** A resource's five calls, made to the plugin. */\nfunction remoteSource(installation: Installation, resource: string, allow: (url: URL) => boolean): DataSource<Record<string, unknown>, Record<string, unknown>> {\n const plugin = installation.manifest.name\n const call = (body: PluginCall, context: SourceContext) => callPlugin(installation, body, context, allow)\n\n return {\n async list(query, context) {\n const answer = await call({ type: 'list', resource, query }, context)\n\n if (!isObject(answer) || !Array.isArray(answer.rows) || typeof answer.total !== 'number') {\n throw new Error(`[admin] the plugin ${plugin} answered a list without { rows, total }`)\n }\n\n return { rows: answer.rows.map((value) => row(value, plugin)), total: answer.total }\n },\n async find(id, context) {\n const answer = await call({ type: 'find', resource, id }, context)\n\n return isObject(answer) && answer.row !== undefined && answer.row !== null ? row(answer.row, plugin) : null\n },\n async create(values, context) {\n return row((await call({ type: 'create', resource, values }, context)) as { row?: unknown } | null, plugin).row as Record<string, unknown>\n },\n async update(id, values, context) {\n return row((await call({ type: 'update', resource, id, values }, context)) as { row?: unknown } | null, plugin).row as Record<string, unknown>\n },\n async delete(id, context) {\n await call({ type: 'delete', resource, id }, context)\n },\n }\n}\n\n// ------------------------------------------------------------------ the form\n\n/**\n * A Standard Schema from the manifest's JSON Schema, so a plugin's form goes\n * through the same parse as any other. It checks what is cheap and safe to\n * check here - types, required, enums, lengths, bounds - and never `pattern`;\n * the plugin's endpoint checks everything again and answers 422.\n */\nexport function jsonSchemaForm(form: ManifestResource['form']): FormSchema {\n const required = new Set(form.required ?? [])\n\n const validate = (value: unknown): { value: Record<string, unknown> } | { issues: { message: string; path: string[] }[] } => {\n if (!isObject(value)) return { issues: [{ message: 'Expected an object', path: [] }] }\n\n const out: Record<string, unknown> = {}\n const issues: { message: string; path: string[] }[] = []\n\n for (const [name, property] of Object.entries(form.properties)) {\n const given = value[name]\n const fail = (message: string) => issues.push({ message, path: [name] })\n\n if (given === undefined || given === null || given === '') {\n if (required.has(name) && property.type !== 'boolean') fail('Required')\n continue\n }\n\n if (property.type === 'boolean') {\n if (typeof given !== 'boolean') fail('Expected true or false')\n else out[name] = given\n continue\n }\n\n if (property.type === 'number' || property.type === 'integer') {\n const number = typeof given === 'number' ? given : Number(given)\n\n if (!Number.isFinite(number)) fail('Expected a number')\n else if (property.type === 'integer' && !Number.isInteger(number)) fail('Expected a whole number')\n else if (property.minimum !== undefined && number < property.minimum) fail(`At least ${property.minimum}`)\n else if (property.maximum !== undefined && number > property.maximum) fail(`At most ${property.maximum}`)\n else out[name] = number\n continue\n }\n\n const string = String(given)\n\n if (property.enum && !property.enum.includes(string)) fail(`One of ${property.enum.join(', ')}`)\n else if (property.minLength !== undefined && string.length < property.minLength) fail(`At least ${property.minLength} characters`)\n else if (property.maxLength !== undefined && string.length > property.maxLength) fail(`At most ${property.maxLength} characters`)\n else out[name] = string\n }\n\n return issues.length > 0 ? { issues } : { value: out }\n }\n\n const json = {\n type: 'object',\n required: form.required ?? [],\n properties: Object.fromEntries(\n Object.entries(form.properties).map(([name, { relation: _relation, title: _title, format, ...property }]) => [\n name,\n { ...property, ...(format && format !== 'textarea' ? { format } : {}) },\n ]),\n ),\n }\n\n return {\n '~standard': {\n version: 1,\n vendor: '@rsc-kit/press/plugin',\n validate,\n jsonSchema: { input: () => json, output: () => json },\n },\n } as unknown as FormSchema\n}\n\n/** An installation's resources, as the panel's own. */\nexport function resourcesOf(installation: Installation, allow: (url: URL) => boolean): Resource[] {\n return installation.manifest.resources.map((described) =>\n defineResource<Record<string, unknown>>()({\n name: described.name,\n ...(described.label ? { label: described.label } : {}),\n ...(described.singular ? { singular: described.singular } : {}),\n key: described.key,\n title: described.title,\n source: remoteSource(installation, described.name, allow),\n table: (col) =>\n described.columns.map((column) => {\n const built = column.relation ? col.relation(column.key, column.relation) : col[column.format ?? 'text'](column.key)\n\n if (column.label) built.label(column.label)\n if (column.sortable) built.sortable()\n if (column.searchable) built.searchable()\n\n return built\n }),\n form: jsonSchemaForm(described.form),\n fields: Object.fromEntries(\n Object.entries(described.form.properties).flatMap(([name, property]) => {\n const override = {\n ...(property.title ? { label: property.title } : {}),\n ...(property.description ? { description: property.description } : {}),\n ...(property.format === 'textarea' ? { type: 'textarea' as const } : {}),\n ...(property.relation ? { relation: property.relation } : {}),\n }\n\n return Object.keys(override).length > 0 ? [[name, override]] : []\n }),\n ),\n ...(described.filters ? { filters: described.filters } : {}),\n ...(described.perPage ? { perPage: described.perPage } : {}),\n ...(described.mode ? { mode: described.mode } : {}),\n ...(described.readOnly ? { readOnly: true } : {}),\n ...(described.description ? { description: described.description } : {}),\n bulkActions: (described.bulkActions ?? []).map((action) => ({\n name: action.name,\n label: action.label,\n ...(action.done ? { done: action.done } : {}),\n ...(action.destructive ? { destructive: true } : {}),\n run: async (rows: Record<string, unknown>[], context: SourceContext) => {\n const answer = await callPlugin(\n installation,\n { type: 'bulk', resource: described.name, action: action.name, ids: rows.map((found) => String(found[described.key])) },\n context,\n allow,\n )\n\n return isObject(answer) && typeof answer.message === 'string' ? answer.message.slice(0, 200) : undefined\n },\n })),\n }),\n )\n}\n\n/** Whether a plugin is told about a change: one of its events, which its scopes or ownership allow. */\nexport function wantsChange(installation: Installation, change: RecordChange): boolean {\n return installation.manifest.events?.includes(change.resource) ?? false\n}\n"]}
1
+ {"version":3,"file":"installable.js","sourceRoot":"","sources":["../src/installable.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plugins installed while the panel runs, with no rebuild: a manifest that\n * says what the plugin adds, and an endpoint of its own that answers for it.\n *\n * Nothing a plugin wrote runs here. Its resources are drawn by the panel's\n * own components from data, its rows arrive as JSON and are shown as text,\n * and every call to it is signed with a secret made at install and scoped to\n * the tenant that installed it. What it may see of the app's own records is\n * what its scopes say, granted by a person who read them on the review page:\n *\n * read:products told when a product changes, and which product one of\n * its own records points to\n *\n * A build-time plugin (definePlugin) is code, trusted like the app's own.\n * This is the other kind: installed by a person, trusted with what they\n * granted and nothing more. design/installable-admin-plugins.md has the\n * reasoning and what is left out.\n */\nimport { ActionValidationError } from '@rsc-kit/core/action'\nimport type { RecordChange } from './plugin.js'\nimport { defineResource } from './resource.js'\nimport type { DataSource, Format, FormSchema, ListQuery, Resource, SourceContext, Tenant } from './resource.js'\nimport { newSecret, signedHeaders } from './signing.js'\n\n/** A plugin, as it describes itself at its manifest url. */\nexport interface PluginManifest {\n /** Lowercase letters, digits and dashes; unique within a tenant. */\n name: string\n label: string\n description?: string\n version?: string\n /** Where the panel POSTs every call. Same origin as the manifest. */\n endpoint: string\n /** What it may see of the app's own resources: read:<resource>. */\n scopes: string[]\n resources: ManifestResource[]\n /** Resources whose changes it is told about: its own, or ones it may read. */\n events?: string[]\n}\n\nexport type ManifestFormat = Exclude<Format, 'relation'>\n\nexport interface ManifestColumn {\n key: string\n label?: string\n format?: ManifestFormat\n /** Shown by that resource's title: one of the plugin's own, or one it may read. */\n relation?: string\n sortable?: boolean\n searchable?: boolean\n}\n\n/** The JSON Schema a manifest's form is written in: flat, one level, scalar fields. */\nexport interface ManifestProperty {\n type: 'string' | 'number' | 'integer' | 'boolean'\n format?: 'email' | 'date' | 'date-time' | 'textarea'\n enum?: string[]\n minLength?: number\n maxLength?: number\n minimum?: number\n maximum?: number\n /** For the browser's pattern attribute only: the plugin checks it, not the panel. */\n pattern?: string\n title?: string\n description?: string\n /** A belongsTo, drawn as a select of that resource's rows. */\n relation?: string\n}\n\nexport interface ManifestResource {\n name: string\n label?: string\n singular?: string\n key: string\n title: string\n description?: string\n columns: ManifestColumn[]\n form: { type: 'object'; properties: Record<string, ManifestProperty>; required?: string[] }\n filters?: string[]\n perPage?: number\n mode?: 'server' | 'client'\n readOnly?: boolean\n bulkActions?: { name: string; label: string; done?: string; destructive?: boolean }[]\n}\n\n/** One plugin installed for one tenant. The secret signs every call to it. */\nexport interface Installation {\n /** Random; the plugin finds this installation's secret by it. */\n id: string\n manifestUrl: string\n manifest: PluginManifest\n secret: string\n /** Until someone confirms they copied the secret into the plugin, the plugins page shows it. */\n secretSeen: boolean\n installedAt: string\n}\n\n/**\n * Where installations are kept: the app's database, in a real app. Each call\n * names the tenant, and a store answers for that tenant alone - one team's\n * installs never reach another's panel. Keep `secret` encrypted at rest.\n */\nexport interface Installations {\n list(tenant: Tenant | null): Promise<Installation[]>\n add(tenant: Tenant | null, installation: Installation): Promise<void>\n remove(tenant: Tenant | null, id: string): Promise<void>\n /** The secret was copied into the plugin; stop showing it. */\n seen(tenant: Tenant | null, id: string): Promise<void>\n}\n\nexport interface Installs {\n store: Installations\n /**\n * Whether the panel may call this url: a manifest's, and so its endpoint's.\n * By default https to a public host name - not localhost, not an address.\n * The panel's server makes the request, so a url that reaches your own\n * network is the thing to refuse; allow what your plugins are, and in\n * development, localhost.\n */\n allow?: (url: URL) => boolean\n /** Who may install and uninstall. The panel's authorize by default; an owner, usually. */\n manage?: () => boolean | Promise<boolean>\n}\n\n/** Keyed by the tenant; on globalThis because a dev server can evaluate this module twice. */\nconst MEMORY = Symbol.for('@rsc-kit/press.installations')\n\n/** Installations in memory: for a demo, a test, a single process. Gone on restart. */\nexport function memoryInstallations(name = 'default'): Installations {\n const all = ((globalThis as Record<symbol, unknown>)[MEMORY] ??= new Map()) as Map<string, Map<string, Installation[]>>\n const kept = all.get(name) ?? new Map<string, Installation[]>()\n\n all.set(name, kept)\n\n const of = (tenant: Tenant | null) => tenant?.id ?? ''\n\n return {\n list: async (tenant) => [...(kept.get(of(tenant)) ?? [])],\n add: async (tenant, installation) => void kept.set(of(tenant), [...(kept.get(of(tenant)) ?? []), installation]),\n remove: async (tenant, id) => void kept.set(of(tenant), (kept.get(of(tenant)) ?? []).filter((candidate) => candidate.id !== id)),\n seen: async (tenant, id) =>\n void kept.set(\n of(tenant),\n (kept.get(of(tenant)) ?? []).map((candidate) => (candidate.id === id ? { ...candidate, secretSeen: true } : candidate)),\n ),\n }\n}\n\n// ---------------------------------------------------------------- the manifest\n\nconst NAME = /^[a-z0-9][a-z0-9-]{0,39}$/\nconst KEY = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/\nconst FORMATS: ManifestFormat[] = ['text', 'money', 'badge', 'boolean', 'date']\n/** The panel's own url segments under its path, which no resource may take. */\nexport const RESERVED = ['plugins', 'new']\n\nconst isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\n\nfunction text(value: unknown, max: number): value is string {\n return typeof value === 'string' && value.trim() !== '' && value.length <= max\n}\n\n/** Keys a manifest object may have. One it does not know is refused: a newer field read as nothing could be a permission ignored. */\nfunction only(where: string, value: Record<string, unknown>, keys: string[], problems: string[]) {\n for (const key of Object.keys(value)) if (!keys.includes(key)) problems.push(`${where}: unknown field ${JSON.stringify(key)}`)\n}\n\n/**\n * Every problem with a manifest, or none. Checked when it is reviewed, when it\n * is installed, and on every request after - the app's resources can change\n * under an installed plugin, and one that no longer fits is left out.\n */\nexport function manifestProblems(manifest: unknown, manifestUrl: string, host: string[]): string[] {\n const problems: string[] = []\n\n if (!isObject(manifest)) return ['the manifest is not a JSON object']\n\n only('manifest', manifest, ['name', 'label', 'description', 'version', 'endpoint', 'scopes', 'resources', 'events'], problems)\n\n if (typeof manifest.name !== 'string' || !NAME.test(manifest.name)) problems.push('name: lowercase letters, digits and dashes, at most 40')\n if (!text(manifest.label, 60)) problems.push('label: required, at most 60 characters')\n if (manifest.description !== undefined && !text(manifest.description, 300)) problems.push('description: at most 300 characters')\n if (manifest.version !== undefined && !text(manifest.version, 30)) problems.push('version: at most 30 characters')\n\n try {\n const endpoint = new URL(String(manifest.endpoint), manifestUrl)\n\n if (endpoint.origin !== new URL(manifestUrl).origin) problems.push('endpoint: must be on the same origin as the manifest')\n } catch {\n problems.push('endpoint: not a url')\n }\n\n const scopes = Array.isArray(manifest.scopes) ? manifest.scopes : null\n const readable: string[] = []\n\n if (!scopes) problems.push('scopes: a list, empty if it reads nothing of yours')\n else {\n for (const scope of scopes) {\n const match = typeof scope === 'string' ? /^read:([a-z0-9][a-z0-9-]*)$/.exec(scope) : null\n\n if (!match) problems.push(`scopes: ${JSON.stringify(scope)} is not read:<resource>`)\n else if (!host.includes(match[1]!)) problems.push(`scopes: ${scope} names a resource this panel does not have`)\n else readable.push(match[1]!)\n }\n }\n\n const resources = Array.isArray(manifest.resources) ? manifest.resources : null\n\n if (!resources || resources.length === 0 || resources.length > 20) {\n problems.push('resources: a list of 1 to 20')\n\n return problems\n }\n\n const own = resources.flatMap((resource) => (isObject(resource) && typeof resource.name === 'string' ? [resource.name] : []))\n const reachable = (name: string) => own.includes(name) || readable.includes(name)\n\n for (const [index, resource] of resources.entries()) {\n const where = `resources[${index}]`\n\n if (!isObject(resource)) {\n problems.push(`${where}: not an object`)\n continue\n }\n\n only(\n where,\n resource,\n ['name', 'label', 'singular', 'key', 'title', 'description', 'columns', 'form', 'filters', 'perPage', 'mode', 'readOnly', 'bulkActions'],\n problems,\n )\n\n const name = typeof resource.name === 'string' && NAME.test(resource.name) ? resource.name : null\n\n if (!name) problems.push(`${where}.name: lowercase letters, digits and dashes`)\n else if (RESERVED.includes(name)) problems.push(`${where}.name: ${name} is the panel's own`)\n else if (host.includes(name)) problems.push(`${where}.name: this panel already has a resource named ${name}`)\n else if (own.indexOf(name) !== index) problems.push(`${where}.name: two resources are named ${name}`)\n\n for (const key of ['label', 'singular', 'description'] as const) {\n if (resource[key] !== undefined && !text(resource[key], key === 'description' ? 300 : 60)) problems.push(`${where}.${key}: too long, or empty`)\n }\n\n const form = resource.form\n const properties = isObject(form) && form.type === 'object' && isObject(form.properties) ? form.properties : null\n\n if (!properties || Object.keys(properties).length === 0 || Object.keys(properties).length > 50) {\n problems.push(`${where}.form: a JSON Schema object with 1 to 50 properties`)\n continue\n }\n\n only(`${where}.form`, form as Record<string, unknown>, ['type', 'properties', 'required'], problems)\n\n const fieldNames = Object.keys(properties)\n\n if (form && (form as { required?: unknown }).required !== undefined) {\n const required = (form as { required?: unknown }).required\n\n if (!Array.isArray(required) || required.some((field) => !fieldNames.includes(field as string))) {\n problems.push(`${where}.form.required: names that are properties`)\n }\n }\n\n for (const [field, property] of Object.entries(properties)) {\n const at = `${where}.form.properties.${field}`\n\n if (!KEY.test(field)) problems.push(`${at}: not a field name`)\n if (!isObject(property)) {\n problems.push(`${at}: not an object`)\n continue\n }\n\n only(at, property, ['type', 'format', 'enum', 'minLength', 'maxLength', 'minimum', 'maximum', 'pattern', 'title', 'description', 'relation'], problems)\n\n if (!['string', 'number', 'integer', 'boolean'].includes(property.type as string)) problems.push(`${at}.type: string, number, integer or boolean`)\n if (property.format !== undefined && !['email', 'date', 'date-time', 'textarea'].includes(property.format as string)) {\n problems.push(`${at}.format: email, date, date-time or textarea`)\n }\n if (property.enum !== undefined && (!Array.isArray(property.enum) || property.enum.length === 0 || property.enum.some((option) => !text(option, 60)))) {\n problems.push(`${at}.enum: a list of strings`)\n }\n for (const bound of ['minLength', 'maxLength', 'minimum', 'maximum'] as const) {\n if (property[bound] !== undefined && typeof property[bound] !== 'number') problems.push(`${at}.${bound}: a number`)\n }\n // Only the browser runs it - a pattern run on the server is a regular\n // expression a stranger wrote, and one can be made to take minutes.\n if (property.pattern !== undefined && !text(property.pattern, 200)) problems.push(`${at}.pattern: at most 200 characters`)\n if (property.relation !== undefined && !(typeof property.relation === 'string' && reachable(property.relation))) {\n problems.push(`${at}.relation: ${String(property.relation)} is neither its own resource nor one its scopes read`)\n }\n }\n\n const fieldOf = (key: unknown) => typeof key === 'string' && (fieldNames.includes(key) || key === resource.key)\n\n if (typeof resource.key !== 'string' || !KEY.test(resource.key)) problems.push(`${where}.key: a field name`)\n if (!fieldOf(resource.title)) problems.push(`${where}.title: one of the form's fields, or the key`)\n\n const columns = Array.isArray(resource.columns) ? resource.columns : null\n\n if (!columns || columns.length === 0 || columns.length > 30) problems.push(`${where}.columns: a list of 1 to 30`)\n else {\n for (const [at, column] of columns.entries()) {\n const where2 = `${where}.columns[${at}]`\n\n if (!isObject(column)) {\n problems.push(`${where2}: not an object`)\n continue\n }\n\n only(where2, column, ['key', 'label', 'format', 'relation', 'sortable', 'searchable'], problems)\n\n if (typeof column.key !== 'string' || !KEY.test(column.key)) problems.push(`${where2}.key: a field name`)\n if (column.label !== undefined && !text(column.label, 60)) problems.push(`${where2}.label: at most 60 characters`)\n if (column.format !== undefined && !FORMATS.includes(column.format as ManifestFormat)) problems.push(`${where2}.format: ${FORMATS.join(', ')}`)\n if (column.relation !== undefined && !(typeof column.relation === 'string' && reachable(column.relation))) {\n problems.push(`${where2}.relation: ${String(column.relation)} is neither its own resource nor one its scopes read`)\n }\n }\n }\n\n if (resource.filters !== undefined) {\n const filters = Array.isArray(resource.filters) ? resource.filters : []\n\n for (const filter of filters) {\n if (typeof filter !== 'string' || !(properties[filter] as ManifestProperty | undefined)?.enum) problems.push(`${where}.filters: ${String(filter)} is not an enum field`)\n }\n }\n\n if (resource.perPage !== undefined && !(Number.isInteger(resource.perPage) && (resource.perPage as number) >= 1 && (resource.perPage as number) <= 100)) {\n problems.push(`${where}.perPage: 1 to 100`)\n }\n if (resource.mode !== undefined && resource.mode !== 'server' && resource.mode !== 'client') problems.push(`${where}.mode: server or client`)\n if (resource.readOnly !== undefined && typeof resource.readOnly !== 'boolean') problems.push(`${where}.readOnly: true or false`)\n\n if (resource.bulkActions !== undefined) {\n const actions = Array.isArray(resource.bulkActions) ? resource.bulkActions : null\n\n if (!actions || actions.length > 10) problems.push(`${where}.bulkActions: a list of at most 10`)\n else if (resource.readOnly === true && actions.length > 0) problems.push(`${where}.bulkActions: a read-only resource has none`)\n else {\n for (const action of actions) {\n if (!isObject(action) || typeof action.name !== 'string' || !NAME.test(action.name) || action.name === 'delete' || !text(action.label, 40)) {\n problems.push(`${where}.bulkActions: each needs a name (not delete) and a label`)\n }\n }\n }\n }\n }\n\n if (manifest.events !== undefined) {\n const events = Array.isArray(manifest.events) ? manifest.events : null\n\n if (!events) problems.push('events: a list of resource names')\n else {\n for (const event of events) {\n if (typeof event !== 'string' || !reachable(event)) problems.push(`events: ${String(event)} is neither its own resource nor one its scopes read`)\n }\n }\n }\n\n return problems\n}\n\n/** The scopes, as the person installing reads them. */\nexport function scopeWords(manifest: PluginManifest, labelOf: (resource: string) => string): string[] {\n return manifest.scopes.map((scope) => {\n const resource = labelOf(scope.slice('read:'.length)).toLowerCase()\n\n return `See your ${resource}: be told when one changes, and which one its own records point to.`\n })\n}\n\n// ---------------------------------------------------------- reaching a plugin\n\n/** Https to a name: not localhost, and not an address, which is how a private network is reached by url. */\nexport function publicHttps(url: URL): boolean {\n if (url.protocol !== 'https:') return false\n\n const host = url.hostname.replace(/^\\[|\\]$/g, '')\n\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local') || host.endsWith('.internal')) return false\n if (/^[\\d.]+$/.test(host) || host.includes(':')) return false\n\n return true\n}\n\nconst MANIFEST_BYTES = 256 * 1024\nconst ANSWER_BYTES = 5 * 1024 * 1024\n\n/** A response's body, up to a limit: a plugin that answers with gigabytes is a plugin that is wrong. */\nasync function bounded(response: Response, limit: number): Promise<string> {\n const declared = Number(response.headers.get('content-length') ?? 0)\n\n if (declared > limit) throw new Error(`[admin] the answer is ${declared} bytes, over ${limit}`)\n\n const body = await response.text()\n\n if (body.length > limit) throw new Error(`[admin] the answer is over ${limit} bytes`)\n\n return body\n}\n\n/** A manifest, fetched and checked. Redirects are refused: a url allowed once must not lead somewhere that was not. */\nexport async function fetchManifest(manifestUrl: string, allow: (url: URL) => boolean, host: string[]): Promise<PluginManifest> {\n let url: URL\n\n try {\n url = new URL(manifestUrl)\n } catch {\n throw new Error('That is not a url.')\n }\n\n if (!allow(url)) throw new Error('This panel does not install plugins from that address.')\n\n const response = await fetch(url, { headers: { accept: 'application/json' }, redirect: 'error', signal: AbortSignal.timeout(5000) }).catch(() => null)\n\n if (!response?.ok) throw new Error(`The manifest could not be fetched${response ? ` (${response.status})` : ''}.`)\n\n let manifest: unknown\n\n try {\n manifest = JSON.parse(await bounded(response, MANIFEST_BYTES))\n } catch {\n throw new Error('The manifest is not JSON.')\n }\n\n const problems = manifestProblems(manifest, url.href, host)\n\n if (problems.length > 0) throw new Error(`The manifest has problems: ${problems.join('; ')}.`)\n\n const checked = manifest as PluginManifest\n\n return { ...checked, endpoint: new URL(checked.endpoint, url).href }\n}\n\n/** A stable digest of a manifest: what was reviewed is what is installed, or the install is refused. */\nexport async function digestOf(manifest: PluginManifest): Promise<string> {\n const bytes = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(JSON.stringify(manifest))))\n\n return [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nexport function newInstallation(manifestUrl: string, manifest: PluginManifest): Installation {\n return { id: crypto.randomUUID(), manifestUrl, manifest, secret: newSecret(), secretSeen: false, installedAt: new Date().toISOString() }\n}\n\n/** What a plugin's endpoint is sent. `tenant` is the installation's, never one the browser named. */\nexport type PluginCall =\n | { type: 'list'; resource: string; query: ListQuery }\n | { type: 'find'; resource: string; id: string }\n | { type: 'create'; resource: string; values: Record<string, unknown> }\n | { type: 'update'; resource: string; id: string; values: Record<string, unknown> }\n | { type: 'delete'; resource: string; id: string }\n | { type: 'bulk'; resource: string; action: string; ids: string[] }\n | { type: 'change'; change: RecordChange }\n\nexport type PluginRequest = PluginCall & { tenant: Tenant | null }\n\n/**\n * One signed call. A 404 is null; a 422 with `{ errors: { field: [message] } }`\n * is the form's field errors, exactly as Laravel's are; anything else that is\n * not a 2xx is a failure with the plugin's name on it.\n */\nexport async function callPlugin(\n installation: Installation,\n call: PluginCall,\n context: SourceContext,\n allow: (url: URL) => boolean,\n timeout = 10_000,\n): Promise<unknown> {\n const endpoint = new URL(installation.manifest.endpoint)\n const name = installation.manifest.name\n\n // Checked again on every call: the rule can tighten after the install.\n if (!allow(endpoint)) throw new Error(`[admin] the plugin ${name}'s endpoint is no longer allowed`)\n\n const body = JSON.stringify({ ...call, tenant: context.tenant ? { id: context.tenant.id, name: context.tenant.name } : null })\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json', ...(await signedHeaders(installation.id, installation.secret, body)) },\n body,\n redirect: 'error',\n signal: AbortSignal.timeout(timeout),\n })\n\n if (response.status === 404) return null\n\n const answer = await bounded(response, ANSWER_BYTES)\n let json: unknown = null\n\n try {\n json = answer === '' ? null : JSON.parse(answer)\n } catch {\n throw new Error(`[admin] the plugin ${name} answered ${response.status} with something that is not JSON`)\n }\n\n if (response.status === 422 && isObject(json) && isObject(json.errors)) {\n const errors = Object.fromEntries(\n Object.entries(json.errors).map(([field, messages]) => [field, ([] as unknown[]).concat(messages).map(String).slice(0, 5)]),\n )\n\n throw new ActionValidationError(errors)\n }\n\n if (!response.ok) throw new Error(`[admin] the plugin ${name} answered ${response.status}`)\n\n return json\n}\n\nconst row = (value: unknown, plugin: string): Record<string, unknown> => {\n if (!isObject(value)) throw new Error(`[admin] the plugin ${plugin} answered a row that is not an object`)\n\n return value\n}\n\n/** A resource's five calls, made to the plugin. */\nfunction remoteSource(installation: Installation, resource: string, allow: (url: URL) => boolean): DataSource<Record<string, unknown>, Record<string, unknown>> {\n const plugin = installation.manifest.name\n const call = (body: PluginCall, context: SourceContext) => callPlugin(installation, body, context, allow)\n\n return {\n async list(query, context) {\n const answer = await call({ type: 'list', resource, query }, context)\n\n const cursor = (value: unknown) => typeof value === 'string' || value === null || value === undefined\n const paged = isObject(answer) && 'next' in answer && cursor(answer.next) && cursor(answer.prev)\n\n if (!isObject(answer) || !Array.isArray(answer.rows) || (typeof answer.total !== 'number' && !paged)) {\n throw new Error(`[admin] the plugin ${plugin} answered a list without { rows, total } or { rows, next }`)\n }\n\n const rows = answer.rows.map((value) => row(value, plugin))\n\n return paged\n ? { rows, next: (answer.next as string | null) ?? null, prev: (answer.prev as string | null | undefined) ?? null }\n : { rows, total: answer.total as number }\n },\n async find(id, context) {\n const answer = await call({ type: 'find', resource, id }, context)\n\n return isObject(answer) && answer.row !== undefined && answer.row !== null ? row(answer.row, plugin) : null\n },\n async create(values, context) {\n return row((await call({ type: 'create', resource, values }, context)) as { row?: unknown } | null, plugin).row as Record<string, unknown>\n },\n async update(id, values, context) {\n return row((await call({ type: 'update', resource, id, values }, context)) as { row?: unknown } | null, plugin).row as Record<string, unknown>\n },\n async delete(id, context) {\n await call({ type: 'delete', resource, id }, context)\n },\n }\n}\n\n// ------------------------------------------------------------------ the form\n\n/**\n * A Standard Schema from the manifest's JSON Schema, so a plugin's form goes\n * through the same parse as any other. It checks what is cheap and safe to\n * check here - types, required, enums, lengths, bounds - and never `pattern`;\n * the plugin's endpoint checks everything again and answers 422.\n */\nexport function jsonSchemaForm(form: ManifestResource['form']): FormSchema {\n const required = new Set(form.required ?? [])\n\n const validate = (value: unknown): { value: Record<string, unknown> } | { issues: { message: string; path: string[] }[] } => {\n if (!isObject(value)) return { issues: [{ message: 'Expected an object', path: [] }] }\n\n const out: Record<string, unknown> = {}\n const issues: { message: string; path: string[] }[] = []\n\n for (const [name, property] of Object.entries(form.properties)) {\n const given = value[name]\n const fail = (message: string) => issues.push({ message, path: [name] })\n\n if (given === undefined || given === null || given === '') {\n if (required.has(name) && property.type !== 'boolean') fail('Required')\n continue\n }\n\n if (property.type === 'boolean') {\n if (typeof given !== 'boolean') fail('Expected true or false')\n else out[name] = given\n continue\n }\n\n if (property.type === 'number' || property.type === 'integer') {\n const number = typeof given === 'number' ? given : Number(given)\n\n if (!Number.isFinite(number)) fail('Expected a number')\n else if (property.type === 'integer' && !Number.isInteger(number)) fail('Expected a whole number')\n else if (property.minimum !== undefined && number < property.minimum) fail(`At least ${property.minimum}`)\n else if (property.maximum !== undefined && number > property.maximum) fail(`At most ${property.maximum}`)\n else out[name] = number\n continue\n }\n\n const string = String(given)\n\n if (property.enum && !property.enum.includes(string)) fail(`One of ${property.enum.join(', ')}`)\n else if (property.minLength !== undefined && string.length < property.minLength) fail(`At least ${property.minLength} characters`)\n else if (property.maxLength !== undefined && string.length > property.maxLength) fail(`At most ${property.maxLength} characters`)\n else out[name] = string\n }\n\n return issues.length > 0 ? { issues } : { value: out }\n }\n\n const json = {\n type: 'object',\n required: form.required ?? [],\n properties: Object.fromEntries(\n Object.entries(form.properties).map(([name, { relation: _relation, title: _title, format, ...property }]) => [\n name,\n { ...property, ...(format && format !== 'textarea' ? { format } : {}) },\n ]),\n ),\n }\n\n return {\n '~standard': {\n version: 1,\n vendor: '@rsc-kit/press/plugin',\n validate,\n jsonSchema: { input: () => json, output: () => json },\n },\n } as unknown as FormSchema\n}\n\n/** An installation's resources, as the panel's own. */\nexport function resourcesOf(installation: Installation, allow: (url: URL) => boolean): Resource[] {\n return installation.manifest.resources.map((described) =>\n defineResource<Record<string, unknown>>()({\n name: described.name,\n ...(described.label ? { label: described.label } : {}),\n ...(described.singular ? { singular: described.singular } : {}),\n key: described.key,\n title: described.title,\n source: remoteSource(installation, described.name, allow),\n table: (col) =>\n described.columns.map((column) => {\n const built = column.relation ? col.relation(column.key, column.relation) : col[column.format ?? 'text'](column.key)\n\n if (column.label) built.label(column.label)\n if (column.sortable) built.sortable()\n if (column.searchable) built.searchable()\n\n return built\n }),\n form: jsonSchemaForm(described.form),\n fields: Object.fromEntries(\n Object.entries(described.form.properties).flatMap(([name, property]) => {\n const override = {\n ...(property.title ? { label: property.title } : {}),\n ...(property.description ? { description: property.description } : {}),\n ...(property.format === 'textarea' ? { type: 'textarea' as const } : {}),\n ...(property.relation ? { relation: property.relation } : {}),\n }\n\n return Object.keys(override).length > 0 ? [[name, override]] : []\n }),\n ),\n ...(described.filters ? { filters: described.filters } : {}),\n ...(described.perPage ? { perPage: described.perPage } : {}),\n ...(described.mode ? { mode: described.mode } : {}),\n ...(described.readOnly ? { readOnly: true } : {}),\n ...(described.description ? { description: described.description } : {}),\n bulkActions: (described.bulkActions ?? []).map((action) => ({\n name: action.name,\n label: action.label,\n ...(action.done ? { done: action.done } : {}),\n ...(action.destructive ? { destructive: true } : {}),\n run: async (rows: Record<string, unknown>[], context: SourceContext) => {\n const answer = await callPlugin(\n installation,\n { type: 'bulk', resource: described.name, action: action.name, ids: rows.map((found) => String(found[described.key])) },\n context,\n allow,\n )\n\n return isObject(answer) && typeof answer.message === 'string' ? answer.message.slice(0, 200) : undefined\n },\n })),\n }),\n )\n}\n\n/** Whether a plugin is told about a change: one of its events, which its scopes or ownership allow. */\nexport function wantsChange(installation: Installation, change: RecordChange): boolean {\n return installation.manifest.events?.includes(change.resource) ?? false\n}\n"]}
@@ -12,6 +12,9 @@
12
12
  */
13
13
  import type { ComponentType, ReactNode } from 'react';
14
14
  import type { StandardSchemaV1 } from '@rsc-kit/core/standardSchema';
15
+ import type { HostAction, HostFields } from './forms/host.js';
16
+ import type { Derivation, Visibility } from './conditions.js';
17
+ import type { BlueprintParts } from './forms/brand.js';
15
18
  import type { Storage } from './uploads.js';
16
19
  /** What the form validates with: any Standard Schema - zod, valibot, arktype, effect. */
17
20
  export type FormSchema = StandardSchemaV1<any, Record<string, unknown>>;
@@ -113,6 +116,14 @@ export interface Field {
113
116
  maxSize?: number;
114
117
  /** The schema allows null: a file field that is emptied saves null, so the source clears it. */
115
118
  nullable?: boolean;
119
+ /**
120
+ * Shown only while another field says so: { when: 'type', is: 'business' }.
121
+ * Hidden, it is not sent, not checked by the browser, and dropped by the
122
+ * server if a post sends it anyway. Required means required when shown.
123
+ */
124
+ visible?: Visibility;
125
+ /** Filled from another field while that is typed, until edited by hand: { field: 'title' } for a slug. */
126
+ from?: Derivation;
116
127
  }
117
128
  export interface Filter {
118
129
  key: string;
@@ -124,6 +135,12 @@ export interface ListQuery {
124
135
  sort?: string;
125
136
  dir: 'asc' | 'desc';
126
137
  page: number;
138
+ /**
139
+ * The cursor a source that pages by cursor answered as next or prev, from
140
+ * the url's ?cursor=; absent for the first page. Such a source reads this
141
+ * and not page.
142
+ */
143
+ cursor?: string;
127
144
  /**
128
145
  * Null asks for every row: a resource whose table works in the browser
129
146
  * (mode: 'client') is loaded whole, and searched, sorted and paged there.
@@ -156,16 +173,30 @@ export interface SourceContext {
156
173
  * In a panel with tenants, a source answers only for context.tenant. find()
157
174
  * returning null for another tenant's record is what makes its url a 404.
158
175
  */
176
+ /**
177
+ * One page of a list. Counted, { rows, total }, and the table numbers its
178
+ * pages. By cursor, { rows, next, prev } - Laravel's cursorPaginate, a keyset
179
+ * query, an API that hands back a cursor - and the table pages with Previous
180
+ * and Next, asking for the cursor it was given. null is no page that way.
181
+ */
182
+ export type ListPage<Row> = {
183
+ rows: Row[];
184
+ total: number;
185
+ } | {
186
+ rows: Row[];
187
+ next: string | null;
188
+ prev?: string | null;
189
+ total?: number;
190
+ };
159
191
  export interface DataSource<Row, Values> {
160
- list(query: ListQuery, context: SourceContext): Promise<{
161
- rows: Row[];
162
- total: number;
163
- }>;
192
+ list(query: ListQuery, context: SourceContext): Promise<ListPage<Row>>;
164
193
  find(id: string, context: SourceContext): Promise<Row | null>;
165
194
  create(values: Values, context: SourceContext): Promise<Row>;
166
195
  update(id: string, values: Values, context: SourceContext): Promise<Row>;
167
196
  delete(id: string, context: SourceContext): Promise<void>;
168
197
  }
198
+ /** A source for a resource whose saves are a backend's actions: it lists, finds and deletes. */
199
+ export type ReadSource<Row> = Pick<DataSource<Row, never>, 'list' | 'find' | 'delete'>;
169
200
  /**
170
201
  * Where a table's search, filters, sort and paging happen.
171
202
  *
@@ -202,7 +233,13 @@ export interface Resource<Row = any, Schema extends FormSchema = FormSchema> {
202
233
  columns: Column[];
203
234
  filters: Filter[];
204
235
  schema: Schema;
236
+ /** The create form's fields. */
205
237
  fields: Field[];
238
+ /** The edit form's: the update action's, for a resource saved by a backend. */
239
+ editFields: Field[];
240
+ editSchema: FormSchema;
241
+ /** The resources its fields name, known before the fields are: a backend's arrive with the server entry. */
242
+ relations: string[];
206
243
  perPage: number;
207
244
  mode: TableMode;
208
245
  /** Listed and searched, never created, edited or deleted from the panel. */
@@ -249,13 +286,47 @@ export interface ResourceDefinition<Row, Schema extends FormSchema> {
249
286
  /** Under the page's heading. */
250
287
  description?: string;
251
288
  }
289
+ /**
290
+ * A resource saved by the backend's own actions, with no schema in
291
+ * TypeScript: the generated stubs for a Laravel FormRequest or a Go struct.
292
+ * The create form is drawn from what `create` takes, the edit form from what
293
+ * `update` takes, and every check is the backend's - its 422 lands under the
294
+ * fields. `update` is called with the record's key after the values:
295
+ * `update(UpdateProductRequest $request, string $product)`.
296
+ */
297
+ export interface HostResourceDefinition<Row, Create extends HostAction, Update extends HostAction> extends Omit<ResourceDefinition<Row, FormSchema>, 'source' | 'form' | 'fields' | 'readOnly'> {
298
+ /** Lists, finds and deletes; the saves are the actions. */
299
+ source: ReadSource<Row>;
300
+ /** `import { productsStore, productsUpdate } from '../server-actions.generated'`. */
301
+ actions: {
302
+ create: Create;
303
+ update: Update;
304
+ };
305
+ /** Labels, controls and relations the backend's types cannot say. */
306
+ fields?: Partial<Record<HostFields<Create> | HostFields<Update>, FieldOverride>>;
307
+ }
308
+ /**
309
+ * A resource whose form is a blueprint: the same fields, checks and saves a
310
+ * page draws with `<product.Form />`. A blueprint that saves - a backend's
311
+ * actions, or a schema's handle and update - needs only a source that lists,
312
+ * finds and deletes; one that leaves saving to the resource needs a whole one.
313
+ */
314
+ export interface BlueprintResourceDefinition<Row> extends Omit<ResourceDefinition<Row, FormSchema>, 'source' | 'form' | 'fields'> {
315
+ source: ReadSource<Row> | DataSource<Row, Record<string, unknown>>;
316
+ /** import { product } from './blueprints/product', defined with defineBlueprint. */
317
+ form: BlueprintParts;
318
+ }
252
319
  /**
253
320
  * Two calls so the row is named and the schema is inferred:
254
321
  * defineResource<Product>()({ ... }).
255
322
  */
256
- export declare function defineResource<Row>(): <Schema extends FormSchema>(definition: ResourceDefinition<Row, Schema>) => Resource<Row, Schema>;
323
+ export declare function defineResource<Row>(): {
324
+ <Schema extends FormSchema>(definition: ResourceDefinition<Row, Schema>): Resource<Row, Schema>;
325
+ <Create extends HostAction, Update extends HostAction>(definition: HostResourceDefinition<Row, Create, Update>): Resource<Row>;
326
+ (definition: BlueprintResourceDefinition<Row>): Resource<Row>;
327
+ };
257
328
  /** A field as the app says it, over what the schema said. */
258
- export type FieldOverride = Partial<Pick<Field, 'type' | 'label' | 'description' | 'required' | 'relation'>> & {
329
+ export type FieldOverride = Partial<Pick<Field, 'type' | 'label' | 'description' | 'required' | 'relation' | 'visible' | 'from'>> & {
259
330
  /** A bare value is labelled by humanizing it: 'in_stock' reads "In stock". */
260
331
  options?: (string | Option)[];
261
332
  /** The kinds a blocks field offers: { type: 'blocks', blocks: [hero, features] }. */