@farthershore/product 0.5.0 → 0.6.0
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 +7 -12
- package/dist/bin.js +1739 -1580
- package/dist/codegen.js +0 -1
- package/dist/index.js +1744 -1585
- package/dist/types/backend.d.ts +41 -0
- package/dist/types/declarations.d.ts +121 -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 +36 -12
- package/dist/types/product-assembly.d.ts +22 -0
- package/dist/types/product.d.ts +30 -68
- package/dist/types/refs.d.ts +11 -0
- package/dist/types/resource-graph.d.ts +1 -1
- package/dist/types/route-metering.d.ts +60 -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;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ActionSpecJson, CacheProfile, CapabilityLayerJson, CountedResourceJson, 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
|
+
trialDays?: number;
|
|
75
|
+
maxMonthlySpendCents?: number;
|
|
76
|
+
minMonthlySpendCents?: number;
|
|
77
|
+
limits?: PlanLimitJson[];
|
|
78
|
+
featureGates?: Record<string, boolean>;
|
|
79
|
+
capabilityLimits?: Record<string, number | boolean>;
|
|
80
|
+
capabilities?: KeyRef[];
|
|
81
|
+
overageBehavior?: "block" | "allow_and_bill";
|
|
82
|
+
selfServeEnabled?: boolean;
|
|
83
|
+
legacy?: boolean;
|
|
84
|
+
archive?: {
|
|
85
|
+
at?: string;
|
|
86
|
+
transitionTo?: string;
|
|
87
|
+
strategy?: "auto" | "explicit" | "block";
|
|
88
|
+
};
|
|
89
|
+
raw?: Record<string, unknown>;
|
|
90
|
+
};
|
|
91
|
+
export type MigrationPlanRefOptions = {
|
|
92
|
+
plan: KeyRef;
|
|
93
|
+
version?: string;
|
|
94
|
+
};
|
|
95
|
+
export type MigrationTargetRefOptions = {
|
|
96
|
+
plan: KeyRef;
|
|
97
|
+
version?: "head";
|
|
98
|
+
};
|
|
99
|
+
export type MigrationPinOptions = Omit<MigrationPinJson, "pinTo"> & {
|
|
100
|
+
pinTo: {
|
|
101
|
+
plan: KeyRef;
|
|
102
|
+
version: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export type MigrationDeclarationOptions = Omit<MigrationDeclJson, "id" | "from" | "to" | "newCustomers" | "pins"> & {
|
|
106
|
+
from: MigrationPlanRefOptions;
|
|
107
|
+
to: MigrationTargetRefOptions;
|
|
108
|
+
newCustomers?: "immediate";
|
|
109
|
+
pins?: MigrationPinOptions[];
|
|
110
|
+
};
|
|
111
|
+
export type ResourceDeclarationOptions = Omit<CountedResourceJson, "name">;
|
|
112
|
+
export declare function buildCapabilityLayer(key: string, options?: CapabilityDeclarationOptions): CapabilityLayerJson;
|
|
113
|
+
export declare function buildFeatureLayer(key: string, options: FeatureDeclarationOptions, buildRoute: (match: string, options: RouteDeclarationOptions) => RouteDefinitionJson): RouteLayerJson;
|
|
114
|
+
export declare function buildPolicyLayer(name: string, options: PolicyDeclarationOptions): PolicyLayerJson;
|
|
115
|
+
export declare function buildSurfaceSpec(type: ProductSurfaceTypeJson, options?: SurfaceDeclarationOptions): ProductSurfaceJson;
|
|
116
|
+
export declare function buildWorkflowSpec(key: string, options?: WorkflowDeclarationOptions): ProductWorkflowJson;
|
|
117
|
+
export declare function buildEntitlementSpec(key: string, options?: EntitlementDeclarationOptions): ProductEntitlementJson;
|
|
118
|
+
export declare function buildPlanSpec(key: string, options: PlanDeclarationOptions): PlanSpecJson;
|
|
119
|
+
export declare function buildMigrationDecl(id: string, options: MigrationDeclarationOptions): MigrationDeclJson;
|
|
120
|
+
export declare function assertUniqueMigrationIds(migrations: readonly MigrationDeclJson[]): void;
|
|
121
|
+
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
|
@@ -57,6 +57,7 @@ export type PlanSpecJson = {
|
|
|
57
57
|
max_monthly_spend_cents?: number;
|
|
58
58
|
min_monthly_spend_cents?: number;
|
|
59
59
|
grants?: GrantJson[];
|
|
60
|
+
capabilities?: string[];
|
|
60
61
|
free?: boolean;
|
|
61
62
|
limits?: PlanLimitJson[];
|
|
62
63
|
featureGates?: Record<string, boolean>;
|
|
@@ -82,6 +83,28 @@ export type RouteDefinitionJson = {
|
|
|
82
83
|
unmetered?: boolean;
|
|
83
84
|
inheritDefaultMeters?: boolean;
|
|
84
85
|
action?: string;
|
|
86
|
+
/** BYO-Backend V1 — route→backend binding id. Omitted = the sole / default
|
|
87
|
+
* backend (single-backend products stay zero-config). */
|
|
88
|
+
backend?: string;
|
|
89
|
+
};
|
|
90
|
+
export type BackendTransportModeJson = "public_origin" | "mtls" | "cloudflare_tunnel";
|
|
91
|
+
export type BackendRunnerJson = "managed_cloudflared" | "sidecar";
|
|
92
|
+
export type BackendDefinitionJson = {
|
|
93
|
+
name?: string;
|
|
94
|
+
slug?: string;
|
|
95
|
+
transport?: {
|
|
96
|
+
mode?: BackendTransportModeJson;
|
|
97
|
+
runner?: BackendRunnerJson;
|
|
98
|
+
};
|
|
99
|
+
verification?: {
|
|
100
|
+
required?: boolean;
|
|
101
|
+
};
|
|
102
|
+
/** Meter allow-list. Omitted = all product meters allowed. */
|
|
103
|
+
meters?: string[];
|
|
104
|
+
/** Marks the default backend when a product declares more than one. */
|
|
105
|
+
default?: boolean;
|
|
106
|
+
originUrl?: string;
|
|
107
|
+
originHostname?: string;
|
|
85
108
|
};
|
|
86
109
|
export type ActionSpecJson = {
|
|
87
110
|
id: string;
|
|
@@ -100,7 +123,7 @@ export type ActionSpecJson = {
|
|
|
100
123
|
effect: "create" | "delete";
|
|
101
124
|
};
|
|
102
125
|
};
|
|
103
|
-
export type
|
|
126
|
+
export type RouteLayerJson = {
|
|
104
127
|
feature: string;
|
|
105
128
|
description?: string;
|
|
106
129
|
mutation_class?: MutationClass;
|
|
@@ -114,11 +137,13 @@ export type RoutesFileJson = {
|
|
|
114
137
|
rollout_key?: string;
|
|
115
138
|
required_flags?: string[];
|
|
116
139
|
};
|
|
117
|
-
capabilities?: string[];
|
|
118
140
|
plans?: string[];
|
|
119
141
|
actions?: ActionSpecJson[];
|
|
142
|
+
/** BYO-Backend V1 — feature-level default backend binding for all routes in
|
|
143
|
+
* this file (routes may override per-route). */
|
|
144
|
+
backend?: string;
|
|
120
145
|
};
|
|
121
|
-
export type
|
|
146
|
+
export type PolicyLayerJson = {
|
|
122
147
|
name: string;
|
|
123
148
|
description?: string;
|
|
124
149
|
type: string;
|
|
@@ -131,7 +156,7 @@ export type PolicyFileJson = {
|
|
|
131
156
|
mutation_class?: MutationClass;
|
|
132
157
|
cacheProfile?: CacheProfile;
|
|
133
158
|
};
|
|
134
|
-
export type
|
|
159
|
+
export type CapabilityLayerJson = {
|
|
135
160
|
capability: string;
|
|
136
161
|
description?: string;
|
|
137
162
|
mutation_class?: MutationClass;
|
|
@@ -294,6 +319,10 @@ export type ProductSpecJson = {
|
|
|
294
319
|
meters?: MeterDefinitionJson[];
|
|
295
320
|
billOn4xx?: boolean;
|
|
296
321
|
};
|
|
322
|
+
/** BYO-Backend V1 — first-class backend declarations keyed by backend id.
|
|
323
|
+
* Emitted only when at least one backend is declared (so single-backend /
|
|
324
|
+
* no-backend products keep their pre-BYOB irHash). */
|
|
325
|
+
backend?: Record<string, BackendDefinitionJson>;
|
|
297
326
|
frontend?: FrontendManifestJson;
|
|
298
327
|
migrations?: MigrationDeclJson[];
|
|
299
328
|
resources?: CountedResourceJson[];
|
|
@@ -312,14 +341,9 @@ export type ManifestIrDocument = {
|
|
|
312
341
|
irVersion: 1;
|
|
313
342
|
sdkVersion: string;
|
|
314
343
|
product: ProductSpecJson;
|
|
315
|
-
routes:
|
|
316
|
-
policies:
|
|
317
|
-
capabilities:
|
|
318
|
-
runtime: {
|
|
319
|
-
rollout: null;
|
|
320
|
-
flags: null;
|
|
321
|
-
migrations: null;
|
|
322
|
-
};
|
|
344
|
+
routes: RouteLayerJson[];
|
|
345
|
+
policies: PolicyLayerJson[];
|
|
346
|
+
capabilities: CapabilityLayerJson[];
|
|
323
347
|
};
|
|
324
348
|
/** Platform compiler result: the validated envelope plus its canonical hash. */
|
|
325
349
|
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, 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;
|
|
@@ -50,26 +56,12 @@ export type CapabilityOptions = {
|
|
|
50
56
|
includesPolicies?: Array<string | PolicyRef>;
|
|
51
57
|
includesCapabilities?: Array<string | CapabilityRef>;
|
|
52
58
|
};
|
|
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;
|
|
59
|
+
export type RouteOptions = RouteMeteringOptions & {
|
|
72
60
|
action?: string | ActionRef;
|
|
61
|
+
/** BYO-Backend V1 — bind this route to a declared backend. Omitted = the
|
|
62
|
+
* product's sole / default backend (single-backend products stay
|
|
63
|
+
* zero-config). */
|
|
64
|
+
backend?: string | BackendRef;
|
|
73
65
|
};
|
|
74
66
|
export type ActionOptions = Omit<ActionSpecJson, "id">;
|
|
75
67
|
export type FrontendNavItemOptions = {
|
|
@@ -117,7 +109,6 @@ export type FeatureOptions = {
|
|
|
117
109
|
/** Per-feature upstream origin override (default: product origin). */
|
|
118
110
|
upstreamOrigin?: string | null;
|
|
119
111
|
policies?: Array<string | PolicyRef>;
|
|
120
|
-
capabilities?: Array<string | CapabilityRef>;
|
|
121
112
|
/** Plans that grant this feature directly. */
|
|
122
113
|
plans?: Array<string | PlanRef>;
|
|
123
114
|
rolloutKey?: string;
|
|
@@ -193,14 +184,6 @@ export type EntitlementOptions = {
|
|
|
193
184
|
limits?: PlanLimitJson[];
|
|
194
185
|
meters?: Array<string | MeterRef>;
|
|
195
186
|
};
|
|
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
187
|
export type ResourceRef = {
|
|
205
188
|
readonly kind: "resource";
|
|
206
189
|
readonly key: string;
|
|
@@ -229,6 +212,10 @@ export type ActionRef = {
|
|
|
229
212
|
readonly kind: "action";
|
|
230
213
|
readonly key: string;
|
|
231
214
|
};
|
|
215
|
+
export type BackendRef = {
|
|
216
|
+
readonly kind: "backend";
|
|
217
|
+
readonly key: string;
|
|
218
|
+
};
|
|
232
219
|
export type FeatureRef = {
|
|
233
220
|
readonly kind: "feature";
|
|
234
221
|
readonly key: string;
|
|
@@ -246,11 +233,6 @@ export type CapabilityRef = {
|
|
|
246
233
|
limits?: Record<string, number | boolean>;
|
|
247
234
|
}): PlanCapabilityGrant;
|
|
248
235
|
};
|
|
249
|
-
export type PlanCapabilityGrant = {
|
|
250
|
-
readonly kind: "capability_grant";
|
|
251
|
-
readonly capability: string;
|
|
252
|
-
readonly limits?: Record<string, number | boolean>;
|
|
253
|
-
};
|
|
254
236
|
/**
|
|
255
237
|
* A synchronous Product SDK module. Use this to split a product across files:
|
|
256
238
|
* `product.use(configureMeters, configureRoutes, configurePlans)`.
|
|
@@ -262,7 +244,6 @@ export declare class Product {
|
|
|
262
244
|
private readonly options;
|
|
263
245
|
private readonly graph;
|
|
264
246
|
private readonly defaultMeterCosts;
|
|
265
|
-
private frontendManifest?;
|
|
266
247
|
private productPatch;
|
|
267
248
|
/** Sugar for binding API routes to features. */
|
|
268
249
|
readonly api: {
|
|
@@ -279,22 +260,26 @@ export declare class Product {
|
|
|
279
260
|
migration: (id: string, options: MigrationOptions) => Product;
|
|
280
261
|
migrations: (migrations: MigrationDeclJson[]) => Product;
|
|
281
262
|
};
|
|
282
|
-
readonly offering: {
|
|
283
|
-
plan: (key: string, options: PlanOptions) => PlanRef;
|
|
284
|
-
};
|
|
285
263
|
/** Escape hatches — raw platform-schema JSON, validated by the compiler. */
|
|
286
264
|
readonly raw: {
|
|
287
265
|
/** Deep-merged onto the emitted product spec (usage, webhooks,
|
|
288
266
|
* environments, add_ons, lifecycle, billing overrides, …). */
|
|
289
267
|
productPatch: (patch: Record<string, unknown>) => Product;
|
|
290
268
|
plan: (spec: PlanSpecJson) => Product;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
frontend: (manifest: FrontendManifestJson) => Product;
|
|
269
|
+
routeLayer: (layer: RouteLayerJson) => Product;
|
|
270
|
+
policyLayer: (layer: PolicyLayerJson) => Product;
|
|
271
|
+
capabilityLayer: (layer: CapabilityLayerJson) => Product;
|
|
295
272
|
};
|
|
296
273
|
constructor(name: string, options: ProductOptions);
|
|
297
274
|
meter(key: string, options: MeterOptions): MeterRef;
|
|
275
|
+
/**
|
|
276
|
+
* BYO-Backend V1 — declare a first-class backend (an always-running HTTP
|
|
277
|
+
* container Farther Shore wraps). Products may declare MULTIPLE backends;
|
|
278
|
+
* routes bind to one via `route(..., { backend })`. A product with exactly
|
|
279
|
+
* one backend (or exactly one marked `default: true`) makes it the implicit
|
|
280
|
+
* default, so single-backend products stay zero-config.
|
|
281
|
+
*/
|
|
282
|
+
backend(id: string, options?: BackendOptions): BackendRef;
|
|
298
283
|
requests(options?: RequestMeterOptions): MeterRef;
|
|
299
284
|
defaultMeters(costs: MeterCost | MeterCost[]): Product;
|
|
300
285
|
resource(name: string, options?: ResourceOptions): ResourceRef;
|
|
@@ -309,40 +294,17 @@ export declare class Product {
|
|
|
309
294
|
/** Inspect the SDK-local declaration graph used to emit the Manifest IR. */
|
|
310
295
|
resourceGraph(): ManifestResourceGraphSnapshot;
|
|
311
296
|
private buildProductSpec;
|
|
312
|
-
private buildMeterDefinitions;
|
|
313
|
-
private routeValueMeterKeys;
|
|
314
297
|
private buildRoute;
|
|
315
|
-
private
|
|
316
|
-
private buildRouteMetering;
|
|
317
|
-
private materializeFeatureFiles;
|
|
318
|
-
private materializeRoute;
|
|
298
|
+
private materializeFeatureLayers;
|
|
319
299
|
private normalizeMeterCost;
|
|
320
|
-
private normalizeMeterCosts;
|
|
321
|
-
private normalizeMeterRefs;
|
|
322
300
|
private ensureFrontendManifest;
|
|
323
|
-
private normalizeMigrationPlanRef;
|
|
324
|
-
private normalizeMigrationTargetRef;
|
|
325
|
-
private assertUniqueMigrationIds;
|
|
326
301
|
private assertNewKey;
|
|
327
302
|
private assertGraphDependenciesSatisfied;
|
|
328
|
-
private
|
|
329
|
-
private
|
|
303
|
+
private getFeatureLayer;
|
|
304
|
+
private registerFeatureLayer;
|
|
330
305
|
private syncFeatureGraphNode;
|
|
331
306
|
private registerAction;
|
|
332
307
|
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
308
|
}
|
|
347
309
|
export declare function isProduct(value: unknown): value is Product;
|
|
348
310
|
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,60 @@
|
|
|
1
|
+
import type { HttpMethod, 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/metering.
|
|
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
|
+
export type RouteMeteringDeps = {
|
|
44
|
+
normalizeMeterCost(cost: MeterCost): MeterCost;
|
|
45
|
+
getMeterDefinition(key: string): MeterDefinitionJson | undefined;
|
|
46
|
+
};
|
|
47
|
+
export declare function parseRouteMatch(match: string): {
|
|
48
|
+
method: HttpMethod;
|
|
49
|
+
path: string;
|
|
50
|
+
};
|
|
51
|
+
export declare function makeMeterRef(key: string): MeterRef;
|
|
52
|
+
export declare function normalizeMeterCost(cost: MeterCost, hasMeter: (meter: string) => boolean): MeterCost;
|
|
53
|
+
export declare function normalizeMeterCosts(costs: RouteMeteringOptions["costs"], normalize: (cost: MeterCost) => MeterCost): MeterCost[];
|
|
54
|
+
export declare function normalizeMeterRefs(refs: string | MeterRef | Array<string | MeterRef>): string[];
|
|
55
|
+
export declare function buildRouteDefinition(match: string, options: RouteBindingOptions, deps: RouteMeteringDeps): RouteDefinitionJson;
|
|
56
|
+
export declare function buildRouteMetering(options: RouteMeteringOptions, deps: RouteMeteringDeps): RouteDefinitionJson["metering"] | undefined;
|
|
57
|
+
export declare function materializeRoute(route: RouteDefinitionJson, defaultMeterCosts: readonly MeterCost[]): RouteDefinitionJson;
|
|
58
|
+
export declare function routeMeterDependencyKeys(route: RouteDefinitionJson): string[];
|
|
59
|
+
export declare function assertRouteMeteringValid(files: RouteLayerJson[], meterDefinitions: Iterable<MeterDefinitionJson>): void;
|
|
60
|
+
export {};
|
package/dist/types/validate.d.ts
CHANGED
|
@@ -12,10 +12,8 @@ export type ValidationResult = {
|
|
|
12
12
|
* Validate a candidate envelope against the platform schemas. On success
|
|
13
13
|
* the returned `ir` is the JSON-normalized ORIGINAL candidate — NOT the
|
|
14
14
|
* zod-parsed value. The platform treats the product spec as a raw document
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* spec via casts that a default-stripping parse would erase). Validation
|
|
18
|
-
* proves the document is acceptable; the bytes stay the author's.
|
|
15
|
+
* because the YAML path never zod-transformed it before storing/compiling.
|
|
16
|
+
* Validation proves the document is acceptable; the bytes stay the author's.
|
|
19
17
|
*/
|
|
20
18
|
export declare function validateManifestIr(candidate: unknown): ValidationResult;
|
|
21
19
|
export declare function hashIr(ir: unknown): string;
|