@flow-like/widget-bundler 0.1.1
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 +388 -0
- package/package.json +40 -0
- package/src/add.ts +109 -0
- package/src/bundle-format.ts +104 -0
- package/src/cli.ts +156 -0
- package/src/contract-types.ts +759 -0
- package/src/csp-reason.ts +307 -0
- package/src/csp-source.ts +361 -0
- package/src/csp.ts +54 -0
- package/src/dev/contract-endpoint.ts +103 -0
- package/src/dev/form-model.ts +63 -0
- package/src/dev/harness-html.ts +864 -0
- package/src/dev/server.ts +297 -0
- package/src/extract.ts +1620 -0
- package/src/generated/widget-source-data.ts +982 -0
- package/src/html.ts +60 -0
- package/src/index.ts +17 -0
- package/src/inline.ts +247 -0
- package/src/pack.ts +502 -0
- package/src/psl.ts +145 -0
- package/src/validate-cmd.ts +268 -0
- package/src/vite.ts +109 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { addWidget } from "./add";
|
|
5
|
+
import { DEFAULT_HARNESS_PORT, startDevServer } from "./dev/server";
|
|
6
|
+
import { pack } from "./pack";
|
|
7
|
+
import { validateBundle, validateProject } from "./validate-cmd";
|
|
8
|
+
|
|
9
|
+
const USAGE = `flow-like-widgets — Flow-Like widget bundler
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
flow-like-widgets pack --project <dir> --out <file> [--serving-prefix <url>] [--created-at <iso>]
|
|
13
|
+
flow-like-widgets dev [--project <dir>] [--port <n>]
|
|
14
|
+
flow-like-widgets validate <project-dir | file.flwb>
|
|
15
|
+
flow-like-widgets add <widget-id> [--group <dir>]
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
pack Build widgets.flwb from a package project (framework groups must be built first)
|
|
19
|
+
dev Start every framework group's dev server + the mock-host harness (default port ${DEFAULT_HARNESS_PORT})
|
|
20
|
+
validate Validate a project's widget contracts, or a built .flwb bundle
|
|
21
|
+
add Scaffold src/widgets/<widget-id>/ inside a framework group
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
function fail(message: string): never {
|
|
25
|
+
console.error(`error: ${message}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const CONNECT_FLAG_REMOVED =
|
|
30
|
+
'The --connect flag was removed: declare network sources per widget in widget.config.ts "csp"';
|
|
31
|
+
|
|
32
|
+
async function runPack(args: string[]): Promise<void> {
|
|
33
|
+
if (args.some((arg) => arg === "--connect" || arg.startsWith("--connect="))) {
|
|
34
|
+
fail(CONNECT_FLAG_REMOVED);
|
|
35
|
+
}
|
|
36
|
+
const { values } = parseArgs({
|
|
37
|
+
args,
|
|
38
|
+
options: {
|
|
39
|
+
project: { type: "string", default: "." },
|
|
40
|
+
out: { type: "string" },
|
|
41
|
+
"serving-prefix": { type: "string" },
|
|
42
|
+
"created-at": { type: "string" },
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
const result = await pack(values.project, {
|
|
46
|
+
out: values.out,
|
|
47
|
+
servingPrefix: values["serving-prefix"] ?? null,
|
|
48
|
+
createdAt: values["created-at"],
|
|
49
|
+
});
|
|
50
|
+
for (const warning of result.warnings) {
|
|
51
|
+
console.warn(`warning: ${warning}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function runDev(args: string[]): Promise<void> {
|
|
56
|
+
const { values } = parseArgs({
|
|
57
|
+
args,
|
|
58
|
+
options: {
|
|
59
|
+
project: { type: "string", default: "." },
|
|
60
|
+
port: { type: "string" },
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
let port: number | undefined;
|
|
64
|
+
if (values.port !== undefined) {
|
|
65
|
+
port = Number(values.port);
|
|
66
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
67
|
+
fail(`invalid --port '${values.port}' (expected 1-65535)`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const handle = await startDevServer(values.project, { port });
|
|
71
|
+
console.log(`\n[harness] mock host ready: ${handle.url}\n`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function runValidate(args: string[]): void {
|
|
75
|
+
const { positionals } = parseArgs({
|
|
76
|
+
args,
|
|
77
|
+
allowPositionals: true,
|
|
78
|
+
options: {},
|
|
79
|
+
});
|
|
80
|
+
const target = positionals[0] ?? ".";
|
|
81
|
+
const isBundle = (() => {
|
|
82
|
+
try {
|
|
83
|
+
return statSync(target).isFile();
|
|
84
|
+
} catch {
|
|
85
|
+
return target.endsWith(".flwb");
|
|
86
|
+
}
|
|
87
|
+
})();
|
|
88
|
+
|
|
89
|
+
if (isBundle) {
|
|
90
|
+
const result = validateBundle(target);
|
|
91
|
+
for (const error of result.errors) console.error(`error: ${error}`);
|
|
92
|
+
if (!result.ok) process.exit(1);
|
|
93
|
+
console.log(
|
|
94
|
+
`ok: ${target} is a valid widget bundle (${result.manifest?.widgets.length ?? 0} widget(s))`,
|
|
95
|
+
);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const result = validateProject(target);
|
|
100
|
+
for (const warning of result.warnings) console.warn(`warning: ${warning}`);
|
|
101
|
+
for (const error of result.errors) console.error(`error: ${error}`);
|
|
102
|
+
if (!result.ok) process.exit(1);
|
|
103
|
+
console.log(
|
|
104
|
+
`ok: ${result.widgets.length} widget contract(s) valid (${result.widgets
|
|
105
|
+
.map((w) => w.id)
|
|
106
|
+
.join(", ")})`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function runAdd(args: string[]): void {
|
|
111
|
+
const { values, positionals } = parseArgs({
|
|
112
|
+
args,
|
|
113
|
+
allowPositionals: true,
|
|
114
|
+
options: { group: { type: "string", default: "." } },
|
|
115
|
+
});
|
|
116
|
+
const widgetId = positionals[0];
|
|
117
|
+
if (!widgetId)
|
|
118
|
+
fail(
|
|
119
|
+
"missing <widget-id> (usage: flow-like-widgets add <widget-id> [--group <dir>])",
|
|
120
|
+
);
|
|
121
|
+
const result = addWidget(values.group, widgetId);
|
|
122
|
+
console.log(`created ${result.widgetDir}`);
|
|
123
|
+
for (const file of result.files) console.log(` ${file}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function main(): Promise<void> {
|
|
127
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
128
|
+
try {
|
|
129
|
+
switch (command) {
|
|
130
|
+
case "pack":
|
|
131
|
+
await runPack(rest);
|
|
132
|
+
break;
|
|
133
|
+
case "dev":
|
|
134
|
+
await runDev(rest);
|
|
135
|
+
break;
|
|
136
|
+
case "validate":
|
|
137
|
+
runValidate(rest);
|
|
138
|
+
break;
|
|
139
|
+
case "add":
|
|
140
|
+
runAdd(rest);
|
|
141
|
+
break;
|
|
142
|
+
case "help":
|
|
143
|
+
case "--help":
|
|
144
|
+
case "-h":
|
|
145
|
+
console.log(USAGE);
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
console.error(USAGE);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
} catch (e) {
|
|
152
|
+
fail(e instanceof Error ? e.message : String(e));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
await main();
|