@vornrun/connector-sdk 0.7.0-beta.7 → 0.7.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/cli.d.ts CHANGED
@@ -1,9 +1,22 @@
1
1
  #!/usr/bin/env node
2
+ import { B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-62s2GvcO.js';
3
+
2
4
  interface CliDeps {
3
5
  load(modulePath: string): Promise<unknown>;
4
6
  write(line: string): void;
5
7
  env?: NodeJS.ProcessEnv;
8
+ /** Directory module paths resolve from; defaults to the working directory. */
9
+ cwd?: string;
10
+ /** Replaced in tests so pack does not shell out to a bundler. */
11
+ bundle?(request: BundleRequest): Promise<BundleOutput>;
12
+ /** Replaced in tests so pack does not start the staged bundle. */
13
+ launch?(dir: string): Promise<CheckFinding[]>;
14
+ /** Writes a scaffold file or a receipt; replaced in tests so nothing touches disk. */
15
+ writeFile?(path: string, contents: string): Promise<void>;
16
+ /** Replaced in tests beside writeFile. */
17
+ exists?(path: string): boolean;
6
18
  }
7
19
  declare function runCli(argv: string[], deps: CliDeps): Promise<number>;
20
+ declare function isEntryPoint(moduleUrl: string, argv?: readonly string[]): boolean;
8
21
 
9
- export { type CliDeps, runCli };
22
+ export { type CliDeps, isEntryPoint, runCli };
package/dist/cli.js CHANGED
@@ -1,31 +1,44 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- checkConnector,
4
3
  connectionSetup,
5
4
  connectorManifest,
5
+ esbuildBundle,
6
6
  formatFindings,
7
+ packConnector,
7
8
  resolveConfig,
9
+ runConformance,
8
10
  runPoll,
11
+ scaffoldFiles,
9
12
  serveConnector
10
- } from "./chunk-457KOZUU.js";
13
+ } from "./chunk-ZKHXHE3O.js";
11
14
 
12
15
  // src/cli.ts
13
- import { pathToFileURL } from "url";
14
- import { resolve } from "path";
15
- var USAGE = `vorn-connector <command> <module> [options]
16
+ import { fileURLToPath, pathToFileURL } from "url";
17
+ import { existsSync, realpathSync } from "fs";
18
+ import { dirname, join, resolve } from "path";
19
+ import { mkdir, writeFile } from "fs/promises";
20
+ var USAGE = `vorn-connector <command> <module | id> [options]
16
21
 
17
22
  Commands:
23
+ new <id> Scaffold a new connector, ready to build
18
24
  manifest <module> Print the connector manifest as JSON
19
25
  setup <module> [trigger] Print the Vorn connection settings to paste
20
26
  check <module> Verify the connector against Vorn's contract
27
+ pack <module> Build an installable .vorn.tgz pack
21
28
  poll <module> <trigger> Run one poll against the current environment
22
29
  serve <module> Serve the connector on stdio (what Vorn runs)
23
30
 
24
31
  Options:
25
32
  --since <iso> Lower bound passed to poll
26
33
  --limit <n> Maximum items to request
