@keystrokehq/cli 0.0.11 → 0.0.13
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/{accept.handler-DWuxmMuY.mjs → accept.handler-BU6kg8ET.mjs} +1 -1
- package/dist/{admin-BK4bFTTd.mjs → admin-B4GNbCl5.mjs} +9 -9
- package/dist/{agent-manifest-sJFbH5H8.mjs → agent-manifest-CZdlCTFs.mjs} +5 -5
- package/dist/{agents-DYnw2VPX.mjs → agents-LtoIcJGY.mjs} +6 -6
- package/dist/api-DuKKdCpF.mjs +246 -0
- package/dist/{api-keys-Dizx3YqE.mjs → api-keys-BE_hLonn.mjs} +5 -5
- package/dist/{auth-BqsKd4IA.mjs → auth-DNK5MYm4.mjs} +5 -5
- package/dist/{auth.handler-BsoWeCFD.mjs → auth.handler-DrjDODhZ.mjs} +1 -1
- package/dist/{build-agents-DfbiMZ_e-CgnKa9A6.mjs → build-agents-DseUtzd4-DIDGsZWL.mjs} +12 -13
- package/dist/{build-metadata-zidV9Cai-Bq37kBOM.mjs → build-metadata-qebrtraZ-D4SQNsBw.mjs} +19 -35
- package/dist/{build-progress-DigAP-BN.mjs → build-progress-CITED2tv.mjs} +1 -1
- package/dist/{build-tasks-O1jYtlv1-Bkw0w1r3.mjs → build-tasks-GVuMLS0h-DnS9QWzf.mjs} +4 -4
- package/dist/{build-workflows-3fdvdHHf-BDTy9QgT.mjs → build-workflows-Dmzay1vP-DKVuBAjD.mjs} +17 -18
- package/dist/{build.handler-B2UDhh72.mjs → build.handler-BZnLQt0_.mjs} +4 -4
- package/dist/{clear.handler-BR97yudD.mjs → clear.handler-B1c17nAi.mjs} +1 -1
- package/dist/{commander-DcftG6dX.mjs → commander-BwtBoukr.mjs} +2 -2
- package/dist/{common-B3bLe3Mk.mjs → common-BaGFkj3n.mjs} +2 -2
- package/dist/{connect-DQ4xIcyE.mjs → connect-IPcL37np.mjs} +12 -6
- package/dist/{connect.handler-CWSLgf87.mjs → connect.handler-ToY6qmMz.mjs} +74 -224
- package/dist/{context-1VgRbzr-.mjs → context-DQ4IA0yO.mjs} +1 -1
- package/dist/{create.handler-C2CkPWsy.mjs → create.handler-BAyG0PmG.mjs} +1 -1
- package/dist/credential-requirements-FtBk5JVB.mjs +250 -0
- package/dist/credentials-Bu1MBiCL.mjs +182 -0
- package/dist/{credentials-D8_AwH9o.mjs → credentials-CZiu-534.mjs} +12 -7
- package/dist/{current-deployment-workflow-B05z0EQa.mjs → current-deployment-workflow-zTmYbUjh.mjs} +5 -5
- package/dist/{current.handler-CuAtMZmm.mjs → current.handler-DA4FGfUP.mjs} +1 -1
- package/dist/{declared-credential-requirements-BtlcsEVn.mjs → declared-credential-requirements-B6h4WRv4.mjs} +5 -34
- package/dist/{delete.handler-DDY3X1Zm.mjs → delete.handler-CJcyvnUF.mjs} +1 -1
- package/dist/{deploy-B8TYutOi.mjs → deploy-BvaFgVvf.mjs} +1 -1
- package/dist/{deploy-Cn6FFnOM.mjs → deploy-DdMP-YaQ.mjs} +2 -2
- package/dist/{deploy-progress-XAfautnA.mjs → deploy-progress-CLO-yidq.mjs} +1 -1
- package/dist/{deploy.handler-D1DcAe-h.mjs → deploy.handler-Bag7rBG-.mjs} +16 -16
- package/dist/{detect-env-access-CwkOYeYM-D4o8gRZs.mjs → detect-env-access-CwkOYeYM-EmkYvbfJ.mjs} +1 -1
- package/dist/{diff.handler-BU6IewNG.mjs → diff.handler-Brgc-Ccl.mjs} +3 -3
- package/dist/{dist-DvO0q6Fo.mjs → dist-BMkNN03r.mjs} +16 -16
- package/dist/{env.handler-C6YAmHLi.mjs → env.handler-DFKzjIQT.mjs} +10 -7
- package/dist/{error-boundary-CpaVvFXk.mjs → error-boundary-B2ZKRkZI.mjs} +1 -1
- package/dist/{file-metadata-BvGM-B2v.mjs → file-metadata-Dwy9KKq_.mjs} +2 -2
- package/dist/{import-module-DDPnzlJ1-BIBSgOhK.mjs → import-module-DEI7R8Yh-Xz-KAPvB.mjs} +248 -246
- package/dist/{init-Da6_obl0.mjs → init-DhnABm3J.mjs} +2 -2
- package/dist/{init.handler-Cq2nk8DO.mjs → init.handler-QgehN8B4.mjs} +4 -4
- package/dist/{inspect.handler-D4YGryQB.mjs → inspect.handler-CMOFOb4G.mjs} +3 -3
- package/dist/{integration-catalog-DtNWaMvh.mjs → integration-catalog-BRrJIAVz.mjs} +5 -5
- package/dist/{integrations-CB_Ukq2g.mjs → integrations-7-U7nmkh.mjs} +7 -6
- package/dist/{invites-BOhuBtoq.mjs → invites-CmGmnUla.mjs} +4 -4
- package/dist/{invites.list.handler-C-Wv6E1g.mjs → invites.list.handler-CmkIf-uW.mjs} +1 -1
- package/dist/{invites.resend.handler-CI78XlQS.mjs → invites.resend.handler-FZl20yat.mjs} +1 -1
- package/dist/{invites.revoke.handler-DigAgNwB.mjs → invites.revoke.handler-D95mrfmB.mjs} +1 -1
- package/dist/keystroke.mjs +21 -21
- package/dist/{list-enrichment-Cxlq6BB9.mjs → list-enrichment-I4XQaMg0.mjs} +5 -1
- package/dist/{list.handler-OiLEylzS.mjs → list.handler-BrTW2viq.mjs} +1 -1
- package/dist/{list.handler-CsODcH6e.mjs → list.handler-Cp767f5l.mjs} +1 -1
- package/dist/{list.handler-BsyGhXns.mjs → list.handler-DRnHsEa0.mjs} +1 -1
- package/dist/{list.handler-B6IByHHB.mjs → list.handler-DXl8igi2.mjs} +13 -5
- package/dist/{list.handler-BpVNYShU.mjs → list.handler-DsYyTUhA.mjs} +1 -1
- package/dist/{list.handler--a1JEGSD.mjs → list.handler-H8aQSsFM.mjs} +3 -3
- package/dist/{list.handler-Dr9Ti-dt.mjs → list.handler-uzC77oIy.mjs} +3 -3
- package/dist/{listen-DUPk6cZC.mjs → listen-DckJq0y0.mjs} +2 -2
- package/dist/{listen.handler-B5WimrfF.mjs → listen.handler-Bf5MXKPO.mjs} +2 -2
- package/dist/{logs-C5_4lh3p.mjs → logs-D_l5BIn2.mjs} +3 -3
- package/dist/{logs.handler-CBHPwDuC.mjs → logs.handler-kYO3Uv9t.mjs} +2 -2
- package/dist/{members.add.handler-LcQJYBsu.mjs → members.add.handler-C2cppd-9.mjs} +1 -1
- package/dist/{members.invite.handler-p279O2aC.mjs → members.invite.handler-DY6kS4LN.mjs} +1 -1
- package/dist/{members.list.handler-Cjukjuot.mjs → members.list.handler-CFBG3SBw.mjs} +1 -1
- package/dist/{members.remove.handler-CzxPiQFv.mjs → members.remove.handler-LQ61_qip.mjs} +1 -1
- package/dist/{members.update.handler-CX5q86e3.mjs → members.update.handler-CqISA1mf.mjs} +1 -1
- package/dist/{normalize-path-CojS-CgQ-D_WTiHKw.mjs → normalize-path-CojS-CgQ-D5D0AIHR.mjs} +1 -1
- package/dist/{org-CnlKW-Hl.mjs → org-KQ2nD0yN.mjs} +15 -15
- package/dist/{orgs.create.handler-DRILhxdn.mjs → orgs.create.handler-Mv5CTGcG.mjs} +1 -1
- package/dist/{orgs.get.handler-Cue6stoX.mjs → orgs.get.handler-DvvOhshX.mjs} +1 -1
- package/dist/{orgs.list.handler-fuDLNI5X.mjs → orgs.list.handler-wWAg6cKg.mjs} +1 -1
- package/dist/{paused.handler-CuOVH4DZ.mjs → paused.handler-CbMkPD9e.mjs} +1 -1
- package/dist/{project-config-D9eFU8Jk.mjs → project-config-CJGSh2RQ.mjs} +4 -7
- package/dist/{projects-DN7dX6nN.mjs → projects-CWLOF5x4.mjs} +656 -3
- package/dist/{projects-DdgHbUpR.mjs → projects-CYqeKQGT.mjs} +4 -4
- package/dist/{requirements.handler-CX13XiXT.mjs → requirements.handler-CnDTBcH5.mjs} +5 -5
- package/dist/{resolve-project-C6UAOfAG.mjs → resolve-project-bVPMcs-y.mjs} +1 -1
- package/dist/{run-polling-1CTIeDea.mjs → run-polling-49w3PYAv.mjs} +3 -3
- package/dist/{run.handler-BxLH75WW.mjs → run.handler-Bma88649.mjs} +5 -5
- package/dist/{runs-lfE7r6i2.mjs → runs-HJejvQnQ.mjs} +2 -2
- package/dist/{schema-BgGlAs8a.mjs → schema-DFJiNWyd.mjs} +2 -1
- package/dist/schemas-DodkHgnS.mjs +280 -0
- package/dist/{skills-sync.handler-CntKndFm.mjs → skills-sync.handler-Cf74vKJA.mjs} +1 -1
- package/dist/{skills.command-X5zZwz2d.mjs → skills.command-KyAwBeST.mjs} +3 -3
- package/dist/{source-analysis-CHkWMC40.mjs → source-analysis-CJPymdaA.mjs} +1 -1
- package/dist/{source-analysis-DEEChuND-Csu0oOlw.mjs → source-analysis-DTnwNwKq-DoBxUDCg.mjs} +5 -5
- package/dist/{src--fCtOxNX.mjs → src-D-dFmoAF.mjs} +1 -1
- package/dist/{switch.handler-RaeKZ3ZB.mjs → switch.handler-DfsKVtR6.mjs} +1 -1
- package/dist/{sync-C89mJp7Y.mjs → sync-Bi2M_TUK.mjs} +2 -2
- package/dist/{sync.handler-BoAHHUQs.mjs → sync.handler-D6YFuVlq.mjs} +6 -6
- package/dist/{schedule-BWAI6qLx.mjs → task-BBgEvdG1.mjs} +395 -25
- package/dist/{task-target-build-D5IrHqSl.mjs → task-target-build-atWwwnSF.mjs} +8 -8
- package/dist/task-target-deploy-CRsrQTOy.mjs +4 -0
- package/dist/{task-target-deploy-Bf5i3ox1-2K0hAwzk.mjs → task-target-deploy-CZBGNC0H-BwPSfaJQ.mjs} +2 -2
- package/dist/task-target-deploy-runner.mjs +5 -5
- package/dist/{test-gPQJRkqa.mjs → test-Ctjy8mwC.mjs} +32 -144
- package/dist/{test.handler-B5GF5txS.mjs → test.handler-St9sBXyH.mjs} +1 -1
- package/dist/{trigger-artifacts-B3OCTX9K-ME6IVdUB.mjs → trigger-artifacts-RizI57RC-C-yCtEi-.mjs} +9 -9
- package/dist/{trigger-manifest-B3Gq1739.mjs → trigger-manifest-D5rnpPkA.mjs} +1 -1
- package/dist/{try-deploy.handler-dA_YGWRq.mjs → try-deploy.handler-BMcWQVST.mjs} +9 -9
- package/dist/{upgrade-xByIxaYu.mjs → upgrade-YavAf8AC.mjs} +2 -2
- package/dist/{upload.handler-BFDM6n_6.mjs → upload.handler-DemogvI1.mjs} +129 -18
- package/dist/{users.get.handler-CzaYM2bi.mjs → users.get.handler-B20PMSbl.mjs} +1 -1
- package/dist/{users.list.handler-CpOWwzBb.mjs → users.list.handler-BplFTjv3.mjs} +1 -1
- package/dist/{users.set-role.handler-BjiSNP2d.mjs → users.set-role.handler-wdmI6o3G.mjs} +1 -1
- package/dist/{utils-C_qCshBA.mjs → utils-DpEtybzI.mjs} +2 -2
- package/dist/{validate.handler-BtDSKAFY.mjs → validate.handler-DSAvNgns.mjs} +3 -3
- package/dist/{workflow-build-Z2_jkOsZ.mjs → workflow-build-Cmu1TOFu.mjs} +32 -32
- package/dist/{workflow-manifest-BfL74mjp.mjs → workflow-build-manifest-OPFqFD6f.mjs} +26 -28
- package/dist/{workflow-bundler-BzHk73PM-tt09RbIA.mjs → workflow-bundler-BzHk73PM-UJQa7Ubk.mjs} +2 -2
- package/dist/{workflows-V09d2r2H.mjs → workflows-DTlypo2t.mjs} +26 -27
- package/dist/{writer-CtvttJdP-DZJ0mZCm.mjs → writer-CtvttJdP-BfNsrheU.mjs} +5 -5
- package/package.json +11 -9
- package/dist/constants-BUgIAu2a.mjs +0 -8
- package/dist/credential-requirements-BCW8aQWS.mjs +0 -480
- package/dist/credentials-DAQfKqn0.mjs +0 -152025
- package/dist/get-intrinsic-BjqiGgLt.mjs +0 -658
- package/dist/hosted-action-dispatcher-registry-BWEtn13o.mjs +0 -126
- package/dist/schema-B-Wgo4rJ.mjs +0 -81
- package/dist/schemas-9FmGqrPT.mjs +0 -42
- package/dist/task-1qz1XNq7.mjs +0 -96
- package/dist/task-target-deploy-Bzfftyru.mjs +0 -4
- /package/dist/{agent-bundle-package-DWV6B_5q-B-qzc3zC.mjs → agent-bundle-package-DWV6B_5q-cB76j6UL.mjs} +0 -0
- /package/dist/{browser-CvuyMLhI.mjs → browser-B4K0VW8p.mjs} +0 -0
- /package/dist/{clear-cache.handler-D-wboLB6.mjs → clear-cache.handler-Dywqc7TG.mjs} +0 -0
- /package/dist/{clear.handler-BC6pz0x-.mjs → clear.handler-ui4e1CnJ.mjs} +0 -0
- /package/dist/{concurrency-gXn9Rw8x-CnBnF2cg.mjs → concurrency-gXn9Rw8x-CaI6Vtbu.mjs} +0 -0
- /package/dist/{credential-env-map-C23GV6LN.mjs → credential-env-map-D0zgoUl0.mjs} +0 -0
- /package/dist/{credential-schema-mismatch-DM9Y91jL.mjs → credential-schema-mismatch-8pqwvswO.mjs} +0 -0
- /package/dist/{diff-utils-AATn2n56.mjs → diff-utils-BoXI705D.mjs} +0 -0
- /package/dist/{layout-CXkZEsXI.mjs → layout-DRf9qUf8.mjs} +0 -0
- /package/dist/{logs.handler-ClIIOeQB.mjs → logs.handler-DxSKmDCq.mjs} +0 -0
- /package/dist/{metadata-layout-C6ed-9dl-C6Bylr_z.mjs → metadata-layout-C6ed-9dl-EF5pCtIH.mjs} +0 -0
- /package/dist/{options-CIVqkc8V.mjs → options-DFPs-tAB.mjs} +0 -0
- /package/dist/{oxc-B3KI3rf_-ghZc3xZ5.mjs → oxc-B3KI3rf_-CHDUXsus.mjs} +0 -0
- /package/dist/{read-credential-keys-77a91T8M-B0eiobOd.mjs → read-credential-keys-77a91T8M-CzXPGxdU.mjs} +0 -0
- /package/dist/{register.handler-CpP_KB2u.mjs → register.handler-D7ZZAnGP.mjs} +0 -0
- /package/dist/{rolldown-runtime-twds-ZHy-RuJszab7.mjs → rolldown-runtime-twds-ZHy-3DMm_Sby.mjs} +0 -0
- /package/dist/{run-polling-DDpkIvwy.mjs → run-polling-Cb4ssXIE.mjs} +0 -0
- /package/dist/{schema-display-DuWBmkwk.mjs → schema-display-CyCWSgfY.mjs} +0 -0
- /package/dist/{skills.handler-CofL4oKs.mjs → skills.handler-C_4VzVmc.mjs} +0 -0
- /package/dist/{spinner-progress-Bt8zXPOc.mjs → spinner-progress-CS1BEdNB.mjs} +0 -0
- /package/dist/{status.handler-6cuHa0R0.mjs → status.handler-Cm9aNUBn.mjs} +0 -0
- /package/dist/{sync-keystroke-agent-skills-D746f2W_.mjs → sync-keystroke-agent-skills-CX9fS5nQ.mjs} +0 -0
- /package/dist/{upgrade.handler-DhKeyCy5.mjs → upgrade.handler-C2eZ_tg3.mjs} +0 -0
- /package/dist/{upload-C1qFWMm0.mjs → upload-C0kaZu08.mjs} +0 -0
|
@@ -2,227 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
import { N as throwReportedCliExit, b as isNetworkError, h as AUTH_HINT, n as ui, x as toErrorMessage } from "./keystroke.mjs";
|
|
4
4
|
import { i as writeJson } from "./output-CGdYhH0p.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as getIntegrationCatalog } from "./integration-catalog-
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
//#region ../../packages/shared-types/src/connections/api.ts
|
|
10
|
-
/**
|
|
11
|
-
* API request/response types for the integration catalog and connection endpoints.
|
|
12
|
-
*
|
|
13
|
-
* These types are shared between the server route handlers, the Keystroke SDK, and
|
|
14
|
-
* any in-repo consumer (CLI, web). They divide the surface into two clearly-scoped
|
|
15
|
-
* endpoints:
|
|
16
|
-
*
|
|
17
|
-
* GET /api/v1/integrations — the static Keystroke integration catalog (what can
|
|
18
|
-
* be connected). Auth required; not org-scoped; long-cached.
|
|
19
|
-
*
|
|
20
|
-
* GET /api/v1/connections — the caller's configured connections for the current
|
|
21
|
-
* org (what has been connected). Auth + org required; no-cache.
|
|
22
|
-
*
|
|
23
|
-
* Each endpoint validates its query string with the exported `*QuerySchema`, and
|
|
24
|
-
* the SDK types its method signatures against the same schema so that invalid
|
|
25
|
-
* params cannot be sent or accepted.
|
|
26
|
-
*/
|
|
27
|
-
const ShopifyShopDomainSchema = z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/i, "Shopify store domain must look like \"example.myshopify.com\".");
|
|
28
|
-
const InitiateConnectionRequestSchema = z.object({
|
|
29
|
-
providerAppId: z.string().optional(),
|
|
30
|
-
shopDomain: ShopifyShopDomainSchema.optional(),
|
|
31
|
-
requestedScopes: z.array(z.string()).optional()
|
|
32
|
-
});
|
|
33
|
-
const InitiateConnectionResponseSchema = z.object({
|
|
34
|
-
authUrl: z.string(),
|
|
35
|
-
initiatedAt: z.number()
|
|
36
|
-
});
|
|
37
|
-
const ConnectionFailureReasonSchema = z.enum([
|
|
38
|
-
"missing_state",
|
|
39
|
-
"invalid_state",
|
|
40
|
-
"provider_denied",
|
|
41
|
-
"unknown_integration",
|
|
42
|
-
"provider_app_not_configured",
|
|
43
|
-
"token_exchange_failed",
|
|
44
|
-
"installation_metadata_invalid",
|
|
45
|
-
"validation_failed",
|
|
46
|
-
"persist_failed",
|
|
47
|
-
"unknown_error"
|
|
48
|
-
]);
|
|
49
|
-
const ConnectionStatusNotStartedSchema = z.object({ status: z.literal("not_started") });
|
|
50
|
-
const ConnectionStatusPendingSchema = z.object({ status: z.literal("pending") });
|
|
51
|
-
const ConnectionStatusConnectedSchema = z.object({ status: z.literal("connected") });
|
|
52
|
-
const ConnectionStatusFailedSchema = z.object({
|
|
53
|
-
status: z.literal("failed"),
|
|
54
|
-
reason: ConnectionFailureReasonSchema,
|
|
55
|
-
/**
|
|
56
|
-
* Optional human-readable detail. Truncated by the server to
|
|
57
|
-
* {@link CONNECTION_FAILURE_DETAIL_MAX_CHARS} characters before being
|
|
58
|
-
* persisted in `credential_sets.last_callback_error_detail` and
|
|
59
|
-
* before being echoed in the callback redirect query.
|
|
60
|
-
*/
|
|
61
|
-
message: z.string().max(300).optional(),
|
|
62
|
-
/** ISO-8601 timestamp of when the failure was recorded. */
|
|
63
|
-
failedAt: z.string()
|
|
64
|
-
});
|
|
65
|
-
const ConnectionStatusResponseSchema = z.discriminatedUnion("status", [
|
|
66
|
-
ConnectionStatusNotStartedSchema,
|
|
67
|
-
ConnectionStatusPendingSchema,
|
|
68
|
-
ConnectionStatusConnectedSchema,
|
|
69
|
-
ConnectionStatusFailedSchema
|
|
70
|
-
]);
|
|
71
|
-
const ConnectionKindSchema = z.enum([
|
|
72
|
-
"oauth",
|
|
73
|
-
"manual",
|
|
74
|
-
"credentials-exchange"
|
|
75
|
-
]);
|
|
76
|
-
const InternalCredentialSetEntrySchema = z.object({
|
|
77
|
-
resolvedCredentialSetId: z.string(),
|
|
78
|
-
publicId: z.string(),
|
|
79
|
-
displayName: z.string(),
|
|
80
|
-
/**
|
|
81
|
-
* Internal credential-set role. Currently the only first-class role is
|
|
82
|
-
* `'provider-app-definition'`; other values are accepted for forward-compat
|
|
83
|
-
* so newer servers can introduce roles without breaking older SDKs.
|
|
84
|
-
*/
|
|
85
|
-
role: z.string()
|
|
86
|
-
});
|
|
87
|
-
const IntegrationCatalogEntryBaseSchema = z.object({
|
|
88
|
-
publicId: z.string(),
|
|
89
|
-
/**
|
|
90
|
-
* Public-facing aliases that resolve to this canonical `publicId`
|
|
91
|
-
* (e.g., `"github"` aliases `"github-account"`). Includes the canonical
|
|
92
|
-
* ID itself — callers can key a lookup table by every entry in this
|
|
93
|
-
* list and get the same catalog record back.
|
|
94
|
-
*/
|
|
95
|
-
aliases: z.array(z.string()),
|
|
96
|
-
name: z.string(),
|
|
97
|
-
description: z.string().optional(),
|
|
98
|
-
/**
|
|
99
|
-
* Resolved credential-set metadata for the integration's primary connection.
|
|
100
|
-
* `storedKeys` drives upload flows (what the vault stores), while
|
|
101
|
-
* `authKeys` describes the post-resolve runtime shape.
|
|
102
|
-
*/
|
|
103
|
-
credentialSet: z.object({
|
|
104
|
-
resolvedCredentialSetId: z.string(),
|
|
105
|
-
authKeys: z.array(z.string()),
|
|
106
|
-
storedKeys: z.array(z.string()),
|
|
107
|
-
optionalStoredKeys: z.array(z.string()).optional(),
|
|
108
|
-
schemaFingerprint: z.string().optional()
|
|
109
|
-
}),
|
|
110
|
-
/**
|
|
111
|
-
* Internal credential sets associated with the integration (e.g., provider
|
|
112
|
-
* app definitions). Populated only when the caller requests
|
|
113
|
-
* `includeInternal=true`; otherwise empty.
|
|
114
|
-
*/
|
|
115
|
-
internalCredentialSets: z.array(InternalCredentialSetEntrySchema)
|
|
116
|
-
});
|
|
117
|
-
const OAuthIntegrationCatalogEntrySchema = IntegrationCatalogEntryBaseSchema.extend({
|
|
118
|
-
connectionKind: z.literal("oauth"),
|
|
119
|
-
tokenType: z.enum(["long-lived", "refreshable"]),
|
|
120
|
-
scopes: z.array(z.string())
|
|
121
|
-
});
|
|
122
|
-
const ManualIntegrationCatalogEntrySchema = IntegrationCatalogEntryBaseSchema.extend({ connectionKind: z.literal("manual") });
|
|
123
|
-
/**
|
|
124
|
-
* Catalog entry for `credentials-exchange`-kind integrations.
|
|
125
|
-
*
|
|
126
|
-
* Carries the JSON-schema projection of the connection's `input` schema so
|
|
127
|
-
* the CLI and web UI can render an input form without re-loading the
|
|
128
|
-
* original Zod schema (which only exists in the integration bundle's
|
|
129
|
-
* runtime module). `credentialSet.storedKeys` reflects the stored-schema
|
|
130
|
-
* keys that get persisted after exchange.
|
|
131
|
-
*
|
|
132
|
-
* @see packages/core/src/credential-set/connection.ts CredentialsExchangeConnectionConfig
|
|
133
|
-
*/
|
|
134
|
-
const CredentialsExchangeIntegrationCatalogEntrySchema = IntegrationCatalogEntryBaseSchema.extend({
|
|
135
|
-
connectionKind: z.literal("credentials-exchange"),
|
|
136
|
-
/** JSON-schema projection of the connection's `input` schema. */
|
|
137
|
-
input: z.record(z.string(), z.unknown()),
|
|
138
|
-
/** Optional free-form copy rendered above the input form. */
|
|
139
|
-
instructions: z.string().optional()
|
|
140
|
-
});
|
|
141
|
-
const IntegrationCatalogEntrySchema = z.discriminatedUnion("connectionKind", [
|
|
142
|
-
OAuthIntegrationCatalogEntrySchema,
|
|
143
|
-
ManualIntegrationCatalogEntrySchema,
|
|
144
|
-
CredentialsExchangeIntegrationCatalogEntrySchema
|
|
145
|
-
]);
|
|
146
|
-
z.object({
|
|
147
|
-
/** Restrict results to one connection kind. */
|
|
148
|
-
connectionKind: ConnectionKindSchema.optional(),
|
|
149
|
-
/**
|
|
150
|
-
* Return only the integration whose `publicId` (or alias) matches.
|
|
151
|
-
* When no integration matches, the endpoint returns an empty array.
|
|
152
|
-
*/
|
|
153
|
-
publicId: z.string().min(1).optional(),
|
|
154
|
-
/**
|
|
155
|
-
* Case-insensitive substring match against `publicId`, `aliases`, and `name`.
|
|
156
|
-
*/
|
|
157
|
-
q: z.string().min(1).optional(),
|
|
158
|
-
/**
|
|
159
|
-
* Opt into `internalCredentialSets[]` on each entry. Defaults to `false`
|
|
160
|
-
* so the common catalog call stays lean. CLI commands that need to render
|
|
161
|
-
* credential-set display names set this to `true`.
|
|
162
|
-
*/
|
|
163
|
-
includeInternal: z.stringbool().optional().default(false)
|
|
164
|
-
}).strict();
|
|
165
|
-
z.object({ integrations: z.array(IntegrationCatalogEntrySchema) });
|
|
166
|
-
const ConnectionEntrySchema = z.object({
|
|
167
|
-
id: z.string(),
|
|
168
|
-
/**
|
|
169
|
-
* Public-facing integration ID this connection is associated with
|
|
170
|
-
* (post alias resolution). `null` when the underlying credential set is
|
|
171
|
-
* not backed by an official Keystroke integration (e.g., user-defined
|
|
172
|
-
* custom credential sets).
|
|
173
|
-
*/
|
|
174
|
-
integrationPublicId: z.string().nullable(),
|
|
175
|
-
/**
|
|
176
|
-
* Resolved credential-set ID, e.g., `"keystroke:slack"` or a custom set's
|
|
177
|
-
* identifier. Stable across alias resolution.
|
|
178
|
-
*/
|
|
179
|
-
credentialSetId: z.string(),
|
|
180
|
-
name: z.string(),
|
|
181
|
-
scope: CredentialScopeSchema,
|
|
182
|
-
platformConnected: z.boolean(),
|
|
183
|
-
connectionStatus: ConnectionStatusSchema,
|
|
184
|
-
expiresAt: z.string().nullable(),
|
|
185
|
-
isDefault: z.boolean(),
|
|
186
|
-
createdAt: z.string()
|
|
187
|
-
});
|
|
188
|
-
/**
|
|
189
|
-
* Coerces a `status` query-param value that may arrive as a single string,
|
|
190
|
-
* a comma-separated string, or (in Hono/ky's query handling) an array of
|
|
191
|
-
* strings, into a canonical `ConnectionStatus[]`. Invalid entries cause the
|
|
192
|
-
* surrounding Zod parse to fail with a helpful issue.
|
|
193
|
-
*
|
|
194
|
-
* The field itself is made optional at the object level (see
|
|
195
|
-
* `ListConnectionsQuerySchema`), so passing `undefined` / omitting the key
|
|
196
|
-
* is always valid; this preprocessor only runs when a value is actually
|
|
197
|
-
* present.
|
|
198
|
-
*/
|
|
199
|
-
const ConnectionStatusQueryParam = z.preprocess((value) => {
|
|
200
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
201
|
-
const trimmed = (Array.isArray(value) ? value : String(value).split(",")).flatMap((entry) => String(entry).split(",")).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
202
|
-
return trimmed.length === 0 ? void 0 : trimmed;
|
|
203
|
-
}, z.array(ConnectionStatusSchema));
|
|
204
|
-
z.object({
|
|
205
|
-
/** Filter to connections for a specific integration's public ID (alias-resolved). */
|
|
206
|
-
integrationPublicId: z.string().min(1).optional(),
|
|
207
|
-
/**
|
|
208
|
-
* Filter by one or more connection statuses. Accepts a single value, a
|
|
209
|
-
* comma-separated string, or repeated query keys. Omit to return all statuses.
|
|
210
|
-
*/
|
|
211
|
-
status: ConnectionStatusQueryParam.optional(),
|
|
212
|
-
scope: CredentialScopeSchema.optional(),
|
|
213
|
-
projectId: z.uuid().optional()
|
|
214
|
-
}).strict();
|
|
215
|
-
z.object({ connections: z.array(ConnectionEntrySchema) });
|
|
216
|
-
//#endregion
|
|
5
|
+
import { t as openBrowser } from "./browser-B4K0VW8p.mjs";
|
|
6
|
+
import { i as InitiateConnectionResponseSchema, n as ConnectionStatusResponseSchema, r as InitiateConnectionRequestSchema } from "./api-DuKKdCpF.mjs";
|
|
7
|
+
import { t as getIntegrationCatalog } from "./integration-catalog-BRrJIAVz.mjs";
|
|
217
8
|
//#region src/commands/connect/connect.handler.ts
|
|
218
9
|
function formatIntegrationLabel(catalog, integrationId) {
|
|
219
10
|
return catalog.lookupByPublicId(integrationId)?.name ?? integrationId;
|
|
220
11
|
}
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
12
|
+
function formatConnectionLabel(connection) {
|
|
13
|
+
return connection.label ?? connection.id;
|
|
14
|
+
}
|
|
15
|
+
function formatConnectionFlags(connection) {
|
|
16
|
+
const flags = [connection.recommended === true ? "recommended" : null, connection.advanced === true ? "advanced" : null].filter((flag) => flag !== null);
|
|
17
|
+
return flags.length > 0 ? `, ${flags.join(", ")}` : "";
|
|
18
|
+
}
|
|
19
|
+
function availableOAuthConnectionHint(connections) {
|
|
20
|
+
const oauthConnections = connections?.filter((connection) => connection.kind === "oauth") ?? [];
|
|
21
|
+
if (oauthConnections.length === 0) return "Run `keystroke integrations list --kind oauth` to see integrations with OAuth connection paths.";
|
|
22
|
+
return `Available OAuth connection IDs: ${oauthConnections.map((connection) => `${connection.id}${connection.recommended ? " (recommended)" : ""}`).join(", ")}.`;
|
|
23
|
+
}
|
|
24
|
+
function selectOAuthConnection(params) {
|
|
25
|
+
const { catalogEntry, requestedCredentialConnectionId, ctx, integrationId } = params;
|
|
26
|
+
const connections = catalogEntry?.connections ?? [];
|
|
27
|
+
if (requestedCredentialConnectionId) {
|
|
28
|
+
const selected = connections.find((connection) => connection.id === requestedCredentialConnectionId);
|
|
29
|
+
if (!selected) exitWithError(ctx, `Credential connection "${requestedCredentialConnectionId}" is not defined for "${integrationId}".`, {
|
|
30
|
+
code: "UNKNOWN_CREDENTIAL_CONNECTION",
|
|
31
|
+
hint: availableOAuthConnectionHint(connections)
|
|
32
|
+
});
|
|
33
|
+
if (selected.kind !== "oauth") exitWithError(ctx, `Credential connection "${selected.id}" for "${integrationId}" is "${selected.kind}", not oauth.`, {
|
|
34
|
+
code: "UNSUPPORTED_CREDENTIAL_CONNECTION",
|
|
35
|
+
hint: availableOAuthConnectionHint(connections)
|
|
36
|
+
});
|
|
37
|
+
return selected;
|
|
38
|
+
}
|
|
39
|
+
return connections.find((connection) => connection.kind === "oauth" && connection.recommended === true) ?? connections.find((connection) => connection.kind === "oauth");
|
|
226
40
|
}
|
|
227
41
|
/**
|
|
228
42
|
* Per-reason CLI hint table for `failed` status responses.
|
|
@@ -261,6 +75,24 @@ function exitWithError(ctx, message, opts) {
|
|
|
261
75
|
if (opts?.hint) ui.hint(opts.hint);
|
|
262
76
|
throwReportedCliExit(message);
|
|
263
77
|
}
|
|
78
|
+
function parseConnectionInput(rawInputs, ctx) {
|
|
79
|
+
const input = {};
|
|
80
|
+
for (const rawInput of rawInputs) {
|
|
81
|
+
const separatorIndex = rawInput.indexOf("=");
|
|
82
|
+
if (separatorIndex <= 0) exitWithError(ctx, `Invalid --input value "${rawInput}".`, {
|
|
83
|
+
code: "USAGE_ERROR",
|
|
84
|
+
hint: "Use --input key=value. Repeat --input for multiple fields."
|
|
85
|
+
});
|
|
86
|
+
const key = rawInput.slice(0, separatorIndex).trim();
|
|
87
|
+
const value = rawInput.slice(separatorIndex + 1);
|
|
88
|
+
if (!key) exitWithError(ctx, `Invalid --input value "${rawInput}".`, {
|
|
89
|
+
code: "USAGE_ERROR",
|
|
90
|
+
hint: "Input keys must be non-empty: --input key=value"
|
|
91
|
+
});
|
|
92
|
+
input[key] = value;
|
|
93
|
+
}
|
|
94
|
+
return input;
|
|
95
|
+
}
|
|
264
96
|
/**
|
|
265
97
|
* Handle the `keystroke connect <integrationId>` command.
|
|
266
98
|
*
|
|
@@ -281,20 +113,27 @@ async function handleConnect(options, ctx) {
|
|
|
281
113
|
hint: "Example: keystroke connect github"
|
|
282
114
|
});
|
|
283
115
|
const catalog = await getIntegrationCatalog(ctx);
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
116
|
+
const catalogEntry = catalog.lookupByPublicId(integrationId);
|
|
117
|
+
const oauthConnection = selectOAuthConnection({
|
|
118
|
+
catalogEntry,
|
|
119
|
+
requestedCredentialConnectionId: options.connection,
|
|
120
|
+
ctx,
|
|
121
|
+
integrationId
|
|
289
122
|
});
|
|
123
|
+
const integrationLabel = Boolean(oauthConnection) ? formatIntegrationLabel(catalog, integrationId) : integrationId;
|
|
124
|
+
const connectionInput = parseConnectionInput(options.input ?? [], ctx);
|
|
290
125
|
if (!ctx.jsonMode) {
|
|
291
126
|
ui.text(`Connect ${integrationLabel}`);
|
|
127
|
+
if (oauthConnection && ((catalogEntry?.connections.length ?? 0) > 1 || options.connection)) ui.text(`Connection: ${formatConnectionLabel(oauthConnection)} (id: ${oauthConnection.id}${formatConnectionFlags(oauthConnection)})`);
|
|
292
128
|
ui.br();
|
|
293
129
|
}
|
|
294
130
|
let authUrl;
|
|
295
131
|
let initiatedAt;
|
|
296
132
|
try {
|
|
297
|
-
const requestBody = InitiateConnectionRequestSchema.parse({
|
|
133
|
+
const requestBody = InitiateConnectionRequestSchema.parse({
|
|
134
|
+
...oauthConnection ? { credentialConnectionId: oauthConnection.id } : {},
|
|
135
|
+
...Object.keys(connectionInput).length > 0 ? { input: connectionInput } : {}
|
|
136
|
+
});
|
|
298
137
|
const hasRequestBody = Object.keys(requestBody).length > 0;
|
|
299
138
|
const response = await fetch(`${baseUrl}/api/v1/connections/${integrationId}/initiate`, {
|
|
300
139
|
method: "POST",
|
|
@@ -348,6 +187,14 @@ async function handleConnect(options, ctx) {
|
|
|
348
187
|
writeJson({
|
|
349
188
|
status: "authorization_required",
|
|
350
189
|
integrationId,
|
|
190
|
+
credentialConnectionId: oauthConnection?.id,
|
|
191
|
+
...oauthConnection ? { selectedConnection: {
|
|
192
|
+
id: oauthConnection.id,
|
|
193
|
+
kind: oauthConnection.kind,
|
|
194
|
+
...oauthConnection.label ? { label: oauthConnection.label } : {},
|
|
195
|
+
...oauthConnection.recommended === true ? { recommended: true } : {},
|
|
196
|
+
...oauthConnection.advanced === true ? { advanced: true } : {}
|
|
197
|
+
} } : {},
|
|
351
198
|
authUrl,
|
|
352
199
|
initiatedAt,
|
|
353
200
|
timeoutSeconds: options.timeout
|
|
@@ -377,7 +224,10 @@ async function handleConnect(options, ctx) {
|
|
|
377
224
|
while (Date.now() - startTime < timeoutMs) {
|
|
378
225
|
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
379
226
|
try {
|
|
380
|
-
const
|
|
227
|
+
const statusUrl = new URL(`${baseUrl}/api/v1/connections/${integrationId}/status`);
|
|
228
|
+
statusUrl.searchParams.set("since", String(initiatedAt));
|
|
229
|
+
if (oauthConnection) statusUrl.searchParams.set("credentialConnectionId", oauthConnection.id);
|
|
230
|
+
const response = await fetch(statusUrl.toString(), { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
381
231
|
if (!response.ok) {
|
|
382
232
|
consecutivePollFailures += 1;
|
|
383
233
|
if (response.status === 401) exitWithError(ctx, "Your CLI session is no longer authenticated.", {
|
|
@@ -36,7 +36,7 @@ async function resolveBaseContext(overrides = {}) {
|
|
|
36
36
|
const authContext = await resolveAuthContext(overrides);
|
|
37
37
|
let client = null;
|
|
38
38
|
if (authContext.apiKey && authContext.baseUrl) try {
|
|
39
|
-
const { createClient } = await import("./src
|
|
39
|
+
const { createClient } = await import("./src-D-dFmoAF.mjs");
|
|
40
40
|
client = createClient({
|
|
41
41
|
apiKey: authContext.apiKey,
|
|
42
42
|
baseUrl: authContext.baseUrl,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { N as throwReportedCliExit, n as ui, x as toErrorMessage } from "./keystroke.mjs";
|
|
4
4
|
import { i as writeJson } from "./output-CGdYhH0p.mjs";
|
|
5
|
-
import { i as requireClient } from "./context-
|
|
5
|
+
import { i as requireClient } from "./context-DQ4IA0yO.mjs";
|
|
6
6
|
//#region src/commands/api-keys/create.handler.ts
|
|
7
7
|
async function handleApiKeysCreate(options, ctx) {
|
|
8
8
|
const client = requireClient(ctx);
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { t as JsonSchemaSchema } from "./common-BaGFkj3n.mjs";
|
|
4
|
+
import { n as credentialSetProxyConfigSchema } from "./schemas-DodkHgnS.mjs";
|
|
5
|
+
import { a as SourceLocationSchema, i as ImportSourceSchema, t as CallKindSchema } from "./source-analysis-CJPymdaA.mjs";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
const IntegrationScopeSchema = z.enum([
|
|
8
|
+
"organization",
|
|
9
|
+
"project",
|
|
10
|
+
"user_provided_credential"
|
|
11
|
+
]);
|
|
12
|
+
const IntegrationCredentialRefSchema = z.discriminatedUnion("type", [z.object({
|
|
13
|
+
type: z.literal("id"),
|
|
14
|
+
id: z.string().startsWith("cset_")
|
|
15
|
+
}), z.object({
|
|
16
|
+
type: z.literal("name"),
|
|
17
|
+
name: z.string().trim().min(1)
|
|
18
|
+
})]);
|
|
19
|
+
function hasProjectOrOrganizationScope(scope) {
|
|
20
|
+
return scope === "organization" || scope === "project";
|
|
21
|
+
}
|
|
22
|
+
const CredentialRefTokenKeyNameSchema = z.string().regex(/^[A-Za-z0-9_]+$/, "Credential key must contain only letters, digits, and underscores (required for ref-token proxying)");
|
|
23
|
+
/** Shared enum for top-level credential-set `onCredentialRevoked` policy. */
|
|
24
|
+
const OnCredentialRevokedSchema = z.enum(["fail", "retry-once"]);
|
|
25
|
+
/** A credential set after resolution in a built manifest. Contains definition id, scope, alias, and credential keys.*/
|
|
26
|
+
const ResolvedCredentialSetSchema = z.object({
|
|
27
|
+
resolvedId: z.string(),
|
|
28
|
+
scope: IntegrationScopeSchema.optional(),
|
|
29
|
+
alias: z.string().optional(),
|
|
30
|
+
credentialRef: IntegrationCredentialRefSchema.optional(),
|
|
31
|
+
/** Auth-shape keys expected post-resolve. */
|
|
32
|
+
credentialKeys: z.array(CredentialRefTokenKeyNameSchema),
|
|
33
|
+
/** Subset of `credentialKeys` that are optional in the auth shape. */
|
|
34
|
+
optionalCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
35
|
+
/** Stored-shape keys required for vault reads and upload flows. */
|
|
36
|
+
storedCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
37
|
+
/** Subset of `storedCredentialKeys` that may be absent from the vault without
|
|
38
|
+
* failing resolution. Derived from the credential set's `stored` schema:
|
|
39
|
+
* a Zod field wrapped in `.optional()` / `.default()` or a JSON Schema
|
|
40
|
+
* property not listed in `required` is considered optional. */
|
|
41
|
+
optionalStoredCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
42
|
+
proxy: credentialSetProxyConfigSchema.optional(),
|
|
43
|
+
/** When true, resolved values are passed raw (no ref-token proxy) for this set. */
|
|
44
|
+
needsRawSecret: z.boolean().optional(),
|
|
45
|
+
/** When true, this requirement uses a registered dynamic resolver phase. */
|
|
46
|
+
needsDynamicResolution: z.boolean().optional(),
|
|
47
|
+
/** Cache TTL in milliseconds for registered dynamic resolver output.
|
|
48
|
+
* `0` or absence means no cache hint. */
|
|
49
|
+
dynamicResolutionCacheMs: z.number().int().nonnegative().optional(),
|
|
50
|
+
/** Policy when a step throws `CredentialRevokedError` against this credential set. */
|
|
51
|
+
onCredentialRevoked: OnCredentialRevokedSchema.optional(),
|
|
52
|
+
/** Persistence-layer schema fingerprint stamped at build time. The
|
|
53
|
+
* resolver's phase 2 compares this against the vault row's stored
|
|
54
|
+
* fingerprint and raises `CredentialSchemaMismatchError` on drift.
|
|
55
|
+
* Optional here so pre-fingerprint artifacts still parse; the
|
|
56
|
+
* workflow builder populates it for every authored credential set
|
|
57
|
+
* that has a resolvable fingerprint. */
|
|
58
|
+
schemaFingerprint: z.string().optional()
|
|
59
|
+
}).superRefine((value, ctx) => {
|
|
60
|
+
if (value.credentialRef && !hasProjectOrOrganizationScope(value.scope)) ctx.addIssue({
|
|
61
|
+
code: z.ZodIssueCode.custom,
|
|
62
|
+
path: ["credentialRef"],
|
|
63
|
+
message: "credentialRef requires scope to be \"project\" or \"organization\""
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
const DeclaredCredentialRequirementSchema = z.object({
|
|
67
|
+
credentialSetId: z.string(),
|
|
68
|
+
/** Auth-shape keys expected post-resolve. */
|
|
69
|
+
credentialKeys: z.array(CredentialRefTokenKeyNameSchema),
|
|
70
|
+
/** Optional subset of the auth-shape keys. */
|
|
71
|
+
optionalCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
72
|
+
/** Stored-shape keys required for vault reads. */
|
|
73
|
+
storedCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
74
|
+
/** Optional subset of the stored-shape keys. */
|
|
75
|
+
optionalStoredCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
76
|
+
schemaFingerprint: z.string().optional(),
|
|
77
|
+
needsDynamicResolution: z.boolean().optional(),
|
|
78
|
+
/** Cache TTL in milliseconds for registered dynamic resolver output.
|
|
79
|
+
* `0` or absence means no cache hint. */
|
|
80
|
+
dynamicResolutionCacheMs: z.number().int().nonnegative().optional(),
|
|
81
|
+
/** Policy when a step throws `CredentialRevokedError` against this credential set. */
|
|
82
|
+
onCredentialRevoked: OnCredentialRevokedSchema.optional(),
|
|
83
|
+
proxy: credentialSetProxyConfigSchema.optional(),
|
|
84
|
+
needsRawSecret: z.boolean().optional(),
|
|
85
|
+
requiredOAuthScopes: z.array(z.string()).optional()
|
|
86
|
+
});
|
|
87
|
+
const CredentialRequirementEntrySchema = z.object({
|
|
88
|
+
credentialSetId: z.string(),
|
|
89
|
+
scope: IntegrationScopeSchema.optional(),
|
|
90
|
+
alias: z.string().optional(),
|
|
91
|
+
credentialRef: IntegrationCredentialRefSchema.optional(),
|
|
92
|
+
/** Auth-shape keys expected post-resolve. */
|
|
93
|
+
credentialKeys: z.array(CredentialRefTokenKeyNameSchema),
|
|
94
|
+
/** Optional subset of the auth-shape keys. */
|
|
95
|
+
optionalCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
96
|
+
/** Stored-shape keys required for vault reads. */
|
|
97
|
+
storedCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
98
|
+
/** Optional subset of the stored-shape keys. */
|
|
99
|
+
optionalStoredCredentialKeys: z.array(CredentialRefTokenKeyNameSchema).optional(),
|
|
100
|
+
schemaFingerprint: z.string().optional(),
|
|
101
|
+
proxy: credentialSetProxyConfigSchema.optional(),
|
|
102
|
+
needsRawSecret: z.boolean().optional(),
|
|
103
|
+
/** When true, this requirement uses a registered dynamic resolver phase. */
|
|
104
|
+
needsDynamicResolution: z.boolean().optional(),
|
|
105
|
+
/** Cache TTL in milliseconds for registered dynamic resolver output.
|
|
106
|
+
* `0` or absence means no cache hint. */
|
|
107
|
+
dynamicResolutionCacheMs: z.number().int().nonnegative().optional(),
|
|
108
|
+
/** Policy when a step throws `CredentialRevokedError` against this credential set. */
|
|
109
|
+
onCredentialRevoked: OnCredentialRevokedSchema.optional(),
|
|
110
|
+
requiredOAuthScopes: z.array(z.string()).optional()
|
|
111
|
+
}).superRefine((value, ctx) => {
|
|
112
|
+
if (value.credentialRef && !hasProjectOrOrganizationScope(value.scope)) ctx.addIssue({
|
|
113
|
+
code: z.ZodIssueCode.custom,
|
|
114
|
+
path: ["credentialRef"],
|
|
115
|
+
message: "credentialRef requires scope to be \"project\" or \"organization\""
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
const CredentialRequirementsSchema = z.object({
|
|
119
|
+
required: z.array(z.string()),
|
|
120
|
+
byStep: z.record(z.string(), z.array(CredentialRequirementEntrySchema))
|
|
121
|
+
});
|
|
122
|
+
const TriggerCallbackNameSchema = z.enum([
|
|
123
|
+
"filter",
|
|
124
|
+
"idempotencyKey",
|
|
125
|
+
"verify",
|
|
126
|
+
"callback"
|
|
127
|
+
]);
|
|
128
|
+
const TriggerCredentialRequirementEntrySchema = CredentialRequirementEntrySchema;
|
|
129
|
+
const TriggerCredentialRequirementsSchema = z.object({
|
|
130
|
+
required: z.array(z.string()),
|
|
131
|
+
byCallback: z.partialRecord(TriggerCallbackNameSchema, z.array(TriggerCredentialRequirementEntrySchema))
|
|
132
|
+
});
|
|
133
|
+
function buildCredentialRequirementEntryKey(entry) {
|
|
134
|
+
const credentialRefKey = entry.credentialRef ? entry.credentialRef.type === "id" ? `id:${entry.credentialRef.id}` : `name:${entry.credentialRef.name}` : "";
|
|
135
|
+
return [
|
|
136
|
+
entry.credentialSetId,
|
|
137
|
+
entry.scope ?? "",
|
|
138
|
+
entry.alias ?? "",
|
|
139
|
+
credentialRefKey,
|
|
140
|
+
entry.schemaFingerprint ?? "",
|
|
141
|
+
[...entry.credentialKeys].sort().join(","),
|
|
142
|
+
[...entry.optionalCredentialKeys ?? []].sort().join(","),
|
|
143
|
+
[...entry.storedCredentialKeys ?? []].sort().join(","),
|
|
144
|
+
[...entry.optionalStoredCredentialKeys ?? []].sort().join(","),
|
|
145
|
+
entry.needsRawSecret === true ? "1" : "0",
|
|
146
|
+
entry.needsDynamicResolution === true ? "1" : "0",
|
|
147
|
+
typeof entry.dynamicResolutionCacheMs === "number" ? String(entry.dynamicResolutionCacheMs) : "",
|
|
148
|
+
entry.onCredentialRevoked ?? "",
|
|
149
|
+
entry.proxy ? JSON.stringify(entry.proxy) : ""
|
|
150
|
+
].join("|");
|
|
151
|
+
}
|
|
152
|
+
function deduplicateCredentialRequirementEntries(entries) {
|
|
153
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
const key = buildCredentialRequirementEntryKey(entry);
|
|
156
|
+
const existing = deduped.get(key);
|
|
157
|
+
if (!existing) deduped.set(key, {
|
|
158
|
+
...entry,
|
|
159
|
+
credentialKeys: [...entry.credentialKeys].sort(),
|
|
160
|
+
...entry.optionalCredentialKeys ? { optionalCredentialKeys: [...entry.optionalCredentialKeys].sort() } : {},
|
|
161
|
+
...entry.storedCredentialKeys ? { storedCredentialKeys: [...entry.storedCredentialKeys].sort() } : {},
|
|
162
|
+
...entry.optionalStoredCredentialKeys ? { optionalStoredCredentialKeys: [...entry.optionalStoredCredentialKeys].sort() } : {}
|
|
163
|
+
});
|
|
164
|
+
else if (entry.requiredOAuthScopes?.length) {
|
|
165
|
+
const merged = new Set([...existing.requiredOAuthScopes ?? [], ...entry.requiredOAuthScopes]);
|
|
166
|
+
deduped.set(key, {
|
|
167
|
+
...existing,
|
|
168
|
+
requiredOAuthScopes: [...merged].sort()
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return [...deduped.values()];
|
|
173
|
+
}
|
|
174
|
+
function collectCredentialRequirementEntries(credentialRequirements) {
|
|
175
|
+
if (!credentialRequirements) return [];
|
|
176
|
+
return deduplicateCredentialRequirementEntries(Object.values(credentialRequirements.byStep ?? {}).flat());
|
|
177
|
+
}
|
|
178
|
+
z.object({ subjectMode: z.enum(["never", "requiredWhenUserProvidedCredential"]) });
|
|
179
|
+
/** A step's entry within a WorkflowManifest. Describes how a step is used in a workflow, not what the step itself is. */
|
|
180
|
+
const WorkflowStepEntrySchema = z.object({
|
|
181
|
+
nodeId: z.string().min(1),
|
|
182
|
+
stepName: z.string().min(1),
|
|
183
|
+
label: z.string().min(1),
|
|
184
|
+
callKind: CallKindSchema,
|
|
185
|
+
stepId: z.string().min(1).optional(),
|
|
186
|
+
source: SourceLocationSchema.optional(),
|
|
187
|
+
astKind: z.string().min(1).optional(),
|
|
188
|
+
importSource: ImportSourceSchema.optional(),
|
|
189
|
+
outputBinding: z.string().min(1).optional(),
|
|
190
|
+
scopeOverride: IntegrationScopeSchema.optional(),
|
|
191
|
+
description: z.string().optional(),
|
|
192
|
+
sourceCode: z.string().optional(),
|
|
193
|
+
exportName: z.string().optional(),
|
|
194
|
+
inputSchema: JsonSchemaSchema.optional(),
|
|
195
|
+
outputSchema: JsonSchemaSchema.optional(),
|
|
196
|
+
credentialSets: z.array(ResolvedCredentialSetSchema).optional()
|
|
197
|
+
});
|
|
198
|
+
const TriggerTypeSchema = z.enum([
|
|
199
|
+
"webhook",
|
|
200
|
+
"cron",
|
|
201
|
+
"polling"
|
|
202
|
+
]);
|
|
203
|
+
/**
|
|
204
|
+
* Persisted on `deployment_triggers.trigger_source`. Mirrors the
|
|
205
|
+
* `webhookTrigger({ source: { type } })` discriminator so the server
|
|
206
|
+
* can index-filter app-source rows during provider-webhook fanout.
|
|
207
|
+
*/
|
|
208
|
+
const TriggerSourceSchema = z.enum(["custom", "app"]);
|
|
209
|
+
const WebhookMethodSchema = z.enum([
|
|
210
|
+
"GET",
|
|
211
|
+
"POST",
|
|
212
|
+
"PUT",
|
|
213
|
+
"PATCH"
|
|
214
|
+
]);
|
|
215
|
+
const TriggerCallbackBundleUploadSchema = z.object({
|
|
216
|
+
code: z.string(),
|
|
217
|
+
hash: z.string(),
|
|
218
|
+
size: z.number()
|
|
219
|
+
});
|
|
220
|
+
const TriggerCallbackExportsSchema = z.object({
|
|
221
|
+
verify: z.string().min(1).optional(),
|
|
222
|
+
filter: z.string().min(1).optional(),
|
|
223
|
+
idempotencyKey: z.string().min(1).optional(),
|
|
224
|
+
callback: z.string().min(1).optional()
|
|
225
|
+
});
|
|
226
|
+
const TransformCallbackExportsSchema = z.object({ transform: z.string().min(1).optional() });
|
|
227
|
+
const TriggerUploadDataSchema = z.object({
|
|
228
|
+
id: z.string(),
|
|
229
|
+
type: TriggerTypeSchema,
|
|
230
|
+
/**
|
|
231
|
+
* Source-of-truth discriminator for webhook triggers. `'custom'` means
|
|
232
|
+
* the trigger owns its own HTTP path; `'app'` means it is fanned out by
|
|
233
|
+
* a Keystroke-managed provider app. Undefined for non-webhook triggers.
|
|
234
|
+
*/
|
|
235
|
+
triggerSource: TriggerSourceSchema.optional(),
|
|
236
|
+
enabled: z.boolean(),
|
|
237
|
+
path: z.string().optional(),
|
|
238
|
+
method: WebhookMethodSchema.optional(),
|
|
239
|
+
schedule: z.string().optional(),
|
|
240
|
+
timezone: z.string().optional(),
|
|
241
|
+
config: z.record(z.string(), z.unknown()).optional(),
|
|
242
|
+
requiredCredentials: TriggerCredentialRequirementsSchema.optional(),
|
|
243
|
+
storagePath: z.string().min(1).optional(),
|
|
244
|
+
callbackBundle: TriggerCallbackBundleUploadSchema.optional(),
|
|
245
|
+
callbackExports: TriggerCallbackExportsSchema.optional(),
|
|
246
|
+
transformCallbackBundle: TriggerCallbackBundleUploadSchema.optional(),
|
|
247
|
+
transformCallbackExports: TransformCallbackExportsSchema.optional()
|
|
248
|
+
});
|
|
249
|
+
//#endregion
|
|
250
|
+
export { TriggerCredentialRequirementsSchema as a, TriggerUploadDataSchema as c, collectCredentialRequirementEntries as d, deduplicateCredentialRequirementEntries as f, ResolvedCredentialSetSchema as i, WebhookMethodSchema as l, DeclaredCredentialRequirementSchema as n, TriggerSourceSchema as o, IntegrationScopeSchema as r, TriggerTypeSchema as s, CredentialRequirementsSchema as t, WorkflowStepEntrySchema as u };
|