@antelopejs/interface-dms-saas 0.3.0 → 0.4.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/README.md +75 -66
- package/dist/billing.d.ts +2 -0
- package/dist/billing.js +2 -1
- package/dist/billing.js.map +1 -1
- package/dist/db/models/billingSettings.model.d.ts +1 -0
- package/dist/db/models/creditNotes.model.d.ts +2 -0
- package/dist/db/models/creditNotes.model.js +9 -0
- package/dist/db/models/creditNotes.model.js.map +1 -1
- package/dist/db/models/features.model.d.ts +1 -0
- package/dist/db/models/invoices.model.d.ts +1 -0
- package/dist/db/models/legalDocuments.model.d.ts +1 -0
- package/dist/db/models/planMigrations.model.d.ts +6 -2
- package/dist/db/models/planMigrations.model.js +25 -8
- package/dist/db/models/planMigrations.model.js.map +1 -1
- package/dist/db/models/plans.model.d.ts +1 -0
- package/dist/db/models/platformNotes.model.d.ts +1 -0
- package/dist/db/models/refunds.model.d.ts +1 -0
- package/dist/db/models/segments.model.d.ts +8 -2
- package/dist/db/models/segments.model.js +14 -3
- package/dist/db/models/segments.model.js.map +1 -1
- package/dist/db/models/stripeWebhookEvents.model.d.ts +1 -0
- package/dist/db/models/tenantBillingInfo.model.d.ts +1 -0
- package/dist/db/models/tenantBillingState.model.d.ts +4 -2
- package/dist/db/models/tenantBillingState.model.js +47 -5
- package/dist/db/models/tenantBillingState.model.js.map +1 -1
- package/dist/db/models/tenantSubscriptions.model.d.ts +2 -0
- package/dist/db/models/tenantSubscriptions.model.js +6 -0
- package/dist/db/models/tenantSubscriptions.model.js.map +1 -1
- package/dist/db/models/trialConsumptions.model.d.ts +1 -0
- package/dist/db/models/userSegments.model.d.ts +3 -1
- package/dist/db/models/userSegments.model.js +2 -2
- package/dist/db/models/userSegments.model.js.map +1 -1
- package/dist/db/tables/billingSettings.table.d.ts +2 -1
- package/dist/db/tables/billingSettings.table.js +5 -1
- package/dist/db/tables/billingSettings.table.js.map +1 -1
- package/dist/db/tables/features.table.js +2 -0
- package/dist/db/tables/features.table.js.map +1 -1
- package/dist/db/tables/invoices.table.d.ts +6 -0
- package/dist/db/tables/invoices.table.js +24 -0
- package/dist/db/tables/invoices.table.js.map +1 -1
- package/dist/db/tables/legalDocuments.table.d.ts +8 -0
- package/dist/db/tables/legalDocuments.table.js +10 -1
- package/dist/db/tables/legalDocuments.table.js.map +1 -1
- package/dist/db/tables/planMigrations.table.d.ts +19 -1
- package/dist/db/tables/planMigrations.table.js +60 -1
- package/dist/db/tables/planMigrations.table.js.map +1 -1
- package/dist/db/tables/plans.table.d.ts +1 -0
- package/dist/db/tables/plans.table.js +2 -1
- package/dist/db/tables/plans.table.js.map +1 -1
- package/dist/db/tables/segments.table.d.ts +6 -0
- package/dist/db/tables/segments.table.js +8 -0
- package/dist/db/tables/segments.table.js.map +1 -1
- package/dist/db/tables/tenantBillingState.table.d.ts +48 -1
- package/dist/db/tables/tenantBillingState.table.js +100 -1
- package/dist/db/tables/tenantBillingState.table.js.map +1 -1
- package/dist/db/tables/tenantSubscriptions.table.d.ts +2 -0
- package/dist/db/tables/tenantSubscriptions.table.js +9 -0
- package/dist/db/tables/tenantSubscriptions.table.js.map +1 -1
- package/dist/page-definitions.d.ts +1 -8
- package/dist/page-definitions.js +1 -27
- package/dist/page-definitions.js.map +1 -1
- package/dist/pages.d.ts +1 -2
- package/dist/pages.js +13 -11
- package/dist/pages.js.map +1 -1
- package/dist/plans.d.ts +1 -1
- package/dist/plans.js +12 -2
- package/dist/plans.js.map +1 -1
- package/docs/1.index.md +47 -0
- package/docs/2.billing.md +66 -0
- package/docs/3.lifecycle-and-usage.md +95 -0
- package/docs/4.pages-plans-data.md +64 -0
- package/docs/tsconfig.json +11 -0
- package/package.json +24 -11
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Lifecycle and usage
|
|
3
|
+
description: Registration extras, durable workspace lifecycle consumers and idempotent invoice usage providers.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lifecycle and usage
|
|
7
|
+
|
|
8
|
+
Use the direct subpaths below or the root's `invoiceLineItems` and `workspaceLifecycle` namespaces. Register consumers/providers from the owning module's lifecycle, not a request handler. Registrations replay when SaaS attaches or reloads and are released when their owner unloads.
|
|
9
|
+
|
|
10
|
+
## Invoice line items
|
|
11
|
+
|
|
12
|
+
Import from `/invoice-line-items`. `RegisterInvoiceLineItemsProvider(provider: InvoiceLineItemsProvider): void` registers `{ id: string, resolve: InvoiceLineItemsResolver }`. `UnregisterInvoiceLineItemsProvider(providerId: string): void` removes it; unknown IDs are ignored. Register during `construct()` and unregister during `stop()`.
|
|
13
|
+
|
|
14
|
+
```ts [Contract]
|
|
15
|
+
interface InvoiceLineItemsContext {
|
|
16
|
+
tenantId: string;
|
|
17
|
+
invoiceId: string;
|
|
18
|
+
currency: string;
|
|
19
|
+
periodStart: Date;
|
|
20
|
+
periodEnd: Date;
|
|
21
|
+
isPreview?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface InvoiceLineItem {
|
|
25
|
+
key: string;
|
|
26
|
+
description: string;
|
|
27
|
+
amountCents: number;
|
|
28
|
+
quantity?: number;
|
|
29
|
+
unit?: string;
|
|
30
|
+
metadata?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type InvoiceLineItemsResolver = (
|
|
34
|
+
context: InvoiceLineItemsContext,
|
|
35
|
+
) => Promise<InvoiceLineItem[]> | InvoiceLineItem[];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The runtime asks providers for `subscription_cycle` renewal invoices, not initial or one-off invoices. The dates cover the cycle just closed, clipped to the subscription's paid usage period. Complimentary/grace usage is excluded; no provider runs for an empty covered window. Read tenant-scoped, pre-aggregated usage because the resolver runs inside the webhook request.
|
|
39
|
+
|
|
40
|
+
`amountCents` is the safe-integer line total in the invoice currency, including negative credits. Quantity and unit are audit metadata, not factors multiplied into the total. Zero amounts are dropped. Empty keys/descriptions, non-safe-integer amounts, keys containing `:`, or combined keys over 150 characters are invalid. Provider IDs must not contain `:`; registration throws if they do. IDs must be globally unique across modules: a collision replaces the earlier provider, and collisions before attachment can collapse silently.
|
|
41
|
+
|
|
42
|
+
Keep each line key stable. The runtime injects at most one line per invoice/provider/key across webhook replays and concurrent workers. A throwing provider is logged and skipped so others can run, but partial/invalid injection ultimately fails the webhook to expose underbilling. Returning lines is not a guarantee that Stripe accepted the invoice items.
|
|
43
|
+
|
|
44
|
+
Preview calls set `isPreview: true`, use a synthetic `upcoming_<subscription id>` invoice ID, and end at the request time. They quote usage without invoicing it. Do not mutate usage accounting inside a resolver. A failed resolver or invalid line makes the preview unavailable.
|
|
45
|
+
|
|
46
|
+
### Line helpers
|
|
47
|
+
|
|
48
|
+
`LINE_KEY_SEPARATOR` is `":"`. `buildInvoiceLineKey(providerId: string, key: string): string` joins the two fragments; it does not validate them.
|
|
49
|
+
|
|
50
|
+
`selectInvoiceLineItemsToCreate(providerId: string, items: readonly InvoiceLineItem[], alreadyInjectedKeys: ReadonlySet<string>): InvoiceLineItemSelection` is synchronous and has no Stripe side effects. It returns `accepted: PreparedInvoiceLineItem[]` (`{ lineKey, item }`, with trimmed item keys) and `skipped: SkippedInvoiceLineItem[]` (`{ lineKey, reason }`). `SkippedLineItemReason` is `already_invoiced`, `duplicate_key`, `zero_amount`, or `invalid`. The set must contain full provider-prefixed keys. This selection helper does not itself provide transactional idempotency.
|
|
51
|
+
|
|
52
|
+
## Workspace lifecycle
|
|
53
|
+
|
|
54
|
+
Import from `/workspace-lifecycle`. `WORKSPACE_LIFECYCLE_TRANSITIONS` contains `created`, `suspended` and `reactivation_requested`; `WorkspaceLifecycleTransition` is their union.
|
|
55
|
+
|
|
56
|
+
```ts [Contract]
|
|
57
|
+
import type { WorkspaceLifecycleTransition } from "@antelopejs/interface-dms-saas/workspace-lifecycle";
|
|
58
|
+
|
|
59
|
+
interface WorkspaceLifecycleMessage {
|
|
60
|
+
tenantId: string;
|
|
61
|
+
operationId: string;
|
|
62
|
+
transition: WorkspaceLifecycleTransition;
|
|
63
|
+
requestedAt: Date;
|
|
64
|
+
}
|
|
65
|
+
interface WorkspaceLifecycleReceipt {
|
|
66
|
+
receiptId: string;
|
|
67
|
+
effectiveAt?: Date;
|
|
68
|
+
}
|
|
69
|
+
interface WorkspaceLifecycleConsumer {
|
|
70
|
+
name: string;
|
|
71
|
+
transitions: readonly WorkspaceLifecycleTransition[];
|
|
72
|
+
consume(message: WorkspaceLifecycleMessage): Promise<WorkspaceLifecycleReceipt>;
|
|
73
|
+
}
|
|
74
|
+
interface WorkspaceLifecycleConsumerRegistration { unregister(): void; }
|
|
75
|
+
|
|
76
|
+
declare function RegisterWorkspaceLifecycleConsumer(
|
|
77
|
+
consumer: WorkspaceLifecycleConsumer,
|
|
78
|
+
): WorkspaceLifecycleConsumerRegistration;
|
|
79
|
+
declare function UnregisterWorkspaceLifecycleConsumer(name: string): void;
|
|
80
|
+
declare function IsWorkspaceProvisioningCommitted(tenantId: string): Promise<boolean>;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Names must match `/^[a-z][a-z0-9._-]{2,63}$/`; invalid names throw synchronously. Pick a stable unique name and explicitly select transitions. Unregister via the returned handle or by name when the module stops.
|
|
84
|
+
|
|
85
|
+
Delivery is **at least once**. Deduplicate by `operationId`, durably link provisioned resources, then return a durable receipt. A rejection is not an acknowledgement. Suspension closes SaaS access before delivery; reactivation keeps access closed until every registered required consumer returns a receipt. `created` arrives after ownership, billing and pre-provisioning hooks succeed and the first invoice is paid, or no payment is required.
|
|
86
|
+
|
|
87
|
+
`IsWorkspaceProvisioningCommitted` returns false for preparing, unpaid or cancelled self-service workspaces; true for committed creations and legacy/bootstrap tenants without a marker. It is not an existence, membership or access check. Storage and missing-implementation errors propagate; fail closed instead of treating an unavailable check as eligibility.
|
|
88
|
+
|
|
89
|
+
## Registration and provisioning
|
|
90
|
+
|
|
91
|
+
`TenantBeingProvisionedPayload` from `/provisioning` has `tenantId: string`, `userId: string`, and optional `extras: Record<string, unknown>`. Use it with the DMS `Hook.TENANT_BEING_PROVISIONED` hook; the hook handler returns `Promise<undefined>`, not `Promise<void>`.
|
|
92
|
+
|
|
93
|
+
Listeners run serially inside provisioning, while the per-card lock is held, after workspace records exist but before registration returns. A throwing listener cancels registration and rolls back the runtime's tenant, subscription, Stripe customer and password-path account. Do not assume external side effects of your listener roll back automatically. Keep it to bounded persistence work rather than network provisioning; use durable `created` delivery for post-payment resources.
|
|
94
|
+
|
|
95
|
+
Extras reach password and OAuth completion paths unchanged, are absent when nothing was captured, and remain consumer-owned. The runtime does not persist or return them. `/registration` exports `RegistrationExtrasLimits` and `REGISTRATION_EXTRAS_LIMITS`: `maxSerialisedBytes: 4096`, `maxKeys: 64`, `maxDepth: 4`. Public registration also rejects `__proto__`, `constructor`, and `prototype` keys. Rejected extras produce HTTP 400 `saas.errors.registration.extras_*` errors before listeners run.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pages, plans and data
|
|
3
|
+
description: Stable page extension anchors, plan projections and safe use of the canonical data exports.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pages, plans and data
|
|
7
|
+
|
|
8
|
+
These contracts let consumers build backend-declared DMS pages without importing private SaaS controllers.
|
|
9
|
+
|
|
10
|
+
## Page extensions
|
|
11
|
+
|
|
12
|
+
Import from `/pages`. `tenantBillingPage` identifies `settings.workspace.billing` at `/settings/workspace/billing`. Its `components` exposes `freeAccessBanner`, `pastDueAlert`, `planCard`, `paymentMethod`, `billingForm`, `refundButton`, and `table` anchors. `TenantBillingPageComponentKey` is the union of those keys; `tenantBillingPageAnchorPaths` maps them to the current nested layout. Use keys instead of copying paths.
|
|
13
|
+
|
|
14
|
+
`RegisterTenantBillingPageExtension(extension: TenantBillingPageExtension): TenantBillingPageExtensionRegistration` registers `{ name: string, components: readonly TenantBillingPageExtensionComponent[] }` and returns `{ unregister(): void }`. Registration may precede page loading; call the handle's `unregister()` during `stop()`.
|
|
15
|
+
|
|
16
|
+
Each component has `key: string`, `component: Component`, and optional `order: number` (default 0). An anchored component adds `side: "before" | "after"` and `anchorKey: TenantBillingPageComponentKey`; an appended component has optional `side: "end"` and no anchor. These are exported as `TenantBillingPageExtensionComponentBase`, `TenantBillingPageAnchoredExtensionComponent`, and `TenantBillingPageAppendedExtensionComponent`. The plan/payment anchors resolve inside their column's stack, not to an extra grid column.
|
|
17
|
+
|
|
18
|
+
`platformSaasModule: CategoryInfo` is a synchronous descriptor, not the canonical registered module object. `GetPlatformSaasModule(): Promise<CategoryInfo>` resolves that object after runtime attachment and rejects when unavailable. `platformWorkspaceDetailPage` identifies `modules.saas.customers.workspaces.detail`, with `header`, `summary` and `body` anchors.
|
|
19
|
+
|
|
20
|
+
`RegisterPlatformWorkspaceDetailPageExtension(extension: PlatformWorkspaceDetailPageExtension): PlatformWorkspaceDetailPageExtensionRegistration` accepts `{ name: string, components: readonly PageExtensionComponent[] }` and returns an unregister handle. Use the DMS `PageExtensionComponent` placement contract for these blocks. These registrations do not grant access: the platform detail remains owner-only, and tenant page components need appropriate metadata/permissions.
|
|
21
|
+
|
|
22
|
+
`/page-definitions` exports `MODULES_ROOT_DEFINITION: PageInfo`, `SAAS_MODULE_ID = "saas"`, and `SAAS_MODULE_DEFINITION` (full ID, full slug and module registration metadata). These are descriptors, not runtime registration functions. The workspace settings category itself comes from `@antelopejs/interface-dms/page`.
|
|
23
|
+
|
|
24
|
+
```ts docs-check
|
|
25
|
+
import { PageController, RegisterPage, workspaceSettingsCategory } from "@antelopejs/interface-dms/page";
|
|
26
|
+
|
|
27
|
+
@RegisterPage()
|
|
28
|
+
export class WorkspaceRegistriesController extends PageController("registries", {
|
|
29
|
+
displayName: "Registries",
|
|
30
|
+
category: workspaceSettingsCategory,
|
|
31
|
+
icon: "i-ph-package",
|
|
32
|
+
order: 10,
|
|
33
|
+
}) {}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Plan helpers
|
|
37
|
+
|
|
38
|
+
Import from `/plans`. These helpers do not charge customers or authorize access.
|
|
39
|
+
|
|
40
|
+
| Function | Contract |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `monthlyPrice(plan: Plan): number` | Returns the price as a monthly amount; yearly prices divide by 12 |
|
|
43
|
+
| `isDowngrade(current: Plan \| null, target: Plan, seats?: number): boolean` | Compares monthly cost, multiplying seat plans by at least one seat; seats default to 1. No current plan returns false; equal cost is not a downgrade |
|
|
44
|
+
| `localizeFeature(feature: Feature, locale: string): Feature` | Applies localization to `displayName`, `description`, `tooltip`, and `unit`, listed by exported `FEATURE_LOCALIZED_FIELDS`; missing translations fall back to the table locale (`en`) |
|
|
45
|
+
| `buildTenantPlanCatalog(planModel: PlanModel, featureModel: FeatureModel, plans: Plan[], locale: string): Promise<TenantPlanCatalog>` | Reads features, resolves plan inheritance, excludes unknown feature IDs and sorts plans/features by order; model read failures reject |
|
|
46
|
+
|
|
47
|
+
`TenantPlanCatalog` has `plans: TenantPlanView[]` and `features: TenantPlanFeature[]`.
|
|
48
|
+
|
|
49
|
+
- `TenantPlanView`: `_id: string`, `name: string`, `price: number`, `currency: string`, `interval: PlanInterval` (`month` or `year`), `order: number`, `checkoutAvailable: boolean`, and `featureValues: Record<string, unknown>`. Checkout availability reflects a Stripe price reference, not an authorization decision.
|
|
50
|
+
- `TenantPlanFeature`: `featureId: string`, `displayName: string`, `tooltip: string | null`, `unit: string | null`, `valueType: FeatureValueType` (`boolean`, `number`, or `string`), `isDetailRow: boolean`, and `order: number`.
|
|
51
|
+
|
|
52
|
+
Keep caller-supplied plan/model scopes authorized. The catalogue builder does not filter an arbitrary plan list to what a user may buy. Write localized feature values using the canonical model's `localize("*")` convention; see the [feature integration guide](/docs/modules/saas/extending#plan-feature-labels-and-values).
|
|
53
|
+
|
|
54
|
+
## HiddenStringFilter
|
|
55
|
+
|
|
56
|
+
`HiddenStringFilter(): PropertyDecorator` is exported from `/data-api` and `/hidden-filter`. It registers string comparisons, including `is` for `TableView.routeParamFilters`, without a visible `@Column`. Apply it to the data controller prototype field, such as `_instance` or `userId`.
|
|
57
|
+
|
|
58
|
+
An unregistered filter can be silently dropped by the data API, so declaring a hidden route filter matters for scoping. The decorator itself does not authenticate a user or make a client-supplied tenant ID trustworthy; enforce the scope at the server authorization boundary.
|
|
59
|
+
|
|
60
|
+
## Canonical database surface
|
|
61
|
+
|
|
62
|
+
`/db` exports the table/model pairs for plans, features, subscriptions, billing info/state/settings, invoices, credit notes, refunds, legal documents, trial consumptions, segments, user segments, platform notes, plan migrations and Stripe webhook events. `/db/models` and `/db/tables` expose those groups separately. For example, `PlanModel` works with `Plan`, `FeatureModel` with `Feature`, and `TenantSubscriptionModel` with `TenantSubscription`; use their shipped TypeScript declarations for persistence fields and methods.
|
|
63
|
+
|
|
64
|
+
These are registered persistence objects, not copies to redeclare. Imports have registration side effects; prefer type-only imports for types. Direct model writes bypass runtime orchestration and require correct tenant scope. See the [database boundary](./1.index.md#database-imports-have-side-effects) before writing seeds or imports, and [recompute derived billing state](./2.billing.md#recomputetenantbillingstate) after writing relevant records.
|
package/package.json
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-dms-saas",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "AntelopeJS interface for the DMS SaaS module: billing, plans, registration, workspace pages and lifecycle extension points.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"antelopejs",
|
|
7
|
+
"billing",
|
|
8
|
+
"dms",
|
|
9
|
+
"interface",
|
|
10
|
+
"saas"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://dms.antelopejs.com/docs/modules/saas/extending",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/AntelopeJS/dms-saas/issues"
|
|
15
|
+
},
|
|
5
16
|
"license": "Apache-2.0",
|
|
6
17
|
"repository": {
|
|
7
18
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/AntelopeJS/dms-saas.git"
|
|
19
|
+
"url": "git+https://github.com/AntelopeJS/dms-saas.git",
|
|
20
|
+
"directory": "packages/interface-dms-saas"
|
|
9
21
|
},
|
|
10
22
|
"files": [
|
|
11
23
|
"dist",
|
|
12
24
|
"!dist/.tsbuildinfo",
|
|
25
|
+
"docs",
|
|
13
26
|
"package.json",
|
|
14
27
|
"README.md",
|
|
15
28
|
"LICENSE"
|
|
@@ -57,13 +70,13 @@
|
|
|
57
70
|
"prepack": "pnpm run build"
|
|
58
71
|
},
|
|
59
72
|
"dependencies": {
|
|
60
|
-
"@antelopejs/interface-data-api": ">=0.
|
|
61
|
-
"@antelopejs/interface-dms": ">=0.
|
|
73
|
+
"@antelopejs/interface-data-api": ">=0.2.2 <1.0.0",
|
|
74
|
+
"@antelopejs/interface-dms": ">=0.7.2 <1.0.0"
|
|
62
75
|
},
|
|
63
76
|
"devDependencies": {
|
|
64
|
-
"@antelopejs/interface-core": ">=0.
|
|
65
|
-
"@antelopejs/interface-database": ">=0.1.
|
|
66
|
-
"@antelopejs/interface-database-decorators": ">=0.1.
|
|
77
|
+
"@antelopejs/interface-core": ">=0.2.4 <1.0.0",
|
|
78
|
+
"@antelopejs/interface-database": ">=0.1.10 <1.0.0",
|
|
79
|
+
"@antelopejs/interface-database-decorators": ">=0.1.9 <1.0.0",
|
|
67
80
|
"@types/node": "^24.0.0",
|
|
68
81
|
"knip": "^6.34.0",
|
|
69
82
|
"oxfmt": "^0.66.0",
|
|
@@ -75,9 +88,9 @@
|
|
|
75
88
|
"typescript": "^6.0.3"
|
|
76
89
|
},
|
|
77
90
|
"peerDependencies": {
|
|
78
|
-
"@antelopejs/interface-core": ">=0.
|
|
79
|
-
"@antelopejs/interface-database": ">=0.1.
|
|
80
|
-
"@antelopejs/interface-database-decorators": ">=0.1.
|
|
91
|
+
"@antelopejs/interface-core": ">=0.2.4 <1.0.0",
|
|
92
|
+
"@antelopejs/interface-database": ">=0.1.10 <1.0.0",
|
|
93
|
+
"@antelopejs/interface-database-decorators": ">=0.1.9 <1.0.0"
|
|
81
94
|
},
|
|
82
95
|
"packageManager": "pnpm@10.2.0",
|
|
83
96
|
"antelopeJs": {}
|