27
- --live Let check poll for real using the environment`;
28
- var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["live"]);
34
+ --live Let check poll for real using the environment
35
+ --mock Run every action against served HTTP, not the network
36
+ --receipt <file> Where check writes what it verified, as JSON
37
+ --out <dir> Directory new and pack write to
38
+ --name <name> Display name for a new connector
39
+ --repo-conventions Scaffold a package shaped for the connectors repository
40
+ --extension Scaffold an extension \u2014 footers, panes and link handlers`;
41
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["live", "mock", "repo-conventions", "extension"]);
29
42
  function parseArgs(args) {
30
43
  const flags = {};
31
44
  const positional = [];
@@ -55,7 +68,7 @@ function pickConnector(loaded, modulePath) {
55
68
  const connector = candidate;
56
69
  if (!connector || typeof connector !== "object" || !Array.isArray(connector.triggers)) {
57
70
  throw new Error(
58
- `${modulePath} does not export a connector built with defineConnector() (default or named "connector")`
71
+ `${modulePath} does not export a connector built with defineConnector() or defineExtension() (default or named "connector")`
59
72
  );
60
73
  }
61
74
  return connector;
@@ -67,11 +80,37 @@ async function runCli(argv, deps) {
67
80
  return command ? 0 : 1;
68
81
  }
69
82
  if (!modulePath) {
70
- deps.write(`Missing <module> argument
83
+ deps.write(`Missing <${command === "new" ? "id" : "module"}> argument
71
84
 
72
85
  ${USAGE}`);
73
86
  return 1;
74
87
  }
88
+ if (command === "new") {
89
+ const { flags: flags2 } = parseArgs(rest);
90
+ if (!deps.writeFile) {
91
+ deps.write("This build cannot write files");
92
+ return 1;
93
+ }
94
+ const files = scaffoldFiles({
95
+ id: modulePath,
96
+ ...flags2.name !== void 0 && { name: flags2.name },
97
+ ...flags2["repo-conventions"] === "true" && { repoConventions: true },
98
+ ...flags2.extension === "true" && { kind: "extension" }
99
+ });
100
+ const root = join(flags2.out ?? deps.cwd ?? ".", modulePath);
101
+ if ((deps.exists ?? existsSync)(root)) {
102
+ deps.write(`${root} already exists; a scaffold never overwrites`);
103
+ return 1;
104
+ }
105
+ for (const file of files) {
106
+ await deps.writeFile(join(root, file.path), file.contents);
107
+ }
108
+ deps.write(`Created ${modulePath} in ${root}`);
109
+ for (const file of files) deps.write(` ${file.path}`);
110
+ deps.write(`
111
+ Next: cd ${root} && yarn install && yarn check`);
112
+ return 0;
113
+ }
75
114
  const connector = pickConnector(await deps.load(modulePath), modulePath);
76
115
  const { flags, positional } = parseArgs(rest);
77
116
  switch (command) {
@@ -95,14 +134,33 @@ ${USAGE}`);
95
134
  return 0;
96
135
  }
97
136
  case "check": {
98
- const findings = await checkConnector(connector, {
137
+ const packaged = flags.mock === "true" ? {
138
+ mock: true,
139
+ packageDir: deps.cwd ?? process.cwd(),
140
+ entry: modulePath,
141
+ bundle: deps.bundle ?? esbuildBundle
142
+ } : {};
143
+ const run = await runConformance(connector, {
144
+ ...packaged,
99
145
  ...flags.live === "true" && {
100
146
  live: true,
101
147
  config: resolveConfig(connector, deps.env ?? process.env)
102
148
  }
103
149
  });
150
+ const { findings } = run;
104
151
  const errors = findings.filter((item) => item.level === "error");
105
152
  if (findings.length > 0) deps.write(formatFindings(findings));
153
+ if (flags.receipt !== void 0) {
154
+ if (run.receipt) {
155
+ const write = deps.writeFile ?? ((path, contents) => writeFile(path, contents));
156
+ await write(flags.receipt, `${JSON.stringify(run.receipt, null, 2)}
157
+ `);
158
+ deps.write(`Verified ${run.receipt.checks.join(", ")} \u2014 wrote ${flags.receipt}`);
159
+ } else {
160
+ deps.write(`No receipt written: nothing could be vouched for`);
161
+ if (errors.length === 0) return 1;
162
+ }
163
+ }
106
164
  deps.write(
107
165
  errors.length > 0 ? `
108
166
  ${errors.length} error(s), ${findings.length - errors.length} warning(s)` : `
@@ -110,6 +168,27 @@ ${connector.id} passed with ${findings.length} warning(s)`
110
168
  );
111
169
  return errors.length > 0 ? 1 : 0;
112
170
  }
171
+ case "pack": {
172
+ const result = await packConnector(connector, {
173
+ entry: modulePath,
174
+ ...flags.out !== void 0 && { outDir: flags.out },
175
+ ...deps.cwd !== void 0 && { resolveDir: deps.cwd },
176
+ ...deps.bundle !== void 0 && { bundle: deps.bundle },
177
+ ...deps.launch !== void 0 && { launch: deps.launch }
178
+ });
179
+ if (result.findings.length > 0) deps.write(formatFindings(result.findings));
180
+ const errors = result.findings.filter((item) => item.level === "error");
181
+ if (!result.file) {
182
+ deps.write(`
183
+ ${errors.length} error(s) \u2014 nothing was packed`);
184
+ return 1;
185
+ }
186
+ deps.write(
187
+ `
188
+ Packed ${connector.id} ${connector.version} to ${result.file} (${Math.max(1, Math.round((result.bytes ?? 0) / 1024))} KB)`
189
+ );
190
+ return 0;
191
+ }
113
192
  case "poll": {
114
193
  const triggerType = positional[0];
115
194
  if (!triggerType) {
@@ -141,12 +220,25 @@ ${USAGE}`);
141
220
  return 1;
142
221
  }
143
222
  }
144
- var invokedDirectly = process.argv[1] !== void 0 && import.meta.url === pathToFileURL(resolve(process.argv[1])).href;
223
+ function isEntryPoint(moduleUrl, argv = process.argv) {
224
+ const invoked = argv[1];
225
+ if (invoked === void 0) return false;
226
+ try {
227
+ return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(resolve(invoked));
228
+ } catch {
229
+ return false;
230
+ }
231
+ }
232
+ var invokedDirectly = isEntryPoint(import.meta.url);
145
233
  if (invokedDirectly) {
146
234
  runCli(process.argv.slice(2), {
147
235
  load: (modulePath) => modulePath.startsWith(".") || modulePath.startsWith("/") ? import(pathToFileURL(resolve(modulePath)).href) : import(modulePath),
148
236
  write: (line) => process.stdout.write(`${line}
149
- `)
237
+ `),
238
+ writeFile: async (path, contents) => {
239
+ await mkdir(dirname(path), { recursive: true });
240
+ await writeFile(path, contents);
241
+ }
150
242
  }).then((code) => {
151
243
  process.exitCode = code;
152
244
  }).catch((error) => {
@@ -156,5 +248,6 @@ if (invokedDirectly) {
156
248
  });
157
249
  }
158
250
  export {
251
+ isEntryPoint,
159
252
  runCli
160
253
  };