@sparelabs/sightline-extension-cli 0.1.0 → 0.1.2
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 +2 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +51 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/template.d.ts +1 -1
- package/dist/template.js +2 -1
- package/dist/webhooks.d.ts +31 -0
- package/dist/webhooks.js +72 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ You need Node 20.19+, [Deno](https://deno.com) (the extension runtime) and Docke
|
|
|
21
21
|
| `deploy [--bindings bindings.json] [--no-build]` | Builds, publishes the release to a workspace (identical bytes are a no-op) and installs it. Refuses when another version is installed: use `upgrade`. |
|
|
22
22
|
| `upgrade [--bindings bindings.json] [--no-build]` | Builds, publishes, and moves the installed extension to the manifest's version. A permission the new version adds needs a binding. |
|
|
23
23
|
| `uninstall [<id>] [--purge --yes]` | Uninstalls. Data is kept 30 days; `--purge --yes` drops it now. |
|
|
24
|
+
| `webhooks send <name> --body <file> [--url <webhook URL>] [--secret-env VAR] [--content-type …] [--timestamp <unix s>]` | Signs the file's raw bytes the way Sightline verifies the manifest webhook `<name>` (HMAC-SHA256 hex after its `prefix`, over `<timestamp>.<raw body>` when it declares a `timestampHeader`) and POSTs them. Without `--url` it goes to the running `dev`, whose emulator verifies it like Sightline (401 with the reason when it fails, 409 for a replay) and forwards it to your `/hooks/<name>`; with `--url` (the webhook URL from the workspace's Setup) to a real workspace. The secret comes from `SL_SECRET_<NAME>` or `--secret-env VAR`, never from a flag; locally `devSecrets` win over the environment, as `dev` injects them, so the delivery is signed with the value the emulator verifies with. Exit 1 on a non-2xx answer. |
|
|
24
25
|
|
|
25
26
|
Common options: `--dir <project>`, `--manifest <file>`, `--config <file>`, `--entry <file>`.
|
|
26
27
|
|
|
@@ -64,7 +65,7 @@ The deploy publishes the server bundle and migrations. Publishing a UI (`ui.fram
|
|
|
64
65
|
|
|
65
66
|
## Programmatic use
|
|
66
67
|
|
|
67
|
-
Everything the commands use is exported: `loadProject`, `build`, `createCoreApi`, `deploy`, `upgrade`, `uninstall`, `templateFiles`, `lintBundle`, `migrationProblems`.
|
|
68
|
+
Everything the commands use is exported: `loadProject`, `build`, `createCoreApi`, `deploy`, `upgrade`, `uninstall`, `templateFiles`, `lintBundle`, `migrationProblems`, `planWebhookSend`.
|
|
68
69
|
|
|
69
70
|
## License
|
|
70
71
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const USAGE = "sightline-ext <command> [options]\n\n init <dir> Scaffold a new extension repository\n [--id <kebab-id>] [--name \"Display name\"] [--publisher <kebab-id>] [--force]\n build Validate the manifest and migrations, bundle server/main.ts into dist/server.mjs\n dev Build, then run the extension against an emulated Sightline, rebuilding on change\n [--port <n>] [--core-port 8787] [--no-db]\n test Build, run the extension against the emulator, and check the HTTP contract\n [--no-build] [--no-db] [--keep-db]\n deploy Build, publish the release and install it in a workspace\n upgrade Build, publish the release and move the installed extension to it\n (deploy, upgrade: [--bindings bindings.json] [--no-build])\n uninstall Remove the extension from the workspace (its data is kept 30 days)\n [--purge --yes]\n\n Common: [--dir <project>] [--manifest sightline.extension.json] [--config sightline-ext.json]\n deploy, upgrade, uninstall: [--url https://<workspace>] [--api-url <core API base>]\n\nDeploying needs the workspace and a deploy token issued by one of its admins:\n SIGHTLINE_URL https://<your workspace> (or SIGHTLINE_API_URL, the full core API base)\n SIGHTLINE_DEPLOY_TOKEN the token (only ever read from the environment)\n SIGHTLINE_API_KEY the gateway's public api key, when your workspace needs one";
|
|
1
|
+
export declare const USAGE = "sightline-ext <command> [options]\n\n init <dir> Scaffold a new extension repository\n [--id <kebab-id>] [--name \"Display name\"] [--publisher <kebab-id>] [--force]\n build Validate the manifest and migrations, bundle server/main.ts into dist/server.mjs\n dev Build, then run the extension against an emulated Sightline, rebuilding on change\n [--port <n>] [--core-port 8787] [--no-db]\n test Build, run the extension against the emulator, and check the HTTP contract\n [--no-build] [--no-db] [--keep-db]\n deploy Build, publish the release and install it in a workspace\n upgrade Build, publish the release and move the installed extension to it\n (deploy, upgrade: [--bindings bindings.json] [--no-build])\n uninstall Remove the extension from the workspace (its data is kept 30 days)\n [--purge --yes]\n webhooks send <name> --body <file>\n Sign the file's raw bytes the way Sightline verifies them and POST them: to the\n running `dev` (verified and forwarded to your /hooks/<name>), or with\n --url <webhook URL from Setup> to a workspace. The secret is read from\n SL_SECRET_<NAME> (or --secret-env VAR, or devSecrets), never from a flag.\n [--url <url>] [--secret-env VAR] [--content-type application/json] [--timestamp <unix s>]\n\n Common: [--dir <project>] [--manifest sightline.extension.json] [--config sightline-ext.json]\n deploy, upgrade, uninstall: [--url https://<workspace>] [--api-url <core API base>]\n\nDeploying needs the workspace and a deploy token issued by one of its admins:\n SIGHTLINE_URL https://<your workspace> (or SIGHTLINE_API_URL, the full core API base)\n SIGHTLINE_DEPLOY_TOKEN the token (only ever read from the environment)\n SIGHTLINE_API_KEY the gateway's public api key, when your workspace needs one";
|
|
2
2
|
export type Out = (line: string) => void;
|
|
3
3
|
export declare function packageVersion(): string;
|
|
4
4
|
export declare function main(argv: string[], out?: Out): Promise<number>;
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// docs/platform/hosted-extensions.md → "The CLI".
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
5
|
-
import { createCoreEmulator, freePort, listen, runExtension, startDatabase } from "@sparelabs/sightline-extension-devkit";
|
|
5
|
+
import { createCoreEmulator, freePort, listen, runExtension, sendWebhook, startDatabase, webhookSignature } from "@sparelabs/sightline-extension-devkit";
|
|
6
6
|
import { lintBundle, MAX_BUNDLE_BYTES, uiAssetProblems, validateManifest } from "@sparelabs/sightline-extension-manifest";
|
|
7
7
|
import { assertContract, formatReport, runContractTests } from "@sparelabs/sightline-extension-testing";
|
|
8
8
|
import { bool, int, parseArgs, str } from "./args.js";
|
|
@@ -11,6 +11,7 @@ import { CoreApiError, createCoreApi, describeError } from "./core-api.js";
|
|
|
11
11
|
import { deploy, parseBindings, uninstall, upgrade } from "./deploy.js";
|
|
12
12
|
import { defaultContract, loadProject } from "./project.js";
|
|
13
13
|
import { templateFiles } from "./template.js";
|
|
14
|
+
import { planWebhookSend } from "./webhooks.js";
|
|
14
15
|
export const USAGE = `sightline-ext <command> [options]
|
|
15
16
|
|
|
16
17
|
init <dir> Scaffold a new extension repository
|
|
@@ -25,6 +26,12 @@ export const USAGE = `sightline-ext <command> [options]
|
|
|
25
26
|
(deploy, upgrade: [--bindings bindings.json] [--no-build])
|
|
26
27
|
uninstall Remove the extension from the workspace (its data is kept 30 days)
|
|
27
28
|
[--purge --yes]
|
|
29
|
+
webhooks send <name> --body <file>
|
|
30
|
+
Sign the file's raw bytes the way Sightline verifies them and POST them: to the
|
|
31
|
+
running \`dev\` (verified and forwarded to your /hooks/<name>), or with
|
|
32
|
+
--url <webhook URL from Setup> to a workspace. The secret is read from
|
|
33
|
+
SL_SECRET_<NAME> (or --secret-env VAR, or devSecrets), never from a flag.
|
|
34
|
+
[--url <url>] [--secret-env VAR] [--content-type application/json] [--timestamp <unix s>]
|
|
28
35
|
|
|
29
36
|
Common: [--dir <project>] [--manifest sightline.extension.json] [--config sightline-ext.json]
|
|
30
37
|
deploy, upgrade, uninstall: [--url https://<workspace>] [--api-url <core API base>]
|
|
@@ -99,10 +106,17 @@ function init(positional, flags, out) {
|
|
|
99
106
|
async function dev(flags, out) {
|
|
100
107
|
const p = project(flags);
|
|
101
108
|
await buildProject(p, out);
|
|
102
|
-
const emulator = await createCoreEmulator({
|
|
109
|
+
const emulator = await createCoreEmulator({
|
|
110
|
+
extension: p.id,
|
|
111
|
+
version: p.version,
|
|
112
|
+
settings: p.config.settings ?? {},
|
|
113
|
+
// Its ext-hooks route verifies webhooks with these, as core does with the installation's secrets.
|
|
114
|
+
manifest: p.manifest,
|
|
115
|
+
secrets: secretEnv(p),
|
|
116
|
+
});
|
|
103
117
|
const core = await listen(emulator.handler, { port: int(flags, "core-port") ?? 8787 });
|
|
104
118
|
emulator.setOrigin(core.url);
|
|
105
|
-
const env = emulator.runtimeEnv(
|
|
119
|
+
const env = emulator.runtimeEnv();
|
|
106
120
|
let db = null;
|
|
107
121
|
if (!bool(flags, "no-db") && hasMigrations(p)) {
|
|
108
122
|
db = await startDatabase({ extension: p.id, migrationsDir: p.migrationsDir });
|
|
@@ -111,6 +125,7 @@ async function dev(flags, out) {
|
|
|
111
125
|
}
|
|
112
126
|
const port = int(flags, "port") ?? (await freePort());
|
|
113
127
|
let ext = await runExtension({ bundle: p.outfile, env, port });
|
|
128
|
+
emulator.setExtensionUrl(ext.url);
|
|
114
129
|
// The devkit's state file, so `npx sightline-devkit invoke …` finds this run.
|
|
115
130
|
mkdirSync(join(p.dir, ".sightline-devkit"), { recursive: true });
|
|
116
131
|
writeFileSync(join(p.dir, ".sightline-devkit", "state.json"), `${JSON.stringify({ coreUrl: core.url, extensionUrl: ext.url }, null, 2)}\n`);
|
|
@@ -118,6 +133,9 @@ async function dev(flags, out) {
|
|
|
118
133
|
out(`extension ${ext.url} (Sightline's runtime flags)`);
|
|
119
134
|
const firstTool = Array.isArray(p.manifest.tools) ? p.manifest.tools.find((t) => typeof t?.name === "string")?.name : undefined;
|
|
120
135
|
out(firstTool ? `try npx sightline-devkit invoke tool ${String(firstTool)} --as user:alice` : "try npx sightline-devkit invoke api /<path> --as user:alice");
|
|
136
|
+
const firstHook = Array.isArray(p.manifest.webhooks) ? p.manifest.webhooks.find((w) => typeof w?.name === "string")?.name : undefined;
|
|
137
|
+
if (firstHook)
|
|
138
|
+
out(`webhooks npx sightline-ext webhooks send ${String(firstHook)} --body event.json (signed, verified like Sightline, forwarded)`);
|
|
121
139
|
out("watching for changes; Ctrl-C stops");
|
|
122
140
|
const esbuild = await import("esbuild");
|
|
123
141
|
let restarting = Promise.resolve();
|
|
@@ -201,6 +219,34 @@ async function test(flags, out) {
|
|
|
201
219
|
await db.stop();
|
|
202
220
|
}
|
|
203
221
|
}
|
|
222
|
+
async function webhooks(positional, flags, out) {
|
|
223
|
+
const [sub, name] = positional;
|
|
224
|
+
if (sub !== "send" || !name)
|
|
225
|
+
throw new Error("usage: sightline-ext webhooks send <name> --body <file> [--url <webhook URL>]");
|
|
226
|
+
const p = project(flags);
|
|
227
|
+
const hook = webhookSignature(p.manifest, name);
|
|
228
|
+
let localCoreUrl;
|
|
229
|
+
try {
|
|
230
|
+
localCoreUrl = JSON.parse(readFileSync(join(p.dir, ".sightline-devkit", "state.json"), "utf8")).coreUrl;
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
localCoreUrl = undefined;
|
|
234
|
+
}
|
|
235
|
+
const plan = planWebhookSend({
|
|
236
|
+
hook: name,
|
|
237
|
+
secretName: hook.secret,
|
|
238
|
+
flags,
|
|
239
|
+
env: process.env,
|
|
240
|
+
devSecrets: p.config.devSecrets,
|
|
241
|
+
readFile: (path) => new Uint8Array(readFileSync(resolve(path))),
|
|
242
|
+
localCoreUrl,
|
|
243
|
+
});
|
|
244
|
+
const result = await sendWebhook({ url: plan.url, hook, secret: plan.secret, body: plan.body, contentType: plan.contentType, timestamp: plan.timestamp });
|
|
245
|
+
out(`POST ${plan.url} (${plan.body.length} bytes, signed with ${plan.secretFrom}${hook.timestampHeader ? `, ${hook.timestampHeader} ${result.headers[hook.timestampHeader]}` : ""})`);
|
|
246
|
+
out(`HTTP ${result.status}`);
|
|
247
|
+
out(typeof result.body === "string" ? result.body : JSON.stringify(result.body, null, 2));
|
|
248
|
+
return result.status >= 200 && result.status < 300 ? 0 : 1;
|
|
249
|
+
}
|
|
204
250
|
function coreApiFromEnv(flags, env = process.env) {
|
|
205
251
|
const token = env.SIGHTLINE_DEPLOY_TOKEN;
|
|
206
252
|
if (!token)
|
|
@@ -266,6 +312,8 @@ export async function main(argv, out = console.log) {
|
|
|
266
312
|
await uninstall(api, id, { purge }, out);
|
|
267
313
|
return 0;
|
|
268
314
|
}
|
|
315
|
+
case "webhooks":
|
|
316
|
+
return await webhooks(rest, flags, out);
|
|
269
317
|
case "version":
|
|
270
318
|
out(packageVersion());
|
|
271
319
|
return 0;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export { deploy, parseBindings, uninstall, upgrade } from "./deploy.ts";
|
|
|
6
6
|
export { CONFIG_FILE, type ContractConfig, defaultContract, hostedRuleProblems, loadProject, MANIFEST_FILE, migrationProblems, type MigrationFile, type Project, type ProjectConfig, readMigrations, readUiFiles, type UiFileOnDisk, uiFrames, } from "./project.ts";
|
|
7
7
|
export { lintBundle, MAX_BUNDLE_BYTES } from "@sparelabs/sightline-extension-manifest";
|
|
8
8
|
export { templateFiles, type TemplateOptions, templateProblems, toolPrefix } from "./template.ts";
|
|
9
|
+
export { planWebhookSend, secretVar, type WebhookSendInput, type WebhookSendPlan } from "./webhooks.ts";
|
package/dist/index.js
CHANGED
|
@@ -10,3 +10,4 @@ export { CONFIG_FILE, defaultContract, hostedRuleProblems, loadProject, MANIFEST
|
|
|
10
10
|
// The bundle lint is the published contract's, the same function core's installer runs.
|
|
11
11
|
export { lintBundle, MAX_BUNDLE_BYTES } from "@sparelabs/sightline-extension-manifest";
|
|
12
12
|
export { templateFiles, templateProblems, toolPrefix } from "./template.js";
|
|
13
|
+
export { planWebhookSend, secretVar } from "./webhooks.js";
|
package/dist/template.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export interface TemplateOptions {
|
|
|
2
2
|
id: string;
|
|
3
3
|
name?: string;
|
|
4
4
|
publisher?: string;
|
|
5
|
-
/** The
|
|
5
|
+
/** The CLI's own version. The packages share MAJOR.MINOR (patches are per package), so dependencies use ^MAJOR.MINOR.0. */
|
|
6
6
|
packagesVersion: string;
|
|
7
7
|
}
|
|
8
8
|
/** kebab-case id → the snake_case prefix of its tool names. */
|
package/dist/template.js
CHANGED
|
@@ -22,7 +22,8 @@ export function templateFiles(options) {
|
|
|
22
22
|
const name = options.name ?? id.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
23
23
|
const publisher = options.publisher ?? id;
|
|
24
24
|
const p = toolPrefix(id);
|
|
25
|
-
const
|
|
25
|
+
const [major, minor] = packagesVersion.split(".");
|
|
26
|
+
const range = `^${major}.${minor}.0`;
|
|
26
27
|
const manifest = {
|
|
27
28
|
manifestVersion: 2,
|
|
28
29
|
id,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Flags } from "./args.ts";
|
|
2
|
+
export interface WebhookSendPlan {
|
|
3
|
+
/** The local emulator's ext-hooks route, or the workspace's webhook URL (`--url`, from Setup). */
|
|
4
|
+
url: string;
|
|
5
|
+
/** The environment variable the secret came from (never the value). */
|
|
6
|
+
secretFrom: string;
|
|
7
|
+
secret: string;
|
|
8
|
+
body: Uint8Array;
|
|
9
|
+
contentType: string;
|
|
10
|
+
timestamp?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface WebhookSendInput {
|
|
13
|
+
hook: string;
|
|
14
|
+
/** The manifest secret that signs this webhook (`verify.secret`). */
|
|
15
|
+
secretName: string;
|
|
16
|
+
flags: Flags;
|
|
17
|
+
env: Record<string, string | undefined>;
|
|
18
|
+
/** sightline-ext.json `devSecrets`: the values `dev` and `test` inject. */
|
|
19
|
+
devSecrets?: Record<string, string>;
|
|
20
|
+
readFile(path: string): Uint8Array;
|
|
21
|
+
/** The running `sightline-ext dev`'s emulator (.sightline-devkit/state.json), if any. */
|
|
22
|
+
localCoreUrl?: string;
|
|
23
|
+
}
|
|
24
|
+
/** `inbound_hook` → `SL_SECRET_INBOUND_HOOK`. */
|
|
25
|
+
export declare function secretVar(secretName: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a send. The secret is read from the environment (`--secret-env`, default
|
|
28
|
+
* `SL_SECRET_<NAME>`) or sightline-ext.json `devSecrets`, never from a flag value,
|
|
29
|
+
* so it stays out of shell history.
|
|
30
|
+
*/
|
|
31
|
+
export declare function planWebhookSend(input: WebhookSendInput): WebhookSendPlan;
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// `sightline-ext webhooks send <name> --body <file>`: where a signed test delivery
|
|
2
|
+
// goes and what signs it. The signing itself is the devkit's `signWebhook`, which
|
|
3
|
+
// signs `<timestamp>.<raw body>` (or the raw body) exactly like core's
|
|
4
|
+
// `signHookDelivery` (docs/platform/hosted-extensions-hooks-secrets.md).
|
|
5
|
+
import { str } from "./args.js";
|
|
6
|
+
const ENV_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
7
|
+
/** `inbound_hook` → `SL_SECRET_INBOUND_HOOK`. */
|
|
8
|
+
export function secretVar(secretName) {
|
|
9
|
+
return `SL_SECRET_${secretName.toUpperCase().replace(/-/g, "_")}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a send. The secret is read from the environment (`--secret-env`, default
|
|
13
|
+
* `SL_SECRET_<NAME>`) or sightline-ext.json `devSecrets`, never from a flag value,
|
|
14
|
+
* so it stays out of shell history.
|
|
15
|
+
*/
|
|
16
|
+
export function planWebhookSend(input) {
|
|
17
|
+
const bodyFile = str(input.flags, "body");
|
|
18
|
+
if (!bodyFile)
|
|
19
|
+
throw new Error("usage: sightline-ext webhooks send <name> --body <file> [--url <webhook URL>]");
|
|
20
|
+
const explicitVar = str(input.flags, "secret-env");
|
|
21
|
+
if (explicitVar !== undefined && !ENV_NAME_RE.test(explicitVar))
|
|
22
|
+
throw new Error("--secret-env names an environment variable, e.g. SL_SECRET_INBOUND_HOOK");
|
|
23
|
+
const variable = explicitVar ?? secretVar(input.secretName);
|
|
24
|
+
let secret = input.env[variable];
|
|
25
|
+
let secretFrom = `$${variable}`;
|
|
26
|
+
// Locally, the same precedence `dev` uses for the emulator and the runtime (devSecrets over the
|
|
27
|
+
// environment), so the delivery is signed with the value it is verified with. A workspace target
|
|
28
|
+
// (--url) never uses devSecrets: those are local values.
|
|
29
|
+
const devValue = input.devSecrets?.[input.secretName];
|
|
30
|
+
if (str(input.flags, "url") === undefined && explicitVar === undefined && typeof devValue === "string" && devValue !== "") {
|
|
31
|
+
secret = devValue;
|
|
32
|
+
secretFrom = `sightline-ext.json devSecrets.${input.secretName}`;
|
|
33
|
+
}
|
|
34
|
+
if (!secret) {
|
|
35
|
+
throw new Error(`no value for the "${input.secretName}" secret: set ${variable} (the workspace's value for a real target; it is never read from a flag)`);
|
|
36
|
+
}
|
|
37
|
+
let url = str(input.flags, "url");
|
|
38
|
+
if (url !== undefined) {
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = new URL(url);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new Error("--url must be the webhook URL, e.g. https://<workspace>/functions/v1/ext-hooks/i/<token>/<hook>");
|
|
45
|
+
}
|
|
46
|
+
const local = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]";
|
|
47
|
+
if (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && local))
|
|
48
|
+
throw new Error("--url must be https (http only for localhost)");
|
|
49
|
+
if (parsed.username || parsed.password)
|
|
50
|
+
throw new Error("--url must not carry credentials");
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (!input.localCoreUrl)
|
|
54
|
+
throw new Error("no running `sightline-ext dev` here: start it, or pass --url <webhook URL> to send to a workspace");
|
|
55
|
+
url = `${input.localCoreUrl.replace(/\/+$/, "")}/functions/v1/ext-hooks/i/devkit/${input.hook}`;
|
|
56
|
+
}
|
|
57
|
+
const ts = str(input.flags, "timestamp");
|
|
58
|
+
let timestamp;
|
|
59
|
+
if (ts !== undefined) {
|
|
60
|
+
timestamp = Number(ts);
|
|
61
|
+
if (!Number.isInteger(timestamp) || timestamp < 0 || timestamp > 999_999_999_999)
|
|
62
|
+
throw new Error("--timestamp is Unix seconds");
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
url,
|
|
66
|
+
secretFrom,
|
|
67
|
+
secret,
|
|
68
|
+
body: input.readFile(bodyFile),
|
|
69
|
+
contentType: str(input.flags, "content-type") ?? "application/json",
|
|
70
|
+
timestamp,
|
|
71
|
+
};
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sparelabs/sightline-extension-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "sightline-ext: scaffold, run, build, test and deploy a hosted Sightline extension.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Spare Labs Inc.",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"typecheck": "tsc -p tsconfig.json"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@sparelabs/sightline-extension-devkit": "0.1.
|
|
38
|
-
"@sparelabs/sightline-extension-manifest": "0.1.
|
|
37
|
+
"@sparelabs/sightline-extension-devkit": "0.1.1",
|
|
38
|
+
"@sparelabs/sightline-extension-manifest": "0.1.2",
|
|
39
39
|
"@sparelabs/sightline-extension-testing": "0.1.0",
|
|
40
40
|
"esbuild": "^0.25.10"
|
|
41
41
|
},
|