@farthershore/product 0.3.0 → 0.4.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 +241 -30
- package/dist/codegen.js +44 -16
- package/dist/index.js +246 -37
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/index.d.ts +4 -6
- package/dist/types/ir-types.d.ts +45 -0
- package/dist/types/{business.d.ts → product.d.ts} +73 -29
- 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
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { CacheProfile, ActionSpecJson, CapabilityFileJson, FrontendComponentId, FrontendGateMode, FrontendManifestJson, GrantJson, ManifestBuildResult, MeterDefinitionJson, MigrationDeclJson, MigrationPinJson, MutationClass, CountedResourceJson, PlanLimitJson, PlanMeterJson, PlanSpecJson, PolicyFileJson, ProductPoliciesJson, ProductCustomerContextJson, RoutesFileJson } from "./ir-types.js";
|
|
1
|
+
import type { CacheProfile, ActionSpecJson, CapabilityFileJson, FrontendComponentId, FrontendGateMode, FrontendManifestJson, GrantJson, ManifestBuildResult, 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,38 +268,44 @@ 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
285
|
/** Escape hatches — raw platform-schema JSON, validated at toIR(). */
|
|
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
311
|
/** Assemble + validate the Manifest IR. Throws ManifestValidationError
|
|
@@ -277,6 +317,8 @@ export declare class Business {
|
|
|
277
317
|
private buildRoute;
|
|
278
318
|
private makeMeterRef;
|
|
279
319
|
private buildRouteMetering;
|
|
320
|
+
private materializeFeatureFiles;
|
|
321
|
+
private materializeRoute;
|
|
280
322
|
private normalizeMeterCost;
|
|
281
323
|
private normalizeMeterCosts;
|
|
282
324
|
private normalizeMeterRefs;
|
|
@@ -293,6 +335,8 @@ export declare class Business {
|
|
|
293
335
|
private syncFrontendGraphNode;
|
|
294
336
|
private capabilityDependsOn;
|
|
295
337
|
private policyDependsOn;
|
|
338
|
+
private entitlementDependsOn;
|
|
339
|
+
private workflowDependsOn;
|
|
296
340
|
private featureDependsOn;
|
|
297
341
|
private routeMeterDependencyKeys;
|
|
298
342
|
private assertRouteMeteringValid;
|
|
@@ -303,5 +347,5 @@ export declare class Business {
|
|
|
303
347
|
private dependenciesFor;
|
|
304
348
|
private existingDependenciesFor;
|
|
305
349
|
}
|
|
306
|
-
export declare function
|
|
307
|
-
export declare function
|
|
350
|
+
export declare function isProduct(value: unknown): value is Product;
|
|
351
|
+
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.4.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",
|