@farthershore/product 0.3.1 → 0.5.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 +42 -31
- package/dist/bin.js +252 -35
- package/dist/codegen.js +43 -16
- package/dist/index.js +253 -41
- package/dist/types/errors.d.ts +3 -3
- package/dist/types/index.d.ts +4 -6
- package/dist/types/ir-types.d.ts +46 -1
- package/dist/types/{business.d.ts → product.d.ts} +74 -33
- package/dist/types/resource-graph.d.ts +1 -1
- package/package.json +4 -4
package/dist/types/ir-types.d.ts
CHANGED
|
@@ -228,6 +228,48 @@ export type ProductCustomerContextJson = {
|
|
|
228
228
|
strategy: CustomerPortalAuthStrategyJson;
|
|
229
229
|
};
|
|
230
230
|
};
|
|
231
|
+
export type ProductSurfaceTypeJson = "frontend" | "api" | "docs" | "widget" | "dashboard" | "webhook" | "worker" | "agent";
|
|
232
|
+
export type ProductSurfaceJson = {
|
|
233
|
+
key: string;
|
|
234
|
+
type: ProductSurfaceTypeJson;
|
|
235
|
+
display?: string;
|
|
236
|
+
description?: string;
|
|
237
|
+
};
|
|
238
|
+
export type ProductEntitlementJson = {
|
|
239
|
+
key: string;
|
|
240
|
+
description?: string;
|
|
241
|
+
capabilities?: string[];
|
|
242
|
+
featureGates?: Record<string, boolean>;
|
|
243
|
+
limits?: PlanLimitJson[];
|
|
244
|
+
meters?: string[];
|
|
245
|
+
};
|
|
246
|
+
export type ProductWorkflowKindJson = "async_job" | "agent_task" | "scheduled" | "lifecycle" | "background";
|
|
247
|
+
export type ProductWorkflowTriggerJson = {
|
|
248
|
+
type: "manual";
|
|
249
|
+
} | {
|
|
250
|
+
type: "schedule";
|
|
251
|
+
cron: string;
|
|
252
|
+
} | {
|
|
253
|
+
type: "event";
|
|
254
|
+
event: string;
|
|
255
|
+
} | {
|
|
256
|
+
type: "api";
|
|
257
|
+
path: string;
|
|
258
|
+
} | {
|
|
259
|
+
type: "lifecycle";
|
|
260
|
+
event: string;
|
|
261
|
+
};
|
|
262
|
+
export type ProductWorkflowJson = {
|
|
263
|
+
key: string;
|
|
264
|
+
title?: string;
|
|
265
|
+
description?: string;
|
|
266
|
+
kind: ProductWorkflowKindJson;
|
|
267
|
+
trigger: ProductWorkflowTriggerJson;
|
|
268
|
+
capabilities?: string[];
|
|
269
|
+
meters?: string[];
|
|
270
|
+
estimates?: Record<string, number>;
|
|
271
|
+
metadata?: Record<string, unknown>;
|
|
272
|
+
};
|
|
231
273
|
export type ProductBlockJson = {
|
|
232
274
|
name: string;
|
|
233
275
|
displayName?: string;
|
|
@@ -257,6 +299,9 @@ export type ProductSpecJson = {
|
|
|
257
299
|
resources?: CountedResourceJson[];
|
|
258
300
|
policies?: ProductPoliciesJson;
|
|
259
301
|
customer_context?: ProductCustomerContextJson;
|
|
302
|
+
surfaces?: ProductSurfaceJson[];
|
|
303
|
+
entitlements?: ProductEntitlementJson[];
|
|
304
|
+
workflows?: ProductWorkflowJson[];
|
|
260
305
|
plans?: PlanSpecJson[];
|
|
261
306
|
/** Legacy / advanced product blocks (usage, features, billing,
|
|
262
307
|
* webhooks, environments, add_ons, lifecycle, ephemeral, …) ride
|
|
@@ -276,7 +321,7 @@ export type ManifestIrDocument = {
|
|
|
276
321
|
migrations: null;
|
|
277
322
|
};
|
|
278
323
|
};
|
|
279
|
-
/**
|
|
324
|
+
/** Platform compiler result: the validated envelope plus its canonical hash. */
|
|
280
325
|
export type ManifestBuildResult = {
|
|
281
326
|
ir: ManifestIrDocument;
|
|
282
327
|
irHash: string;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { CacheProfile, ActionSpecJson, CapabilityFileJson, FrontendComponentId, FrontendGateMode, FrontendManifestJson, GrantJson,
|
|
1
|
+
import type { CacheProfile, ActionSpecJson, CapabilityFileJson, FrontendComponentId, FrontendGateMode, FrontendManifestJson, GrantJson, MeterDefinitionJson, MigrationDeclJson, MigrationPinJson, MutationClass, CountedResourceJson, PlanLimitJson, PlanMeterJson, PlanSpecJson, PolicyFileJson, ProductPoliciesJson, ProductCustomerContextJson, ProductWorkflowKindJson, ProductWorkflowTriggerJson, ProductSurfaceTypeJson, RoutesFileJson } from "./ir-types.js";
|
|
2
2
|
import type { PriceSpec } from "./price.js";
|
|
3
3
|
import { type ManifestResourceGraphSnapshot } from "./resource-graph.js";
|
|
4
|
-
/** Brand symbol so the bin can recognize a
|
|
4
|
+
/** Brand symbol so the bin can recognize a Product across SDK copies
|
|
5
5
|
* (the repo's pinned SDK vs whatever loaded the entry). */
|
|
6
|
-
export declare const
|
|
7
|
-
export type
|
|
8
|
-
/**
|
|
9
|
-
|
|
6
|
+
export declare const PRODUCT_BRAND: unique symbol;
|
|
7
|
+
export type ProductOptions = {
|
|
8
|
+
/** Business logic origin Farther Shore calls for customer-facing actions. */
|
|
9
|
+
origin: string;
|
|
10
10
|
displayName?: string;
|
|
11
11
|
description?: string;
|
|
12
|
-
|
|
12
|
+
sandboxOrigin?: string;
|
|
13
13
|
visibility?: "public" | "private";
|
|
14
14
|
logoUrl?: string;
|
|
15
15
|
primaryColor?: string;
|
|
@@ -27,7 +27,7 @@ export type BusinessOptions = {
|
|
|
27
27
|
customerContext?: {
|
|
28
28
|
identityRequirement?: ProductCustomerContextJson["identity_requirement"];
|
|
29
29
|
contextTokens?: ProductCustomerContextJson["context_tokens"];
|
|
30
|
-
|
|
30
|
+
customerAuth?: ProductCustomerContextJson["portal_auth"];
|
|
31
31
|
};
|
|
32
32
|
billing?: {
|
|
33
33
|
gracePeriodDays?: number;
|
|
@@ -114,7 +114,7 @@ export type FeatureOptions = {
|
|
|
114
114
|
description?: string;
|
|
115
115
|
mutationClass?: MutationClass;
|
|
116
116
|
cacheProfile?: CacheProfile;
|
|
117
|
-
/** Per-feature upstream origin override (default: product
|
|
117
|
+
/** Per-feature upstream origin override (default: product origin). */
|
|
118
118
|
upstreamOrigin?: string | null;
|
|
119
119
|
policies?: Array<string | PolicyRef>;
|
|
120
120
|
capabilities?: Array<string | CapabilityRef>;
|
|
@@ -171,6 +171,28 @@ export type PlanOptions = {
|
|
|
171
171
|
/** Escape hatch: merged onto the emitted plan spec last (e.g. variants). */
|
|
172
172
|
raw?: Record<string, unknown>;
|
|
173
173
|
};
|
|
174
|
+
export type SurfaceOptions = {
|
|
175
|
+
key?: string;
|
|
176
|
+
display?: string;
|
|
177
|
+
description?: string;
|
|
178
|
+
};
|
|
179
|
+
export type WorkflowOptions = {
|
|
180
|
+
title?: string;
|
|
181
|
+
description?: string;
|
|
182
|
+
kind?: ProductWorkflowKindJson;
|
|
183
|
+
trigger?: ProductWorkflowTriggerJson;
|
|
184
|
+
capabilities?: Array<string | CapabilityRef>;
|
|
185
|
+
meters?: Array<string | MeterRef>;
|
|
186
|
+
estimates?: Record<string, number>;
|
|
187
|
+
metadata?: Record<string, unknown>;
|
|
188
|
+
};
|
|
189
|
+
export type EntitlementOptions = {
|
|
190
|
+
description?: string;
|
|
191
|
+
capabilities?: Array<string | CapabilityRef>;
|
|
192
|
+
featureGates?: Record<string, boolean>;
|
|
193
|
+
limits?: PlanLimitJson[];
|
|
194
|
+
meters?: Array<string | MeterRef>;
|
|
195
|
+
};
|
|
174
196
|
export type MeterRef = {
|
|
175
197
|
readonly kind: "meter";
|
|
176
198
|
readonly key: string;
|
|
@@ -191,6 +213,18 @@ export type PlanRef = {
|
|
|
191
213
|
readonly kind: "plan";
|
|
192
214
|
readonly key: string;
|
|
193
215
|
};
|
|
216
|
+
export type SurfaceRef = {
|
|
217
|
+
readonly kind: "surface";
|
|
218
|
+
readonly key: string;
|
|
219
|
+
};
|
|
220
|
+
export type WorkflowRef = {
|
|
221
|
+
readonly kind: "workflow";
|
|
222
|
+
readonly key: string;
|
|
223
|
+
};
|
|
224
|
+
export type EntitlementRef = {
|
|
225
|
+
readonly kind: "entitlement";
|
|
226
|
+
readonly key: string;
|
|
227
|
+
};
|
|
194
228
|
export type ActionRef = {
|
|
195
229
|
readonly kind: "action";
|
|
196
230
|
readonly key: string;
|
|
@@ -221,9 +255,9 @@ export type PlanCapabilityGrant = {
|
|
|
221
255
|
* A synchronous Product SDK module. Use this to split a product across files:
|
|
222
256
|
* `product.use(configureMeters, configureRoutes, configurePlans)`.
|
|
223
257
|
*/
|
|
224
|
-
export type ProductModule = (product:
|
|
225
|
-
export declare class
|
|
226
|
-
readonly [
|
|
258
|
+
export type ProductModule = (product: Product) => void;
|
|
259
|
+
export declare class Product {
|
|
260
|
+
readonly [PRODUCT_BRAND] = true;
|
|
227
261
|
readonly name: string;
|
|
228
262
|
private readonly options;
|
|
229
263
|
private readonly graph;
|
|
@@ -234,49 +268,54 @@ export declare class Business {
|
|
|
234
268
|
readonly api: {
|
|
235
269
|
route: (match: string, options: {
|
|
236
270
|
feature: string | FeatureRef;
|
|
237
|
-
} & RouteOptions) =>
|
|
271
|
+
} & RouteOptions) => Product;
|
|
238
272
|
};
|
|
239
273
|
readonly frontend: {
|
|
240
|
-
nav: (items: FrontendNavItemOptions[]) =>
|
|
241
|
-
page: (path: string, options: FrontendPageOptions) =>
|
|
242
|
-
manifest: (manifest: FrontendManifestJson) =>
|
|
274
|
+
nav: (items: FrontendNavItemOptions[]) => Product;
|
|
275
|
+
page: (path: string, options: FrontendPageOptions) => Product;
|
|
276
|
+
manifest: (manifest: FrontendManifestJson) => Product;
|
|
243
277
|
};
|
|
244
278
|
readonly lifecycle: {
|
|
245
|
-
migration: (id: string, options: MigrationOptions) =>
|
|
246
|
-
migrations: (migrations: MigrationDeclJson[]) =>
|
|
279
|
+
migration: (id: string, options: MigrationOptions) => Product;
|
|
280
|
+
migrations: (migrations: MigrationDeclJson[]) => Product;
|
|
281
|
+
};
|
|
282
|
+
readonly offering: {
|
|
283
|
+
plan: (key: string, options: PlanOptions) => PlanRef;
|
|
247
284
|
};
|
|
248
|
-
/** Escape hatches — raw platform-schema JSON, validated
|
|
285
|
+
/** Escape hatches — raw platform-schema JSON, validated by the compiler. */
|
|
249
286
|
readonly raw: {
|
|
250
287
|
/** Deep-merged onto the emitted product spec (usage, webhooks,
|
|
251
288
|
* environments, add_ons, lifecycle, billing overrides, …). */
|
|
252
|
-
productPatch: (patch: Record<string, unknown>) =>
|
|
253
|
-
plan: (spec: PlanSpecJson) =>
|
|
254
|
-
routesFile: (file: RoutesFileJson) =>
|
|
255
|
-
policyFile: (file: PolicyFileJson) =>
|
|
256
|
-
capabilityFile: (file: CapabilityFileJson) =>
|
|
257
|
-
frontend: (manifest: FrontendManifestJson) =>
|
|
289
|
+
productPatch: (patch: Record<string, unknown>) => Product;
|
|
290
|
+
plan: (spec: PlanSpecJson) => Product;
|
|
291
|
+
routesFile: (file: RoutesFileJson) => Product;
|
|
292
|
+
policyFile: (file: PolicyFileJson) => Product;
|
|
293
|
+
capabilityFile: (file: CapabilityFileJson) => Product;
|
|
294
|
+
frontend: (manifest: FrontendManifestJson) => Product;
|
|
258
295
|
};
|
|
259
|
-
constructor(name: string, options:
|
|
296
|
+
constructor(name: string, options: ProductOptions);
|
|
260
297
|
meter(key: string, options: MeterOptions): MeterRef;
|
|
261
298
|
requests(options?: RequestMeterOptions): MeterRef;
|
|
262
|
-
defaultMeters(costs: MeterCost | MeterCost[]):
|
|
299
|
+
defaultMeters(costs: MeterCost | MeterCost[]): Product;
|
|
263
300
|
resource(name: string, options?: ResourceOptions): ResourceRef;
|
|
264
301
|
capability(key: string, options?: CapabilityOptions): CapabilityRef;
|
|
265
302
|
feature(key: string, options?: FeatureOptions): FeatureRef;
|
|
266
303
|
policy(name: string, options: PolicyOptions): PolicyRef;
|
|
304
|
+
surface(type: ProductSurfaceTypeJson, options?: SurfaceOptions): SurfaceRef;
|
|
305
|
+
workflow(key: string, options?: WorkflowOptions): WorkflowRef;
|
|
306
|
+
entitlement(key: string, options?: EntitlementOptions): EntitlementRef;
|
|
267
307
|
plan(key: string, options: PlanOptions): PlanRef;
|
|
268
|
-
use(...modules: ProductModule[]):
|
|
308
|
+
use(...modules: ProductModule[]): Product;
|
|
269
309
|
/** Inspect the SDK-local declaration graph used to emit the Manifest IR. */
|
|
270
310
|
resourceGraph(): ManifestResourceGraphSnapshot;
|
|
271
|
-
/** Assemble + validate the Manifest IR. Throws ManifestValidationError
|
|
272
|
-
* with structured issues when the declared state is invalid. */
|
|
273
|
-
toIR(): ManifestBuildResult;
|
|
274
311
|
private buildProductSpec;
|
|
275
312
|
private buildMeterDefinitions;
|
|
276
313
|
private routeValueMeterKeys;
|
|
277
314
|
private buildRoute;
|
|
278
315
|
private makeMeterRef;
|
|
279
316
|
private buildRouteMetering;
|
|
317
|
+
private materializeFeatureFiles;
|
|
318
|
+
private materializeRoute;
|
|
280
319
|
private normalizeMeterCost;
|
|
281
320
|
private normalizeMeterCosts;
|
|
282
321
|
private normalizeMeterRefs;
|
|
@@ -293,6 +332,8 @@ export declare class Business {
|
|
|
293
332
|
private syncFrontendGraphNode;
|
|
294
333
|
private capabilityDependsOn;
|
|
295
334
|
private policyDependsOn;
|
|
335
|
+
private entitlementDependsOn;
|
|
336
|
+
private workflowDependsOn;
|
|
296
337
|
private featureDependsOn;
|
|
297
338
|
private routeMeterDependencyKeys;
|
|
298
339
|
private assertRouteMeteringValid;
|
|
@@ -303,5 +344,5 @@ export declare class Business {
|
|
|
303
344
|
private dependenciesFor;
|
|
304
345
|
private existingDependenciesFor;
|
|
305
346
|
}
|
|
306
|
-
export declare function
|
|
307
|
-
export declare function
|
|
347
|
+
export declare function isProduct(value: unknown): value is Product;
|
|
348
|
+
export declare function product(name: string, options: ProductOptions, configure?: ProductModule): Product;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ManifestResourceKind = "product" | "meter" | "counted_resource" | "capability" | "policy" | "feature" | "action" | "plan" | "frontend" | "lifecycle_migration";
|
|
1
|
+
export type ManifestResourceKind = "product" | "meter" | "counted_resource" | "capability" | "surface" | "entitlement" | "workflow" | "policy" | "feature" | "action" | "plan" | "frontend" | "lifecycle_migration";
|
|
2
2
|
export type ManifestResourceUrn = `urn:farthershore:product:${ManifestResourceKind}:${string}`;
|
|
3
3
|
export type ManifestResourceRef = {
|
|
4
4
|
readonly kind: ManifestResourceKind;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farthershore/product",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Farther Shore product-as-code SDK — declare your
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Farther Shore product-as-code SDK — declare your software product in TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"keywords": [
|
|
32
32
|
"farthershore",
|
|
33
33
|
"product-as-code",
|
|
34
|
-
"
|
|
34
|
+
"software-product",
|
|
35
35
|
"billing",
|
|
36
|
-
"
|
|
36
|
+
"monetization"
|
|
37
37
|
],
|
|
38
38
|
"author": "Farther Shore",
|
|
39
39
|
"license": "MIT",
|