@rsc-kit/press 0.0.0-stage → 0.30.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -2
- package/dist/admin/actions.d.ts +30 -0
- package/dist/admin/actions.js +171 -0
- package/dist/admin/actions.js.map +1 -0
- package/dist/admin/index.d.ts +5 -0
- package/dist/admin/index.js +2 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/panel.d.ts +96 -0
- package/dist/admin/panel.js +354 -0
- package/dist/admin/panel.js.map +1 -0
- package/dist/admin/registry.d.ts +58 -0
- package/dist/admin/registry.js +90 -0
- package/dist/admin/registry.js.map +1 -0
- package/dist/admin/theme.d.ts +251 -0
- package/dist/admin/theme.js +2 -0
- package/dist/admin/theme.js.map +1 -0
- package/dist/admin/url.d.ts +24 -0
- package/dist/admin/url.js +45 -0
- package/dist/admin/url.js.map +1 -0
- package/dist/blocks.d.ts +46 -0
- package/dist/blocks.js +33 -0
- package/dist/blocks.js.map +1 -0
- package/dist/forms/actions.d.ts +7 -0
- package/dist/forms/actions.js +26 -0
- package/dist/forms/actions.js.map +1 -0
- package/dist/forms/form.d.ts +42 -0
- package/dist/forms/form.js +44 -0
- package/dist/forms/form.js.map +1 -0
- package/dist/forms/honeypot.d.ts +2 -0
- package/dist/forms/honeypot.js +3 -0
- package/dist/forms/honeypot.js.map +1 -0
- package/dist/forms/index.d.ts +3 -0
- package/dist/forms/index.js +2 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/registry.d.ts +10 -0
- package/dist/forms/registry.js +17 -0
- package/dist/forms/registry.js.map +1 -0
- package/dist/forms/theme.d.ts +29 -0
- package/dist/forms/theme.js +2 -0
- package/dist/forms/theme.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/installable.d.ts +173 -0
- package/dist/installable.js +490 -0
- package/dist/installable.js.map +1 -0
- package/dist/memory.d.ts +7 -0
- package/dist/memory.js +50 -0
- package/dist/memory.js.map +1 -0
- package/dist/pages/index.d.ts +2 -0
- package/dist/pages/index.js +2 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/pages.d.ts +78 -0
- package/dist/pages/pages.js +183 -0
- package/dist/pages/pages.js.map +1 -0
- package/dist/plugin.d.ts +51 -0
- package/dist/plugin.js +20 -0
- package/dist/plugin.js.map +1 -0
- package/dist/resource.d.ts +320 -0
- package/dist/resource.js +415 -0
- package/dist/resource.js.map +1 -0
- package/dist/shadcn/breadcrumbs.d.ts +6 -0
- package/dist/shadcn/breadcrumbs.js +21 -0
- package/dist/shadcn/breadcrumbs.js.map +1 -0
- package/dist/shadcn/components/ui/alert-dialog.d.ts +18 -0
- package/dist/shadcn/components/ui/alert-dialog.js +44 -0
- package/dist/shadcn/components/ui/alert-dialog.js.map +1 -0
- package/dist/shadcn/components/ui/avatar.d.ts +11 -0
- package/dist/shadcn/components/ui/avatar.js +25 -0
- package/dist/shadcn/components/ui/avatar.js.map +1 -0
- package/dist/shadcn/components/ui/badge.d.ts +7 -0
- package/dist/shadcn/components/ui/badge.js +34 -0
- package/dist/shadcn/components/ui/badge.js.map +1 -0
- package/dist/shadcn/components/ui/breadcrumb.d.ts +10 -0
- package/dist/shadcn/components/ui/breadcrumb.js +38 -0
- package/dist/shadcn/components/ui/breadcrumb.js.map +1 -0
- package/dist/shadcn/components/ui/button.d.ts +8 -0
- package/dist/shadcn/components/ui/button.js +35 -0
- package/dist/shadcn/components/ui/button.js.map +1 -0
- package/dist/shadcn/components/ui/card.d.ts +11 -0
- package/dist/shadcn/components/ui/card.js +26 -0
- package/dist/shadcn/components/ui/card.js.map +1 -0
- package/dist/shadcn/components/ui/checkbox.d.ts +3 -0
- package/dist/shadcn/components/ui/checkbox.js +10 -0
- package/dist/shadcn/components/ui/checkbox.js.map +1 -0
- package/dist/shadcn/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/shadcn/components/ui/dropdown-menu.js +53 -0
- package/dist/shadcn/components/ui/dropdown-menu.js.map +1 -0
- package/dist/shadcn/components/ui/field.d.ts +24 -0
- package/dist/shadcn/components/ui/field.js +69 -0
- package/dist/shadcn/components/ui/field.js.map +1 -0
- package/dist/shadcn/components/ui/input.d.ts +3 -0
- package/dist/shadcn/components/ui/input.js +9 -0
- package/dist/shadcn/components/ui/input.js.map +1 -0
- package/dist/shadcn/components/ui/label.d.ts +3 -0
- package/dist/shadcn/components/ui/label.js +9 -0
- package/dist/shadcn/components/ui/label.js.map +1 -0
- package/dist/shadcn/components/ui/select.d.ts +15 -0
- package/dist/shadcn/components/ui/select.js +36 -0
- package/dist/shadcn/components/ui/select.js.map +1 -0
- package/dist/shadcn/components/ui/separator.d.ts +3 -0
- package/dist/shadcn/components/ui/separator.js +9 -0
- package/dist/shadcn/components/ui/separator.js.map +1 -0
- package/dist/shadcn/components/ui/sheet.d.ts +14 -0
- package/dist/shadcn/components/ui/sheet.js +39 -0
- package/dist/shadcn/components/ui/sheet.js.map +1 -0
- package/dist/shadcn/components/ui/sidebar.d.ts +63 -0
- package/dist/shadcn/components/ui/sidebar.js +257 -0
- package/dist/shadcn/components/ui/sidebar.js.map +1 -0
- package/dist/shadcn/components/ui/skeleton.d.ts +2 -0
- package/dist/shadcn/components/ui/skeleton.js +7 -0
- package/dist/shadcn/components/ui/skeleton.js.map +1 -0
- package/dist/shadcn/components/ui/sonner.d.ts +3 -0
- package/dist/shadcn/components/ui/sonner.js +38 -0
- package/dist/shadcn/components/ui/sonner.js.map +1 -0
- package/dist/shadcn/components/ui/switch.d.ts +5 -0
- package/dist/shadcn/components/ui/switch.js +9 -0
- package/dist/shadcn/components/ui/switch.js.map +1 -0
- package/dist/shadcn/components/ui/table.d.ts +10 -0
- package/dist/shadcn/components/ui/table.js +30 -0
- package/dist/shadcn/components/ui/table.js.map +1 -0
- package/dist/shadcn/components/ui/textarea.d.ts +3 -0
- package/dist/shadcn/components/ui/textarea.js +8 -0
- package/dist/shadcn/components/ui/textarea.js.map +1 -0
- package/dist/shadcn/components/ui/tooltip.d.ts +6 -0
- package/dist/shadcn/components/ui/tooltip.js +18 -0
- package/dist/shadcn/components/ui/tooltip.js.map +1 -0
- package/dist/shadcn/data-table.d.ts +12 -0
- package/dist/shadcn/data-table.js +195 -0
- package/dist/shadcn/data-table.js.map +1 -0
- package/dist/shadcn/fields.d.ts +20 -0
- package/dist/shadcn/fields.js +179 -0
- package/dist/shadcn/fields.js.map +1 -0
- package/dist/shadcn/flash-toasts.d.ts +2 -0
- package/dist/shadcn/flash-toasts.js +11 -0
- package/dist/shadcn/flash-toasts.js.map +1 -0
- package/dist/shadcn/hooks/use-mobile.d.ts +1 -0
- package/dist/shadcn/hooks/use-mobile.js +16 -0
- package/dist/shadcn/hooks/use-mobile.js.map +1 -0
- package/dist/shadcn/index.d.ts +10 -0
- package/dist/shadcn/index.js +31 -0
- package/dist/shadcn/index.js.map +1 -0
- package/dist/shadcn/mode-toggle.d.ts +7 -0
- package/dist/shadcn/mode-toggle.js +52 -0
- package/dist/shadcn/mode-toggle.js.map +1 -0
- package/dist/shadcn/nav.d.ts +5 -0
- package/dist/shadcn/nav.js +19 -0
- package/dist/shadcn/nav.js.map +1 -0
- package/dist/shadcn/pages.d.ts +15 -0
- package/dist/shadcn/pages.js +59 -0
- package/dist/shadcn/pages.js.map +1 -0
- package/dist/shadcn/plugin-forms.d.ts +16 -0
- package/dist/shadcn/plugin-forms.js +25 -0
- package/dist/shadcn/plugin-forms.js.map +1 -0
- package/dist/shadcn/public-form.d.ts +8 -0
- package/dist/shadcn/public-form.js +26 -0
- package/dist/shadcn/public-form.js.map +1 -0
- package/dist/shadcn/resource-form.d.ts +19 -0
- package/dist/shadcn/resource-form.js +30 -0
- package/dist/shadcn/resource-form.js.map +1 -0
- package/dist/shadcn/styles.css +12 -0
- package/dist/shadcn/tenant-switcher.d.ts +3 -0
- package/dist/shadcn/tenant-switcher.js +17 -0
- package/dist/shadcn/tenant-switcher.js.map +1 -0
- package/dist/shadcn/theme-script.d.ts +7 -0
- package/dist/shadcn/theme-script.js +10 -0
- package/dist/shadcn/theme-script.js.map +1 -0
- package/dist/shadcn/user-menu.d.ts +3 -0
- package/dist/shadcn/user-menu.js +23 -0
- package/dist/shadcn/user-menu.js.map +1 -0
- package/dist/signing.d.ts +43 -0
- package/dist/signing.js +82 -0
- package/dist/signing.js.map +1 -0
- package/dist/tenant.d.ts +12 -0
- package/dist/tenant.js +29 -0
- package/dist/tenant.js.map +1 -0
- package/dist/uploads.d.ts +32 -0
- package/dist/uploads.js +28 -0
- package/dist/uploads.js.map +1 -0
- package/package.json +74 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA","sourcesContent":["export { defineForm } from './form.js'\nexport type { FormDefinition, PublicForm } from './form.js'\nexport type { FormsTheme, PublicFormProps } from './theme.js'\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Field, FormSchema } from '../resource.js';
|
|
2
|
+
export interface FormHandle {
|
|
3
|
+
name: string;
|
|
4
|
+
schema: FormSchema;
|
|
5
|
+
fields: Field[];
|
|
6
|
+
handle: (values: Record<string, unknown>) => void | Promise<void>;
|
|
7
|
+
redirect: string | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function registerForm(form: FormHandle): void;
|
|
10
|
+
export declare function formNamed(name: string): FormHandle;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forms by name. An action receives a name, not a form - only what can be
|
|
3
|
+
* serialised crosses to the browser and back - so the form is looked up here.
|
|
4
|
+
* On globalThis because a dev server can evaluate this module more than once.
|
|
5
|
+
*/
|
|
6
|
+
const KEY = Symbol.for('@rsc-kit/press.forms');
|
|
7
|
+
const forms = (globalThis[KEY] ??= new Map());
|
|
8
|
+
export function registerForm(form) {
|
|
9
|
+
forms.set(form.name, form);
|
|
10
|
+
}
|
|
11
|
+
export function formNamed(name) {
|
|
12
|
+
const form = forms.get(name);
|
|
13
|
+
if (!form)
|
|
14
|
+
throw new Error(`[forms] no form named ${name}; defineForm({ name: ${JSON.stringify(name)} }) has not run`);
|
|
15
|
+
return form;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { Field } from '../resource.js';
|
|
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
|
|
7
|
+
* server's refusals under their fields.
|
|
8
|
+
*/
|
|
9
|
+
export interface FormsTheme {
|
|
10
|
+
PublicForm: ComponentType<PublicFormProps>;
|
|
11
|
+
}
|
|
12
|
+
export interface PublicFormProps {
|
|
13
|
+
/** Checks and sends the form. A refusal is a 422 whose messages belong under their fields. */
|
|
14
|
+
action: (form: FormData) => Promise<unknown>;
|
|
15
|
+
fields: Field[];
|
|
16
|
+
/** The submit button's words: Send message. */
|
|
17
|
+
submit: string;
|
|
18
|
+
/**
|
|
19
|
+
* What the visitor reads once it is sent, in place of the form. Absent when
|
|
20
|
+
* the form redirects instead.
|
|
21
|
+
*/
|
|
22
|
+
done?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The name of a field people never see and bots fill in. The theme renders
|
|
25
|
+
* it hidden from sight, from screen readers and from the tab order, with
|
|
26
|
+
* autocomplete off; a submission with it filled is thanked and dropped.
|
|
27
|
+
*/
|
|
28
|
+
honeypot: string;
|
|
29
|
+
}
|
|
@@ -0,0 +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"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
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';
|
|
3
|
+
export { IMAGE_TYPES } from './uploads.js';
|
|
4
|
+
export type { Storage, StorageContext } from './uploads.js';
|
|
5
|
+
export { Blocks, defineBlock } from './blocks.js';
|
|
6
|
+
export type { Block, BlockDefinition, BlockValue } from './blocks.js';
|
|
7
|
+
export { memorySource } from './memory.js';
|
|
8
|
+
export { perTenant } from './tenant.js';
|
|
9
|
+
export { definePlugin } from './plugin.js';
|
|
10
|
+
export type { PanelPlugin, RecordChange, Widget } from './plugin.js';
|
|
11
|
+
export { memoryInstallations, manifestProblems, publicHttps } from './installable.js';
|
|
12
|
+
export type { Installation, Installations, Installs, ManifestColumn, ManifestProperty, ManifestResource, PluginManifest, PluginRequest } from './installable.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { defineResource, fieldsOf, humanize, parse, valuesFrom } from './resource.js';
|
|
2
|
+
export { IMAGE_TYPES } from './uploads.js';
|
|
3
|
+
export { Blocks, defineBlock } from './blocks.js';
|
|
4
|
+
export { memorySource } from './memory.js';
|
|
5
|
+
export { perTenant } from './tenant.js';
|
|
6
|
+
export { definePlugin } from './plugin.js';
|
|
7
|
+
export { memoryInstallations, manifestProblems, publicHttps } from './installable.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { RecordChange } from './plugin.js';
|
|
2
|
+
import type { Format, FormSchema, ListQuery, Resource, SourceContext, Tenant } from './resource.js';
|
|
3
|
+
/** A plugin, as it describes itself at its manifest url. */
|
|
4
|
+
export interface PluginManifest {
|
|
5
|
+
/** Lowercase letters, digits and dashes; unique within a tenant. */
|
|
6
|
+
name: string;
|
|
7
|
+
label: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
/** Where the panel POSTs every call. Same origin as the manifest. */
|
|
11
|
+
endpoint: string;
|
|
12
|
+
/** What it may see of the app's own resources: read:<resource>. */
|
|
13
|
+
scopes: string[];
|
|
14
|
+
resources: ManifestResource[];
|
|
15
|
+
/** Resources whose changes it is told about: its own, or ones it may read. */
|
|
16
|
+
events?: string[];
|
|
17
|
+
}
|
|
18
|
+
export type ManifestFormat = Exclude<Format, 'relation'>;
|
|
19
|
+
export interface ManifestColumn {
|
|
20
|
+
key: string;
|
|
21
|
+
label?: string;
|
|
22
|
+
format?: ManifestFormat;
|
|
23
|
+
/** Shown by that resource's title: one of the plugin's own, or one it may read. */
|
|
24
|
+
relation?: string;
|
|
25
|
+
sortable?: boolean;
|
|
26
|
+
searchable?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** The JSON Schema a manifest's form is written in: flat, one level, scalar fields. */
|
|
29
|
+
export interface ManifestProperty {
|
|
30
|
+
type: 'string' | 'number' | 'integer' | 'boolean';
|
|
31
|
+
format?: 'email' | 'date' | 'date-time' | 'textarea';
|
|
32
|
+
enum?: string[];
|
|
33
|
+
minLength?: number;
|
|
34
|
+
maxLength?: number;
|
|
35
|
+
minimum?: number;
|
|
36
|
+
maximum?: number;
|
|
37
|
+
/** For the browser's pattern attribute only: the plugin checks it, not the panel. */
|
|
38
|
+
pattern?: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
/** A belongsTo, drawn as a select of that resource's rows. */
|
|
42
|
+
relation?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ManifestResource {
|
|
45
|
+
name: string;
|
|
46
|
+
label?: string;
|
|
47
|
+
singular?: string;
|
|
48
|
+
key: string;
|
|
49
|
+
title: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
columns: ManifestColumn[];
|
|
52
|
+
form: {
|
|
53
|
+
type: 'object';
|
|
54
|
+
properties: Record<string, ManifestProperty>;
|
|
55
|
+
required?: string[];
|
|
56
|
+
};
|
|
57
|
+
filters?: string[];
|
|
58
|
+
perPage?: number;
|
|
59
|
+
mode?: 'server' | 'client';
|
|
60
|
+
readOnly?: boolean;
|
|
61
|
+
bulkActions?: {
|
|
62
|
+
name: string;
|
|
63
|
+
label: string;
|
|
64
|
+
done?: string;
|
|
65
|
+
destructive?: boolean;
|
|
66
|
+
}[];
|
|
67
|
+
}
|
|
68
|
+
/** One plugin installed for one tenant. The secret signs every call to it. */
|
|
69
|
+
export interface Installation {
|
|
70
|
+
/** Random; the plugin finds this installation's secret by it. */
|
|
71
|
+
id: string;
|
|
72
|
+
manifestUrl: string;
|
|
73
|
+
manifest: PluginManifest;
|
|
74
|
+
secret: string;
|
|
75
|
+
/** Until someone confirms they copied the secret into the plugin, the plugins page shows it. */
|
|
76
|
+
secretSeen: boolean;
|
|
77
|
+
installedAt: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Where installations are kept: the app's database, in a real app. Each call
|
|
81
|
+
* names the tenant, and a store answers for that tenant alone - one team's
|
|
82
|
+
* installs never reach another's panel. Keep `secret` encrypted at rest.
|
|
83
|
+
*/
|
|
84
|
+
export interface Installations {
|
|
85
|
+
list(tenant: Tenant | null): Promise<Installation[]>;
|
|
86
|
+
add(tenant: Tenant | null, installation: Installation): Promise<void>;
|
|
87
|
+
remove(tenant: Tenant | null, id: string): Promise<void>;
|
|
88
|
+
/** The secret was copied into the plugin; stop showing it. */
|
|
89
|
+
seen(tenant: Tenant | null, id: string): Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
export interface Installs {
|
|
92
|
+
store: Installations;
|
|
93
|
+
/**
|
|
94
|
+
* Whether the panel may call this url: a manifest's, and so its endpoint's.
|
|
95
|
+
* By default https to a public host name - not localhost, not an address.
|
|
96
|
+
* The panel's server makes the request, so a url that reaches your own
|
|
97
|
+
* network is the thing to refuse; allow what your plugins are, and in
|
|
98
|
+
* development, localhost.
|
|
99
|
+
*/
|
|
100
|
+
allow?: (url: URL) => boolean;
|
|
101
|
+
/** Who may install and uninstall. The panel's authorize by default; an owner, usually. */
|
|
102
|
+
manage?: () => boolean | Promise<boolean>;
|
|
103
|
+
}
|
|
104
|
+
/** Installations in memory: for a demo, a test, a single process. Gone on restart. */
|
|
105
|
+
export declare function memoryInstallations(name?: string): Installations;
|
|
106
|
+
/** The panel's own url segments under its path, which no resource may take. */
|
|
107
|
+
export declare const RESERVED: string[];
|
|
108
|
+
/**
|
|
109
|
+
* Every problem with a manifest, or none. Checked when it is reviewed, when it
|
|
110
|
+
* is installed, and on every request after - the app's resources can change
|
|
111
|
+
* under an installed plugin, and one that no longer fits is left out.
|
|
112
|
+
*/
|
|
113
|
+
export declare function manifestProblems(manifest: unknown, manifestUrl: string, host: string[]): string[];
|
|
114
|
+
/** The scopes, as the person installing reads them. */
|
|
115
|
+
export declare function scopeWords(manifest: PluginManifest, labelOf: (resource: string) => string): string[];
|
|
116
|
+
/** Https to a name: not localhost, and not an address, which is how a private network is reached by url. */
|
|
117
|
+
export declare function publicHttps(url: URL): boolean;
|
|
118
|
+
/** A manifest, fetched and checked. Redirects are refused: a url allowed once must not lead somewhere that was not. */
|
|
119
|
+
export declare function fetchManifest(manifestUrl: string, allow: (url: URL) => boolean, host: string[]): Promise<PluginManifest>;
|
|
120
|
+
/** A stable digest of a manifest: what was reviewed is what is installed, or the install is refused. */
|
|
121
|
+
export declare function digestOf(manifest: PluginManifest): Promise<string>;
|
|
122
|
+
export declare function newInstallation(manifestUrl: string, manifest: PluginManifest): Installation;
|
|
123
|
+
/** What a plugin's endpoint is sent. `tenant` is the installation's, never one the browser named. */
|
|
124
|
+
export type PluginCall = {
|
|
125
|
+
type: 'list';
|
|
126
|
+
resource: string;
|
|
127
|
+
query: ListQuery;
|
|
128
|
+
} | {
|
|
129
|
+
type: 'find';
|
|
130
|
+
resource: string;
|
|
131
|
+
id: string;
|
|
132
|
+
} | {
|
|
133
|
+
type: 'create';
|
|
134
|
+
resource: string;
|
|
135
|
+
values: Record<string, unknown>;
|
|
136
|
+
} | {
|
|
137
|
+
type: 'update';
|
|
138
|
+
resource: string;
|
|
139
|
+
id: string;
|
|
140
|
+
values: Record<string, unknown>;
|
|
141
|
+
} | {
|
|
142
|
+
type: 'delete';
|
|
143
|
+
resource: string;
|
|
144
|
+
id: string;
|
|
145
|
+
} | {
|
|
146
|
+
type: 'bulk';
|
|
147
|
+
resource: string;
|
|
148
|
+
action: string;
|
|
149
|
+
ids: string[];
|
|
150
|
+
} | {
|
|
151
|
+
type: 'change';
|
|
152
|
+
change: RecordChange;
|
|
153
|
+
};
|
|
154
|
+
export type PluginRequest = PluginCall & {
|
|
155
|
+
tenant: Tenant | null;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* One signed call. A 404 is null; a 422 with `{ errors: { field: [message] } }`
|
|
159
|
+
* is the form's field errors, exactly as Laravel's are; anything else that is
|
|
160
|
+
* not a 2xx is a failure with the plugin's name on it.
|
|
161
|
+
*/
|
|
162
|
+
export declare function callPlugin(installation: Installation, call: PluginCall, context: SourceContext, allow: (url: URL) => boolean, timeout?: number): Promise<unknown>;
|
|
163
|
+
/**
|
|
164
|
+
* A Standard Schema from the manifest's JSON Schema, so a plugin's form goes
|
|
165
|
+
* through the same parse as any other. It checks what is cheap and safe to
|
|
166
|
+
* check here - types, required, enums, lengths, bounds - and never `pattern`;
|
|
167
|
+
* the plugin's endpoint checks everything again and answers 422.
|
|
168
|
+
*/
|
|
169
|
+
export declare function jsonSchemaForm(form: ManifestResource['form']): FormSchema;
|
|
170
|
+
/** An installation's resources, as the panel's own. */
|
|
171
|
+
export declare function resourcesOf(installation: Installation, allow: (url: URL) => boolean): Resource[];
|
|
172
|
+
/** Whether a plugin is told about a change: one of its events, which its scopes or ownership allow. */
|
|
173
|
+
export declare function wantsChange(installation: Installation, change: RecordChange): boolean;
|