@farthershore/product 0.3.1 → 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.
@@ -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 Business across SDK copies
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 BUSINESS_BRAND: unique symbol;
7
- export type BusinessOptions = {
8
- /** Upstream origin the gateway proxies to. */
9
- baseUrl: string;
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
- sandboxBaseUrl?: string;
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
- portalAuth?: ProductCustomerContextJson["portal_auth"];
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 baseUrl). */
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: Business) => void;
225
- export declare class Business {
226
- readonly [BUSINESS_BRAND] = true;
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) => Business;
271
+ } & RouteOptions) => Product;
238
272
  };
239
273
  readonly frontend: {
240
- nav: (items: FrontendNavItemOptions[]) => Business;
241
- page: (path: string, options: FrontendPageOptions) => Business;
242
- manifest: (manifest: FrontendManifestJson) => Business;
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) => Business;
246
- migrations: (migrations: MigrationDeclJson[]) => Business;
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>) => Business;
253
- plan: (spec: PlanSpecJson) => Business;
254
- routesFile: (file: RoutesFileJson) => Business;
255
- policyFile: (file: PolicyFileJson) => Business;
256
- capabilityFile: (file: CapabilityFileJson) => Business;
257
- frontend: (manifest: FrontendManifestJson) => Business;
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: BusinessOptions);
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[]): Business;
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[]): Business;
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 isBusiness(value: unknown): value is Business;
307
- export declare function business(name: string, options: BusinessOptions, configure?: ProductModule): Business;
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.3.1",
4
- "description": "Farther Shore product-as-code SDK — declare your business in TypeScript",
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
- "api",
34
+ "software-product",
35
35
  "billing",
36
- "api-monetization"
36
+ "monetization"
37
37
  ],
38
38
  "author": "Farther Shore",
39
39
  "license": "MIT",