@antelopejs/interface-dms 0.13.3 → 0.14.1
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/CHANGELOG.md +231 -2
- package/README.md +9 -9
- package/dist/auth/db/models/sessions.model.d.ts +3 -3
- package/dist/auth/db/models/userExternalIdentities.model.d.ts +3 -3
- package/dist/auth/db/models/users.model.d.ts +3 -3
- package/dist/auth/db/tables/users.table.d.ts +3 -3
- package/dist/base/activity-feed.d.ts +2 -2
- package/dist/base/block-registry/types.d.ts +1 -1
- package/dist/base/chart-schemas.d.ts +70 -70
- package/dist/base/chart.d.ts +1 -1
- package/dist/base/data-types/default/choices.d.ts +1 -1
- package/dist/base/data-types/default/choices.js +3 -6
- package/dist/base/data-types/default/choices.js.map +1 -1
- package/dist/base/data-types/default/inputs.d.ts +1 -1
- package/dist/base/data-types/default/numbers.d.ts +2 -1
- package/dist/base/data-types/default/numbers.js +4 -3
- package/dist/base/data-types/default/numbers.js.map +1 -1
- package/dist/base/data-types/default/relations.d.ts +0 -6
- package/dist/base/data-types/default/relations.js +0 -1
- package/dist/base/data-types/default/relations.js.map +1 -1
- package/dist/base/data-types/default-types.d.ts +0 -1
- package/dist/base/data-types/default-types.js +0 -2
- package/dist/base/data-types/default-types.js.map +1 -1
- package/dist/base/data-types/index.js +0 -1
- package/dist/base/data-types/index.js.map +1 -1
- package/dist/base/data-types/internal/relation-endpoints.js +5 -3
- package/dist/base/data-types/internal/relation-endpoints.js.map +1 -1
- package/dist/base/data-types/internal/table-view-meta-slot.d.ts +17 -0
- package/dist/base/data-types/internal/table-view-meta-slot.js +25 -0
- package/dist/base/data-types/internal/table-view-meta-slot.js.map +1 -0
- package/dist/base/empty-state.d.ts +1 -1
- package/dist/base/export-jobs.d.ts +47 -19
- package/dist/base/export-jobs.js +39 -4
- package/dist/base/export-jobs.js.map +1 -1
- package/dist/base/form-schema.d.ts +0 -1
- package/dist/base/form-schema.js +12 -12
- package/dist/base/form-schema.js.map +1 -1
- package/dist/base/grid.js +1 -1
- package/dist/base/grid.js.map +1 -1
- package/dist/base/guard.d.ts +4 -4
- package/dist/base/guard.js +1 -1
- package/dist/base/guard.js.map +1 -1
- package/dist/base/helpers/file-refs.js +4 -6
- package/dist/base/helpers/file-refs.js.map +1 -1
- package/dist/base/internal/chart.d.ts +1 -1
- package/dist/base/internal/chart.js +1 -1
- package/dist/base/internal/chart.js.map +1 -1
- package/dist/base/internal/export-jobs.d.ts +11 -0
- package/dist/base/internal/export-jobs.js +11 -0
- package/dist/base/internal/export-jobs.js.map +1 -1
- package/dist/base/internal/form-block-schema.d.ts +1 -1
- package/dist/base/internal/form-block-schema.js +1 -1
- package/dist/base/internal/form-block-schema.js.map +1 -1
- package/dist/base/key-value-list.d.ts +6 -6
- package/dist/base/meter.d.ts +1 -1
- package/dist/base/placeholder.js +1 -1
- package/dist/base/placeholder.js.map +1 -1
- package/dist/base/searchable.d.ts +3 -3
- package/dist/base/searchable.js.map +1 -1
- package/dist/base/stack.js +1 -1
- package/dist/base/stack.js.map +1 -1
- package/dist/base/tab.js +1 -1
- package/dist/base/tab.js.map +1 -1
- package/dist/base/table-view/data-functions.d.ts +10 -11
- package/dist/base/table-view/data-functions.js.map +1 -1
- package/dist/base/table-view/factory.js +2 -0
- package/dist/base/table-view/factory.js.map +1 -1
- package/dist/base/table-view/internal/archive-filter.d.ts +21 -0
- package/dist/base/table-view/internal/archive-filter.js +48 -0
- package/dist/base/table-view/internal/archive-filter.js.map +1 -0
- package/dist/base/table-view/internal/auth.d.ts +2 -2
- package/dist/base/table-view/internal/auth.js +1 -3
- package/dist/base/table-view/internal/auth.js.map +1 -1
- package/dist/base/table-view/internal/column-conditions.js.map +1 -1
- package/dist/base/table-view/internal/data-functions.d.ts +2 -2
- package/dist/base/table-view/internal/factory-lifecycle-created.js +3 -2
- package/dist/base/table-view/internal/factory-lifecycle-created.js.map +1 -1
- package/dist/base/table-view/internal/footer.js +21 -13
- package/dist/base/table-view/internal/footer.js.map +1 -1
- package/dist/base/table-view/internal/guards.d.ts +1 -1
- package/dist/base/table-view/internal/guards.js +11 -8
- package/dist/base/table-view/internal/guards.js.map +1 -1
- package/dist/base/table-view/internal/meta-helpers.js +3 -2
- package/dist/base/table-view/internal/meta-helpers.js.map +1 -1
- package/dist/base/table-view/internal/nav-badges.js +1 -3
- package/dist/base/table-view/internal/nav-badges.js.map +1 -1
- package/dist/base/table-view/internal/option-views.d.ts +7 -4
- package/dist/base/table-view/internal/row-actions-schema.d.ts +6 -6
- package/dist/base/table-view/meta.d.ts +5 -5
- package/dist/base/table-view/meta.js +6 -2
- package/dist/base/table-view/meta.js.map +1 -1
- package/dist/base/table-view/routes.d.ts +39 -12
- package/dist/base/table-view/routes.js +0 -1
- package/dist/base/table-view/routes.js.map +1 -1
- package/dist/base/table-view/schema.d.ts +127 -127
- package/dist/base/top-list-card.d.ts +4 -4
- package/dist/component-options/data-type.d.ts +2 -1
- package/dist/component-options/data-type.js +1 -1
- package/dist/component-options/data-type.js.map +1 -1
- package/dist/component-slots.js +1 -1
- package/dist/component-slots.js.map +1 -1
- package/dist/connection-access.d.ts +46 -0
- package/dist/connection-access.js +73 -0
- package/dist/connection-access.js.map +1 -0
- package/dist/data-controllers/members.d.ts +15 -2
- package/dist/data-controllers/roles.d.ts +15 -2
- package/dist/db/internal/exportJobs.model.d.ts +3 -3
- package/dist/db/internal/inviteResolutions.model.d.ts +16 -3
- package/dist/db/internal/inviteResolutions.model.js +38 -0
- package/dist/db/internal/inviteResolutions.model.js.map +1 -1
- package/dist/db/internal/tenantLifecycle.model.d.ts +4 -4
- package/dist/db/internal/tenantLifecycle.model.js +2 -3
- package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
- package/dist/db/models/roles.model.d.ts +3 -3
- package/dist/db/models/tenantMembers.model.d.ts +3 -3
- package/dist/db/models/tenants.model.d.ts +3 -3
- package/dist/db/models/user_invites.model.d.ts +18 -3
- package/dist/db/models/user_invites.model.js +28 -0
- package/dist/db/models/user_invites.model.js.map +1 -1
- package/dist/db/tables/user_invites.table.d.ts +6 -1
- package/dist/db/tables/user_invites.table.js +3 -0
- package/dist/db/tables/user_invites.table.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/component-slots.js +1 -1
- package/dist/internal/component-slots.js.map +1 -1
- package/dist/internal/invite-content.d.ts +8 -0
- package/dist/internal/invite-content.js +36 -0
- package/dist/internal/invite-content.js.map +1 -0
- package/dist/internal/invite-resolution.js +5 -2
- package/dist/internal/invite-resolution.js.map +1 -1
- package/dist/internal/tenant-ownership.d.ts +5 -4
- package/dist/internal/tenant-ownership.js +5 -4
- package/dist/internal/tenant-ownership.js.map +1 -1
- package/dist/invite-extensions/internal/delivery.d.ts +3 -2
- package/dist/invite-extensions/internal/delivery.js +3 -2
- package/dist/invite-extensions/internal/delivery.js.map +1 -1
- package/dist/invite-resolution.d.ts +5 -1
- package/dist/invite-resolution.js +10 -26
- package/dist/invite-resolution.js.map +1 -1
- package/dist/invites.d.ts +5 -0
- package/dist/invites.js +58 -1
- package/dist/invites.js.map +1 -1
- package/dist/notifications/internal.d.ts +0 -1
- package/dist/notifications/internal.js +0 -1
- package/dist/notifications/internal.js.map +1 -1
- package/dist/notifications/sendable.d.ts +1 -2
- package/dist/notifications/sendable.js +1 -12
- package/dist/notifications/sendable.js.map +1 -1
- package/dist/notifications/types.d.ts +1 -4
- package/dist/page/categories.d.ts +6 -0
- package/dist/page/categories.js +10 -3
- package/dist/page/categories.js.map +1 -1
- package/dist/page/controllers.d.ts +6 -9
- package/dist/page/controllers.js +5 -6
- package/dist/page/controllers.js.map +1 -1
- package/dist/page/internal/categories.js +43 -32
- package/dist/page/internal/categories.js.map +1 -1
- package/dist/page/internal/category-resolution.d.ts +31 -0
- package/dist/page/internal/category-resolution.js +63 -0
- package/dist/page/internal/category-resolution.js.map +1 -0
- package/dist/page/internal/metadata-extension-contributions.js +1 -2
- package/dist/page/internal/metadata-extension-contributions.js.map +1 -1
- package/dist/page/internal/metadata-info.js +19 -7
- package/dist/page/internal/metadata-info.js.map +1 -1
- package/dist/page/internal/metadata-layout.d.ts +3 -2
- package/dist/page/internal/metadata-layout.js.map +1 -1
- package/dist/page/internal/metadata-lifecycle.js +1 -4
- package/dist/page/internal/metadata-lifecycle.js.map +1 -1
- package/dist/page/internal/metadata-publish.js +7 -6
- package/dist/page/internal/metadata-publish.js.map +1 -1
- package/dist/page/internal/metadata-registration.js +8 -6
- package/dist/page/internal/metadata-registration.js.map +1 -1
- package/dist/page/internal/page-controller.d.ts +18 -0
- package/dist/page/internal/page-controller.js +36 -0
- package/dist/page/internal/page-controller.js.map +1 -0
- package/dist/page/metadata.d.ts +3 -3
- package/dist/page/metadata.js +4 -2
- package/dist/page/metadata.js.map +1 -1
- package/dist/page/types.d.ts +8 -2
- package/dist/page.d.ts +1 -1
- package/dist/page.js +2 -1
- package/dist/page.js.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.js +5 -2
- package/dist/permissions.js.map +1 -1
- package/dist/tenant-provisioning.js +1 -1
- package/dist/tenant-provisioning.js.map +1 -1
- package/dist/types.d.ts +7 -3
- package/docs/1.core/11.modules-and-dynamic-menus.md +3 -3
- package/docs/1.core/2.pages-and-modules.md +2 -1
- package/docs/1.core/4.permissions.md +2 -2
- package/docs/1.core/5.tenancy.md +1 -1
- package/docs/1.core/6.invites.md +3 -1
- package/docs/2.auth/2.authentication.md +1 -1
- package/docs/2.auth/3.tokens-and-sessions.md +1 -1
- package/docs/3.base/1.introduction.md +1 -1
- package/docs/3.base/14.table-events-and-helpers.md +1 -1
- package/docs/3.base/15.table-sources-and-gates.md +14 -2
- package/docs/3.base/3.forms.md +1 -1
- package/docs/3.base/4.tables.md +1 -1
- package/docs/3.base/5.charts-and-widgets.md +3 -3
- package/docs/3.base/8.data-types.md +1 -1
- package/docs/3.base/9.helpers.md +16 -5
- package/docs/4.notifications/3.sending.md +0 -11
- package/docs/index.md +1 -1
- package/package.json +11 -11
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Table sources and tenant gates"
|
|
3
|
-
description: Table views over a module's own route,
|
|
3
|
+
description: Table views over a module's own route, table views that stay readable behind a tenant access gate, and table views over an external connection.
|
|
4
4
|
mode: reference
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
A [table view](/docs/interfaces/base/tables) usually reads a data controller. These
|
|
7
|
+
A [table view](/docs/interfaces/base/tables) usually reads a data controller. These three cases differ: a table view over a module's own route, a table view that stays readable while a tenant access gate denies the tenant, and a table view over a table of an external connection.
|
|
8
8
|
|
|
9
9
|
## Tables over a module's route
|
|
10
10
|
|
|
@@ -22,3 +22,15 @@ Data routes are registered against the controller, not against a page, so the op
|
|
|
22
22
|
|
|
23
23
|
- Declaring the flag on a controller opens its routes for every table view built on it, including one mounted on an ordinary page.
|
|
24
24
|
- Actions that carry no permission id, such as a plain list on a component that was never mounted, are then served to any member of a denied tenant. That is the escape hatch working as intended, so keep every action of a flagged controller stamped with a permission.
|
|
25
|
+
|
|
26
|
+
## Write to an external connection
|
|
27
|
+
|
|
28
|
+
`@ExternalConnection(connection)`, from `@antelopejs/interface-dms/connection-access`, marks a data controller whose table belongs to an external connection, as the builder does on each table it maps. Its `TableViewRoutes` write routes (`new`, `edit`, `delete`, `archive`, `restore`) then call `AssertConnectionWritable` first, which answers 403 unless `GetConnectionAccess(connection)` is `"read-write"`. Reads are not affected.
|
|
29
|
+
|
|
30
|
+
```typescript fragment
|
|
31
|
+
@RegisterDataController()
|
|
32
|
+
@ExternalConnection("erp")
|
|
33
|
+
export class CountryDataAPI extends DataController(Country, TableViewRoutes.All, Controller("/erp/countries")) {}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The module that owns the connections answers their access with `RegisterConnectionAccessSource(id, source)` during `construct()`, as `dms-database` does from `config.externalConnections`. `source(connection)` returns `"read"`, `"read-write"`, or `undefined` for a connection it does not own. A connection is `"read-write"` only when a source answers `"read-write"` and none answers `"read"`, so a connection no source answers stays read-only. A route a module writes itself on a marked controller calls `AssertConnectionWritable(controller)` before it writes.
|
package/docs/3.base/3.forms.md
CHANGED
|
@@ -301,7 +301,7 @@ The option interfaces live in the same namespace. The ones with more than a plac
|
|
|
301
301
|
| `DatePickerRangeOptions` | `minDate?`, `maxDate?` |
|
|
302
302
|
| `RelationOptions` | `searchUrl: string`, `placeholder?`, `multiple?`, `deselectable?`, `keyMapping?: { label?, value?, avatar?, disabled? }`, `addForm?: ComponentInfoSerialized<FormPropsSerialized>`, `addPermissionIds?: string[]`, `addFormTexts?: { displayName?, description? }` |
|
|
303
303
|
| `CascaderRelationKeyMapping` | `label: string`, `value: string`, `parent: string`, `disabled?` |
|
|
304
|
-
| `CascaderRelationOptions` | `searchUrl: string`, `keyMapping: CascaderRelationKeyMapping`, `placeholder?`, `multiple?`, `deselectable?`, `maxDepth?`, `leafOnly
|
|
304
|
+
| `CascaderRelationOptions` | `searchUrl: string`, `keyMapping: CascaderRelationKeyMapping`, `placeholder?`, `multiple?`, `deselectable?`, `maxDepth?`, `leafOnly?` |
|
|
305
305
|
| `AddressOptions` | `placeholder?` (per address component), `autocomplete?: DefaultDataTypes.AddressAutocomplete` |
|
|
306
306
|
| `FileOptions` | `multiple?`, `constraints?: { maxSize?, allowedMimetypes? }`, `path?`, `storage?` |
|
|
307
307
|
| `ImageOptions` | `FileOptions` plus `max?` and `resize?: ImageResizeOptions` |
|
package/docs/3.base/4.tables.md
CHANGED
|
@@ -178,7 +178,7 @@ export class customerDataAPI extends DataController(/* … */) {
|
|
|
178
178
|
|
|
179
179
|
### The archive field
|
|
180
180
|
|
|
181
|
-
`@ArchiveField` marks the boolean field that carries the archived state. It
|
|
181
|
+
`@ArchiveField` marks the boolean field that carries the archived state. It makes the field `Listable()` and registers a filter that reads `true` or `false` with `eq` or `ne`. `TableView` throws when another `Filter` replaces it.
|
|
182
182
|
|
|
183
183
|
```typescript fragment
|
|
184
184
|
import { ArchiveField } from "@antelopejs/interface-dms/base/table-view";
|
|
@@ -310,7 +310,7 @@ const card = ChartCard({
|
|
|
310
310
|
| `periodScope` | `string` | Id of the `PeriodSelector` to follow. |
|
|
311
311
|
| `valueFormat` | `ValueFormat` | How the headline value is formatted. |
|
|
312
312
|
| `currencyCode` | `string` | Currency for `valueFormat: "currency"`. |
|
|
313
|
-
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted
|
|
313
|
+
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted uses the format's default: whole currency amounts, at most one fraction digit for percent and compact. Also applies to the previous value and nested chart's value axis and tooltip. |
|
|
314
314
|
| `showDelta` | `boolean` | Show the change against the comparison period. |
|
|
315
315
|
| `invert` | `boolean` | Treat an increase as bad, for metrics where lower is better. |
|
|
316
316
|
| `showLegend` | `boolean` | Show the primary / comparison legend. Defaults to `true`. |
|
|
@@ -349,7 +349,7 @@ const denied = KpiCard({
|
|
|
349
349
|
| `realtimeTopic` | `string \| string[]` | Topics whose events make the card read `fetchUrl` again, through the page's `live` gate. The builder registers them on the page. |
|
|
350
350
|
| `valueFormat` | `ValueFormat` | How the value is formatted. |
|
|
351
351
|
| `currencyCode` | `string` | Currency for `valueFormat: "currency"`. |
|
|
352
|
-
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted
|
|
352
|
+
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted uses the format's default: whole currency amounts, at most one fraction digit for percent and compact. |
|
|
353
353
|
| `showDelta` | `boolean` | Show the change against the comparison period. |
|
|
354
354
|
| `showPreviousValue` | `boolean` | Show the route's `previousValue` next to the change ("vs €42,900"), formatted as the value. Defaults to `true`. |
|
|
355
355
|
| `showSparkline` | `boolean` | Show the sparkline. |
|
|
@@ -389,7 +389,7 @@ const topSkills = TopListCard({
|
|
|
389
389
|
| `periodScope` | `string` | Id of the `PeriodSelector` to follow. |
|
|
390
390
|
| `valueFormat` | `ValueFormat` | How each item's value is formatted. |
|
|
391
391
|
| `currencyCode` | `string` | Currency for `valueFormat: "currency"`. |
|
|
392
|
-
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted
|
|
392
|
+
| `valuePrecision` | `ValuePrecision` | Fixed fraction digits or `"native"` Intl defaults; omitted uses the format's default: whole currency amounts, at most one fraction digit for percent and compact. |
|
|
393
393
|
| `valueSuffix` | `string` | Unit written right after each formatted value, space included (`" ms"`); a `$`-prefixed key is translated. Not added to a `valueLabel`. |
|
|
394
394
|
| `showRank` | `boolean` | Show the rank number. |
|
|
395
395
|
| `highlightTopN` | `number` | How many leading items are highlighted. |
|
|
@@ -361,7 +361,7 @@ The type's options are `placeholder` (one string per address component), `autoco
|
|
|
361
361
|
|
|
362
362
|
`FileTypeOptions` has `multiple?`, `constraints?: UploadConstraints`, `path?`, `storage?` and `fallback?`. `ImageTypeOptions` has `multiple?`, `max?`, `constraints?`, `path?`, `storage?` and `resize?`, the `FormComponents.ImageResizeOptions` the input applies client-side before uploading ([Forms](/docs/interfaces/base/forms)). Both accept `attachmentField?` for a stable native field identity and `visibility?: "private" | "public"`, defaulting to private. `constraints` is the `UploadConstraints` type from `@antelopejs/interface-file-storage`; `storage` names the storage backend and `path` the prefix uploads land under.
|
|
363
363
|
|
|
364
|
-
A file value is the resource key as a string. Metadata-based validation checks configured constraints, matching `allowedMimetypes` patterns including the `type/*` form. A native field's save integration also validates upload provenance and canonical metadata before persistence.
|
|
364
|
+
A file value is the resource key as a string. Metadata-based validation checks configured constraints, matching `allowedMimetypes` patterns including the `type/*` form. A native field's save integration also validates upload provenance and canonical metadata before persistence. A key with no recorded upload is refused with HTTP 403, both in the submitted document and in the previously stored one, and the native metadata endpoint does not read it. A storage outage propagates as a server error rather than becoming a field validation error. An image value is an `ImageValue`, `{ key: string; alt?: string; principal?: boolean }`, and `ImageType` defaults `allowedMimetypes` to `["image/*"]`, caps the array at `max` when `multiple` is set, and rejects a list with more than one `principal` image.
|
|
365
365
|
|
|
366
366
|
Both types enable the table view's native file handling: authorized saves promote staging keys, and successful edits or deletes clean removed native references. Failed saves retain promoted objects; cleanup is not reference-counted across records. See [File storage](/docs/components/file-storage) for authorization, visibility, retries, and custom save routes, and [Helpers](/docs/interfaces/base/helpers) for comparing references within records.
|
|
367
367
|
|
package/docs/3.base/9.helpers.md
CHANGED
|
@@ -145,7 +145,7 @@ function runExportJob<TContext = unknown>(
|
|
|
145
145
|
| `ctx` | `RequestContext` | The request. The job is stored in the schema of the tenant the request resolves to. Required. |
|
|
146
146
|
| `user` | `User` | The owner of the job. Required; a missing user fails with `401`. |
|
|
147
147
|
| `scope` | `string` | Free-form identifier for the origin of the job, checked again on status and download when you pass it there. Required. |
|
|
148
|
-
| `context` | `TContext` | Scope-specific payload stored with the job
|
|
148
|
+
| `context` | `TContext` | Scope-specific payload stored with the job as JSON. `generate` receives it as passed; `isOwnedBy` receives it read back through `contextSchema`. |
|
|
149
149
|
| `filename` | `string` | Base name of the produced file, without extension or timestamp. Required. |
|
|
150
150
|
| `extension` | `string` | File extension. Required. |
|
|
151
151
|
| `contentType` | `string` | MIME type used when uploading and when streaming the file back. Required. |
|
|
@@ -188,7 +188,7 @@ By default a job is deleted once it has been downloaded. Set `retainUntilExpiry`
|
|
|
188
188
|
| `jobId` | `string` | Identifier of this job. |
|
|
189
189
|
| `tenantId` | `string` | Tenant the job belongs to. |
|
|
190
190
|
| `localPath` | `string` | Path your generator writes the file to. |
|
|
191
|
-
| `context` | `TContext` | The payload passed as `context` to `runExportJob
|
|
191
|
+
| `context` | `TContext \| undefined` | The payload passed as `context` to `runExportJob`, `undefined` when it passed none. |
|
|
192
192
|
| `reportProgress` | `(progress: number) => Promise<void>` | Records progress. The value is floored and clamped to `0` through `99`; repeating the last value writes nothing. Throws once the job is aborted. |
|
|
193
193
|
| `signal` | `AbortSignal` | Aborted when the job exceeds `maxExecutionTimeMs`. |
|
|
194
194
|
|
|
@@ -216,7 +216,7 @@ function downloadExportJob<TContext = unknown>(
|
|
|
216
216
|
|
|
217
217
|
`downloadExportJob` requires a completed job with a stored result. Anything else fails with `400` or `500`. It sets `Content-Disposition` (with a filename built by `buildExportFilename`), `Content-Length` when the size is known, and `Access-Control-Expose-Headers`, then pipes the stored object to the response. The function returns as soon as the pipe is set up rather than awaiting it; once the response stream closes, the stored object and the job record are both deleted.
|
|
218
218
|
|
|
219
|
-
`loadExportJobForUser(ctx, user, jobId, access?)` is the shared step underneath both: it resolves the tenant, loads the record, runs the access checks, and returns the model
|
|
219
|
+
`loadExportJobForUser(ctx, user, jobId, access?)` is the shared step underneath both: it resolves the tenant, loads the record, runs the access checks, and returns the model and the record. Use it when you need the record itself rather than its status.
|
|
220
220
|
|
|
221
221
|
`downloadExportJob` deletes the stored object and the job record once the response stream closes, unless the job was started with `retainUntilExpiry`, in which case both survive until the sweep.
|
|
222
222
|
|
|
@@ -239,9 +239,20 @@ Returns the caller's own jobs, most recent first: the history a scope such as a
|
|
|
239
239
|
| Option | Type | Description |
|
|
240
240
|
| --- | --- | --- |
|
|
241
241
|
| `scope` | `string` | When set, the job's stored `scope` must match. |
|
|
242
|
-
| `
|
|
242
|
+
| `contextSchema` | `ZodType<TContext, ZodTypeDef, unknown>` | Reads back the `context` the job was started with, from the JSON it was stored as: `null` for a job started without one, a `Date` as its ISO string. A stored context it refuses refuses the job. Required with `isOwnedBy`. |
|
|
243
|
+
| `isOwnedBy` | `(record, context, user) => boolean` | Extra ACL evaluated after the ownership and scope checks, on the context `contextSchema` read. Required with `contextSchema`. |
|
|
243
244
|
|
|
244
|
-
`
|
|
245
|
+
`ExportJobContextCheck<TContext>` is the pair `contextSchema` and `isOwnedBy`. `ExportJobOwnership<TContext>` is that pair or neither of its members, and `ExportJobAccessOptions<TContext>` adds `scope` to it. The job's `userId` is always compared against the caller regardless of what you pass, and every failed check answers `403`.
|
|
246
|
+
|
|
247
|
+
```typescript fragment
|
|
248
|
+
import { z } from "zod";
|
|
249
|
+
|
|
250
|
+
const status = await getExportJobStatus(ctx, user, jobId, {
|
|
251
|
+
scope: SCOPE,
|
|
252
|
+
contextSchema: z.object({ year: z.number() }),
|
|
253
|
+
isOwnedBy: (_record, context) => context.year === new Date().getFullYear(),
|
|
254
|
+
});
|
|
255
|
+
```
|
|
245
256
|
|
|
246
257
|
### Formats and delivery
|
|
247
258
|
|
|
@@ -202,17 +202,6 @@ A shared-read send derives a stable group ID from the event key. The DMS checks
|
|
|
202
202
|
|
|
203
203
|
Realtime publishing is best-effort and happens only after a newly inserted delivery. A crash or a lost acknowledgement can leave a stored notification without a realtime event, and a retry does not replay it. The delivery rules still apply, and a skipped recipient gets no receipt.
|
|
204
204
|
|
|
205
|
-
Before it sends, every keyed dispatch asks the DMS implementation, through `SupportsIdempotency`, whether it supports keyed delivery. If the implementation does not answer `true`, the dispatch throws `DMS idempotent notification delivery is unavailable` and sends nothing, rather than delivering without deduplication.
|
|
206
|
-
|
|
207
|
-
If your module can load against a DMS implementation that has no `toUsersIdempotently` method, check for the method and fail closed. Keep the pending outbox work until the DMS packages provide it:
|
|
208
|
-
|
|
209
|
-
```typescript fragment
|
|
210
|
-
if (!("toUsersIdempotently" in shipped) || typeof shipped.toUsersIdempotently !== "function") {
|
|
211
|
-
throw new Error("DMS idempotent notification delivery is unavailable");
|
|
212
|
-
}
|
|
213
|
-
await shipped.toUsersIdempotently([ownerId, managerId], event.id);
|
|
214
|
-
```
|
|
215
|
-
|
|
216
205
|
## Delivery rules
|
|
217
206
|
|
|
218
207
|
Every dispatch method resolves to one delivery per user, so the DMS applies the same rules to each of them:
|
package/docs/index.md
CHANGED
|
@@ -87,7 +87,7 @@ Each subpath is its own entry point, and importing one does not load the others.
|
|
|
87
87
|
|
|
88
88
|
Beyond these entry points, built files are importable through the `./*` export (`@antelopejs/interface-dms/base/form-types`). Moving or renaming a public path is a breaking change, like removing an export.
|
|
89
89
|
|
|
90
|
-
Importability does not make a declaration public. Paths under `internal/`, symbols tagged `@internal`, and `internal` namespaces are wiring between the interface and its implementation, not supported consumer APIs. This includes
|
|
90
|
+
Importability does not make a declaration public. Paths under `internal/`, symbols tagged `@internal`, and `internal` namespaces are wiring between the interface and its implementation, not supported consumer APIs. This includes internal symbols kept at a path a module already imports. Public types named by a supported signature remain part of its contract. Use the documented entry points rather than calling internal proxies or raw writer helpers.
|
|
91
91
|
|
|
92
92
|
## How a domain folder is laid out
|
|
93
93
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-dms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Public AntelopeJS interfaces of the DMS: pages, components, permissions, tenancy, auth, notifications and HTML rendering.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
@@ -43,25 +43,25 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"randomstring": "^1.3.1",
|
|
46
|
-
"zod": "
|
|
46
|
+
"zod": "^3.24.2",
|
|
47
47
|
"zod-to-json-schema": "~3.24.6"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@antelopejs/interface-api": ">=0.3.0 <1.0.0",
|
|
51
51
|
"@antelopejs/interface-api-util": ">=0.1.3 <1.0.0",
|
|
52
|
-
"@antelopejs/interface-core": ">=0.
|
|
53
|
-
"@antelopejs/interface-data-api": ">=0.
|
|
54
|
-
"@antelopejs/interface-database": ">=0.
|
|
55
|
-
"@antelopejs/interface-database-decorators": ">=0.
|
|
52
|
+
"@antelopejs/interface-core": ">=0.5.1 <1.0.0",
|
|
53
|
+
"@antelopejs/interface-data-api": ">=0.8.0 <0.9.0",
|
|
54
|
+
"@antelopejs/interface-database": ">=0.4.0 <0.5.0",
|
|
55
|
+
"@antelopejs/interface-database-decorators": ">=0.5.2 <0.6.0",
|
|
56
56
|
"@antelopejs/interface-file-storage": ">=0.1.4 <1.0.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@antelopejs/interface-api": ">=0.
|
|
59
|
+
"@antelopejs/interface-api": ">=0.3.0 <1.0.0",
|
|
60
60
|
"@antelopejs/interface-api-util": ">=0.3.0 <1.0.0",
|
|
61
|
-
"@antelopejs/interface-core": ">=0.
|
|
62
|
-
"@antelopejs/interface-data-api": ">=0.
|
|
63
|
-
"@antelopejs/interface-database": ">=0.
|
|
64
|
-
"@antelopejs/interface-database-decorators": ">=0.
|
|
61
|
+
"@antelopejs/interface-core": ">=0.5.1 <1.0.0",
|
|
62
|
+
"@antelopejs/interface-data-api": ">=0.8.0 <0.9.0",
|
|
63
|
+
"@antelopejs/interface-database": ">=0.4.0 <0.5.0",
|
|
64
|
+
"@antelopejs/interface-database-decorators": ">=0.5.2 <0.6.0",
|
|
65
65
|
"@antelopejs/interface-file-storage": ">=0.1.4 <1.0.0",
|
|
66
66
|
"@types/node": "^24.0.0",
|
|
67
67
|
"@types/randomstring": "^1.3.0",
|