@farthershore/product 0.5.0 → 0.6.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 +8 -13
- package/dist/bin.js +1864 -1723
- package/dist/codegen.js +203 -166
- package/dist/index.js +1866 -1725
- package/dist/types/backend.d.ts +41 -0
- package/dist/types/codegen/index.d.ts +9 -1
- package/dist/types/declarations.d.ts +123 -0
- package/dist/types/dependencies.d.ts +13 -0
- package/dist/types/frontend.d.ts +23 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/ir-types.d.ts +49 -13
- package/dist/types/product-assembly.d.ts +22 -0
- package/dist/types/product.d.ts +41 -71
- package/dist/types/refs.d.ts +11 -0
- package/dist/types/resource-graph.d.ts +1 -1
- package/dist/types/route-metering.d.ts +53 -0
- package/dist/types/validate.d.ts +2 -4
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { BackendDefinitionJson, BackendRunnerJson, BackendTransportModeJson, MeterDefinitionJson, RouteLayerJson } from "./ir-types.js";
|
|
2
|
+
import { type KeyRef } from "./refs.js";
|
|
3
|
+
import type { MeterRef } from "./route-metering.js";
|
|
4
|
+
export type BackendTransportOptions = {
|
|
5
|
+
mode?: BackendTransportModeJson;
|
|
6
|
+
runner?: BackendRunnerJson;
|
|
7
|
+
};
|
|
8
|
+
export type BackendOptions = {
|
|
9
|
+
/** Human-friendly label (defaults to the id). */
|
|
10
|
+
name?: string;
|
|
11
|
+
/** Stable slug (defaults to the id). */
|
|
12
|
+
slug?: string;
|
|
13
|
+
transport?: BackendTransportOptions;
|
|
14
|
+
/** Per-request gateway->backend signature verification. Defaults false until
|
|
15
|
+
* the JWKS + signer keystone is proven (deploy-order hard sequence). */
|
|
16
|
+
verification?: {
|
|
17
|
+
required?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Meter allow-list. Omitted = all product meters allowed. */
|
|
20
|
+
meters?: Array<KeyRef | MeterRef>;
|
|
21
|
+
/** Marks this as the default backend when a product declares more than one. */
|
|
22
|
+
default?: boolean;
|
|
23
|
+
originUrl?: string;
|
|
24
|
+
originHostname?: string;
|
|
25
|
+
};
|
|
26
|
+
export type BackendNode = {
|
|
27
|
+
id: string;
|
|
28
|
+
} & BackendDefinitionJson;
|
|
29
|
+
export declare function createBackendNode(id: string, options?: BackendOptions): BackendNode;
|
|
30
|
+
/**
|
|
31
|
+
* Project registered backend nodes into a record keyed by id, sorted by id for
|
|
32
|
+
* stable, reviewable IR. The synthetic `id` field is stripped because the map
|
|
33
|
+
* key carries it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildBackendBlock(backendNodes: readonly BackendNode[]): Record<string, BackendDefinitionJson>;
|
|
36
|
+
/**
|
|
37
|
+
* BYO-Backend V1 — eager build-time validation of route->backend resolution,
|
|
38
|
+
* mirroring the compiler's `emit-backends` diagnostics so a builder gets a
|
|
39
|
+
* friendly error before the bytes ever reach the platform compiler.
|
|
40
|
+
*/
|
|
41
|
+
export declare function assertBackendBindingsValid(files: readonly RouteLayerJson[], backendNodes: readonly BackendNode[], meterDefinitions: readonly MeterDefinitionJson[]): void;
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
import type { ManifestIrDocument } from "../ir-types.js";
|
|
1
|
+
import type { ManifestIrDocument, PlanSpecJson } from "../ir-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Emit a single `product.plan("key", { ... })` statement — the structured plan
|
|
4
|
+
* block for WS4 dashboard authoring. Reuses the same faithful `planOptions` +
|
|
5
|
+
* `lit` printer as full-file generation (price sugar, grants, capability_limits,
|
|
6
|
+
* the `raw` escape hatch), so the snippet a builder applies via a GitHub edit /
|
|
7
|
+
* PR is byte-identical to what full regeneration would emit for that plan.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generatePlanStatement(plan: PlanSpecJson): string;
|
|
2
10
|
export declare function generateManifestSource(ir: ManifestIrDocument): string;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { ActionSpecJson, CacheProfile, CapabilityLayerJson, CountedResourceJson, CreditPolicyJson, GrantJson, MigrationDeclJson, MigrationPinJson, MutationClass, PlanLimitJson, PlanMeterJson, PlanSpecJson, PolicyLayerJson, ProductEntitlementJson, ProductSurfaceJson, ProductSurfaceTypeJson, ProductWorkflowJson, ProductWorkflowKindJson, ProductWorkflowTriggerJson, RouteDefinitionJson, RouteLayerJson } from "./ir-types.js";
|
|
2
|
+
import type { PriceSpec } from "./price.js";
|
|
3
|
+
import { type KeyRef, type PlanCapabilityGrant } from "./refs.js";
|
|
4
|
+
import type { MeterRef, RouteMeteringOptions } from "./route-metering.js";
|
|
5
|
+
type RouteDeclarationOptions = RouteMeteringOptions & {
|
|
6
|
+
action?: KeyRef;
|
|
7
|
+
backend?: KeyRef;
|
|
8
|
+
};
|
|
9
|
+
export type CapabilityDeclarationOptions = {
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
mutationClass?: MutationClass;
|
|
13
|
+
includesFeatures?: KeyRef[];
|
|
14
|
+
includesPolicies?: KeyRef[];
|
|
15
|
+
includesCapabilities?: KeyRef[];
|
|
16
|
+
};
|
|
17
|
+
export type FeatureDeclarationOptions = {
|
|
18
|
+
description?: string;
|
|
19
|
+
mutationClass?: MutationClass;
|
|
20
|
+
cacheProfile?: CacheProfile;
|
|
21
|
+
upstreamOrigin?: string | null;
|
|
22
|
+
policies?: KeyRef[];
|
|
23
|
+
plans?: KeyRef[];
|
|
24
|
+
rolloutKey?: string;
|
|
25
|
+
requiredFlags?: string[];
|
|
26
|
+
actions?: Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
} & Omit<ActionSpecJson, "id">>;
|
|
29
|
+
routes?: Array<{
|
|
30
|
+
match: string;
|
|
31
|
+
} & RouteDeclarationOptions>;
|
|
32
|
+
};
|
|
33
|
+
export type PolicyDeclarationOptions = {
|
|
34
|
+
type: string;
|
|
35
|
+
config: Record<string, unknown>;
|
|
36
|
+
description?: string;
|
|
37
|
+
mutationClass?: MutationClass;
|
|
38
|
+
cacheProfile?: CacheProfile;
|
|
39
|
+
compatibleWith?: {
|
|
40
|
+
routeTypes?: string[];
|
|
41
|
+
meters?: Array<KeyRef | MeterRef>;
|
|
42
|
+
authModes?: string[];
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type SurfaceDeclarationOptions = {
|
|
46
|
+
key?: string;
|
|
47
|
+
display?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
};
|
|
50
|
+
export type WorkflowDeclarationOptions = {
|
|
51
|
+
title?: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
kind?: ProductWorkflowKindJson;
|
|
54
|
+
trigger?: ProductWorkflowTriggerJson;
|
|
55
|
+
capabilities?: KeyRef[];
|
|
56
|
+
meters?: Array<KeyRef | MeterRef>;
|
|
57
|
+
estimates?: Record<string, number>;
|
|
58
|
+
metadata?: Record<string, unknown>;
|
|
59
|
+
};
|
|
60
|
+
export type EntitlementDeclarationOptions = {
|
|
61
|
+
description?: string;
|
|
62
|
+
capabilities?: KeyRef[];
|
|
63
|
+
featureGates?: Record<string, boolean>;
|
|
64
|
+
limits?: PlanLimitJson[];
|
|
65
|
+
meters?: Array<KeyRef | MeterRef>;
|
|
66
|
+
};
|
|
67
|
+
export type PlanDeclarationOptions = {
|
|
68
|
+
name: string;
|
|
69
|
+
description?: string;
|
|
70
|
+
details?: string[];
|
|
71
|
+
price?: PriceSpec;
|
|
72
|
+
meters?: PlanMeterJson[];
|
|
73
|
+
grants?: Array<GrantJson | PlanCapabilityGrant>;
|
|
74
|
+
/** Non-grant credit policies (rollover + auto-recharge). */
|
|
75
|
+
creditPolicy?: CreditPolicyJson;
|
|
76
|
+
trialDays?: number;
|
|
77
|
+
maxMonthlySpendCents?: number;
|
|
78
|
+
minMonthlySpendCents?: number;
|
|
79
|
+
limits?: PlanLimitJson[];
|
|
80
|
+
featureGates?: Record<string, boolean>;
|
|
81
|
+
capabilityLimits?: Record<string, number | boolean>;
|
|
82
|
+
capabilities?: KeyRef[];
|
|
83
|
+
overageBehavior?: "block" | "allow_and_bill";
|
|
84
|
+
selfServeEnabled?: boolean;
|
|
85
|
+
legacy?: boolean;
|
|
86
|
+
archive?: {
|
|
87
|
+
at?: string;
|
|
88
|
+
transitionTo?: string;
|
|
89
|
+
strategy?: "auto" | "explicit" | "block";
|
|
90
|
+
};
|
|
91
|
+
raw?: Record<string, unknown>;
|
|
92
|
+
};
|
|
93
|
+
export type MigrationPlanRefOptions = {
|
|
94
|
+
plan: KeyRef;
|
|
95
|
+
version?: string;
|
|
96
|
+
};
|
|
97
|
+
export type MigrationTargetRefOptions = {
|
|
98
|
+
plan: KeyRef;
|
|
99
|
+
version?: "head";
|
|
100
|
+
};
|
|
101
|
+
export type MigrationPinOptions = Omit<MigrationPinJson, "pinTo"> & {
|
|
102
|
+
pinTo: {
|
|
103
|
+
plan: KeyRef;
|
|
104
|
+
version: string;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
export type MigrationDeclarationOptions = Omit<MigrationDeclJson, "id" | "from" | "to" | "newCustomers" | "pins"> & {
|
|
108
|
+
from: MigrationPlanRefOptions;
|
|
109
|
+
to: MigrationTargetRefOptions;
|
|
110
|
+
newCustomers?: "immediate";
|
|
111
|
+
pins?: MigrationPinOptions[];
|
|
112
|
+
};
|
|
113
|
+
export type ResourceDeclarationOptions = Omit<CountedResourceJson, "name">;
|
|
114
|
+
export declare function buildCapabilityLayer(key: string, options?: CapabilityDeclarationOptions): CapabilityLayerJson;
|
|
115
|
+
export declare function buildFeatureLayer(key: string, options: FeatureDeclarationOptions, buildRoute: (match: string, options: RouteDeclarationOptions) => RouteDefinitionJson): RouteLayerJson;
|
|
116
|
+
export declare function buildPolicyLayer(name: string, options: PolicyDeclarationOptions): PolicyLayerJson;
|
|
117
|
+
export declare function buildSurfaceSpec(type: ProductSurfaceTypeJson, options?: SurfaceDeclarationOptions): ProductSurfaceJson;
|
|
118
|
+
export declare function buildWorkflowSpec(key: string, options?: WorkflowDeclarationOptions): ProductWorkflowJson;
|
|
119
|
+
export declare function buildEntitlementSpec(key: string, options?: EntitlementDeclarationOptions): ProductEntitlementJson;
|
|
120
|
+
export declare function buildPlanSpec(key: string, options: PlanDeclarationOptions): PlanSpecJson;
|
|
121
|
+
export declare function buildMigrationDecl(id: string, options: MigrationDeclarationOptions): MigrationDeclJson;
|
|
122
|
+
export declare function assertUniqueMigrationIds(migrations: readonly MigrationDeclJson[]): void;
|
|
123
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ActionSpecJson, CapabilityLayerJson, FrontendManifestJson, MigrationDeclJson, PlanSpecJson, PolicyLayerJson, ProductEntitlementJson, ProductWorkflowJson, RouteLayerJson } from "./ir-types.js";
|
|
2
|
+
import { type ManifestResourceKind, type ManifestResourceUrn, type MissingManifestResourceDependency } from "./resource-graph.js";
|
|
3
|
+
export type ResourceExists = (kind: ManifestResourceKind, key: string) => boolean;
|
|
4
|
+
export declare function capabilityDependsOn(file: CapabilityLayerJson): ManifestResourceUrn[];
|
|
5
|
+
export declare function policyDependsOn(file: PolicyLayerJson): ManifestResourceUrn[];
|
|
6
|
+
export declare function entitlementDependsOn(entitlement: ProductEntitlementJson, hasResource: ResourceExists): ManifestResourceUrn[];
|
|
7
|
+
export declare function workflowDependsOn(workflow: ProductWorkflowJson): ManifestResourceUrn[];
|
|
8
|
+
export declare function featureDependsOn(file: RouteLayerJson): ManifestResourceUrn[];
|
|
9
|
+
export declare function actionDependsOn(featureKey: string, action: ActionSpecJson): ManifestResourceUrn[];
|
|
10
|
+
export declare function planDependsOn(plan: PlanSpecJson, hasResource: ResourceExists): ManifestResourceUrn[];
|
|
11
|
+
export declare function migrationDependsOn(migration: MigrationDeclJson): ManifestResourceUrn[];
|
|
12
|
+
export declare function frontendDependsOn(manifest: FrontendManifestJson): ManifestResourceUrn[];
|
|
13
|
+
export declare function assertResourceDependenciesSatisfied(missing: readonly MissingManifestResourceDependency[]): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FrontendComponentId, FrontendGateMode, FrontendManifestJson } from "./ir-types.js";
|
|
2
|
+
import { type KeyRef } from "./refs.js";
|
|
3
|
+
export type FrontendNavItemInput = {
|
|
4
|
+
label: string;
|
|
5
|
+
path: string;
|
|
6
|
+
capability?: KeyRef;
|
|
7
|
+
};
|
|
8
|
+
export type FrontendComponentInput = {
|
|
9
|
+
component: FrontendComponentId;
|
|
10
|
+
props?: Record<string, unknown>;
|
|
11
|
+
capability?: KeyRef;
|
|
12
|
+
gateMode?: FrontendGateMode;
|
|
13
|
+
};
|
|
14
|
+
export type FrontendPageInput = {
|
|
15
|
+
title: string;
|
|
16
|
+
requiresAuth: boolean;
|
|
17
|
+
capability?: KeyRef;
|
|
18
|
+
components?: FrontendComponentInput[];
|
|
19
|
+
};
|
|
20
|
+
export declare function createFrontendManifest(): FrontendManifestJson;
|
|
21
|
+
export declare function setFrontendNav(manifest: FrontendManifestJson, items: FrontendNavItemInput[]): void;
|
|
22
|
+
export declare function addFrontendPage(manifest: FrontendManifestJson, path: string, options: FrontendPageInput): void;
|
|
23
|
+
export declare function frontendCapabilityKeys(manifest: FrontendManifestJson): string[];
|
package/dist/types/index.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ export { price } from "./price.js";
|
|
|
12
12
|
export { validateManifestIr, hashIr, canonicalIrJson } from "./validate.js";
|
|
13
13
|
export { ManifestValidationError, ManifestBuilderError } from "./errors.js";
|
|
14
14
|
export { SDK_VERSION } from "./version.js";
|
|
15
|
-
export type { ProductOptions, MeterOptions, RequestMeterOptions, MeterCost, ResourceOptions, CapabilityOptions, ActionOptions, FrontendNavItemOptions, FrontendPageOptions, FrontendComponentOptions, MigrationOptions, FeatureOptions, RouteOptions, PolicyOptions, PlanOptions, SurfaceOptions, EntitlementOptions, MeterRef, ResourceRef, ActionRef, PolicyRef, PlanRef, SurfaceRef, EntitlementRef, FeatureRef, CapabilityRef, PlanCapabilityGrant, ProductModule, } from "./product.js";
|
|
15
|
+
export type { ProductOptions, MeterOptions, RequestMeterOptions, MeterCost, ResourceOptions, CapabilityOptions, ActionOptions, FrontendNavItemOptions, FrontendPageOptions, FrontendComponentOptions, MigrationOptions, FeatureOptions, RouteOptions, BackendOptions, BackendTransportOptions, PolicyOptions, PlanOptions, SurfaceOptions, EntitlementOptions, MeterRef, ResourceRef, ActionRef, BackendRef, PolicyRef, PlanRef, SurfaceRef, EntitlementRef, FeatureRef, CapabilityRef, PlanCapabilityGrant, ProductModule, } from "./product.js";
|
|
16
16
|
export type { ManifestResourceGraphSnapshot, ManifestResourceKind, ManifestResourceUrn, } from "./resource-graph.js";
|
|
17
17
|
export type { PriceSpec } from "./price.js";
|
|
18
18
|
export type { ManifestIssue } from "./errors.js";
|
|
19
19
|
export type { ValidationResult } from "./validate.js";
|
|
20
|
-
export type { ManifestIrDocument, ManifestBuildResult, ProductSpecJson, PlanSpecJson,
|
|
20
|
+
export type { ManifestIrDocument, ManifestBuildResult, ProductSpecJson, PlanSpecJson, RouteLayerJson, RouteDefinitionJson, BackendDefinitionJson, BackendTransportModeJson, BackendRunnerJson, PolicyLayerJson, CapabilityLayerJson, FrontendManifestJson, FrontendNavItemJson, FrontendPageJson, FrontendComponentJson, FrontendComponentId, FrontendGateMode, MeterDefinitionJson, PlanMeterJson, PlanLimitJson, GrantJson, HttpMethod, MutationClass, CacheProfile, } from "./ir-types.js";
|
package/dist/types/ir-types.d.ts
CHANGED
|
@@ -22,9 +22,20 @@ export type PlanMeterJson = {
|
|
|
22
22
|
[key: string]: unknown;
|
|
23
23
|
};
|
|
24
24
|
export type GrantJson = {
|
|
25
|
-
kind: "
|
|
25
|
+
kind: "credit" | "top_up";
|
|
26
26
|
[key: string]: unknown;
|
|
27
27
|
};
|
|
28
|
+
/** Non-grant credit policies (rollover + auto-recharge) — mirrors the
|
|
29
|
+
* platform creditPolicySchema. */
|
|
30
|
+
export type CreditPolicyJson = {
|
|
31
|
+
rollover?: {
|
|
32
|
+
percent: number;
|
|
33
|
+
};
|
|
34
|
+
auto_recharge?: {
|
|
35
|
+
threshold_cents: number;
|
|
36
|
+
refill_cents: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
28
39
|
export type PlanLimitWindowJson = {
|
|
29
40
|
type: "named";
|
|
30
41
|
name: "second" | "minute" | "hour" | "day" | "week" | "month";
|
|
@@ -57,6 +68,8 @@ export type PlanSpecJson = {
|
|
|
57
68
|
max_monthly_spend_cents?: number;
|
|
58
69
|
min_monthly_spend_cents?: number;
|
|
59
70
|
grants?: GrantJson[];
|
|
71
|
+
creditPolicy?: CreditPolicyJson;
|
|
72
|
+
capabilities?: string[];
|
|
60
73
|
free?: boolean;
|
|
61
74
|
limits?: PlanLimitJson[];
|
|
62
75
|
featureGates?: Record<string, boolean>;
|
|
@@ -82,6 +95,28 @@ export type RouteDefinitionJson = {
|
|
|
82
95
|
unmetered?: boolean;
|
|
83
96
|
inheritDefaultMeters?: boolean;
|
|
84
97
|
action?: string;
|
|
98
|
+
/** BYO-Backend V1 — route→backend binding id. Omitted = the sole / default
|
|
99
|
+
* backend (single-backend products stay zero-config). */
|
|
100
|
+
backend?: string;
|
|
101
|
+
};
|
|
102
|
+
export type BackendTransportModeJson = "public_origin" | "mtls" | "cloudflare_tunnel";
|
|
103
|
+
export type BackendRunnerJson = "managed_cloudflared" | "sidecar";
|
|
104
|
+
export type BackendDefinitionJson = {
|
|
105
|
+
name?: string;
|
|
106
|
+
slug?: string;
|
|
107
|
+
transport?: {
|
|
108
|
+
mode?: BackendTransportModeJson;
|
|
109
|
+
runner?: BackendRunnerJson;
|
|
110
|
+
};
|
|
111
|
+
verification?: {
|
|
112
|
+
required?: boolean;
|
|
113
|
+
};
|
|
114
|
+
/** Meter allow-list. Omitted = all product meters allowed. */
|
|
115
|
+
meters?: string[];
|
|
116
|
+
/** Marks the default backend when a product declares more than one. */
|
|
117
|
+
default?: boolean;
|
|
118
|
+
originUrl?: string;
|
|
119
|
+
originHostname?: string;
|
|
85
120
|
};
|
|
86
121
|
export type ActionSpecJson = {
|
|
87
122
|
id: string;
|
|
@@ -100,7 +135,7 @@ export type ActionSpecJson = {
|
|
|
100
135
|
effect: "create" | "delete";
|
|
101
136
|
};
|
|
102
137
|
};
|
|
103
|
-
export type
|
|
138
|
+
export type RouteLayerJson = {
|
|
104
139
|
feature: string;
|
|
105
140
|
description?: string;
|
|
106
141
|
mutation_class?: MutationClass;
|
|
@@ -114,11 +149,13 @@ export type RoutesFileJson = {
|
|
|
114
149
|
rollout_key?: string;
|
|
115
150
|
required_flags?: string[];
|
|
116
151
|
};
|
|
117
|
-
capabilities?: string[];
|
|
118
152
|
plans?: string[];
|
|
119
153
|
actions?: ActionSpecJson[];
|
|
154
|
+
/** BYO-Backend V1 — feature-level default backend binding for all routes in
|
|
155
|
+
* this file (routes may override per-route). */
|
|
156
|
+
backend?: string;
|
|
120
157
|
};
|
|
121
|
-
export type
|
|
158
|
+
export type PolicyLayerJson = {
|
|
122
159
|
name: string;
|
|
123
160
|
description?: string;
|
|
124
161
|
type: string;
|
|
@@ -131,7 +168,7 @@ export type PolicyFileJson = {
|
|
|
131
168
|
mutation_class?: MutationClass;
|
|
132
169
|
cacheProfile?: CacheProfile;
|
|
133
170
|
};
|
|
134
|
-
export type
|
|
171
|
+
export type CapabilityLayerJson = {
|
|
135
172
|
capability: string;
|
|
136
173
|
description?: string;
|
|
137
174
|
mutation_class?: MutationClass;
|
|
@@ -294,6 +331,10 @@ export type ProductSpecJson = {
|
|
|
294
331
|
meters?: MeterDefinitionJson[];
|
|
295
332
|
billOn4xx?: boolean;
|
|
296
333
|
};
|
|
334
|
+
/** BYO-Backend V1 — first-class backend declarations keyed by backend id.
|
|
335
|
+
* Emitted only when at least one backend is declared (so single-backend /
|
|
336
|
+
* no-backend products keep their pre-BYOB irHash). */
|
|
337
|
+
backend?: Record<string, BackendDefinitionJson>;
|
|
297
338
|
frontend?: FrontendManifestJson;
|
|
298
339
|
migrations?: MigrationDeclJson[];
|
|
299
340
|
resources?: CountedResourceJson[];
|
|
@@ -312,14 +353,9 @@ export type ManifestIrDocument = {
|
|
|
312
353
|
irVersion: 1;
|
|
313
354
|
sdkVersion: string;
|
|
314
355
|
product: ProductSpecJson;
|
|
315
|
-
routes:
|
|
316
|
-
policies:
|
|
317
|
-
capabilities:
|
|
318
|
-
runtime: {
|
|
319
|
-
rollout: null;
|
|
320
|
-
flags: null;
|
|
321
|
-
migrations: null;
|
|
322
|
-
};
|
|
356
|
+
routes: RouteLayerJson[];
|
|
357
|
+
policies: PolicyLayerJson[];
|
|
358
|
+
capabilities: CapabilityLayerJson[];
|
|
323
359
|
};
|
|
324
360
|
/** Platform compiler result: the validated envelope plus its canonical hash. */
|
|
325
361
|
export type ManifestBuildResult = {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type BackendNode } from "./backend.js";
|
|
2
|
+
import type { CountedResourceJson, FrontendManifestJson, MeterDefinitionJson, MigrationDeclJson, PlanSpecJson, ProductEntitlementJson, ProductSpecJson, ProductSurfaceJson, ProductWorkflowJson, RouteLayerJson } from "./ir-types.js";
|
|
3
|
+
import type { ProductOptions } from "./product.js";
|
|
4
|
+
import type { MeterCost } from "./route-metering.js";
|
|
5
|
+
export type ProductSpecAssemblyInput = {
|
|
6
|
+
name: string;
|
|
7
|
+
options: ProductOptions;
|
|
8
|
+
productPatch: Record<string, unknown>;
|
|
9
|
+
meters: readonly MeterDefinitionJson[];
|
|
10
|
+
defaultMeterCosts: readonly MeterCost[];
|
|
11
|
+
backends: readonly BackendNode[];
|
|
12
|
+
surfaces: readonly ProductSurfaceJson[];
|
|
13
|
+
entitlements: readonly ProductEntitlementJson[];
|
|
14
|
+
workflows: readonly ProductWorkflowJson[];
|
|
15
|
+
frontendManifest?: FrontendManifestJson;
|
|
16
|
+
migrations: readonly MigrationDeclJson[];
|
|
17
|
+
resources: readonly CountedResourceJson[];
|
|
18
|
+
plans: readonly PlanSpecJson[];
|
|
19
|
+
featureLayers: readonly RouteLayerJson[];
|
|
20
|
+
};
|
|
21
|
+
export declare function assembleProductSpec(input: ProductSpecAssemblyInput): ProductSpecJson;
|
|
22
|
+
export declare function mergeProductPatch(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown>;
|
package/dist/types/product.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type { CacheProfile, ActionSpecJson,
|
|
1
|
+
import type { CacheProfile, ActionSpecJson, CapabilityLayerJson, FrontendComponentId, FrontendGateMode, FrontendManifestJson, GrantJson, CreditPolicyJson, MeterDefinitionJson, MigrationDeclJson, MigrationPinJson, MutationClass, CountedResourceJson, PlanLimitJson, PlanMeterJson, PlanSpecJson, PolicyLayerJson, ProductPoliciesJson, ProductCustomerContextJson, ProductWorkflowKindJson, ProductWorkflowTriggerJson, ProductSurfaceTypeJson, RouteLayerJson } from "./ir-types.js";
|
|
2
2
|
import type { PriceSpec } from "./price.js";
|
|
3
3
|
import { type ManifestResourceGraphSnapshot } from "./resource-graph.js";
|
|
4
|
+
import { type BackendOptions } from "./backend.js";
|
|
5
|
+
import { type PlanCapabilityGrant } from "./refs.js";
|
|
6
|
+
import { type MeterCost, type MeterRef, type RouteMeteringOptions } from "./route-metering.js";
|
|
7
|
+
export type { MeterCost, MeterEstimate, MeterRef } from "./route-metering.js";
|
|
8
|
+
export type { BackendOptions, BackendTransportOptions } from "./backend.js";
|
|
9
|
+
export type { PlanCapabilityGrant } from "./refs.js";
|
|
4
10
|
/** Brand symbol so the bin can recognize a Product across SDK copies
|
|
5
11
|
* (the repo's pinned SDK vs whatever loaded the entry). */
|
|
6
12
|
export declare const PRODUCT_BRAND: unique symbol;
|
|
@@ -30,7 +36,6 @@ export type ProductOptions = {
|
|
|
30
36
|
customerAuth?: ProductCustomerContextJson["portal_auth"];
|
|
31
37
|
};
|
|
32
38
|
billing?: {
|
|
33
|
-
gracePeriodDays?: number;
|
|
34
39
|
applyLimitUpgradesInstantly?: boolean;
|
|
35
40
|
};
|
|
36
41
|
};
|
|
@@ -50,26 +55,12 @@ export type CapabilityOptions = {
|
|
|
50
55
|
includesPolicies?: Array<string | PolicyRef>;
|
|
51
56
|
includesCapabilities?: Array<string | CapabilityRef>;
|
|
52
57
|
};
|
|
53
|
-
export type
|
|
54
|
-
readonly kind: "meter_cost";
|
|
55
|
-
readonly meter: string;
|
|
56
|
-
readonly value: number;
|
|
57
|
-
};
|
|
58
|
-
export type RouteOptions = {
|
|
59
|
-
/**
|
|
60
|
-
* Dynamic meter keys the upstream may report with @farthershore/metering.
|
|
61
|
-
*/
|
|
62
|
-
reports?: string | MeterRef | Array<string | MeterRef>;
|
|
63
|
-
/** Fixed gateway-known route costs. */
|
|
64
|
-
costs?: MeterCost | Array<MeterCost>;
|
|
65
|
-
/** Route-specific pre-request estimates for dynamic reports. */
|
|
66
|
-
estimates?: Record<string, number>;
|
|
67
|
-
/** Override the default successful-response range. */
|
|
68
|
-
onStatusCodes?: string | number[];
|
|
69
|
-
/** Disable product.defaultMeters()/product.requests() for this route only. */
|
|
70
|
-
inheritDefaultMeters?: boolean;
|
|
71
|
-
unmetered?: boolean;
|
|
58
|
+
export type RouteOptions = RouteMeteringOptions & {
|
|
72
59
|
action?: string | ActionRef;
|
|
60
|
+
/** BYO-Backend V1 — bind this route to a declared backend. Omitted = the
|
|
61
|
+
* product's sole / default backend (single-backend products stay
|
|
62
|
+
* zero-config). */
|
|
63
|
+
backend?: string | BackendRef;
|
|
73
64
|
};
|
|
74
65
|
export type ActionOptions = Omit<ActionSpecJson, "id">;
|
|
75
66
|
export type FrontendNavItemOptions = {
|
|
@@ -89,9 +80,16 @@ export type FrontendPageOptions = {
|
|
|
89
80
|
capability?: string | CapabilityRef;
|
|
90
81
|
components?: FrontendComponentOptions[];
|
|
91
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* A plan-version reference: `"head"` (newest ACTIVE version) or a
|
|
85
|
+
* positive-integer string ("1", "2", ...). The template-literal type rejects
|
|
86
|
+
* obvious mistakes like date strings (`"2026-06-01"`) at compile time; the
|
|
87
|
+
* contracts `versionRefSchema` is the runtime source of truth.
|
|
88
|
+
*/
|
|
89
|
+
export type VersionRef = "head" | `${number}`;
|
|
92
90
|
export type MigrationPlanRefOptions = {
|
|
93
91
|
plan: string | PlanRef;
|
|
94
|
-
version?:
|
|
92
|
+
version?: VersionRef;
|
|
95
93
|
};
|
|
96
94
|
export type MigrationTargetRefOptions = {
|
|
97
95
|
plan: string | PlanRef;
|
|
@@ -100,7 +98,7 @@ export type MigrationTargetRefOptions = {
|
|
|
100
98
|
export type MigrationPinOptions = Omit<MigrationPinJson, "pinTo"> & {
|
|
101
99
|
pinTo: {
|
|
102
100
|
plan: string | PlanRef;
|
|
103
|
-
version:
|
|
101
|
+
version: VersionRef;
|
|
104
102
|
};
|
|
105
103
|
};
|
|
106
104
|
export type MigrationOptions = Omit<MigrationDeclJson, "id" | "from" | "to" | "newCustomers" | "pins"> & {
|
|
@@ -117,7 +115,6 @@ export type FeatureOptions = {
|
|
|
117
115
|
/** Per-feature upstream origin override (default: product origin). */
|
|
118
116
|
upstreamOrigin?: string | null;
|
|
119
117
|
policies?: Array<string | PolicyRef>;
|
|
120
|
-
capabilities?: Array<string | CapabilityRef>;
|
|
121
118
|
/** Plans that grant this feature directly. */
|
|
122
119
|
plans?: Array<string | PlanRef>;
|
|
123
120
|
rolloutKey?: string;
|
|
@@ -152,6 +149,8 @@ export type PlanOptions = {
|
|
|
152
149
|
meters?: PlanMeterJson[];
|
|
153
150
|
/** Credit grants and/or capability enablements from `cap.enable()`. */
|
|
154
151
|
grants?: Array<GrantJson | PlanCapabilityGrant>;
|
|
152
|
+
/** Non-grant credit policies (rollover + auto-recharge). */
|
|
153
|
+
creditPolicy?: CreditPolicyJson;
|
|
155
154
|
trialDays?: number;
|
|
156
155
|
maxMonthlySpendCents?: number;
|
|
157
156
|
minMonthlySpendCents?: number;
|
|
@@ -193,14 +192,6 @@ export type EntitlementOptions = {
|
|
|
193
192
|
limits?: PlanLimitJson[];
|
|
194
193
|
meters?: Array<string | MeterRef>;
|
|
195
194
|
};
|
|
196
|
-
export type MeterRef = {
|
|
197
|
-
readonly kind: "meter";
|
|
198
|
-
readonly key: string;
|
|
199
|
-
/** Fixed gateway-known usage for route/product defaults. */
|
|
200
|
-
fixed(value: number): MeterCost;
|
|
201
|
-
/** Convenience value for APIs that want an explicit estimate helper. */
|
|
202
|
-
estimate(value: number): MeterCost;
|
|
203
|
-
};
|
|
204
195
|
export type ResourceRef = {
|
|
205
196
|
readonly kind: "resource";
|
|
206
197
|
readonly key: string;
|
|
@@ -229,6 +220,10 @@ export type ActionRef = {
|
|
|
229
220
|
readonly kind: "action";
|
|
230
221
|
readonly key: string;
|
|
231
222
|
};
|
|
223
|
+
export type BackendRef = {
|
|
224
|
+
readonly kind: "backend";
|
|
225
|
+
readonly key: string;
|
|
226
|
+
};
|
|
232
227
|
export type FeatureRef = {
|
|
233
228
|
readonly kind: "feature";
|
|
234
229
|
readonly key: string;
|
|
@@ -246,11 +241,6 @@ export type CapabilityRef = {
|
|
|
246
241
|
limits?: Record<string, number | boolean>;
|
|
247
242
|
}): PlanCapabilityGrant;
|
|
248
243
|
};
|
|
249
|
-
export type PlanCapabilityGrant = {
|
|
250
|
-
readonly kind: "capability_grant";
|
|
251
|
-
readonly capability: string;
|
|
252
|
-
readonly limits?: Record<string, number | boolean>;
|
|
253
|
-
};
|
|
254
244
|
/**
|
|
255
245
|
* A synchronous Product SDK module. Use this to split a product across files:
|
|
256
246
|
* `product.use(configureMeters, configureRoutes, configurePlans)`.
|
|
@@ -262,7 +252,6 @@ export declare class Product {
|
|
|
262
252
|
private readonly options;
|
|
263
253
|
private readonly graph;
|
|
264
254
|
private readonly defaultMeterCosts;
|
|
265
|
-
private frontendManifest?;
|
|
266
255
|
private productPatch;
|
|
267
256
|
/** Sugar for binding API routes to features. */
|
|
268
257
|
readonly api: {
|
|
@@ -279,22 +268,26 @@ export declare class Product {
|
|
|
279
268
|
migration: (id: string, options: MigrationOptions) => Product;
|
|
280
269
|
migrations: (migrations: MigrationDeclJson[]) => Product;
|
|
281
270
|
};
|
|
282
|
-
readonly offering: {
|
|
283
|
-
plan: (key: string, options: PlanOptions) => PlanRef;
|
|
284
|
-
};
|
|
285
271
|
/** Escape hatches — raw platform-schema JSON, validated by the compiler. */
|
|
286
272
|
readonly raw: {
|
|
287
273
|
/** Deep-merged onto the emitted product spec (usage, webhooks,
|
|
288
274
|
* environments, add_ons, lifecycle, billing overrides, …). */
|
|
289
275
|
productPatch: (patch: Record<string, unknown>) => Product;
|
|
290
276
|
plan: (spec: PlanSpecJson) => Product;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
frontend: (manifest: FrontendManifestJson) => Product;
|
|
277
|
+
routeLayer: (layer: RouteLayerJson) => Product;
|
|
278
|
+
policyLayer: (layer: PolicyLayerJson) => Product;
|
|
279
|
+
capabilityLayer: (layer: CapabilityLayerJson) => Product;
|
|
295
280
|
};
|
|
296
281
|
constructor(name: string, options: ProductOptions);
|
|
297
282
|
meter(key: string, options: MeterOptions): MeterRef;
|
|
283
|
+
/**
|
|
284
|
+
* BYO-Backend V1 — declare a first-class backend (an always-running HTTP
|
|
285
|
+
* container Farther Shore wraps). Products may declare MULTIPLE backends;
|
|
286
|
+
* routes bind to one via `route(..., { backend })`. A product with exactly
|
|
287
|
+
* one backend (or exactly one marked `default: true`) makes it the implicit
|
|
288
|
+
* default, so single-backend products stay zero-config.
|
|
289
|
+
*/
|
|
290
|
+
backend(id: string, options?: BackendOptions): BackendRef;
|
|
298
291
|
requests(options?: RequestMeterOptions): MeterRef;
|
|
299
292
|
defaultMeters(costs: MeterCost | MeterCost[]): Product;
|
|
300
293
|
resource(name: string, options?: ResourceOptions): ResourceRef;
|
|
@@ -309,40 +302,17 @@ export declare class Product {
|
|
|
309
302
|
/** Inspect the SDK-local declaration graph used to emit the Manifest IR. */
|
|
310
303
|
resourceGraph(): ManifestResourceGraphSnapshot;
|
|
311
304
|
private buildProductSpec;
|
|
312
|
-
private buildMeterDefinitions;
|
|
313
|
-
private routeValueMeterKeys;
|
|
314
305
|
private buildRoute;
|
|
315
|
-
private
|
|
316
|
-
private buildRouteMetering;
|
|
317
|
-
private materializeFeatureFiles;
|
|
318
|
-
private materializeRoute;
|
|
306
|
+
private materializeFeatureLayers;
|
|
319
307
|
private normalizeMeterCost;
|
|
320
|
-
private normalizeMeterCosts;
|
|
321
|
-
private normalizeMeterRefs;
|
|
322
308
|
private ensureFrontendManifest;
|
|
323
|
-
private normalizeMigrationPlanRef;
|
|
324
|
-
private normalizeMigrationTargetRef;
|
|
325
|
-
private assertUniqueMigrationIds;
|
|
326
309
|
private assertNewKey;
|
|
327
310
|
private assertGraphDependenciesSatisfied;
|
|
328
|
-
private
|
|
329
|
-
private
|
|
311
|
+
private getFeatureLayer;
|
|
312
|
+
private registerFeatureLayer;
|
|
330
313
|
private syncFeatureGraphNode;
|
|
331
314
|
private registerAction;
|
|
332
315
|
private syncFrontendGraphNode;
|
|
333
|
-
private capabilityDependsOn;
|
|
334
|
-
private policyDependsOn;
|
|
335
|
-
private entitlementDependsOn;
|
|
336
|
-
private workflowDependsOn;
|
|
337
|
-
private featureDependsOn;
|
|
338
|
-
private routeMeterDependencyKeys;
|
|
339
|
-
private assertRouteMeteringValid;
|
|
340
|
-
private actionDependsOn;
|
|
341
|
-
private planDependsOn;
|
|
342
|
-
private migrationDependsOn;
|
|
343
|
-
private frontendDependsOn;
|
|
344
|
-
private dependenciesFor;
|
|
345
|
-
private existingDependenciesFor;
|
|
346
316
|
}
|
|
347
317
|
export declare function isProduct(value: unknown): value is Product;
|
|
348
318
|
export declare function product(name: string, options: ProductOptions, configure?: ProductModule): Product;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type KeyRef = string | {
|
|
2
|
+
key: string;
|
|
3
|
+
};
|
|
4
|
+
export type PlanCapabilityGrant = {
|
|
5
|
+
readonly kind: "capability_grant";
|
|
6
|
+
readonly capability: string;
|
|
7
|
+
readonly limits?: Record<string, number | boolean>;
|
|
8
|
+
};
|
|
9
|
+
export declare function isCapabilityGrant(value: unknown): value is PlanCapabilityGrant;
|
|
10
|
+
export declare function keyOf(ref: KeyRef): string;
|
|
11
|
+
export declare function displayFromKey(key: string): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ManifestResourceKind = "product" | "meter" | "counted_resource" | "capability" | "surface" | "entitlement" | "workflow" | "policy" | "feature" | "action" | "plan" | "frontend" | "lifecycle_migration";
|
|
1
|
+
export type ManifestResourceKind = "product" | "meter" | "counted_resource" | "capability" | "surface" | "entitlement" | "workflow" | "policy" | "feature" | "action" | "plan" | "backend" | "frontend" | "lifecycle_migration";
|
|
2
2
|
export type ManifestResourceUrn = `urn:farthershore:product:${ManifestResourceKind}:${string}`;
|
|
3
3
|
export type ManifestResourceRef = {
|
|
4
4
|
readonly kind: ManifestResourceKind;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { MeterDefinitionJson, RouteDefinitionJson, RouteLayerJson } from "./ir-types.js";
|
|
2
|
+
import { type KeyRef } from "./refs.js";
|
|
3
|
+
export type MeterCost = {
|
|
4
|
+
readonly kind: "meter_cost";
|
|
5
|
+
readonly meter: string;
|
|
6
|
+
readonly value: number;
|
|
7
|
+
};
|
|
8
|
+
export type MeterEstimate = {
|
|
9
|
+
readonly kind: "meter_estimate";
|
|
10
|
+
readonly meter: string;
|
|
11
|
+
readonly value: number;
|
|
12
|
+
};
|
|
13
|
+
export type MeterRef = {
|
|
14
|
+
readonly kind: "meter";
|
|
15
|
+
readonly key: string;
|
|
16
|
+
/** Fixed gateway-known usage for route/product defaults. */
|
|
17
|
+
fixed(value: number): MeterCost;
|
|
18
|
+
/** Convenience value for APIs that want an explicit estimate helper. */
|
|
19
|
+
estimate(value: number): MeterEstimate;
|
|
20
|
+
};
|
|
21
|
+
export type RouteMeteringOptions = {
|
|
22
|
+
/**
|
|
23
|
+
* Dynamic meter keys the upstream may report with @farthershore/backend.
|
|
24
|
+
*/
|
|
25
|
+
reports?: string | MeterRef | Array<string | MeterRef>;
|
|
26
|
+
/** Fixed gateway-known route costs. */
|
|
27
|
+
costs?: MeterCost | Array<MeterCost>;
|
|
28
|
+
/** Route-specific pre-request estimates for dynamic reports. */
|
|
29
|
+
estimates?: Record<string, number> | MeterEstimate | MeterEstimate[];
|
|
30
|
+
/** Override the default successful-response range. */
|
|
31
|
+
onStatusCodes?: string | number[];
|
|
32
|
+
/** Disable product.defaultMeters()/product.requests() for this route only. */
|
|
33
|
+
inheritDefaultMeters?: boolean;
|
|
34
|
+
unmetered?: boolean;
|
|
35
|
+
};
|
|
36
|
+
type RouteBindingOptions = RouteMeteringOptions & {
|
|
37
|
+
action?: KeyRef;
|
|
38
|
+
/** BYO-Backend V1 — bind this route to a declared backend. Omitted = the
|
|
39
|
+
* product's sole / default backend (single-backend products stay
|
|
40
|
+
* zero-config). */
|
|
41
|
+
backend?: KeyRef;
|
|
42
|
+
};
|
|
43
|
+
type RouteMeteringDeps = {
|
|
44
|
+
normalizeMeterCost(cost: MeterCost): MeterCost;
|
|
45
|
+
getMeterDefinition(key: string): MeterDefinitionJson | undefined;
|
|
46
|
+
};
|
|
47
|
+
export declare function makeMeterRef(key: string): MeterRef;
|
|
48
|
+
export declare function normalizeMeterCost(cost: MeterCost, hasMeter: (meter: string) => boolean): MeterCost;
|
|
49
|
+
export declare function buildRouteDefinition(match: string, options: RouteBindingOptions, deps: RouteMeteringDeps): RouteDefinitionJson;
|
|
50
|
+
export declare function materializeRoute(route: RouteDefinitionJson, defaultMeterCosts: readonly MeterCost[]): RouteDefinitionJson;
|
|
51
|
+
export declare function routeMeterDependencyKeys(route: RouteDefinitionJson): string[];
|
|
52
|
+
export declare function assertRouteMeteringValid(files: RouteLayerJson[], meterDefinitions: Iterable<MeterDefinitionJson>): void;
|
|
53
|
+
export {};
|