flagwire-typegen 0.1.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/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +29 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FlagWire contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# `flagwire-typegen`
|
|
2
|
+
|
|
3
|
+
Generate TypeScript flag declarations from a FlagWire project.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx flagwire-typegen \
|
|
7
|
+
--key "$FLAGWIRE_SERVER_KEY" \
|
|
8
|
+
--out src/flags.gen.ts
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The key may be supplied through `FLAGWIRE_SERVER_KEY` instead of `--key`. Generated files are
|
|
12
|
+
written atomically. Never commit a server key.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
3
|
+
[key: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
export interface TypegenManifest {
|
|
6
|
+
flags: Array<{
|
|
7
|
+
key: string;
|
|
8
|
+
type: "boolean" | "json" | "string";
|
|
9
|
+
variants: Array<{
|
|
10
|
+
key: string;
|
|
11
|
+
value: JsonValue;
|
|
12
|
+
}>;
|
|
13
|
+
}>;
|
|
14
|
+
projectId: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function generateTypes(manifest: TypegenManifest): string;
|
|
17
|
+
export declare function run(argv?: string[]): Promise<void>;
|
|
18
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{realpathSync as y}from"node:fs";import{mkdir as d,rename as w,writeFile as m}from"node:fs/promises";import{dirname as h,resolve as f}from"node:path";import{pathToFileURL as v}from"node:url";function k(t){return JSON.stringify(t)}function b(t){if(t.type==="boolean")return"boolean";let r=t.variants.map(e=>e.value).filter(e=>t.type==="json"||typeof e=="string").map(k);return[...new Set(r)].join(" | ")||"never"}function E(t){return t.flags.map(r=>` readonly ${JSON.stringify(r.key)}: ${b(r)};`).join(`
|
|
3
|
+
`)}function j(t){let r=t.flags.map(n=>JSON.stringify(n.key)).join(" | ")||"never",e=E(t);return`/* Generated by flagwire-typegen. Do not edit manually. */
|
|
4
|
+
import type {} from "@flagwire/sdk-js";
|
|
5
|
+
import type {} from "@flagwire/sdk-node";
|
|
6
|
+
|
|
7
|
+
export type FlagKey = ${r};
|
|
8
|
+
|
|
9
|
+
export interface FlagwireGeneratedFlags {
|
|
10
|
+
${e}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare module "@flagwire/sdk-js" {
|
|
14
|
+
interface FlagwireFlags {
|
|
15
|
+
${e}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module "@flagwire/sdk-node" {
|
|
20
|
+
interface FlagwireFlags {
|
|
21
|
+
${e}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {};
|
|
26
|
+
`}function F(t){let r=new Map;for(let e=0;e<t.length;e+=1){let n=t[e];if(n==="--help"||n==="-h")return{help:!0};if(!n.startsWith("--"))throw new Error(`Unknown argument: ${n}`);let o=n.indexOf("="),s=n.slice(2,o===-1?void 0:o),i=o===-1?t[++e]:n.slice(o+1);if(!i||i.startsWith("--"))throw new Error(`Missing value for --${s}`);if(!["base-url","key","out","project"].includes(s))throw new Error(`Unknown option: --${s}`);r.set(s,i)}return{help:!1,values:r}}function $(t){if(!t||typeof t!="object")return!1;let r=t;return typeof r.projectId=="string"&&Array.isArray(r.flags)&&r.flags.every(e=>e!==null&&typeof e=="object"&&typeof e.key=="string"&&(e.type==="boolean"||e.type==="string"||e.type==="json")&&Array.isArray(e.variants)&&e.variants.every(n=>n!==null&&typeof n=="object"&&typeof n.key=="string"&&"value"in n))}async function _(t=process.argv.slice(2)){let r=F(t);if(r.help){process.stdout.write(`Usage: flagwire-typegen --key sk_live_... --out src/flags.gen.ts [--project project_id] [--base-url https://api.flagwire.dev]
|
|
27
|
+
`);return}let e=r.values.get("key")??process.env.FLAGWIRE_SERVER_KEY,n=r.values.get("out");if(!e||!/^sk_live_[A-Za-z0-9_-]{43}$/.test(e))throw new Error("Provide a valid server key with --key or FLAGWIRE_SERVER_KEY");if(!n)throw new Error("Provide an output path with --out");let o=new URL(r.values.get("base-url")??"https://api.flagwire.dev");if(o.protocol!=="https:"&&o.protocol!=="http:")throw new Error("--base-url must use http or https");if(o.username||o.password)throw new Error("--base-url cannot contain credentials");let s=r.values.get("project"),i=s?`/v1/typegen/${encodeURIComponent(s)}`:"/v1/typegen",a=await fetch(new URL(i,o),{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(15e3)});if(!a.ok)throw new Error(`FlagWire type generation failed with HTTP ${a.status}`);let u=Number(a.headers.get("Content-Length"));if(Number.isFinite(u)&&u>1048576)throw new Error("FlagWire type manifest exceeded 1MB");let c=await a.text();if(c.length>1048576)throw new Error("FlagWire type manifest exceeded 1MB");let l;try{l=JSON.parse(c)}catch{throw new Error("FlagWire returned an invalid type manifest")}if(!$(l))throw new Error("FlagWire returned an invalid type manifest");let p=f(n),g=`${p}.${process.pid}.tmp`;await d(h(p),{recursive:!0}),await m(g,j(l),{encoding:"utf8",mode:420}),await w(g,p),process.stdout.write(`Generated ${l.flags.length} FlagWire flag types in ${p}
|
|
28
|
+
`)}var x=process.argv[1]?v(y(f(process.argv[1]))).href:"";import.meta.url===x&&_().catch(t=>{process.stderr.write(`${t instanceof Error?t.message:"Type generation failed"}
|
|
29
|
+
`),process.exitCode=1});export{j as generateTypes,_ as run};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flagwire-typegen",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate type-safe FlagWire flag definitions",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"flagwire-typegen": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/flagwire/flagwire-js.git",
|
|
26
|
+
"directory": "tools/typegen-cli"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"provenance": true
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "24.3.0",
|
|
33
|
+
"esbuild": "0.28.2"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "node ../../scripts/clean-package-dist.mjs && tsc -p tsconfig.build.json && esbuild src/index.ts --bundle --minify --format=esm --platform=node --target=node20 --outfile=dist/index.js",
|
|
37
|
+
"lint": "eslint src",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
40
|
+
}
|
|
41
|
+
}
|