@farthershore/product 0.0.0 → 0.2.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 +153 -0
- package/dist/bin.js +457 -75
- package/dist/codegen.js +23 -0
- package/dist/index.js +418 -70
- package/dist/types/business.d.ts +35 -10
- package/dist/types/index.d.ts +2 -1
- package/dist/types/ir-types.d.ts +25 -0
- package/dist/types/resource-graph.d.ts +36 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# @farthershore/product
|
|
2
|
+
|
|
3
|
+
Product-as-Code SDK for Farther Shore. Builder repos use this package from
|
|
4
|
+
`product/product.config.ts` to declare product contracts in TypeScript. Builders
|
|
5
|
+
author and export a `Business`; the Farther Shore GitHub bot compiles that
|
|
6
|
+
program to backend-owned IR, validates it, and publishes through Core when repo
|
|
7
|
+
changes land.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @farthershore/product
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Builder repos generated by Farther Shore already pin this dependency in
|
|
16
|
+
`product/package.json`.
|
|
17
|
+
|
|
18
|
+
## Repo Layout
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
product/
|
|
22
|
+
package.json
|
|
23
|
+
product.config.ts
|
|
24
|
+
meters.ts
|
|
25
|
+
plans/
|
|
26
|
+
free.ts
|
|
27
|
+
pro.ts
|
|
28
|
+
routes/
|
|
29
|
+
api.ts
|
|
30
|
+
frontend/
|
|
31
|
+
...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`product/` is authored Product SDK code. `frontend/` is the generated editable
|
|
35
|
+
frontend app and is built by the frontend pipeline only. Runtime state and
|
|
36
|
+
compiled IR are not checked into the builder repo; Farther Shore stores them in
|
|
37
|
+
Core.
|
|
38
|
+
|
|
39
|
+
## Example
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { fs } from "@farthershore/product";
|
|
43
|
+
import { configureMeters } from "./meters.js";
|
|
44
|
+
import { configureCronRoutes } from "./routes/cron.js";
|
|
45
|
+
import { configurePlans } from "./plans/index.js";
|
|
46
|
+
|
|
47
|
+
const business = fs.business("croncloud", {
|
|
48
|
+
baseUrl: "https://api.example.com",
|
|
49
|
+
displayName: "CronCloud",
|
|
50
|
+
description: "Managed cron jobs",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
business.use(configureMeters, configureCronRoutes, configurePlans);
|
|
54
|
+
|
|
55
|
+
export default business;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Modules are plain synchronous functions:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { fs, type ProductModule } from "@farthershore/product";
|
|
62
|
+
|
|
63
|
+
export const configureMeters: ProductModule = (product) => {
|
|
64
|
+
product.meter("requests", { display: "Requests" });
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const configurePlans: ProductModule = (product) => {
|
|
68
|
+
product.plan("starter", {
|
|
69
|
+
name: "Starter",
|
|
70
|
+
price: fs.price.monthly(29),
|
|
71
|
+
limits: [
|
|
72
|
+
{
|
|
73
|
+
dimension: "requests",
|
|
74
|
+
window: { type: "named", name: "minute" },
|
|
75
|
+
capacity: 600,
|
|
76
|
+
enforcement: "enforce",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Bot build
|
|
84
|
+
|
|
85
|
+
Normal product repos do not call platform release or IR APIs. The GitHub bot
|
|
86
|
+
owns that workflow:
|
|
87
|
+
|
|
88
|
+
1. Loads `product/product.config.ts`.
|
|
89
|
+
2. Requires the default export to be the `Business` returned by
|
|
90
|
+
`fs.business(...)` or `fs.product(...)`.
|
|
91
|
+
3. Executes imported modules and compiles the business into deterministic
|
|
92
|
+
Manifest IR.
|
|
93
|
+
4. Validates the result against the deployed platform contract.
|
|
94
|
+
5. Publishes the accepted release through Core so edge artifacts propagate.
|
|
95
|
+
|
|
96
|
+
The bundled `farthershore-manifest-build` binary is bot/build-runner plumbing.
|
|
97
|
+
Run it locally only when debugging the automation itself; it is not part of the
|
|
98
|
+
normal builder workflow.
|
|
99
|
+
|
|
100
|
+
## Public API
|
|
101
|
+
|
|
102
|
+
- `fs.business(name, options)` / `fs.product(name, options)` — create the
|
|
103
|
+
product builder.
|
|
104
|
+
- `business.use(...modules)` — compose Product SDK modules from any files under
|
|
105
|
+
`product/`.
|
|
106
|
+
- `business.meter(...)` — declare billable or enforceable dimensions.
|
|
107
|
+
- `business.resource(...)` — declare counted resources for resource-count
|
|
108
|
+
constraints.
|
|
109
|
+
- `business.capability(...)` — declare capability bundles and plan grants.
|
|
110
|
+
- `business.feature(...)` / `business.api.route(...)` — declare gateway routes,
|
|
111
|
+
meters, and action metadata.
|
|
112
|
+
- `business.policy(...)` — declare policy files in code.
|
|
113
|
+
- `business.plan(...)` — declare plan pricing, limits, grants, and lifecycle
|
|
114
|
+
behavior.
|
|
115
|
+
- `business.lifecycle.*` — declare migrations.
|
|
116
|
+
- `business.raw.*` — escape hatches for platform-schema JSON when the typed SDK
|
|
117
|
+
does not yet have sugar.
|
|
118
|
+
|
|
119
|
+
## Determinism
|
|
120
|
+
|
|
121
|
+
`product/product.config.ts` and everything it imports must be deterministic: no
|
|
122
|
+
dates, randomness, network calls, or process state. Sorted collections produce
|
|
123
|
+
stable output, while route order remains semantic because the gateway matcher is
|
|
124
|
+
first-match-wins.
|
|
125
|
+
|
|
126
|
+
The GitHub bot runs the build twice and rejects the push if the two generated
|
|
127
|
+
hashes differ.
|
|
128
|
+
|
|
129
|
+
## Release
|
|
130
|
+
|
|
131
|
+
`@farthershore/product` publishes to public npm through the GitHub workflow
|
|
132
|
+
`.github/workflows/publish-product-sdk.yml`.
|
|
133
|
+
|
|
134
|
+
Release sequence:
|
|
135
|
+
|
|
136
|
+
1. Bump `packages/product/package.json` version.
|
|
137
|
+
2. Run the package checks:
|
|
138
|
+
```bash
|
|
139
|
+
pnpm --filter @farthershore/product run lint
|
|
140
|
+
pnpm --filter @farthershore/product run test
|
|
141
|
+
pnpm --filter @farthershore/product run build
|
|
142
|
+
pnpm --filter @farthershore/product run pack:check
|
|
143
|
+
```
|
|
144
|
+
3. Commit, push, and merge through the normal PR flow.
|
|
145
|
+
4. Tag from `main` with the exact package version:
|
|
146
|
+
```bash
|
|
147
|
+
git tag product-v<version>
|
|
148
|
+
git push origin product-v<version>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The publish workflow verifies that the tag equals
|
|
152
|
+
`product-v<packages/product/package.json version>`, builds/tests the package and
|
|
153
|
+
its dependencies, runs `pack:check`, then publishes with `NPM_PUBLISH_TOKEN`.
|