@executor-js/plugin-keychain 0.0.1-beta.5 → 0.0.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-AWJ4XIQJ.js → chunk-XGNRIWKJ.js} +5 -13
- package/dist/chunk-XGNRIWKJ.js.map +1 -0
- package/dist/core.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/promise.d.ts +1 -1
- package/dist/provider.d.ts +1 -1
- package/package.json +19 -18
- package/dist/chunk-AWJ4XIQJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -44,10 +44,10 @@ Secrets written through this plugin are available to every other plugin that res
|
|
|
44
44
|
|
|
45
45
|
## Using with Effect
|
|
46
46
|
|
|
47
|
-
If you're building on `@executor/sdk
|
|
47
|
+
If you're building on `@executor/sdk` (the raw Effect entry), import this plugin from its `/core` subpath instead:
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
import { keychainPlugin } from "@executor/plugin-keychain
|
|
50
|
+
import { keychainPlugin } from "@executor/plugin-keychain";
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
## Status
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { Effect as Effect3 } from "effect";
|
|
3
|
-
import {
|
|
4
|
-
definePlugin
|
|
5
|
-
} from "@executor-js/sdk/core";
|
|
3
|
+
import { definePlugin } from "@executor-js/sdk";
|
|
6
4
|
|
|
7
5
|
// src/keyring.ts
|
|
8
6
|
import { Effect } from "effect";
|
|
@@ -75,15 +73,9 @@ import { Effect as Effect2 } from "effect";
|
|
|
75
73
|
var makeKeychainProvider = (serviceName) => ({
|
|
76
74
|
key: "keychain",
|
|
77
75
|
writable: true,
|
|
78
|
-
get: (secretId) => getPassword(serviceName, secretId).pipe(
|
|
79
|
-
|
|
80
|
-
),
|
|
81
|
-
set: (secretId, value) => setPassword(serviceName, secretId, value).pipe(
|
|
82
|
-
Effect2.orElseSucceed(() => void 0)
|
|
83
|
-
),
|
|
84
|
-
delete: (secretId) => deletePassword(serviceName, secretId).pipe(
|
|
85
|
-
Effect2.orElseSucceed(() => false)
|
|
86
|
-
),
|
|
76
|
+
get: (secretId) => getPassword(serviceName, secretId).pipe(Effect2.orElseSucceed(() => null)),
|
|
77
|
+
set: (secretId, value) => setPassword(serviceName, secretId, value).pipe(Effect2.orElseSucceed(() => void 0)),
|
|
78
|
+
delete: (secretId) => deletePassword(serviceName, secretId).pipe(Effect2.orElseSucceed(() => false)),
|
|
87
79
|
// Keychain doesn't support enumerating — you need to know the account name
|
|
88
80
|
list: void 0
|
|
89
81
|
});
|
|
@@ -115,4 +107,4 @@ export {
|
|
|
115
107
|
makeKeychainProvider,
|
|
116
108
|
keychainPlugin
|
|
117
109
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
110
|
+
//# sourceMappingURL=chunk-XGNRIWKJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/keyring.ts","../src/errors.ts","../src/provider.ts"],"sourcesContent":["import { Effect } from \"effect\";\n\nimport { definePlugin, type SecretId, type ExecutorPlugin } from \"@executor/sdk\";\n\nimport { displayName, isSupportedPlatform, resolveServiceName } from \"./keyring\";\nimport { getPassword } from \"./keyring\";\nimport { makeKeychainProvider } from \"./provider\";\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { KeychainError } from \"./errors\";\nexport { makeKeychainProvider } from \"./provider\";\nexport { isSupportedPlatform, displayName } from \"./keyring\";\n\n// ---------------------------------------------------------------------------\n// Plugin config\n// ---------------------------------------------------------------------------\n\nexport interface KeychainPluginConfig {\n /** Override the keychain service name (default: \"executor\") */\n readonly serviceName?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin extension — public API on executor.keychain\n// ---------------------------------------------------------------------------\n\nexport interface KeychainExtension {\n /** Human-readable name for the keychain on this platform */\n readonly displayName: string;\n\n /** Whether the current platform supports system keychain */\n readonly isSupported: boolean;\n\n /** Check if a secret exists in the system keychain */\n readonly has: (secretId: SecretId) => Effect.Effect<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin definition\n// ---------------------------------------------------------------------------\n\nconst PLUGIN_KEY = \"keychain\";\n\nexport const keychainPlugin = (\n config?: KeychainPluginConfig,\n): ExecutorPlugin<typeof PLUGIN_KEY, KeychainExtension> =>\n definePlugin({\n key: PLUGIN_KEY,\n init: (ctx) =>\n Effect.gen(function* () {\n // Scope the service name to the current scope so each folder gets its own keychain entries\n const baseServiceName = resolveServiceName(config?.serviceName);\n const serviceName = `${baseServiceName}/${ctx.scope.id}`;\n\n yield* ctx.secrets.addProvider(makeKeychainProvider(serviceName));\n\n const extension: KeychainExtension = {\n displayName: displayName(),\n isSupported: isSupportedPlatform(),\n\n has: (secretId) =>\n getPassword(serviceName, secretId).pipe(\n Effect.map((v) => v !== null),\n Effect.orElseSucceed(() => false),\n ),\n };\n\n return { extension };\n }),\n });\n","import { Effect } from \"effect\";\n\nimport { KeychainError } from \"./errors\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SERVICE_NAME = \"executor\";\nconst SERVICE_NAME_ENV = \"EXECUTOR_KEYCHAIN_SERVICE_NAME\";\n\n// ---------------------------------------------------------------------------\n// Platform helpers\n// ---------------------------------------------------------------------------\n\nexport const isSupportedPlatform = () =>\n process.platform === \"darwin\" || process.platform === \"linux\" || process.platform === \"win32\";\n\nexport const displayName = () =>\n process.platform === \"darwin\"\n ? \"macOS Keychain\"\n : process.platform === \"win32\"\n ? \"Windows Credential Manager\"\n : \"Desktop Keyring\";\n\nexport const resolveServiceName = (explicit?: string): string =>\n explicit?.trim() || process.env[SERVICE_NAME_ENV]?.trim() || DEFAULT_SERVICE_NAME;\n\n// ---------------------------------------------------------------------------\n// Lazy-load @napi-rs/keyring (native module)\n// ---------------------------------------------------------------------------\n\ntype EntryConstructor = (typeof import(\"@napi-rs/keyring\"))[\"Entry\"];\n\nlet entryCtorPromise: Promise<EntryConstructor> | null = null;\n\nconst loadEntry = (): Effect.Effect<EntryConstructor, KeychainError> =>\n Effect.tryPromise({\n try: async () => {\n if (!isSupportedPlatform()) {\n throw new Error(`unsupported platform '${process.platform}'`);\n }\n entryCtorPromise ??= import(\"@napi-rs/keyring\").then(({ Entry }) => Entry);\n return await entryCtorPromise;\n },\n catch: (cause) =>\n new KeychainError({\n message: `Failed loading native keyring: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n });\n\nconst createEntry = (serviceName: string, account: string) =>\n Effect.flatMap(loadEntry(), (Entry) =>\n Effect.try({\n try: () => new Entry(serviceName, account),\n catch: (cause) =>\n new KeychainError({\n message: `Failed creating keyring entry: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n }),\n );\n\n// ---------------------------------------------------------------------------\n// Low-level keychain operations\n// ---------------------------------------------------------------------------\n\nexport const getPassword = (\n serviceName: string,\n account: string,\n): Effect.Effect<string | null, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => entry.getPassword(),\n catch: () => new KeychainError({ message: `Failed reading secret for account '${account}'` }),\n }),\n );\n\nexport const setPassword = (\n serviceName: string,\n account: string,\n value: string,\n): Effect.Effect<void, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => entry.setPassword(value),\n catch: (cause) =>\n new KeychainError({\n message: `Failed writing secret: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n }).pipe(Effect.asVoid),\n );\n\nexport const deletePassword = (\n serviceName: string,\n account: string,\n): Effect.Effect<boolean, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => {\n entry.deletePassword();\n return true;\n },\n catch: () =>\n new KeychainError({ message: `Failed deleting secret for account '${account}'` }),\n }),\n );\n","import { Data } from \"effect\";\n\nexport class KeychainError extends Data.TaggedError(\"KeychainError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n","import { Effect } from \"effect\";\n\nimport type { SecretProvider } from \"@executor/sdk\";\n\nimport { getPassword, setPassword, deletePassword } from \"./keyring\";\n\n// ---------------------------------------------------------------------------\n// SecretProvider adapter — bridges keyring into SDK resolution chain\n// ---------------------------------------------------------------------------\n\nexport const makeKeychainProvider = (serviceName: string): SecretProvider => ({\n key: \"keychain\",\n writable: true,\n get: (secretId) => getPassword(serviceName, secretId).pipe(Effect.orElseSucceed(() => null)),\n set: (secretId, value) =>\n setPassword(serviceName, secretId, value).pipe(Effect.orElseSucceed(() => undefined)),\n delete: (secretId) =>\n deletePassword(serviceName, secretId).pipe(Effect.orElseSucceed(() => false)),\n // Keychain doesn't support enumerating — you need to know the account name\n list: undefined,\n});\n"],"mappings":"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","names":["Effect","Effect","Effect","Effect"]}
|
package/dist/core.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { type SecretId, type ExecutorPlugin } from "@executor-js/sdk
|
|
2
|
+
import { type SecretId, type ExecutorPlugin } from "@executor-js/sdk";
|
|
3
3
|
export { KeychainError } from "./errors";
|
|
4
4
|
export { makeKeychainProvider } from "./provider";
|
|
5
5
|
export { isSupportedPlatform, displayName } from "./keyring";
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/promise.ts"],"sourcesContent":["import { keychainPlugin as keychainPluginEffect } from \"./index\";\n\nexport type { KeychainPluginConfig } from \"./index\";\n\nexport const keychainPlugin = (
|
|
1
|
+
{"version":3,"sources":["../src/promise.ts"],"sourcesContent":["import { keychainPlugin as keychainPluginEffect } from \"./index\";\n\nexport type { KeychainPluginConfig } from \"./index\";\n\nexport const keychainPlugin = (config?: { readonly serviceName?: string }) =>\n keychainPluginEffect(config);\n"],"mappings":";;;;;AAIO,IAAMA,kBAAiB,CAAC,WAC7B,eAAqB,MAAM;","names":["keychainPlugin"]}
|
package/dist/promise.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export type { KeychainPluginConfig } from "./index";
|
|
2
2
|
export declare const keychainPlugin: (config?: {
|
|
3
3
|
readonly serviceName?: string;
|
|
4
|
-
}) => import("@executor-js/sdk
|
|
4
|
+
}) => import("@executor-js/sdk").ExecutorPlugin<"keychain", import("./index").KeychainExtension>;
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { SecretProvider } from "@executor-js/sdk
|
|
1
|
+
import type { SecretProvider } from "@executor-js/sdk";
|
|
2
2
|
export declare const makeKeychainProvider: (serviceName: string) => SecretProvider;
|
package/package.json
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@executor-js/plugin-keychain",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"version": "0.0.1-beta.6",
|
|
4
|
+
"homepage": "https://github.com/RhysSullivan/executor/tree/main/packages/plugins/keychain",
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/RhysSullivan/executor/issues"
|
|
7
|
+
},
|
|
5
8
|
"license": "MIT",
|
|
6
9
|
"repository": {
|
|
7
10
|
"type": "git",
|
|
8
11
|
"url": "git+https://github.com/RhysSullivan/executor.git",
|
|
9
12
|
"directory": "packages/plugins/keychain"
|
|
10
13
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
15
18
|
"exports": {
|
|
16
19
|
".": {
|
|
17
20
|
"import": {
|
|
@@ -26,28 +29,26 @@
|
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
29
35
|
"scripts": {
|
|
30
36
|
"build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)",
|
|
31
|
-
"typecheck": "
|
|
37
|
+
"typecheck": "tsgo --noEmit",
|
|
32
38
|
"test": "vitest run",
|
|
33
|
-
"test:watch": "vitest"
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"typecheck:slow": "bunx tsc --noEmit -p tsconfig.json"
|
|
34
41
|
},
|
|
35
42
|
"dependencies": {
|
|
43
|
+
"@executor-js/sdk": "0.0.1-beta.6",
|
|
36
44
|
"@napi-rs/keyring": "^1.2.0",
|
|
37
|
-
"@executor-js/sdk": "0.0.1-beta.5",
|
|
38
45
|
"effect": "^3.21.0"
|
|
39
46
|
},
|
|
40
47
|
"devDependencies": {
|
|
41
48
|
"@effect/vitest": "^0.29.0",
|
|
42
49
|
"@types/node": "^24.3.1",
|
|
43
50
|
"bun-types": "^1.2.22",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
}
|
|
47
|
-
"publishConfig": {
|
|
48
|
-
"access": "public"
|
|
49
|
-
},
|
|
50
|
-
"files": [
|
|
51
|
-
"dist"
|
|
52
|
-
]
|
|
51
|
+
"tsup": "^8.5.0",
|
|
52
|
+
"vitest": "^4.1.3"
|
|
53
|
+
}
|
|
53
54
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/keyring.ts","../src/errors.ts","../src/provider.ts"],"sourcesContent":["import { Effect } from \"effect\";\n\nimport {\n definePlugin,\n type SecretId,\n type ExecutorPlugin,\n} from \"@executor/sdk/core\";\n\nimport { displayName, isSupportedPlatform, resolveServiceName } from \"./keyring\";\nimport { getPassword } from \"./keyring\";\nimport { makeKeychainProvider } from \"./provider\";\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { KeychainError } from \"./errors\";\nexport { makeKeychainProvider } from \"./provider\";\nexport { isSupportedPlatform, displayName } from \"./keyring\";\n\n// ---------------------------------------------------------------------------\n// Plugin config\n// ---------------------------------------------------------------------------\n\nexport interface KeychainPluginConfig {\n /** Override the keychain service name (default: \"executor\") */\n readonly serviceName?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin extension — public API on executor.keychain\n// ---------------------------------------------------------------------------\n\nexport interface KeychainExtension {\n /** Human-readable name for the keychain on this platform */\n readonly displayName: string;\n\n /** Whether the current platform supports system keychain */\n readonly isSupported: boolean;\n\n /** Check if a secret exists in the system keychain */\n readonly has: (secretId: SecretId) => Effect.Effect<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin definition\n// ---------------------------------------------------------------------------\n\nconst PLUGIN_KEY = \"keychain\";\n\nexport const keychainPlugin = (\n config?: KeychainPluginConfig,\n): ExecutorPlugin<typeof PLUGIN_KEY, KeychainExtension> =>\n definePlugin({\n key: PLUGIN_KEY,\n init: (ctx) =>\n Effect.gen(function* () {\n // Scope the service name to the current scope so each folder gets its own keychain entries\n const baseServiceName = resolveServiceName(config?.serviceName);\n const serviceName = `${baseServiceName}/${ctx.scope.id}`;\n\n yield* ctx.secrets.addProvider(makeKeychainProvider(serviceName));\n\n const extension: KeychainExtension = {\n displayName: displayName(),\n isSupported: isSupportedPlatform(),\n\n has: (secretId) =>\n getPassword(serviceName, secretId).pipe(\n Effect.map((v) => v !== null),\n Effect.orElseSucceed(() => false),\n ),\n };\n\n return { extension };\n }),\n });\n","import { Effect } from \"effect\";\n\nimport { KeychainError } from \"./errors\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SERVICE_NAME = \"executor\";\nconst SERVICE_NAME_ENV = \"EXECUTOR_KEYCHAIN_SERVICE_NAME\";\n\n// ---------------------------------------------------------------------------\n// Platform helpers\n// ---------------------------------------------------------------------------\n\nexport const isSupportedPlatform = () =>\n process.platform === \"darwin\" ||\n process.platform === \"linux\" ||\n process.platform === \"win32\";\n\nexport const displayName = () =>\n process.platform === \"darwin\"\n ? \"macOS Keychain\"\n : process.platform === \"win32\"\n ? \"Windows Credential Manager\"\n : \"Desktop Keyring\";\n\nexport const resolveServiceName = (explicit?: string): string =>\n explicit?.trim() || process.env[SERVICE_NAME_ENV]?.trim() || DEFAULT_SERVICE_NAME;\n\n// ---------------------------------------------------------------------------\n// Lazy-load @napi-rs/keyring (native module)\n// ---------------------------------------------------------------------------\n\ntype EntryConstructor = (typeof import(\"@napi-rs/keyring\"))[\"Entry\"];\n\nlet entryCtorPromise: Promise<EntryConstructor> | null = null;\n\nconst loadEntry = (): Effect.Effect<EntryConstructor, KeychainError> =>\n Effect.tryPromise({\n try: async () => {\n if (!isSupportedPlatform()) {\n throw new Error(`unsupported platform '${process.platform}'`);\n }\n entryCtorPromise ??= import(\"@napi-rs/keyring\").then(({ Entry }) => Entry);\n return await entryCtorPromise;\n },\n catch: (cause) =>\n new KeychainError({\n message: `Failed loading native keyring: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n });\n\nconst createEntry = (serviceName: string, account: string) =>\n Effect.flatMap(loadEntry(), (Entry) =>\n Effect.try({\n try: () => new Entry(serviceName, account),\n catch: (cause) =>\n new KeychainError({\n message: `Failed creating keyring entry: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n }),\n );\n\n// ---------------------------------------------------------------------------\n// Low-level keychain operations\n// ---------------------------------------------------------------------------\n\nexport const getPassword = (\n serviceName: string,\n account: string,\n): Effect.Effect<string | null, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => entry.getPassword(),\n catch: () => new KeychainError({ message: `Failed reading secret for account '${account}'` }),\n }),\n );\n\nexport const setPassword = (\n serviceName: string,\n account: string,\n value: string,\n): Effect.Effect<void, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => entry.setPassword(value),\n catch: (cause) =>\n new KeychainError({\n message: `Failed writing secret: ${cause instanceof Error ? cause.message : String(cause)}`,\n cause,\n }),\n }).pipe(Effect.asVoid),\n );\n\nexport const deletePassword = (\n serviceName: string,\n account: string,\n): Effect.Effect<boolean, KeychainError> =>\n Effect.flatMap(createEntry(serviceName, account), (entry) =>\n Effect.try({\n try: () => {\n entry.deletePassword();\n return true;\n },\n catch: () => new KeychainError({ message: `Failed deleting secret for account '${account}'` }),\n }),\n );\n","import { Data } from \"effect\";\n\nexport class KeychainError extends Data.TaggedError(\"KeychainError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n","import { Effect } from \"effect\";\n\nimport type { SecretProvider } from \"@executor/sdk/core\";\n\nimport { getPassword, setPassword, deletePassword } from \"./keyring\";\n\n// ---------------------------------------------------------------------------\n// SecretProvider adapter — bridges keyring into SDK resolution chain\n// ---------------------------------------------------------------------------\n\nexport const makeKeychainProvider = (serviceName: string): SecretProvider => ({\n key: \"keychain\",\n writable: true,\n get: (secretId) =>\n getPassword(serviceName, secretId).pipe(\n Effect.orElseSucceed(() => null),\n ),\n set: (secretId, value) =>\n setPassword(serviceName, secretId, value).pipe(\n Effect.orElseSucceed(() => undefined),\n ),\n delete: (secretId) =>\n deletePassword(serviceName, secretId).pipe(\n Effect.orElseSucceed(() => false),\n ),\n // Keychain doesn't support enumerating — you need to know the account name\n list: undefined,\n});\n"],"mappings":"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","names":["Effect","Effect","Effect","Effect"]}
|