wizards 0.1.9
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 +110 -0
- package/README.md +170 -0
- package/apps/runtime/dist/agents/architect.js +453 -0
- package/apps/runtime/dist/agents/project-assistant.js +354 -0
- package/apps/runtime/dist/agents/subscription.js +206 -0
- package/apps/runtime/dist/agents/thought.js +21 -0
- package/apps/runtime/dist/agents/website.js +197 -0
- package/apps/runtime/dist/app.js +153 -0
- package/apps/runtime/dist/auth/account.js +121 -0
- package/apps/runtime/dist/auth/index.js +329 -0
- package/apps/runtime/dist/auth/keys.js +55 -0
- package/apps/runtime/dist/auth/local-ticket.js +23 -0
- package/apps/runtime/dist/authoring/example.js +73 -0
- package/apps/runtime/dist/authoring/guide.js +259 -0
- package/apps/runtime/dist/authoring/ops.js +117 -0
- package/apps/runtime/dist/cli/autostart.js +134 -0
- package/apps/runtime/dist/cli/clients.js +44 -0
- package/apps/runtime/dist/cli/environment.js +81 -0
- package/apps/runtime/dist/cli/exec.js +45 -0
- package/apps/runtime/dist/cli/home.js +74 -0
- package/apps/runtime/dist/cli/machine.js +145 -0
- package/apps/runtime/dist/cli/main.js +125 -0
- package/apps/runtime/dist/cli/setup.js +273 -0
- package/apps/runtime/dist/cli/start.js +190 -0
- package/apps/runtime/dist/cli/status.js +120 -0
- package/apps/runtime/dist/cli/ui.js +12 -0
- package/apps/runtime/dist/cli/update.js +58 -0
- package/apps/runtime/dist/connectors/builtin.js +70 -0
- package/apps/runtime/dist/connectors/external.js +400 -0
- package/apps/runtime/dist/connectors/gmail.js +107 -0
- package/apps/runtime/dist/connectors/imap.js +217 -0
- package/apps/runtime/dist/connectors/index.js +266 -0
- package/apps/runtime/dist/connectors/mail.js +72 -0
- package/apps/runtime/dist/connectors/outlook.js +90 -0
- package/apps/runtime/dist/credits/credits.js +103 -0
- package/apps/runtime/dist/credits/estimate.js +132 -0
- package/apps/runtime/dist/db/adopt.js +149 -0
- package/apps/runtime/dist/db/client.js +146 -0
- package/apps/runtime/dist/db/control-schema.js +70 -0
- package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
- package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
- package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
- package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
- package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
- package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
- package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
- package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
- package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/schema.js +278 -0
- package/apps/runtime/dist/documents/parse.js +230 -0
- package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
- package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
- package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
- package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
- package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
- package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
- package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
- package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
- package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
- package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +359 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
- package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
- package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
- package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
- package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
- package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
- package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
- package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +464 -0
- package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
- package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
- package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
- package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
- package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
- package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
- package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
- package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
- package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
- package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
- package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
- package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
- package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
- package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
- package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
- package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
- package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
- package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
- package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
- package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
- package/apps/runtime/dist/engenty/shims/web-ingest.js +3 -0
- package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
- package/apps/runtime/dist/engine/asks.js +60 -0
- package/apps/runtime/dist/engine/events.js +46 -0
- package/apps/runtime/dist/engine/input.js +170 -0
- package/apps/runtime/dist/engine/prepare.js +51 -0
- package/apps/runtime/dist/engine/requirements.js +124 -0
- package/apps/runtime/dist/engine/resources.js +89 -0
- package/apps/runtime/dist/engine/runner.js +560 -0
- package/apps/runtime/dist/engine/steps.js +598 -0
- package/apps/runtime/dist/engine/template.js +183 -0
- package/apps/runtime/dist/engine/types.js +3 -0
- package/apps/runtime/dist/env.js +224 -0
- package/apps/runtime/dist/files/blobs.js +22 -0
- package/apps/runtime/dist/files/objects.js +86 -0
- package/apps/runtime/dist/files/storage.js +95 -0
- package/apps/runtime/dist/geocode.js +58 -0
- package/apps/runtime/dist/harness/claude.js +138 -0
- package/apps/runtime/dist/harness/codex.js +228 -0
- package/apps/runtime/dist/harness/cursor.js +93 -0
- package/apps/runtime/dist/harness/env.js +124 -0
- package/apps/runtime/dist/harness/gemini.js +126 -0
- package/apps/runtime/dist/harness/index.js +99 -0
- package/apps/runtime/dist/harness/model.js +267 -0
- package/apps/runtime/dist/harness/prompt.js +121 -0
- package/apps/runtime/dist/harness/terminal.js +193 -0
- package/apps/runtime/dist/harness/types.js +7 -0
- package/apps/runtime/dist/index.js +76 -0
- package/apps/runtime/dist/limits.js +57 -0
- package/apps/runtime/dist/link-preview.js +59 -0
- package/apps/runtime/dist/manage.js +151 -0
- package/apps/runtime/dist/mcp/auth.js +102 -0
- package/apps/runtime/dist/mcp/bridge.js +59 -0
- package/apps/runtime/dist/mcp/handler.js +42 -0
- package/apps/runtime/dist/mcp/scopes.js +5 -0
- package/apps/runtime/dist/mcp/tools.js +401 -0
- package/apps/runtime/dist/media/ffmpeg.js +121 -0
- package/apps/runtime/dist/media/generate.js +120 -0
- package/apps/runtime/dist/media/marking.js +121 -0
- package/apps/runtime/dist/media/transcribe.js +30 -0
- package/apps/runtime/dist/model-errors.js +3 -0
- package/apps/runtime/dist/models.js +489 -0
- package/apps/runtime/dist/plugin.js +61 -0
- package/apps/runtime/dist/render/chromium.js +85 -0
- package/apps/runtime/dist/render/convert.js +161 -0
- package/apps/runtime/dist/render/downloads.js +277 -0
- package/apps/runtime/dist/render/guard.js +25 -0
- package/apps/runtime/dist/routes/api.js +74 -0
- package/apps/runtime/dist/routes/delivery.js +52 -0
- package/apps/runtime/dist/routes/internal.js +49 -0
- package/apps/runtime/dist/routes/marketplace.js +36 -0
- package/apps/runtime/dist/routes/runs.js +805 -0
- package/apps/runtime/dist/routes/studio.js +702 -0
- package/apps/runtime/dist/routes/wizard-stream.js +30 -0
- package/apps/runtime/dist/running.js +39 -0
- package/apps/runtime/dist/sandbox/agentos.js +191 -0
- package/apps/runtime/dist/sandbox/docker.js +77 -0
- package/apps/runtime/dist/sandbox/index.js +30 -0
- package/apps/runtime/dist/sandbox/types.js +1 -0
- package/apps/runtime/dist/secrets/crypto.js +28 -0
- package/apps/runtime/dist/secrets/signing.js +34 -0
- package/apps/runtime/dist/secrets/vault.js +59 -0
- package/apps/runtime/dist/services/architect.js +92 -0
- package/apps/runtime/dist/services/brand.js +20 -0
- package/apps/runtime/dist/services/cloud.js +52 -0
- package/apps/runtime/dist/services/draft-events.js +27 -0
- package/apps/runtime/dist/services/errors.js +24 -0
- package/apps/runtime/dist/services/files.js +129 -0
- package/apps/runtime/dist/services/links.js +16 -0
- package/apps/runtime/dist/services/marketplace.js +292 -0
- package/apps/runtime/dist/services/package.js +202 -0
- package/apps/runtime/dist/services/profile.js +23 -0
- package/apps/runtime/dist/services/project-files.js +266 -0
- package/apps/runtime/dist/services/project-index.js +109 -0
- package/apps/runtime/dist/services/projects.js +181 -0
- package/apps/runtime/dist/services/runs.js +224 -0
- package/apps/runtime/dist/services/shares.js +129 -0
- package/apps/runtime/dist/services/widgets.js +34 -0
- package/apps/runtime/dist/services/wizards.js +342 -0
- package/apps/runtime/dist/settings.js +16 -0
- package/apps/runtime/dist/store/index.js +279 -0
- package/apps/runtime/dist/tenants/control.js +106 -0
- package/apps/runtime/dist/tenants/tenant.js +26 -0
- package/apps/runtime/dist/tools/browser.js +380 -0
- package/apps/runtime/dist/tools/connector.js +204 -0
- package/apps/runtime/dist/tools/index.js +234 -0
- package/apps/runtime/dist/tools/mail.js +104 -0
- package/apps/runtime/dist/tools/net-guard.js +59 -0
- package/apps/runtime/dist/tools/project.js +53 -0
- package/apps/runtime/dist/tools/shared.js +42 -0
- package/apps/runtime/dist/tools/store.js +238 -0
- package/apps/runtime/dist/update.js +118 -0
- package/apps/runtime/dist/widgets/bundle.js +99 -0
- package/apps/runtime/dist/widgets/render.js +312 -0
- package/apps/runtime/dist/widgets/runtime.js +84 -0
- package/apps/runtime/dist/widgets/script.js +30 -0
- package/apps/runtime/dist/widgets/step.js +192 -0
- package/apps/web/dist/ai-labels/ai-black.svg +20 -0
- package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
- package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
- package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
- package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
- package/apps/web/dist/ai-labels/ai-white.svg +21 -0
- package/apps/web/dist/assets/ChangelogDialog-O00vEnbm.js +1 -0
- package/apps/web/dist/assets/ChatPanel-CH9ry0Hp.js +1 -0
- package/apps/web/dist/assets/CreditsDialog-DRzecwUw.js +1 -0
- package/apps/web/dist/assets/EditorPage-BRnBf02Q.js +2 -0
- package/apps/web/dist/assets/FlowPreview-DDOj8IAH.js +1 -0
- package/apps/web/dist/assets/HomePage-CAGTTG3N.js +1 -0
- package/apps/web/dist/assets/ImportWizard-0RRrAnX3.js +1 -0
- package/apps/web/dist/assets/LocalRuntime-BrP-ENHg.css +1 -0
- package/apps/web/dist/assets/LocalRuntime-C-TBYrzs.js +16 -0
- package/apps/web/dist/assets/NewWizardPage-kI90h3_9.js +2 -0
- package/apps/web/dist/assets/PublicRunner-CKRDeIVd.js +1 -0
- package/apps/web/dist/assets/RunnerView-Rc4H8wYH.js +2 -0
- package/apps/web/dist/assets/SettingsPage-CESMuZxq.js +2 -0
- package/apps/web/dist/assets/SetupPage-D1rrYU14.js +1 -0
- package/apps/web/dist/assets/SharePage-COTAmOgh.js +1 -0
- package/apps/web/dist/assets/api-BY28cjGY.js +10 -0
- package/apps/web/dist/assets/arrow-left-UpjOBfQp.js +1 -0
- package/apps/web/dist/assets/arrow-right-CucQycEy.js +1 -0
- package/apps/web/dist/assets/changelog-p3wsaDDS.js +1 -0
- package/apps/web/dist/assets/check-Bjx41xbB.js +1 -0
- package/apps/web/dist/assets/createLucideIcon-DBu2Ovxj.js +1 -0
- package/apps/web/dist/assets/definition-cy7uvY5L.js +55 -0
- package/apps/web/dist/assets/engenty-CWIFpgKq.js +1 -0
- package/apps/web/dist/assets/esm-D1OEhjTK.js +7 -0
- package/apps/web/dist/assets/external-link-CRg6DVdO.js +1 -0
- package/apps/web/dist/assets/fluffy-engenty-CJ3wCQgT.js +456 -0
- package/apps/web/dist/assets/index-CQ_q9iMO.css +1 -0
- package/apps/web/dist/assets/index-D0gxh90t.js +10 -0
- package/apps/web/dist/assets/jsx-runtime-Dk72oS4N.js +1 -0
- package/apps/web/dist/assets/meta-BbSdtTUa.js +1 -0
- package/apps/web/dist/assets/mic-CeqQ89Dj.js +1 -0
- package/apps/web/dist/assets/oss-credits-cPuZUFHD.js +1 -0
- package/apps/web/dist/assets/outputs-D6pxH6ve.js +69 -0
- package/apps/web/dist/assets/plus-HA210wXA.js +1 -0
- package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
- package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
- package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
- package/apps/web/dist/assets/type-BzYgVWKL.js +1 -0
- package/apps/web/dist/assets/ui-Ddwl35A6.js +1 -0
- package/apps/web/dist/assets/upload-DsgLfQ3U.js +1 -0
- package/apps/web/dist/assets/video-Dk1fuTDl.js +1 -0
- package/apps/web/dist/assets/wand-sparkles-Bf97fs8T.js +1 -0
- package/apps/web/dist/embed.js +102 -0
- package/apps/web/dist/favicon.svg +1 -0
- package/apps/web/dist/icons/apple-touch-icon.png +0 -0
- package/apps/web/dist/icons/icon-192.png +0 -0
- package/apps/web/dist/icons/icon-512.png +0 -0
- package/apps/web/dist/icons/icon-maskable-512.png +0 -0
- package/apps/web/dist/index.html +46 -0
- package/apps/web/dist/install.sh +532 -0
- package/apps/web/dist/manifest.webmanifest +20 -0
- package/apps/web/dist/sw.js +15 -0
- package/bin/wizards.mjs +13 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +1415 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.js +762 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +216 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +86 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +133 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +298 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +211 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +74 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.js +96 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +219 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +1 -0
- package/node_modules/@engenty-wizards/shared/dist/store.d.ts +100 -0
- package/node_modules/@engenty-wizards/shared/dist/store.js +44 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
- package/node_modules/@engenty-wizards/shared/package.json +10 -0
- package/package.json +62 -0
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/.mcp.json +8 -0
- package/plugin/commands/wizard.md +8 -0
- package/plugin/skills/build-wizard/SKILL.md +27 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { createServer } from "node:net";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
import { styleText } from "node:util";
|
|
7
|
+
import { mintLocalTicket } from "../auth/local-ticket.js";
|
|
8
|
+
import { readRunning } from "../running.js";
|
|
9
|
+
import { RESTART_EXIT } from "../update.js";
|
|
10
|
+
import { runtimeEnv } from "./environment.js";
|
|
11
|
+
import { packageRoot, readEnvFile } from "./home.js";
|
|
12
|
+
import { findOnPath } from "./machine.js";
|
|
13
|
+
const DEFAULT_PORT = 24368;
|
|
14
|
+
const START_TIMEOUT_MS = 60_000;
|
|
15
|
+
/** The settings this install starts with: its `.env`, overridden by the terminal's variables. */
|
|
16
|
+
export function settings(paths, env = process.env) {
|
|
17
|
+
const fileEnv = readEnvFile(paths.envFile);
|
|
18
|
+
const value = (key) => env[key]?.trim() || fileEnv[key]?.trim() || "";
|
|
19
|
+
return {
|
|
20
|
+
fileEnv,
|
|
21
|
+
dataDir: value("DATA_DIR") ? resolve(paths.home, value("DATA_DIR")) : paths.data,
|
|
22
|
+
port: Number(value("API_PORT")) || null,
|
|
23
|
+
appUrl: value("APP_URL").replace(/\/$/, ""),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export async function healthy(port) {
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch(`http://127.0.0.1:${port}/api/health`, {
|
|
29
|
+
signal: AbortSignal.timeout(1500),
|
|
30
|
+
});
|
|
31
|
+
return response.ok;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function portIsFree(port) {
|
|
38
|
+
return new Promise((done) => {
|
|
39
|
+
const probe = createServer();
|
|
40
|
+
probe.once("error", () => done(false));
|
|
41
|
+
probe.listen(port, "127.0.0.1", () => probe.close(() => done(true)));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** The usual port, or the next free one after it. */
|
|
45
|
+
async function freePort() {
|
|
46
|
+
for (let port = DEFAULT_PORT; port < DEFAULT_PORT + 20; port++) {
|
|
47
|
+
if (await portIsFree(port)) {
|
|
48
|
+
return port;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`No free port between ${DEFAULT_PORT} and ${DEFAULT_PORT + 19}.`);
|
|
52
|
+
}
|
|
53
|
+
/** The runtime that already runs on this install's data folder and answers. */
|
|
54
|
+
export async function runningRuntime(dataDir) {
|
|
55
|
+
const running = readRunning(dataDir);
|
|
56
|
+
return running && (await healthy(running.port)) ? running : null;
|
|
57
|
+
}
|
|
58
|
+
/** A link that lets this browser into a running runtime: a ticket signed with the data folder's secret. */
|
|
59
|
+
export function entryUrl(running, dataDir) {
|
|
60
|
+
try {
|
|
61
|
+
const secret = readFileSync(join(dataDir, "secret"), "utf8").trim();
|
|
62
|
+
return `${running.url}/api/local/enter?t=${mintLocalTicket(secret)}`;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// APP_SECRET is set elsewhere: the browser gets in if it was let in before.
|
|
66
|
+
return `${running.url}/`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Opens an address in the person's browser; false when this machine has none to open it with. */
|
|
70
|
+
export function openBrowser(url) {
|
|
71
|
+
const opener = process.platform === "darwin"
|
|
72
|
+
? "open"
|
|
73
|
+
: process.env.DISPLAY || process.env.WAYLAND_DISPLAY
|
|
74
|
+
? "xdg-open"
|
|
75
|
+
: null;
|
|
76
|
+
if (!opener || !findOnPath(opener, process.env.PATH ?? "")) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
spawn(opener, [url], { stdio: "ignore", detached: true }).unref();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function show(url, entry, open) {
|
|
88
|
+
const opened = open && openBrowser(entry);
|
|
89
|
+
console.log("");
|
|
90
|
+
console.log(` ${styleText("green", "●")} engenty wizards is running: ${styleText("cyan", url)}`);
|
|
91
|
+
if (opened) {
|
|
92
|
+
console.log(styleText("dim", " The studio opens in your browser."));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log(` Open the studio: ${entry}`);
|
|
96
|
+
console.log(styleText("dim", " The link lets one browser in and works once."));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Starts the runtime of this install in the foreground and opens the studio. If one already
|
|
101
|
+
* runs on the same data folder (another terminal, the desktop app), that one is opened instead.
|
|
102
|
+
*/
|
|
103
|
+
export async function start(paths, options) {
|
|
104
|
+
const { fileEnv, dataDir, port: wanted, appUrl } = settings(paths);
|
|
105
|
+
mkdirSync(dataDir, { recursive: true });
|
|
106
|
+
mkdirSync(paths.logs, { recursive: true });
|
|
107
|
+
const running = await runningRuntime(dataDir);
|
|
108
|
+
if (running) {
|
|
109
|
+
show(running.url, entryUrl(running, dataDir), options.open);
|
|
110
|
+
console.log(styleText("dim", " It was already running; stop it with `wizards stop`."));
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
const port = wanted ?? (await freePort());
|
|
114
|
+
if (!wanted && port !== DEFAULT_PORT) {
|
|
115
|
+
console.log(styleText("dim", ` Port ${DEFAULT_PORT} is taken, using ${port}.`));
|
|
116
|
+
}
|
|
117
|
+
const accessKey = randomBytes(24).toString("hex");
|
|
118
|
+
const url = appUrl || `http://localhost:${port}`;
|
|
119
|
+
const child = spawn(process.execPath, [join(packageRoot, "apps/runtime/dist/index.js")], {
|
|
120
|
+
cwd: paths.home,
|
|
121
|
+
env: {
|
|
122
|
+
...runtimeEnv(paths, { port, url, dataDir, accessKey }, process.env, fileEnv),
|
|
123
|
+
// This command starts it again when it exits with RESTART_EXIT.
|
|
124
|
+
ENGENTY_WIZARDS_RESTARTS: "1",
|
|
125
|
+
},
|
|
126
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
127
|
+
});
|
|
128
|
+
let current = child;
|
|
129
|
+
let exited = null;
|
|
130
|
+
const ended = new Promise((done) => {
|
|
131
|
+
child.on("error", (error) => {
|
|
132
|
+
console.error(`The runtime did not start: ${error.message}`);
|
|
133
|
+
exited = 1;
|
|
134
|
+
done(1);
|
|
135
|
+
});
|
|
136
|
+
child.on("exit", (code, signal) => {
|
|
137
|
+
exited = code ?? (signal ? 0 : 1);
|
|
138
|
+
done(exited);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// Ctrl-C reaches the runtime as well (same terminal); it closes its browser and its databases.
|
|
142
|
+
process.on("SIGINT", () => undefined);
|
|
143
|
+
process.on("SIGTERM", () => current.kill("SIGTERM"));
|
|
144
|
+
const began = Date.now();
|
|
145
|
+
while (exited === null && !(await healthy(port))) {
|
|
146
|
+
if (Date.now() - began > START_TIMEOUT_MS) {
|
|
147
|
+
child.kill("SIGTERM");
|
|
148
|
+
console.error("The runtime did not answer within 60 seconds.");
|
|
149
|
+
return 1;
|
|
150
|
+
}
|
|
151
|
+
await new Promise((wait) => setTimeout(wait, 150));
|
|
152
|
+
}
|
|
153
|
+
if (exited !== null) {
|
|
154
|
+
return exited || 1;
|
|
155
|
+
}
|
|
156
|
+
show(url, `${url}/api/local/enter?k=${accessKey}`, options.open);
|
|
157
|
+
console.log(styleText("dim", " Stop it with Ctrl-C."));
|
|
158
|
+
console.log("");
|
|
159
|
+
const code = await ended;
|
|
160
|
+
if (code !== RESTART_EXIT) {
|
|
161
|
+
return code;
|
|
162
|
+
}
|
|
163
|
+
// Updated: the command as it is on disk now starts the new version, in this terminal or
|
|
164
|
+
// under the login item, which keeps waiting on this process.
|
|
165
|
+
console.log(styleText("dim", " Updated; starting the new version."));
|
|
166
|
+
const wrapper = join(paths.bin, "wizards");
|
|
167
|
+
current = existsSync(wrapper)
|
|
168
|
+
? spawn(wrapper, ["start", "--no-open"], { stdio: "inherit" })
|
|
169
|
+
: spawn(process.execPath, [join(packageRoot, "bin/wizards.mjs"), "start", "--no-open"], {
|
|
170
|
+
stdio: "inherit",
|
|
171
|
+
});
|
|
172
|
+
return new Promise((done) => {
|
|
173
|
+
current.on("error", () => done(1));
|
|
174
|
+
current.on("exit", (exit) => done(exit ?? 0));
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/** `wizards open`: lets the browser into the runtime that runs. */
|
|
178
|
+
export async function open(paths, print) {
|
|
179
|
+
const { dataDir } = settings(paths);
|
|
180
|
+
const running = await runningRuntime(dataDir);
|
|
181
|
+
if (!running) {
|
|
182
|
+
console.error("engenty wizards is not running. Start it with `wizards`.");
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
const entry = entryUrl(running, dataDir);
|
|
186
|
+
if (print || !openBrowser(entry)) {
|
|
187
|
+
console.log(entry);
|
|
188
|
+
}
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { accessSync, constants, existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { autostartState, setAutostart } from "./autostart.js";
|
|
4
|
+
import { installedByScript, isCheckout, packageRoot, packageVersion } from "./home.js";
|
|
5
|
+
import { detectClients, findChrome, findFfmpeg, nodeIsCurrent } from "./machine.js";
|
|
6
|
+
import { runningRuntime, settings } from "./start.js";
|
|
7
|
+
import { bad, badge, cyan, dim, no, ok, tilde } from "./ui.js";
|
|
8
|
+
/**
|
|
9
|
+
* What is installed and what runs. With `checks` (`doctor`) it also says what is wrong and
|
|
10
|
+
* returns 1 when something is.
|
|
11
|
+
*/
|
|
12
|
+
export async function status(paths, checks) {
|
|
13
|
+
const { dataDir } = settings(paths);
|
|
14
|
+
const [running, clients, ffmpeg, atLogin] = await Promise.all([
|
|
15
|
+
runningRuntime(dataDir),
|
|
16
|
+
detectClients(paths),
|
|
17
|
+
findFfmpeg(),
|
|
18
|
+
autostartState(paths),
|
|
19
|
+
]);
|
|
20
|
+
const chrome = findChrome();
|
|
21
|
+
const row = (label, value) => console.log(` ${label.padEnd(9)} ${value}`);
|
|
22
|
+
console.log(`\n${badge("engenty wizards")} ${dim(packageVersion())}\n`);
|
|
23
|
+
row("Install", installedByScript()
|
|
24
|
+
? tilde(paths.home)
|
|
25
|
+
: `${tilde(packageRoot)} ${dim(isCheckout() ? "(a checkout)" : "(npm)")}`);
|
|
26
|
+
row("Data", tilde(dataDir));
|
|
27
|
+
row("Node", `${process.version} ${dim(tilde(process.execPath))}`);
|
|
28
|
+
row("Running", running
|
|
29
|
+
? `${ok} ${cyan(running.url)} ${dim(`pid ${running.pid}, since ${running.startedAt}`)}`
|
|
30
|
+
: `${no} not running`);
|
|
31
|
+
if (!("unavailable" in atLogin)) {
|
|
32
|
+
row("At login", atLogin.on ? `${ok} starts ${dim(`(${atLogin.how})`)}` : `${no} does not start`);
|
|
33
|
+
}
|
|
34
|
+
for (const { client, path, version } of clients) {
|
|
35
|
+
row(client.name.split(" ")[0], path ? `${ok} ${version} ${dim(tilde(path))}` : `${no} not installed`);
|
|
36
|
+
}
|
|
37
|
+
row("Browser", chrome ? `${ok} ${dim(tilde(chrome))}` : `${no} none for PDF and PNG`);
|
|
38
|
+
row("ffmpeg", ffmpeg.path ? `${ok} ${ffmpeg.version ?? ""}` : `${no} none for MP4`);
|
|
39
|
+
console.log("");
|
|
40
|
+
if (!checks) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const problems = [];
|
|
44
|
+
if (!nodeIsCurrent()) {
|
|
45
|
+
problems.push(`Node ${process.version} is too old: 24.11 or newer is needed.`);
|
|
46
|
+
}
|
|
47
|
+
for (const part of ["apps/runtime/dist/index.js", "apps/web/dist/index.html", "plugin"]) {
|
|
48
|
+
if (!existsSync(join(packageRoot, part))) {
|
|
49
|
+
problems.push(`${part} is missing from this install (${tilde(packageRoot)}).`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
mkdirSync(paths.home, { recursive: true });
|
|
54
|
+
accessSync(paths.home, constants.W_OK);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
problems.push(`${tilde(paths.home)} cannot be written to.`);
|
|
58
|
+
}
|
|
59
|
+
if (!clients.some((state) => state.path)) {
|
|
60
|
+
console.log(` ${no} No AI client: the studio needs an API key or Ollama instead. ${dim("`setup` installs one.")}`);
|
|
61
|
+
}
|
|
62
|
+
for (const problem of problems) {
|
|
63
|
+
console.log(` ${bad} ${problem}`);
|
|
64
|
+
}
|
|
65
|
+
if (!problems.length) {
|
|
66
|
+
console.log(` ${ok} Nothing wrong with this install.`);
|
|
67
|
+
}
|
|
68
|
+
console.log("");
|
|
69
|
+
return problems.length ? 1 : 0;
|
|
70
|
+
}
|
|
71
|
+
/** Stops the runtime that runs on this install's data folder. */
|
|
72
|
+
export async function stop(paths) {
|
|
73
|
+
const { dataDir } = settings(paths);
|
|
74
|
+
const running = await runningRuntime(dataDir);
|
|
75
|
+
if (!running) {
|
|
76
|
+
console.log("engenty wizards is not running.");
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
process.kill(running.pid, "SIGTERM");
|
|
80
|
+
for (let waited = 0; waited < 8000; waited += 100) {
|
|
81
|
+
try {
|
|
82
|
+
process.kill(running.pid, 0);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
console.log(`Stopped (pid ${running.pid}). Your data is kept.`);
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
await new Promise((wait) => setTimeout(wait, 100));
|
|
89
|
+
}
|
|
90
|
+
console.error(`The runtime (pid ${running.pid}) did not stop within 8 seconds.`);
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
/** `autostart [on|off]`: whether it starts at login, and the switch. */
|
|
94
|
+
export async function autostart(paths, value) {
|
|
95
|
+
if (value && value !== "on" && value !== "off") {
|
|
96
|
+
console.error("autostart takes on or off.");
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
let state = await autostartState(paths);
|
|
100
|
+
if (value && !("unavailable" in state)) {
|
|
101
|
+
try {
|
|
102
|
+
state = await setAutostart(paths, value === "on");
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error(`Starting at login could not be switched ${value}: ${error.message}`);
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if ("unavailable" in state) {
|
|
110
|
+
console.error(`Starting at login is not possible here: ${state.unavailable}.`);
|
|
111
|
+
return value ? 1 : 0;
|
|
112
|
+
}
|
|
113
|
+
console.log(state.on
|
|
114
|
+
? `${ok} engenty wizards starts at login: ${state.how}.`
|
|
115
|
+
: `${no} engenty wizards does not start at login. ${dim("`autostart on` switches it on.")}`);
|
|
116
|
+
if (state.on && process.platform === "linux") {
|
|
117
|
+
console.log(dim(" Before anybody logs in, too: loginctl enable-linger"));
|
|
118
|
+
}
|
|
119
|
+
return value && state.on !== (value === "on") ? 1 : 0;
|
|
120
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
|
+
const colours = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
4
|
+
/** The name on engenty's orange. */
|
|
5
|
+
export const badge = (text) => colours ? `\x1b[48;2;224;83;27m\x1b[97m\x1b[1m ${text} \x1b[0m` : text;
|
|
6
|
+
export const dim = (text) => styleText("dim", text);
|
|
7
|
+
export const cyan = (text) => styleText("cyan", text);
|
|
8
|
+
export const ok = styleText("green", "✓");
|
|
9
|
+
export const no = styleText("yellow", "–");
|
|
10
|
+
export const bad = styleText("red", "✗");
|
|
11
|
+
/** A path as the person would write it. */
|
|
12
|
+
export const tilde = (path) => path.startsWith(homedir()) ? `~${path.slice(homedir().length)}` : path;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { installedByScript, isCheckout } from "./home.js";
|
|
5
|
+
import { runningRuntime, settings } from "./start.js";
|
|
6
|
+
import { cyan } from "./ui.js";
|
|
7
|
+
/** The installer this install was made with; it also updates one. */
|
|
8
|
+
const INSTALLER = "https://engenty.ai/install.sh";
|
|
9
|
+
async function installer(into) {
|
|
10
|
+
const source = process.env.ENGENTY_WIZARDS_INSTALLER?.trim() || INSTALLER;
|
|
11
|
+
if (!/^https?:\/\//.test(source)) {
|
|
12
|
+
return source;
|
|
13
|
+
}
|
|
14
|
+
const response = await fetch(source);
|
|
15
|
+
const text = response.ok ? await response.text() : "";
|
|
16
|
+
// The address answers with the studio's page while a server has no installer yet.
|
|
17
|
+
if (!text.startsWith("#!")) {
|
|
18
|
+
throw new Error(`${source} did not answer with the installer.`);
|
|
19
|
+
}
|
|
20
|
+
const file = join(into, "install.sh");
|
|
21
|
+
writeFileSync(file, text, { mode: 0o700 });
|
|
22
|
+
return file;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Brings an install made by install.sh to the newest version by running the installer again
|
|
26
|
+
* without its questions: Node, the runtime and the command.
|
|
27
|
+
*/
|
|
28
|
+
export async function update(paths) {
|
|
29
|
+
if (!installedByScript(paths)) {
|
|
30
|
+
console.log(isCheckout()
|
|
31
|
+
? `This copy is a checkout. The newest version: ${cyan("git pull && pnpm install && pnpm build")}`
|
|
32
|
+
: `This copy runs from npm. The newest version: ${cyan("npx wizards@latest")}`);
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
const tmp = mkdtempSync(join(paths.home, "update-"));
|
|
36
|
+
try {
|
|
37
|
+
const script = await installer(tmp);
|
|
38
|
+
const code = await new Promise((done) => {
|
|
39
|
+
const child = spawn("bash", [script, "--no-setup"], { stdio: "inherit" });
|
|
40
|
+
child.on("error", () => done(127));
|
|
41
|
+
child.on("exit", (exit) => done(exit ?? 1));
|
|
42
|
+
});
|
|
43
|
+
if (code !== 0) {
|
|
44
|
+
return code;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(error.message);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
if (await runningRuntime(settings(paths).dataDir)) {
|
|
55
|
+
console.log(` The runtime that is running is still the old one. Restart it: ${cyan("wizards stop")}, then ${cyan("wizards")}.`);
|
|
56
|
+
}
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createGuardedFetch } from "../engenty/connections-external/net/guarded-fetch.js";
|
|
2
|
+
import { githubConnector } from "../engenty/connections-github/connector.js";
|
|
3
|
+
import { googleConnectors } from "../engenty/connections-google/definitions.js";
|
|
4
|
+
import { hubspotConnector } from "../engenty/connections-hubspot/connector.js";
|
|
5
|
+
import { microsoftOneDriveConnector } from "../engenty/connections-microsoft/onedrive.js";
|
|
6
|
+
import { microsoftOutlookConnector } from "../engenty/connections-microsoft/outlook.js";
|
|
7
|
+
import { s3Connector } from "../engenty/connections-s3/s3.js";
|
|
8
|
+
import { hasOAuth2ClientCredentials, } from "../engenty/connections-sdk/oauth2.js";
|
|
9
|
+
import { registerConnectorDefinition } from "../engenty/connections-sdk/registry.js";
|
|
10
|
+
import { slackConnector } from "../engenty/connections-slack/connector.js";
|
|
11
|
+
import { gmailConnector as mailGmail } from "./gmail.js";
|
|
12
|
+
import { imapConnector } from "./imap.js";
|
|
13
|
+
import { outlookConnector as mailOutlook } from "./outlook.js";
|
|
14
|
+
/**
|
|
15
|
+
* engenty's own connectors, as engenty ships them: Gmail, Drive, Calendar, Contacts, Outlook,
|
|
16
|
+
* OneDrive, Slack, GitHub, HubSpot, S3. Every project has them; an OAuth one can be connected
|
|
17
|
+
* once its client is configured.
|
|
18
|
+
*/
|
|
19
|
+
export const BUILTIN_CONNECTORS = [
|
|
20
|
+
...googleConnectors,
|
|
21
|
+
microsoftOutlookConnector,
|
|
22
|
+
microsoftOneDriveConnector,
|
|
23
|
+
slackConnector,
|
|
24
|
+
githubConnector,
|
|
25
|
+
hubspotConnector,
|
|
26
|
+
s3Connector,
|
|
27
|
+
];
|
|
28
|
+
/** The connectors behind a connection of kind "mail": one read-only shape for any mailbox. */
|
|
29
|
+
export const MAIL_CONNECTORS = [mailGmail, mailOutlook, imapConnector];
|
|
30
|
+
// One registry for all of them, so an imported connector can never take a built-in's id.
|
|
31
|
+
for (const connector of [...BUILTIN_CONNECTORS, ...MAIL_CONNECTORS]) {
|
|
32
|
+
registerConnectorDefinition(connector);
|
|
33
|
+
}
|
|
34
|
+
export function builtinConnector(id) {
|
|
35
|
+
return BUILTIN_CONNECTORS.find((c) => c.id === id);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* engenty names OAuth clients `<VENDOR>_OAUTH_CLIENT_ID`. Google and Microsoft allow one client
|
|
39
|
+
* several redirect addresses, so the client this product signs people in with (`<VENDOR>_CLIENT_ID`)
|
|
40
|
+
* serves connections too. GitHub and Slack tie a client to one address: they need their own.
|
|
41
|
+
*/
|
|
42
|
+
export const resolveEnv = async (key) => {
|
|
43
|
+
const own = process.env[key]?.trim();
|
|
44
|
+
if (own || !/^(GOOGLE|MICROSOFT)_OAUTH_/.test(key)) {
|
|
45
|
+
return own || undefined;
|
|
46
|
+
}
|
|
47
|
+
return process.env[key.replace("_OAUTH_", "_")]?.trim() || undefined;
|
|
48
|
+
};
|
|
49
|
+
/** Whether a person can connect an account with this connector right now. */
|
|
50
|
+
export async function usable(connector) {
|
|
51
|
+
if (connector.auth.kind !== "oauth2") {
|
|
52
|
+
return connector.auth.kind === "api_key";
|
|
53
|
+
}
|
|
54
|
+
// A connector that registers its own OAuth client needs none configured.
|
|
55
|
+
return (connector.auth.oauth2.dynamicClientRegistration === true ||
|
|
56
|
+
hasOAuth2ClientCredentials(connector.auth.oauth2, resolveEnv));
|
|
57
|
+
}
|
|
58
|
+
/** What the server's owner has to set for an OAuth connector that is not usable yet. */
|
|
59
|
+
export function missingSetup(connector) {
|
|
60
|
+
if (connector.auth.kind !== "oauth2") {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const { clientIdEnv, clientSecretEnv } = connector.auth.oauth2;
|
|
64
|
+
return clientIdEnv && clientSecretEnv ? `${clientIdEnv}, ${clientSecretEnv}` : null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Connector actions reach addresses that come from a person or a spec (an S3 endpoint, an API's
|
|
68
|
+
* base URL): every request is checked to stay on the public internet.
|
|
69
|
+
*/
|
|
70
|
+
export const connectorFetch = createGuardedFetch();
|