terse-cli 0.2.0 → 0.2.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/dist/_tmp_create_project.d.ts +2 -0
- package/dist/_tmp_create_project.d.ts.map +1 -0
- package/dist/_tmp_create_project.js +17 -0
- package/dist/_tmp_create_project.js.map +1 -0
- package/dist/_tmp_delete_agent.d.ts +2 -0
- package/dist/_tmp_delete_agent.d.ts.map +1 -0
- package/dist/_tmp_delete_agent.js +14 -0
- package/dist/_tmp_delete_agent.js.map +1 -0
- package/dist/_tmp_manual_trigger.d.ts +2 -0
- package/dist/_tmp_manual_trigger.d.ts.map +1 -0
- package/dist/_tmp_manual_trigger.js +17 -0
- package/dist/_tmp_manual_trigger.js.map +1 -0
- package/dist/_tmp_patch_active.d.ts +2 -0
- package/dist/_tmp_patch_active.d.ts.map +1 -0
- package/dist/_tmp_patch_active.js +21 -0
- package/dist/_tmp_patch_active.js.map +1 -0
- package/dist/codegen.d.ts +15 -0
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +466 -81
- package/dist/codegen.js.map +1 -1
- package/dist/commands/deployTheme.d.ts +28 -0
- package/dist/commands/deployTheme.d.ts.map +1 -0
- package/dist/commands/deployTheme.js +68 -0
- package/dist/commands/deployTheme.js.map +1 -0
- package/dist/commands/dev.d.ts +3 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +47 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/fsExec.d.ts +8 -0
- package/dist/commands/fsExec.d.ts.map +1 -0
- package/dist/commands/fsExec.js +46 -0
- package/dist/commands/fsExec.js.map +1 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +11 -0
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/integrate.d.ts +6 -0
- package/dist/commands/integrate.d.ts.map +1 -1
- package/dist/commands/integrate.js +79 -2
- package/dist/commands/integrate.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +2 -23
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/secrets.d.ts +2 -0
- package/dist/commands/secrets.d.ts.map +1 -1
- package/dist/commands/secrets.js +7 -0
- package/dist/commands/secrets.js.map +1 -1
- package/dist/commands/serve.d.ts +1 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +2 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/state.d.ts +19 -0
- package/dist/commands/state.d.ts.map +1 -0
- package/dist/commands/state.js +109 -0
- package/dist/commands/state.js.map +1 -0
- package/dist/commands/terseCliTheme.d.ts +28 -0
- package/dist/commands/terseCliTheme.d.ts.map +1 -0
- package/dist/commands/terseCliTheme.js +68 -0
- package/dist/commands/terseCliTheme.js.map +1 -0
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +5 -33
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/tool.d.ts +6 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +34 -0
- package/dist/commands/tool.js.map +1 -0
- package/dist/data/standardSlackEmoji.d.ts +2 -0
- package/dist/data/standardSlackEmoji.d.ts.map +1 -0
- package/dist/data/standardSlackEmoji.js +1978 -0
- package/dist/data/standardSlackEmoji.js.map +1 -0
- package/dist/data/standardSlackEmoji.json +1974 -0
- package/dist/deploy.d.ts +2 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +61 -38
- package/dist/deploy.js.map +1 -1
- package/dist/envMirror.d.ts +3 -0
- package/dist/envMirror.d.ts.map +1 -0
- package/dist/envMirror.js +121 -0
- package/dist/envMirror.js.map +1 -0
- package/dist/eventFixture.d.ts +3 -0
- package/dist/eventFixture.d.ts.map +1 -0
- package/dist/eventFixture.js +36 -0
- package/dist/eventFixture.js.map +1 -0
- package/dist/generate.d.ts +2 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +67 -69
- package/dist/generate.js.map +1 -1
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +2 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +45 -96
- package/dist/init.js.map +1 -1
- package/dist/integrate.d.ts +1 -0
- package/dist/integrate.d.ts.map +1 -1
- package/dist/integrate.js +191 -11
- package/dist/integrate.js.map +1 -1
- package/dist/nonInteractive.d.ts +4 -2
- package/dist/nonInteractive.d.ts.map +1 -1
- package/dist/nonInteractive.js +5 -2
- package/dist/nonInteractive.js.map +1 -1
- package/dist/perf.d.ts +9 -0
- package/dist/perf.d.ts.map +1 -0
- package/dist/perf.js +59 -0
- package/dist/perf.js.map +1 -0
- package/dist/providers/codegen.test.d.ts +2 -0
- package/dist/providers/codegen.test.d.ts.map +1 -0
- package/dist/providers/codegen.test.js +45 -0
- package/dist/providers/codegen.test.js.map +1 -0
- package/dist/providers/codegenTypes.d.ts +1 -0
- package/dist/providers/codegenTypes.d.ts.map +1 -1
- package/dist/providers/python/PythonProvider.js +1 -0
- package/dist/providers/python/PythonProvider.js.map +1 -1
- package/dist/providers/python/PythonProvider.test.d.ts +2 -0
- package/dist/providers/python/PythonProvider.test.d.ts.map +1 -0
- package/dist/providers/python/PythonProvider.test.js +169 -0
- package/dist/providers/python/PythonProvider.test.js.map +1 -0
- package/dist/providers/typescript/prepareCodegenData.d.ts +1 -0
- package/dist/providers/typescript/prepareCodegenData.d.ts.map +1 -1
- package/dist/providers/typescript/prepareCodegenData.js +1 -0
- package/dist/providers/typescript/prepareCodegenData.js.map +1 -1
- package/dist/providers/typescript/prepareCodegenData.test.d.ts +2 -0
- package/dist/providers/typescript/prepareCodegenData.test.d.ts.map +1 -0
- package/dist/providers/typescript/prepareCodegenData.test.js +54 -0
- package/dist/providers/typescript/prepareCodegenData.test.js.map +1 -0
- package/dist/providers/typescript/projectedTypes.d.ts +11 -0
- package/dist/providers/typescript/projectedTypes.d.ts.map +1 -0
- package/dist/providers/typescript/projectedTypes.js +53 -0
- package/dist/providers/typescript/projectedTypes.js.map +1 -0
- package/dist/providers/typescript/triggerPayloads.d.ts +7 -0
- package/dist/providers/typescript/triggerPayloads.d.ts.map +1 -0
- package/dist/providers/typescript/triggerPayloads.js +60 -0
- package/dist/providers/typescript/triggerPayloads.js.map +1 -0
- package/dist/run.d.ts +2 -11
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +42 -153
- package/dist/run.js.map +1 -1
- package/dist/sampleEventId.d.ts +0 -4
- package/dist/sampleEventId.d.ts.map +1 -1
- package/dist/sampleEventId.js +0 -4
- package/dist/sampleEventId.js.map +1 -1
- package/dist/shared/ApiRoutes.d.ts +19 -0
- package/dist/shared/ApiRoutes.d.ts.map +1 -1
- package/dist/shared/ApiRoutes.js +17 -1
- package/dist/shared/ApiRoutes.js.map +1 -1
- package/dist/shared/Configs.d.ts +24 -2
- package/dist/shared/Configs.d.ts.map +1 -1
- package/dist/shared/Configs.js +32 -2
- package/dist/shared/Configs.js.map +1 -1
- package/dist/shared/Integrations.d.ts +18 -1
- package/dist/shared/Integrations.d.ts.map +1 -1
- package/dist/shared/Integrations.js +10 -1
- package/dist/shared/Integrations.js.map +1 -1
- package/dist/shared/InvalidationKeys.d.ts +1 -0
- package/dist/shared/InvalidationKeys.d.ts.map +1 -1
- package/dist/shared/InvalidationKeys.js +3 -0
- package/dist/shared/InvalidationKeys.js.map +1 -1
- package/dist/shared/ModelEvents.d.ts +9 -0
- package/dist/shared/ModelEvents.d.ts.map +1 -1
- package/dist/shared/ModelEvents.js +15 -0
- package/dist/shared/ModelEvents.js.map +1 -1
- package/dist/shared/ToolDisplayUtils.d.ts.map +1 -1
- package/dist/shared/ToolDisplayUtils.js +107 -11
- package/dist/shared/ToolDisplayUtils.js.map +1 -1
- package/dist/shared/types.d.ts +1013 -108
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/test.d.ts +2 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +43 -23
- package/dist/test.js.map +1 -1
- package/dist/toolCatalog.d.ts +12 -0
- package/dist/toolCatalog.d.ts.map +1 -0
- package/dist/toolCatalog.js +33 -0
- package/dist/toolCatalog.js.map +1 -0
- package/dist/util.d.ts +2 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +3 -3
- package/dist/util.js.map +1 -1
- package/package.json +3 -3
- package/templates/typescript/codegen/partials/header.hbs +5 -0
- package/dist/jsonOutput.d.ts +0 -19
- package/dist/jsonOutput.d.ts.map +0 -1
- package/dist/jsonOutput.js +0 -25
- package/dist/jsonOutput.js.map +0 -1
- package/dist/providers/typescript/parkSignals.d.ts +0 -7
- package/dist/providers/typescript/parkSignals.d.ts.map +0 -1
- package/dist/providers/typescript/parkSignals.js +0 -45
- package/dist/providers/typescript/parkSignals.js.map +0 -1
- package/dist/replay.d.ts +0 -3
- package/dist/replay.d.ts.map +0 -1
- package/dist/replay.js +0 -20
- package/dist/replay.js.map +0 -1
- package/dist/urls.d.ts +0 -3
- package/dist/urls.d.ts.map +0 -1
- package/dist/urls.js +0 -27
- package/dist/urls.js.map +0 -1
package/dist/deploy.d.ts
CHANGED
package/dist/deploy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAGvE,wBAAsB,MAAM,CAAC,QAAQ,GAAE,gBAAoC,EAAE,SAAS,CAAC,EAAE,MAAM,iBA2F9F"}
|
package/dist/deploy.js
CHANGED
|
@@ -1,35 +1,45 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { zipSync } from "fflate";
|
|
1
3
|
import fs from "node:fs";
|
|
2
4
|
import path from "node:path";
|
|
3
|
-
import chalk from "chalk";
|
|
4
5
|
import ora from "ora";
|
|
5
|
-
import {
|
|
6
|
-
import { fetchWithAuth,
|
|
7
|
-
import { assertProjectRoot } from "./assertProjectRoot.js";
|
|
6
|
+
import { ApiRoutes, sdkDeployRequestBodySchema } from "terse-types";
|
|
7
|
+
import { fetchWithAuth, readApiKeyOrBail, readEnvVar } from "./api.js";
|
|
8
8
|
import { loadJobRegistry } from "./loadJob.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
console.error(chalk.red("Error: No TERSE_API_KEY found in .env"));
|
|
17
|
-
console.error(chalk.dim("Run `terse init` to set up your project, or add TERSE_API_KEY to your .env file."));
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
const registry = await loadJobRegistry();
|
|
9
|
+
import { resolveProvider } from "./providers/resolveProvider.js";
|
|
10
|
+
export async function deploy(provider = resolveProvider(), entryFile) {
|
|
11
|
+
const apiKey = readApiKeyOrBail({
|
|
12
|
+
title: "Error: No TERSE_API_KEY found in .env",
|
|
13
|
+
detail: "Run `terse init` to set up your project, or add TERSE_API_KEY to your .env file."
|
|
14
|
+
});
|
|
15
|
+
const registry = await loadJobRegistry(provider, entryFile);
|
|
21
16
|
const jobs = [...registry.values()];
|
|
22
|
-
|
|
17
|
+
// If TERSE_REMOTE_SERVER_URL (or legacy TERSE_JOB_URL) is set in .env, deploy
|
|
18
|
+
// in URL mode (user infrastructure). No source code is zipped or uploaded.
|
|
19
|
+
const remoteServerUrl = readEnvVar("TERSE_REMOTE_SERVER_URL") ?? readEnvVar("TERSE_JOB_URL");
|
|
20
|
+
const isUrlMode = !!remoteServerUrl;
|
|
21
|
+
let sourceZipBase64;
|
|
22
|
+
let fileCount = 0;
|
|
23
|
+
let zipSizeBytes = 0;
|
|
24
|
+
if (!isUrlMode) {
|
|
25
|
+
const zipPayload = buildZipPayload(provider);
|
|
26
|
+
sourceZipBase64 = zipPayload.sourceZipBase64;
|
|
27
|
+
fileCount = zipPayload.fileCount;
|
|
28
|
+
zipSizeBytes = zipPayload.zipSizeBytes;
|
|
29
|
+
}
|
|
23
30
|
const spinner = ora(`Deploying ${jobs.length} job${jobs.length === 1 ? "" : "s"}...`).start();
|
|
24
31
|
try {
|
|
25
|
-
const
|
|
32
|
+
const body = sdkDeployRequestBodySchema.parse({
|
|
26
33
|
jobs: jobs.map(job => ({
|
|
27
34
|
jobName: job.name,
|
|
28
|
-
triggers: job.triggers
|
|
29
|
-
|
|
35
|
+
triggers: job.triggers,
|
|
36
|
+
outputs: job.skills ?? [],
|
|
37
|
+
toolApprovals: job.toolApprovals ?? []
|
|
30
38
|
})),
|
|
39
|
+
remoteServerUrl: isUrlMode ? remoteServerUrl : undefined,
|
|
31
40
|
sourceZipBase64
|
|
32
|
-
}
|
|
41
|
+
});
|
|
42
|
+
const result = await fetchWithAuth(ApiRoutes.SDK.DEPLOY, apiKey, body, "POST");
|
|
33
43
|
if (!result.success) {
|
|
34
44
|
spinner.fail(chalk.red(`Deploy failed: ${result.error}`));
|
|
35
45
|
if (result.details) {
|
|
@@ -41,9 +51,31 @@ export async function deploy() {
|
|
|
41
51
|
for (const r of result.results) {
|
|
42
52
|
const verb = r.isUpdate ? "Updated" : "Created";
|
|
43
53
|
console.log(chalk.dim(` ${verb} "${r.jobName}" (${r.automationId})`));
|
|
54
|
+
if (r.triggers) {
|
|
55
|
+
for (const t of r.triggers) {
|
|
56
|
+
if (t.metadata?.webhookUrl) {
|
|
57
|
+
console.log(chalk.cyan(` Webhook URL: ${t.metadata.webhookUrl}`));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (isUrlMode) {
|
|
63
|
+
console.log(chalk.dim(` Mode: user infrastructure`));
|
|
64
|
+
console.log(chalk.dim(` Server URL: ${remoteServerUrl}`));
|
|
65
|
+
const signingSecret = result.results.find(r => r.signingSecret)?.signingSecret;
|
|
66
|
+
if (signingSecret) {
|
|
67
|
+
const existingSecret = readEnvVar("TERSE_SIGNING_SECRET");
|
|
68
|
+
if (!existingSecret) {
|
|
69
|
+
console.log(`\n Add this to your ${chalk.bold(".env")} file:\n`);
|
|
70
|
+
console.log(`TERSE_SIGNING_SECRET=${signingSecret}`);
|
|
71
|
+
console.log("");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.log(chalk.dim(` Files: ${fileCount}`));
|
|
77
|
+
console.log(chalk.dim(` Zip size: ${(zipSizeBytes / 1024).toFixed(1)} KB`));
|
|
44
78
|
}
|
|
45
|
-
console.log(chalk.dim(` Files: ${fileCount}`));
|
|
46
|
-
console.log(chalk.dim(` Zip size: ${(zipSizeBytes / 1024).toFixed(1)} KB`));
|
|
47
79
|
if (result.removed.length > 0) {
|
|
48
80
|
console.log(chalk.yellow(`\nRemoved ${result.removed.length} stale job${result.removed.length === 1 ? "" : "s"} no longer in project:`));
|
|
49
81
|
for (const r of result.removed) {
|
|
@@ -56,17 +88,17 @@ export async function deploy() {
|
|
|
56
88
|
process.exit(1);
|
|
57
89
|
}
|
|
58
90
|
}
|
|
59
|
-
function collectFiles(dir, baseDir) {
|
|
91
|
+
function collectFiles(dir, baseDir, provider) {
|
|
60
92
|
const entries = {};
|
|
61
93
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
62
|
-
if (
|
|
94
|
+
if (provider.deployExclusions.dirs.has(entry.name))
|
|
63
95
|
continue;
|
|
64
|
-
if (
|
|
96
|
+
if (provider.deployExclusions.files.has(entry.name))
|
|
65
97
|
continue;
|
|
66
98
|
const fullPath = path.join(dir, entry.name);
|
|
67
99
|
const relativePath = path.relative(baseDir, fullPath);
|
|
68
100
|
if (entry.isDirectory()) {
|
|
69
|
-
Object.assign(entries, collectFiles(fullPath, baseDir));
|
|
101
|
+
Object.assign(entries, collectFiles(fullPath, baseDir, provider));
|
|
70
102
|
}
|
|
71
103
|
else if (entry.isFile()) {
|
|
72
104
|
entries[relativePath] = new Uint8Array(fs.readFileSync(fullPath));
|
|
@@ -74,18 +106,9 @@ function collectFiles(dir, baseDir) {
|
|
|
74
106
|
}
|
|
75
107
|
return entries;
|
|
76
108
|
}
|
|
77
|
-
function
|
|
78
|
-
const { isComplete, formatForAgent, configType, integrationType, integrationId, ...rest } = config;
|
|
79
|
-
return {
|
|
80
|
-
configType,
|
|
81
|
-
integrationType,
|
|
82
|
-
integrationId,
|
|
83
|
-
config: rest
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function buildZipPayload() {
|
|
109
|
+
function buildZipPayload(provider) {
|
|
87
110
|
const cwd = process.cwd();
|
|
88
|
-
const files = collectFiles(cwd, cwd);
|
|
111
|
+
const files = collectFiles(cwd, cwd, provider);
|
|
89
112
|
const fileCount = Object.keys(files).length;
|
|
90
113
|
if (fileCount === 0) {
|
|
91
114
|
console.error(chalk.red("No files found to deploy"));
|
package/dist/deploy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envMirror.d.ts","sourceRoot":"","sources":["../src/envMirror.ts"],"names":[],"mappings":"AAUA,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAUrG;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAWxF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { CliError } from "./cliError.js";
|
|
7
|
+
const ENV_FILENAME = ".env";
|
|
8
|
+
export function mirrorSecretToLocalEnv(name, value, cwd = process.cwd()) {
|
|
9
|
+
let outcome;
|
|
10
|
+
try {
|
|
11
|
+
outcome = upsertEnvEntry(cwd, name, value);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
warnMirrorFailed(`write ${name} to`, error);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
reportOutcome(name, outcome);
|
|
18
|
+
if (outcome !== "unchanged")
|
|
19
|
+
warnIfNotGitignored(cwd);
|
|
20
|
+
}
|
|
21
|
+
export function removeSecretFromLocalEnv(name, cwd = process.cwd()) {
|
|
22
|
+
let removed;
|
|
23
|
+
try {
|
|
24
|
+
removed = removeEnvEntry(cwd, name);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
warnMirrorFailed(`remove ${name} from`, error);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (removed) {
|
|
31
|
+
process.stdout.write(`Removed ${name} from ${ENV_FILENAME}.\n`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function upsertEnvEntry(cwd, name, value) {
|
|
35
|
+
const filePath = path.join(cwd, ENV_FILENAME);
|
|
36
|
+
const entry = `${name}=${serializeEnvValue(name, value)}`;
|
|
37
|
+
if (!fs.existsSync(filePath)) {
|
|
38
|
+
fs.writeFileSync(filePath, `${entry}\n`, { mode: 0o600 });
|
|
39
|
+
return "created";
|
|
40
|
+
}
|
|
41
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
42
|
+
if (dotenv.parse(raw)[name] === value)
|
|
43
|
+
return "unchanged";
|
|
44
|
+
const eol = raw.includes("\r\n") ? "\r\n" : "\n";
|
|
45
|
+
const lines = raw.split(/\r?\n/);
|
|
46
|
+
const [firstMatch, ...duplicateMatches] = lines.flatMap((line, index) => (envLineName(line) === name ? [index] : []));
|
|
47
|
+
if (firstMatch === undefined) {
|
|
48
|
+
const body = raw.length === 0 || raw.endsWith("\n") ? raw : `${raw}${eol}`;
|
|
49
|
+
fs.writeFileSync(filePath, `${body}${entry}${eol}`);
|
|
50
|
+
return "added";
|
|
51
|
+
}
|
|
52
|
+
const updatedLines = lines.map((line, index) => (index === firstMatch ? entry : line)).filter((_, index) => !duplicateMatches.includes(index));
|
|
53
|
+
fs.writeFileSync(filePath, updatedLines.join(eol));
|
|
54
|
+
return "updated";
|
|
55
|
+
}
|
|
56
|
+
function removeEnvEntry(cwd, name) {
|
|
57
|
+
const filePath = path.join(cwd, ENV_FILENAME);
|
|
58
|
+
if (!fs.existsSync(filePath))
|
|
59
|
+
return false;
|
|
60
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
61
|
+
const eol = raw.includes("\r\n") ? "\r\n" : "\n";
|
|
62
|
+
const lines = raw.split(/\r?\n/);
|
|
63
|
+
const remaining = lines.filter(line => envLineName(line) !== name);
|
|
64
|
+
if (remaining.length === lines.length)
|
|
65
|
+
return false;
|
|
66
|
+
fs.writeFileSync(filePath, remaining.join(eol));
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
function serializeEnvValue(name, value) {
|
|
70
|
+
const candidates = [value, `'${value}'`, `"${value}"`, `"${value.replace(/\r/g, "\\r").replace(/\n/g, "\\n")}"`];
|
|
71
|
+
const usable = candidates.find(candidate => !/[\r\n]/.test(candidate) && dotenv.parse(`${name}=${candidate}`)[name] === value);
|
|
72
|
+
if (usable === undefined) {
|
|
73
|
+
throw new CliError("env_value_unwritable", `Could not represent the value of ${name} in ${ENV_FILENAME}.`);
|
|
74
|
+
}
|
|
75
|
+
return usable;
|
|
76
|
+
}
|
|
77
|
+
function envLineName(line) {
|
|
78
|
+
const separatorIndex = line.indexOf("=");
|
|
79
|
+
if (separatorIndex <= 0)
|
|
80
|
+
return null;
|
|
81
|
+
return line.slice(0, separatorIndex).trim();
|
|
82
|
+
}
|
|
83
|
+
function reportOutcome(name, outcome) {
|
|
84
|
+
switch (outcome) {
|
|
85
|
+
case "created":
|
|
86
|
+
process.stdout.write(`Created ${ENV_FILENAME} with ${name} for local runs.\n`);
|
|
87
|
+
return;
|
|
88
|
+
case "added":
|
|
89
|
+
process.stdout.write(`Added ${name} to ${ENV_FILENAME} for local runs.\n`);
|
|
90
|
+
return;
|
|
91
|
+
case "updated":
|
|
92
|
+
process.stdout.write(`Updated ${name} in ${ENV_FILENAME} (replaced a different local value).\n`);
|
|
93
|
+
return;
|
|
94
|
+
case "unchanged":
|
|
95
|
+
return;
|
|
96
|
+
default:
|
|
97
|
+
throw outcome;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function warnIfNotGitignored(cwd) {
|
|
101
|
+
if (isEnvGitignored(cwd) === false) {
|
|
102
|
+
process.stdout.write(chalk.yellow(`Warning: ${ENV_FILENAME} is not ignored by git. Add it to your .gitignore so secret values are not committed.\n`));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function isEnvGitignored(cwd) {
|
|
106
|
+
try {
|
|
107
|
+
execFileSync("git", ["check-ignore", "-q", ENV_FILENAME], { cwd, stdio: "ignore" });
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return isCheckIgnoreMiss(error) ? false : null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function isCheckIgnoreMiss(error) {
|
|
115
|
+
return typeof error === "object" && error !== null && "status" in error && error.status === 1;
|
|
116
|
+
}
|
|
117
|
+
function warnMirrorFailed(action, error) {
|
|
118
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
119
|
+
process.stdout.write(chalk.yellow(`Warning: could not ${action} ${ENV_FILENAME} (${detail}). Update it manually so local runs stay in sync.\n`));
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=envMirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envMirror.js","sourceRoot":"","sources":["../src/envMirror.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,YAAY,GAAG,MAAM,CAAA;AAE3B,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,KAAa,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAC3F,IAAI,OAAyB,CAAA;IAC7B,IAAI,CAAC;QACD,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,gBAAgB,CAAC,SAAS,IAAI,KAAK,EAAE,KAAK,CAAC,CAAA;QAC3C,OAAM;IACV,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC5B,IAAI,OAAO,KAAK,WAAW;QAAE,mBAAmB,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAC9E,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACD,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,gBAAgB,CAAC,UAAU,IAAI,OAAO,EAAE,KAAK,CAAC,CAAA;QAC9C,OAAM;IACV,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,YAAY,KAAK,CAAC,CAAA;IACnE,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,GAAW,EAAE,IAAY,EAAE,KAAa;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAC7C,MAAM,KAAK,GAAG,GAAG,IAAI,IAAI,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAA;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACzD,OAAO,SAAS,CAAA;IACpB,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC7C,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK;QAAE,OAAO,WAAW,CAAA;IAEzD,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChC,MAAM,CAAC,UAAU,EAAE,GAAG,gBAAgB,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAErH,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,CAAA;QAC1E,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,EAAE,CAAC,CAAA;QACnD,OAAO,OAAO,CAAA;IAClB,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAC9I,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAClD,OAAO,SAAS,CAAA;AACpB,CAAC;AAED,SAAS,cAAc,CAAC,GAAW,EAAE,IAAY;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAE1C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;IAClE,IAAI,SAAS,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAEnD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/C,OAAO,IAAI,CAAA;AACf,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,KAAa;IAClD,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;IAChH,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAA;IAC9H,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,oCAAoC,IAAI,OAAO,YAAY,GAAG,CAAC,CAAA;IAC9G,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,cAAc,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,EAAE,CAAA;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,OAAyB;IAC1D,QAAQ,OAAO,EAAE,CAAC;QACd,KAAK,SAAS;YACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,YAAY,SAAS,IAAI,oBAAoB,CAAC,CAAA;YAC9E,OAAM;QACV,KAAK,OAAO;YACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,YAAY,oBAAoB,CAAC,CAAA;YAC1E,OAAM;QACV,KAAK,SAAS;YACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,IAAI,OAAO,YAAY,wCAAwC,CAAC,CAAA;YAChG,OAAM;QACV,KAAK,WAAW;YACZ,OAAM;QACV;YACI,MAAM,OAAuB,CAAA;IACrC,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACpC,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,YAAY,yFAAyF,CAAC,CAAC,CAAA;IACzJ,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAChC,IAAI,CAAC;QACD,YAAY,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QACnF,OAAO,IAAI,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;IAClD,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAA;AACjG,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc,EAAE,KAAc;IACpD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,MAAM,IAAI,YAAY,KAAK,MAAM,qDAAqD,CAAC,CAAC,CAAA;AACpJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventFixture.d.ts","sourceRoot":"","sources":["../src/eventFixture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAKlD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,eAAe,CASvF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { eventFixtureSchema, hydrateSerializedEvent } from "terse-types";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { CliError } from "./cliError.js";
|
|
4
|
+
export function parseEventFixtureJson(raw, sourceLabel) {
|
|
5
|
+
const parsed = parseJson(raw, sourceLabel);
|
|
6
|
+
const result = eventFixtureSchema.safeParse(parsed);
|
|
7
|
+
if (result.success) {
|
|
8
|
+
return hydrateSerializedEvent(result.data);
|
|
9
|
+
}
|
|
10
|
+
throw new CliError("invalid_event_shape", `${sourceLabel} does not match the canonical Trigger schema.`, {
|
|
11
|
+
detail: `${z.prettifyError(result.error)}\n\n${EXPECTED_FIXTURE_HINT}`
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function parseJson(raw, sourceLabel) {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
throw new CliError("invalid_event_json", `${sourceLabel} must be valid JSON.`, {
|
|
20
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const EXPECTED_FIXTURE_HINT = [
|
|
25
|
+
"Expected a flat trigger fixture, e.g. for a webhook:",
|
|
26
|
+
"{",
|
|
27
|
+
' "integrationType": "webhook",',
|
|
28
|
+
' "eventType": "webhook",',
|
|
29
|
+
' "method": "POST",',
|
|
30
|
+
' "headers": { "content-type": "application/json" },',
|
|
31
|
+
' "body": { "your": "payload" }',
|
|
32
|
+
"}",
|
|
33
|
+
'Optional top-level "formattedContent" / "debugLog" strings override the derived prompt and log text.',
|
|
34
|
+
"Tip: `terse test show <id> --json` emits ready-to-use fixtures."
|
|
35
|
+
].join("\n");
|
|
36
|
+
//# sourceMappingURL=eventFixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventFixture.js","sourceRoot":"","sources":["../src/eventFixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAExE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,WAAmB;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACnD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC9C,CAAC;IACD,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,GAAG,WAAW,+CAA+C,EAAE;QACrG,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,qBAAqB,EAAE;KACzE,CAAC,CAAA;AACN,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,WAAmB;IAC/C,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,GAAG,WAAW,sBAAsB,EAAE;YAC3E,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC3D,CAAC,CAAA;IACN,CAAC;AACL,CAAC;AAED,MAAM,qBAAqB,GAAG;IAC1B,sDAAsD;IACtD,GAAG;IACH,iCAAiC;IACjC,2BAA2B;IAC3B,qBAAqB;IACrB,sDAAsD;IACtD,iCAAiC;IACjC,GAAG;IACH,sGAAsG;IACtG,iEAAiE;CACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA"}
|
package/dist/generate.d.ts
CHANGED
package/dist/generate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAkBvE,wBAAsB,QAAQ,CAAC,QAAQ,GAAE,gBAAoC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoT5F"}
|
package/dist/generate.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import chalk from "chalk";
|
|
4
4
|
import ora from "ora";
|
|
5
|
+
import { IntegrationType, isValidToolName } from "terse-types";
|
|
6
|
+
import { ApiRoutes, buildRoute } from "terse-types";
|
|
7
|
+
import { fetchWithAuth, readApiKeyOrBail } from "./api.js";
|
|
5
8
|
import { assertProjectRoot } from "./assertProjectRoot.js";
|
|
6
|
-
import {
|
|
7
|
-
import { IntegrationType } from "./shared/Integrations.js";
|
|
8
|
-
import { ApiRoutes } from "./shared/ApiRoutes.js";
|
|
9
|
-
import { fetchWithAuth, readApiKey } from "./api.js";
|
|
9
|
+
import { resolveProvider } from "./providers/resolveProvider.js";
|
|
10
10
|
// ── Main ──────────────────────────────────────────────────────────────
|
|
11
|
-
export async function generate() {
|
|
12
|
-
assertProjectRoot();
|
|
11
|
+
export async function generate(provider = resolveProvider()) {
|
|
12
|
+
assertProjectRoot(provider, provider.detectionMarkers);
|
|
13
13
|
const totalStart = performance.now();
|
|
14
14
|
// 1. Read API key
|
|
15
|
-
const apiKey =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
15
|
+
const apiKey = readApiKeyOrBail({
|
|
16
|
+
title: "\n Missing TERSE_API_KEY in .env\n",
|
|
17
|
+
detail: " Create a project with `terse init` or add TERSE_API_KEY to your .env file.\n"
|
|
18
|
+
});
|
|
21
19
|
// 2. Fetch active integrations
|
|
22
20
|
const spinner = ora("Fetching integrations...").start();
|
|
23
21
|
let activeTypes;
|
|
@@ -33,8 +31,7 @@ export async function generate() {
|
|
|
33
31
|
message.toLowerCase().includes("unauthorized") ||
|
|
34
32
|
message.toLowerCase().includes("forbidden");
|
|
35
33
|
if (isAuthError) {
|
|
36
|
-
console.error(chalk.red("\n Authentication failed: your TERSE_API_KEY was rejected.\n") +
|
|
37
|
-
chalk.dim(" Update TERSE_API_KEY in .env and try again.\n"));
|
|
34
|
+
console.error(chalk.red("\n Authentication failed: your TERSE_API_KEY was rejected.\n") + chalk.dim(" Update TERSE_API_KEY in .env and try again.\n"));
|
|
38
35
|
}
|
|
39
36
|
else {
|
|
40
37
|
console.error(chalk.red(`\n ${message}\n`));
|
|
@@ -49,6 +46,11 @@ export async function generate() {
|
|
|
49
46
|
// Filter to only tools whose integration matches an active integration type
|
|
50
47
|
const activeSet = new Set(activeTypes);
|
|
51
48
|
toolDefs = resp.tools.filter(t => activeSet.has(t.integration));
|
|
49
|
+
const skippedToolNames = [...new Set(toolDefs.filter(t => !isValidToolName(t.name)).map(t => t.name))].sort();
|
|
50
|
+
toolDefs = toolDefs.filter(t => isValidToolName(t.name));
|
|
51
|
+
if (skippedToolNames.length > 0) {
|
|
52
|
+
console.warn(chalk.yellow(`\n Skipped ${skippedToolNames.length} tool(s) absent from terse-types ToolDefinitions: ${skippedToolNames.join(", ")}\n`));
|
|
53
|
+
}
|
|
52
54
|
}
|
|
53
55
|
catch {
|
|
54
56
|
// Non-fatal: proceed without tool definitions
|
|
@@ -56,11 +58,18 @@ export async function generate() {
|
|
|
56
58
|
// 4. Fetch all integration instances + resources in parallel
|
|
57
59
|
spinner.text = "Fetching integration details...";
|
|
58
60
|
const input = {
|
|
59
|
-
github: [],
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
github: [],
|
|
62
|
+
slack: [],
|
|
63
|
+
gmail: [],
|
|
64
|
+
linear: [],
|
|
65
|
+
notion: [],
|
|
66
|
+
posthog: [],
|
|
67
|
+
datadog: [],
|
|
68
|
+
launchdarkly: [],
|
|
69
|
+
workos: [],
|
|
70
|
+
attio: [],
|
|
71
|
+
snowflake: [],
|
|
72
|
+
tools: toolDefs
|
|
64
73
|
};
|
|
65
74
|
const has = (t) => activeTypes.includes(t);
|
|
66
75
|
const promises = [];
|
|
@@ -91,37 +100,18 @@ export async function generate() {
|
|
|
91
100
|
}));
|
|
92
101
|
}));
|
|
93
102
|
}
|
|
94
|
-
// ── Figma (no resources) ──
|
|
95
|
-
if (has(IntegrationType.FIGMA)) {
|
|
96
|
-
promises.push(safely(async () => {
|
|
97
|
-
const instances = await fetchWithAuth(ApiRoutes.FIGMA.INTEGRATIONS, apiKey);
|
|
98
|
-
input.figma = instances.map(inst => ({ id: inst.id, displayName: inst.handle || inst.id }));
|
|
99
|
-
}));
|
|
100
|
-
}
|
|
101
103
|
// ── Linear (fetches teams per instance) ──
|
|
102
104
|
if (has(IntegrationType.LINEAR)) {
|
|
103
105
|
promises.push(safely(async () => {
|
|
104
106
|
const instances = await fetchWithAuth(ApiRoutes.LINEAR.INTEGRATIONS, apiKey);
|
|
105
107
|
input.linear = await Promise.all(instances.map(async (inst) => {
|
|
106
108
|
const teams = await fetchWithAuth(`${ApiRoutes.LINEAR.TEAMS}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => []);
|
|
107
|
-
|
|
108
|
-
}));
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
// ── Atlassian — fetches Jira projects + Confluence pages per instance ──
|
|
112
|
-
if (has(IntegrationType.ATLASSIAN)) {
|
|
113
|
-
promises.push(safely(async () => {
|
|
114
|
-
const instances = await fetchWithAuth(ApiRoutes.ATLASSIAN.INTEGRATIONS, apiKey);
|
|
115
|
-
input.atlassian = await Promise.all(instances.map(async (inst) => {
|
|
116
|
-
const [jiraResp, confResp] = await Promise.all([
|
|
117
|
-
fetchWithAuth(`${ApiRoutes.JIRA.RESOURCES}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => null),
|
|
118
|
-
fetchWithAuth(`${ApiRoutes.CONFLUENCE.RESOURCES}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => null),
|
|
119
|
-
]);
|
|
109
|
+
const projects = await fetchWithAuth(`${ApiRoutes.LINEAR.PROJECTS}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => []);
|
|
120
110
|
return {
|
|
121
111
|
id: inst.id,
|
|
122
|
-
displayName: inst.
|
|
123
|
-
|
|
124
|
-
|
|
112
|
+
displayName: inst.workspaceName || inst.id,
|
|
113
|
+
teams: Array.isArray(teams) ? teams : [],
|
|
114
|
+
projects: Array.isArray(projects) ? projects : []
|
|
125
115
|
};
|
|
126
116
|
}));
|
|
127
117
|
}));
|
|
@@ -137,7 +127,7 @@ export async function generate() {
|
|
|
137
127
|
id: inst.id,
|
|
138
128
|
displayName: inst.workspaceName || inst.id,
|
|
139
129
|
databases: resources.filter(r => r.type === "database"),
|
|
140
|
-
pages: resources.filter(r => r.type === "page")
|
|
130
|
+
pages: resources.filter(r => r.type === "page")
|
|
141
131
|
};
|
|
142
132
|
}));
|
|
143
133
|
}));
|
|
@@ -157,7 +147,9 @@ export async function generate() {
|
|
|
157
147
|
promises.push(safely(async () => {
|
|
158
148
|
const instances = await fetchWithAuth(ApiRoutes.DATADOG.INTEGRATIONS, apiKey);
|
|
159
149
|
input.datadog = await Promise.all(instances.map(async (inst) => {
|
|
160
|
-
const resp = await fetchWithAuth(`${ApiRoutes.DATADOG.INDEXES}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => ({
|
|
150
|
+
const resp = await fetchWithAuth(`${ApiRoutes.DATADOG.INDEXES}?integrationId=${encodeURIComponent(inst.id)}`, apiKey).catch(() => ({
|
|
151
|
+
indexes: []
|
|
152
|
+
}));
|
|
161
153
|
return { id: inst.id, displayName: inst.region || inst.id, indexes: resp.indexes || [] };
|
|
162
154
|
}));
|
|
163
155
|
}));
|
|
@@ -167,7 +159,7 @@ export async function generate() {
|
|
|
167
159
|
promises.push(safely(async () => {
|
|
168
160
|
const instances = await fetchWithAuth(ApiRoutes.LAUNCHDARKLY.INTEGRATIONS, apiKey);
|
|
169
161
|
input.launchdarkly = await Promise.all(instances.map(async (inst) => {
|
|
170
|
-
const resp = await fetchWithAuth(ApiRoutes.LAUNCHDARKLY.PROJECTS_BY_INTEGRATION_ID
|
|
162
|
+
const resp = await fetchWithAuth(buildRoute(ApiRoutes.LAUNCHDARKLY.PROJECTS_BY_INTEGRATION_ID, { integrationId: inst.id }), apiKey).catch(() => ({ projects: [] }));
|
|
171
163
|
return { id: inst.id, displayName: inst.tokenName || inst.email || inst.id, projects: resp.projects || [] };
|
|
172
164
|
}));
|
|
173
165
|
}));
|
|
@@ -184,23 +176,35 @@ export async function generate() {
|
|
|
184
176
|
promises.push(safely(async () => {
|
|
185
177
|
const instances = await fetchWithAuth(ApiRoutes.ATTIO.INTEGRATIONS, apiKey);
|
|
186
178
|
input.attio = await Promise.all(instances.map(async (inst) => {
|
|
187
|
-
const objects = await fetchWithAuth(ApiRoutes.ATTIO.OBJECTS
|
|
179
|
+
const objects = await fetchWithAuth(buildRoute(ApiRoutes.ATTIO.OBJECTS, { integrationId: inst.id }), apiKey).catch(() => []);
|
|
188
180
|
return { id: inst.id, displayName: inst.workspaceName || inst.id, objects: Array.isArray(objects) ? objects : [] };
|
|
189
181
|
}));
|
|
190
182
|
}));
|
|
191
183
|
}
|
|
184
|
+
if (has(IntegrationType.SNOWFLAKE)) {
|
|
185
|
+
promises.push(safely(async () => {
|
|
186
|
+
const instances = await fetchWithAuth(ApiRoutes.SNOWFLAKE.INTEGRATIONS, apiKey);
|
|
187
|
+
input.snowflake = instances.map(inst => ({ id: inst.id, name: inst.accountIdentifier }));
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
192
190
|
await Promise.all(promises);
|
|
193
|
-
const integrationCount = input.github.length +
|
|
194
|
-
input.
|
|
195
|
-
input.
|
|
196
|
-
input.
|
|
191
|
+
const integrationCount = input.github.length +
|
|
192
|
+
input.slack.length +
|
|
193
|
+
input.gmail.length +
|
|
194
|
+
input.linear.length +
|
|
195
|
+
input.notion.length +
|
|
196
|
+
input.posthog.length +
|
|
197
|
+
input.datadog.length +
|
|
198
|
+
input.launchdarkly.length +
|
|
199
|
+
input.workos.length +
|
|
200
|
+
input.attio.length;
|
|
197
201
|
spinner.succeed(`Fetched ${integrationCount} integration(s)`);
|
|
198
202
|
// 5. Generate code
|
|
199
203
|
const codegenStart = performance.now();
|
|
200
|
-
const code =
|
|
204
|
+
const code = provider.renderGeneratedCode(input);
|
|
201
205
|
const codegenMs = performance.now() - codegenStart;
|
|
202
206
|
// 6. Write output
|
|
203
|
-
writeOutput(code);
|
|
207
|
+
writeOutput(code, provider);
|
|
204
208
|
// 7. Summary
|
|
205
209
|
const totalMs = performance.now() - totalStart;
|
|
206
210
|
console.log("");
|
|
@@ -211,7 +215,7 @@ export async function generate() {
|
|
|
211
215
|
console.log(` ${chalk.green("+")} Schedule trigger`);
|
|
212
216
|
console.log(` ${chalk.green("+")} Terse skills (web search)`);
|
|
213
217
|
console.log("");
|
|
214
|
-
console.log(` ${chalk.green.bold("Generated")}
|
|
218
|
+
console.log(` ${chalk.green.bold("Generated")} ${path.relative(process.cwd(), provider.resolveGeneratedCodePath(process.cwd()))}`);
|
|
215
219
|
console.log(` ${chalk.dim(`Codegen: ${codegenMs.toFixed(0)}ms | Total: ${totalMs.toFixed(0)}ms`)}`);
|
|
216
220
|
console.log("");
|
|
217
221
|
}
|
|
@@ -220,14 +224,17 @@ async function safely(fn) {
|
|
|
220
224
|
try {
|
|
221
225
|
await fn();
|
|
222
226
|
}
|
|
223
|
-
catch {
|
|
227
|
+
catch {
|
|
228
|
+
/* skip failed integrations */
|
|
229
|
+
}
|
|
224
230
|
}
|
|
225
|
-
function writeOutput(code) {
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
231
|
+
function writeOutput(code, provider) {
|
|
232
|
+
const outputPath = provider.resolveGeneratedCodePath(process.cwd());
|
|
233
|
+
const outputDir = path.dirname(outputPath);
|
|
234
|
+
if (!fs.existsSync(outputDir)) {
|
|
235
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
229
236
|
}
|
|
230
|
-
fs.writeFileSync(
|
|
237
|
+
fs.writeFileSync(outputPath, code);
|
|
231
238
|
}
|
|
232
239
|
function printSummary(input) {
|
|
233
240
|
const g = chalk.green("+");
|
|
@@ -243,19 +250,10 @@ function printSummary(input) {
|
|
|
243
250
|
const n = inst.channels.length;
|
|
244
251
|
console.log(` ${g} Slack (${inst.displayName}) — ${n} ${n === 1 ? "channel" : "channels"}`);
|
|
245
252
|
}
|
|
246
|
-
for (const inst of input.figma) {
|
|
247
|
-
console.log(` ${g} Figma (${inst.displayName})`);
|
|
248
|
-
}
|
|
249
253
|
for (const inst of input.linear) {
|
|
250
254
|
const n = inst.teams.length;
|
|
251
255
|
console.log(` ${g} Linear (${inst.displayName}) — ${n} ${n === 1 ? "team" : "teams"}`);
|
|
252
256
|
}
|
|
253
|
-
for (const inst of input.atlassian) {
|
|
254
|
-
const jp = inst.jiraProjects.length;
|
|
255
|
-
const cp = inst.confluencePages.length;
|
|
256
|
-
console.log(` ${g} Jira (${inst.displayName}) — ${jp} ${jp === 1 ? "project" : "projects"}`);
|
|
257
|
-
console.log(` ${g} Confluence (${inst.displayName}) — ${cp} ${cp === 1 ? "page" : "pages"}`);
|
|
258
|
-
}
|
|
259
257
|
for (const inst of input.notion) {
|
|
260
258
|
const d = inst.databases.length;
|
|
261
259
|
const p = inst.pages.length;
|