@intentius/chant-lexicon-fly 0.44.13 → 0.45.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/dist/codegen/docs.d.ts +0 -6
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/codegen/docs.ts +0 -86
- package/src/import/roundtrip.test.ts +2 -2
- package/src/serializer.test.ts +16 -16
package/dist/codegen/docs.d.ts
CHANGED
|
@@ -12,12 +12,6 @@
|
|
|
12
12
|
* Machines, Storage, Networking, Secrets).
|
|
13
13
|
*/
|
|
14
14
|
export declare function serviceFromType(resourceType: string): string;
|
|
15
|
-
/**
|
|
16
|
-
* The reference doc URL for a fly resource type. The Machines API (flaps) is
|
|
17
|
-
* documented at docs.machines.dev, tagged by resource; resources flaps does not
|
|
18
|
-
* own (public IPs, certificates) link to the matching fly.io docs page.
|
|
19
|
-
*/
|
|
20
|
-
export declare function resourceTypeUrl(resourceType: string): string;
|
|
21
15
|
/**
|
|
22
16
|
* Generate documentation for the fly Machines lexicon.
|
|
23
17
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAiB5D;AA2DD;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBjF"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "aed323ed6c59f96ab9470a796a81e75ddac9d72d7b1a5f7522cc7a544d88df42",
|
|
5
5
|
"meta.json": "e46e65ba7544fafc6dbb3fd48b841904b5ae6f7cb4d517a940ed68b01626c097",
|
|
6
6
|
"types/index.d.ts": "a76090adb6eda33a2c07a074183299a59e953b48dd3f2020d7ef11278d59341e",
|
|
7
7
|
"rules/guest-sizing.ts": "bc749d218df8f3cc3d8fbe388205ae96e6b204ae0d6d77e8bf82cb936cc53ff6",
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
"skills/chant-fly-ops.md": "b8eef6504e203133e6a35c83aabb08404eec95060705395515a0046d42269cf1",
|
|
16
16
|
"skills/chant-fly-sprites.md": "89ba52db63a71a17eab483d99233a4ae67f5d34920445010e750f81c95200b4e"
|
|
17
17
|
},
|
|
18
|
-
"composite": "
|
|
18
|
+
"composite": "2831247df3815a0f1f18a99d8a7dc4baeb905952268fec353746037d2d8a86c2"
|
|
19
19
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-fly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src/",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"typescript": "^5.9.3"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@intentius/chant": "^0.
|
|
60
|
+
"@intentius/chant": "^0.45.0",
|
|
61
61
|
"typescript": "^5.9.3"
|
|
62
62
|
},
|
|
63
63
|
"description": "Fly.io Machines lexicon for chant — declarative IaC in TypeScript",
|
package/src/codegen/docs.ts
CHANGED
|
@@ -12,20 +12,6 @@ import { docsPipeline, writeDocsSite, type DocsConfig } from "@intentius/chant/c
|
|
|
12
12
|
|
|
13
13
|
const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* The curated top-level fly resources (#741), in the order they read best in a
|
|
17
|
-
* reference table. Property types (MachineConfig, MachineGuest, ...) are grouped
|
|
18
|
-
* separately by the pipeline and are not repeated here.
|
|
19
|
-
*/
|
|
20
|
-
const RESOURCES: Array<{ className: string; resourceType: string }> = [
|
|
21
|
-
{ className: "App", resourceType: "Fly::Machines::App" },
|
|
22
|
-
{ className: "Machine", resourceType: "Fly::Machines::Machine" },
|
|
23
|
-
{ className: "Volume", resourceType: "Fly::Machines::Volume" },
|
|
24
|
-
{ className: "IPAddress", resourceType: "Fly::Machines::IPAddress" },
|
|
25
|
-
{ className: "Certificate", resourceType: "Fly::Machines::Certificate" },
|
|
26
|
-
{ className: "Secret", resourceType: "Fly::Machines::Secret" },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
15
|
/**
|
|
30
16
|
* Group a fly resource type into a service bucket for the reference sidebar.
|
|
31
17
|
* fly type names are `Fly::Machines::<Kind>`, so the middle segment is always
|
|
@@ -51,31 +37,6 @@ export function serviceFromType(resourceType: string): string {
|
|
|
51
37
|
}
|
|
52
38
|
}
|
|
53
39
|
|
|
54
|
-
/**
|
|
55
|
-
* The reference doc URL for a fly resource type. The Machines API (flaps) is
|
|
56
|
-
* documented at docs.machines.dev, tagged by resource; resources flaps does not
|
|
57
|
-
* own (public IPs, certificates) link to the matching fly.io docs page.
|
|
58
|
-
*/
|
|
59
|
-
export function resourceTypeUrl(resourceType: string): string {
|
|
60
|
-
const kind = resourceType.split("::")[2] ?? resourceType;
|
|
61
|
-
switch (kind) {
|
|
62
|
-
case "App":
|
|
63
|
-
return "https://docs.machines.dev/#tag/apps";
|
|
64
|
-
case "Machine":
|
|
65
|
-
return "https://docs.machines.dev/#tag/machines";
|
|
66
|
-
case "Volume":
|
|
67
|
-
return "https://docs.machines.dev/#tag/volumes";
|
|
68
|
-
case "Secret":
|
|
69
|
-
return "https://docs.machines.dev/#tag/secrets";
|
|
70
|
-
case "IPAddress":
|
|
71
|
-
return "https://fly.io/docs/networking/services/";
|
|
72
|
-
case "Certificate":
|
|
73
|
-
return "https://fly.io/docs/networking/custom-domains-with-fly/";
|
|
74
|
-
default:
|
|
75
|
-
return "https://docs.machines.dev/";
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
40
|
const overview = `The **Fly Machines** lexicon defines Fly.io apps and machines using chant's declarative TypeScript syntax. Resources are serialized to the JSON create bodies the Machines API ("flaps") accepts, so the applier can POST them straight through and the mudflaps emulator can round-trip them offline.
|
|
80
41
|
|
|
81
42
|
This lexicon is generated from Fly's published [Machines API OpenAPI spec](https://docs.machines.dev/openapi.json).
|
|
@@ -133,17 +94,6 @@ Every serialized machine carries the \`managed-by: chant\` ownership marker in \
|
|
|
133
94
|
|
|
134
95
|
The output is applied against flaps directly (or the mudflaps emulator offline). Endpoint and auth come from \`FLY_FLAPS_BASE_URL\` and \`FLY_API_TOKEN\`.`;
|
|
135
96
|
|
|
136
|
-
const resourcesPage = `The fly lexicon ships ${RESOURCES.length} top-level resources. Each maps to a Machines API create body; follow the reference link for the underlying API shape.
|
|
137
|
-
|
|
138
|
-
| Resource | Type | Service | Machines API |
|
|
139
|
-
|----------|------|---------|--------------|
|
|
140
|
-
${RESOURCES.map(
|
|
141
|
-
(r) =>
|
|
142
|
-
`| \`${r.className}\` | \`${r.resourceType}\` | ${serviceFromType(r.resourceType)} | [reference](${resourceTypeUrl(r.resourceType)}) |`,
|
|
143
|
-
).join("\n")}
|
|
144
|
-
|
|
145
|
-
Property types such as \`MachineConfig\`, \`MachineGuest\`, \`MachineService\`, \`MachinePort\`, and \`MachineMount\` are authored inline on a resource and are documented alongside the resources they belong to.`;
|
|
146
|
-
|
|
147
97
|
/**
|
|
148
98
|
* Generate documentation for the fly Machines lexicon.
|
|
149
99
|
*/
|
|
@@ -159,42 +109,6 @@ export async function generateDocs(options?: { verbose?: boolean }): Promise<voi
|
|
|
159
109
|
overview,
|
|
160
110
|
outputFormat,
|
|
161
111
|
serviceFromType,
|
|
162
|
-
extraPages: [
|
|
163
|
-
{
|
|
164
|
-
slug: "resources",
|
|
165
|
-
title: "Resource Reference",
|
|
166
|
-
description: "The fly resource types and their Machines API documentation links",
|
|
167
|
-
content: resourcesPage,
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
slug: "pseudo-params",
|
|
171
|
-
title: "Pseudo-parameters",
|
|
172
|
-
description: "Environment-resolved values: Fly.Region, Fly.OrgSlug, Fly.AppName",
|
|
173
|
-
content: `Pseudo-parameters stand in for values that vary by environment. Reference them instead of hard-coding, and the serializer resolves each from an environment variable at build time.
|
|
174
|
-
|
|
175
|
-
| Pseudo-parameter | Environment variable | Fallback |
|
|
176
|
-
|------------------|----------------------|----------|
|
|
177
|
-
| \`Fly.Region\` | \`FLY_REGION\` | \`iad\` |
|
|
178
|
-
| \`Fly.OrgSlug\` | \`FLY_ORG\`, then \`FLY_ORG_SLUG\` | \`personal\` |
|
|
179
|
-
| \`Fly.AppName\` | \`FLY_APP_NAME\` | \`app\` |
|
|
180
|
-
|
|
181
|
-
\`\`\`typescript
|
|
182
|
-
import { App, Machine, MachineConfig, MachineGuest, Fly } from "@intentius/chant-lexicon-fly";
|
|
183
|
-
|
|
184
|
-
const app = new App({ name: "my-app", org_slug: Fly.OrgSlug });
|
|
185
|
-
|
|
186
|
-
const web = new Machine({
|
|
187
|
-
region: Fly.Region,
|
|
188
|
-
config: new MachineConfig({
|
|
189
|
-
image: "flyio/hellofly:latest",
|
|
190
|
-
guest: new MachineGuest({ cpu_kind: "shared", cpus: 1, memory_mb: 256 }),
|
|
191
|
-
}),
|
|
192
|
-
});
|
|
193
|
-
\`\`\`
|
|
194
|
-
|
|
195
|
-
With \`FLY_REGION=lhr\` set, \`region\` serializes to \`"lhr"\`; unset, it falls back to \`"iad"\`.`,
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
112
|
};
|
|
199
113
|
|
|
200
114
|
const result = docsPipeline(config);
|
|
@@ -49,7 +49,7 @@ describe("roundtrip: declared entities → serialize → parse → generate →
|
|
|
49
49
|
["app", app],
|
|
50
50
|
["web", web],
|
|
51
51
|
]);
|
|
52
|
-
const planA = JSON.parse(flySerializer.serialize(entities));
|
|
52
|
+
const planA = JSON.parse(flySerializer.serialize(entities) as string);
|
|
53
53
|
|
|
54
54
|
// 2. Parse the plan and generate TypeScript.
|
|
55
55
|
const ir = parser.parse(JSON.stringify(planA));
|
|
@@ -67,7 +67,7 @@ describe("roundtrip: declared entities → serialize → parse → generate →
|
|
|
67
67
|
|
|
68
68
|
// 4. Re-serialize the regenerated entities.
|
|
69
69
|
const regenerated = new Map<string, any>(Object.entries(mod));
|
|
70
|
-
const planB = JSON.parse(flySerializer.serialize(regenerated));
|
|
70
|
+
const planB = JSON.parse(flySerializer.serialize(regenerated) as string);
|
|
71
71
|
|
|
72
72
|
// The bodies survive the round-trip. Entity keys differ (variable names are
|
|
73
73
|
// camelCased from the resource name), so compare the create bodies by kind.
|
package/src/serializer.test.ts
CHANGED
|
@@ -11,7 +11,7 @@ function stack(...entries: Array<[string, unknown]>): Map<string, Declarable> {
|
|
|
11
11
|
|
|
12
12
|
describe("fly serializer", () => {
|
|
13
13
|
it("serializes an empty map to valid JSON", () => {
|
|
14
|
-
const result = flySerializer.serialize(new Map());
|
|
14
|
+
const result = flySerializer.serialize(new Map()) as string;
|
|
15
15
|
expect(typeof result).toBe("string");
|
|
16
16
|
expect(JSON.parse(result)).toEqual({});
|
|
17
17
|
});
|
|
@@ -27,7 +27,7 @@ describe("fly serializer", () => {
|
|
|
27
27
|
new App({ name: "my-app", org_slug: "acme" }),
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
30
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
31
31
|
expect(out.web).toEqual({
|
|
32
32
|
endpoint: "/v1/apps",
|
|
33
33
|
method: "POST",
|
|
@@ -36,7 +36,7 @@ describe("fly serializer", () => {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it("falls back to the entity name for app_name when no explicit name", () => {
|
|
39
|
-
const out = JSON.parse(flySerializer.serialize(stack(["billing", new App({ org_slug: "acme" })])));
|
|
39
|
+
const out = JSON.parse(flySerializer.serialize(stack(["billing", new App({ org_slug: "acme" })])) as string);
|
|
40
40
|
expect(out.billing.body.app_name).toBe("billing");
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -57,7 +57,7 @@ describe("fly serializer", () => {
|
|
|
57
57
|
],
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
60
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
61
61
|
expect(out.api.endpoint).toBe("/v1/apps/my-app/machines");
|
|
62
62
|
expect(out.api.method).toBe("POST");
|
|
63
63
|
expect(out.api.body.name).toBe("api-1");
|
|
@@ -79,7 +79,7 @@ describe("fly serializer", () => {
|
|
|
79
79
|
],
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
82
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
83
83
|
// No user metadata → marker still present.
|
|
84
84
|
expect(out.bare.body.config.metadata["managed-by"]).toBe("chant");
|
|
85
85
|
// User metadata is preserved and the marker is merged in.
|
|
@@ -94,7 +94,7 @@ describe("fly serializer", () => {
|
|
|
94
94
|
);
|
|
95
95
|
|
|
96
96
|
const out = JSON.parse(
|
|
97
|
-
flySerializer.serialize(entities, undefined, { ownership: { stack: "billing", env: "prod" } }),
|
|
97
|
+
flySerializer.serialize(entities, undefined, { ownership: { stack: "billing", env: "prod" } }) as string,
|
|
98
98
|
);
|
|
99
99
|
const meta = out.api.body.config.metadata;
|
|
100
100
|
expect(meta["managed-by"]).toBe("chant");
|
|
@@ -110,7 +110,7 @@ describe("fly serializer", () => {
|
|
|
110
110
|
new Machine({ name: "api-1", region: "iad", config: new MachineConfig({ image: "nginx" }) }),
|
|
111
111
|
],
|
|
112
112
|
);
|
|
113
|
-
const body = JSON.parse(flySerializer.serialize(entities)).api.body;
|
|
113
|
+
const body = JSON.parse(flySerializer.serialize(entities) as string).api.body;
|
|
114
114
|
// Only fields present on flaps CreateMachineRequest / MachineConfig.
|
|
115
115
|
expect(Object.keys(body).sort()).toEqual(["config", "name", "region"]);
|
|
116
116
|
expect(Object.keys(body.config.guest ?? {})).toEqual([]);
|
|
@@ -123,7 +123,7 @@ describe("fly serializer", () => {
|
|
|
123
123
|
["app", new App({ name: "my-app" })],
|
|
124
124
|
["data", new Volume({ name: "data", region: "iad", size_gb: 10, encrypted: true })],
|
|
125
125
|
);
|
|
126
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
126
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
127
127
|
expect(out.data).toEqual({
|
|
128
128
|
endpoint: "/v1/apps/my-app/volumes",
|
|
129
129
|
method: "POST",
|
|
@@ -138,7 +138,7 @@ describe("fly serializer", () => {
|
|
|
138
138
|
["app", new App({ name: "my-app" })],
|
|
139
139
|
["ip", new IPAddress({ type: "shared_v4", region: "iad", org_slug: "acme", service_name: "web", network: "default" })],
|
|
140
140
|
);
|
|
141
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
141
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
142
142
|
expect(out.ip).toEqual({
|
|
143
143
|
endpoint: "/v1/apps/my-app/ip_assignments",
|
|
144
144
|
method: "POST",
|
|
@@ -151,7 +151,7 @@ describe("fly serializer", () => {
|
|
|
151
151
|
["app", new App({ name: "my-app" })],
|
|
152
152
|
["cert", new Certificate({ hostname: "example.com" })],
|
|
153
153
|
);
|
|
154
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
154
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
155
155
|
expect(out.cert).toEqual({
|
|
156
156
|
endpoint: "/v1/apps/my-app/certificates",
|
|
157
157
|
method: "POST",
|
|
@@ -164,7 +164,7 @@ describe("fly serializer", () => {
|
|
|
164
164
|
["app", new App({ name: "my-app" })],
|
|
165
165
|
["db-password", new Secret({ value: "s3cret" })],
|
|
166
166
|
);
|
|
167
|
-
const out = JSON.parse(flySerializer.serialize(entities));
|
|
167
|
+
const out = JSON.parse(flySerializer.serialize(entities) as string);
|
|
168
168
|
expect(out["db-password"]).toEqual({
|
|
169
169
|
endpoint: "/v1/apps/my-app/secrets/db-password",
|
|
170
170
|
method: "POST",
|
|
@@ -195,7 +195,7 @@ describe("fly serializer pseudo-parameters", () => {
|
|
|
195
195
|
["app", new App({ name: "my-app" })],
|
|
196
196
|
["web", new Machine({ region: Fly.Region, config: new MachineConfig({ image: "nginx" }) })],
|
|
197
197
|
);
|
|
198
|
-
const body = JSON.parse(flySerializer.serialize(entities)).web.body;
|
|
198
|
+
const body = JSON.parse(flySerializer.serialize(entities) as string).web.body;
|
|
199
199
|
expect(body.region).toBe("lhr");
|
|
200
200
|
});
|
|
201
201
|
|
|
@@ -205,28 +205,28 @@ describe("fly serializer pseudo-parameters", () => {
|
|
|
205
205
|
["app", new App({ name: "my-app" })],
|
|
206
206
|
["web", new Machine({ region: Fly.Region, config: new MachineConfig({ image: "nginx" }) })],
|
|
207
207
|
);
|
|
208
|
-
const body = JSON.parse(flySerializer.serialize(entities)).web.body;
|
|
208
|
+
const body = JSON.parse(flySerializer.serialize(entities) as string).web.body;
|
|
209
209
|
expect(body.region).toBe("iad");
|
|
210
210
|
});
|
|
211
211
|
|
|
212
212
|
it("resolves Fly.OrgSlug from FLY_ORG (preferred over FLY_ORG_SLUG)", () => {
|
|
213
213
|
process.env.FLY_ORG = "acme";
|
|
214
214
|
process.env.FLY_ORG_SLUG = "ignored";
|
|
215
|
-
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])));
|
|
215
|
+
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])) as string);
|
|
216
216
|
expect(out.app.body.org_slug).toBe("acme");
|
|
217
217
|
});
|
|
218
218
|
|
|
219
219
|
it("resolves Fly.OrgSlug from FLY_ORG_SLUG when FLY_ORG is unset", () => {
|
|
220
220
|
delete process.env.FLY_ORG;
|
|
221
221
|
process.env.FLY_ORG_SLUG = "beta-org";
|
|
222
|
-
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])));
|
|
222
|
+
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])) as string);
|
|
223
223
|
expect(out.app.body.org_slug).toBe("beta-org");
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
it("falls back to personal for Fly.OrgSlug when no org env var is set", () => {
|
|
227
227
|
delete process.env.FLY_ORG;
|
|
228
228
|
delete process.env.FLY_ORG_SLUG;
|
|
229
|
-
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])));
|
|
229
|
+
const out = JSON.parse(flySerializer.serialize(stack(["app", new App({ name: "my-app", org_slug: Fly.OrgSlug })])) as string);
|
|
230
230
|
expect(out.app.body.org_slug).toBe("personal");
|
|
231
231
|
});
|
|
232
232
|
});
|