@executor-js/plugin-keychain 0.0.1-beta.3 → 0.0.1-beta.4

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 CHANGED
@@ -1,4 +1,4 @@
1
- # @executor-js/plugin-keychain
1
+ # @executor/plugin-keychain
2
2
 
3
3
  OS-keychain-backed secret store for the executor. Reads and writes secrets to:
4
4
 
@@ -8,21 +8,21 @@ OS-keychain-backed secret store for the executor. Reads and writes secrets to:
8
8
 
9
9
  Secrets are encrypted at rest by the operating system and never touch your project's filesystem.
10
10
 
11
- Pairs with [`@executor-js/sdk`](https://www.npmjs.com/package/@executor-js/sdk) (promise-based) or [`@executor-js/core`](https://www.npmjs.com/package/@executor-js/core) (Effect-based).
11
+ Pairs with [`@executor/sdk`](https://www.npmjs.com/package/@executor/sdk) (promise-based) or [`@executor/core`](https://www.npmjs.com/package/@executor/core) (Effect-based).
12
12
 
13
13
  ## Install
14
14
 
15
15
  ```sh
16
- bun add @executor-js/sdk @executor-js/plugin-keychain
16
+ bun add @executor/sdk @executor/plugin-keychain
17
17
  # or
18
- npm install @executor-js/sdk @executor-js/plugin-keychain
18
+ npm install @executor/sdk @executor/plugin-keychain
19
19
  ```
20
20
 
21
21
  ## Usage
22
22
 
23
23
  ```ts
24
- import { createExecutor } from "@executor-js/sdk";
25
- import { keychainPlugin } from "@executor-js/plugin-keychain";
24
+ import { createExecutor } from "@executor/sdk";
25
+ import { keychainPlugin } from "@executor/plugin-keychain";
26
26
 
27
27
  const executor = await createExecutor({
28
28
  scope: { name: "my-app" },
@@ -42,14 +42,14 @@ if (executor.keychain.isSupported) {
42
42
  }
43
43
  ```
44
44
 
45
- Secrets written through this plugin are available to every other plugin that resolves secrets by ID — so you can store a token once and use it across `@executor-js/plugin-openapi`, `@executor-js/plugin-graphql`, etc. via `{ secretId, prefix }` headers.
45
+ Secrets written through this plugin are available to every other plugin that resolves secrets by ID — so you can store a token once and use it across `@executor/plugin-openapi`, `@executor/plugin-graphql`, etc. via `{ secretId, prefix }` headers.
46
46
 
47
47
  ## Effect entry point
48
48
 
49
- If you're using `@executor-js/core` directly, import from the `/core` subpath:
49
+ If you're using `@executor/core` directly, import from the `/core` subpath:
50
50
 
51
51
  ```ts
52
- import { keychainPlugin } from "@executor-js/plugin-keychain/core";
52
+ import { keychainPlugin } from "@executor/plugin-keychain/core";
53
53
  ```
54
54
 
55
55
  ## Status
@@ -8,14 +8,8 @@ import {
8
8
  import { Effect } from "effect";
9
9
 
10
10
  // src/errors.ts
11
- import { Schema } from "effect";
12
- var KeychainError = class extends Schema.TaggedError()(
13
- "KeychainError",
14
- {
15
- message: Schema.String,
16
- cause: Schema.optional(Schema.Unknown)
17
- }
18
- ) {
11
+ import { Data } from "effect";
12
+ var KeychainError = class extends Data.TaggedError("KeychainError") {
19
13
  };
20
14
 
21
15
  // src/keyring.ts
@@ -121,4 +115,4 @@ export {
121
115
  makeKeychainProvider,
122
116
  keychainPlugin
123
117
  };
124
- //# sourceMappingURL=chunk-OFXK6TNJ.js.map
118
+ //# sourceMappingURL=chunk-AWJ4XIQJ.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 {\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"]}
package/dist/core.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  isSupportedPlatform,
5
5
  keychainPlugin,
6
6
  makeKeychainProvider
7
- } from "./chunk-OFXK6TNJ.js";
7
+ } from "./chunk-AWJ4XIQJ.js";
8
8
  export {
9
9
  KeychainError,
10
10
  displayName,
package/dist/errors.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { Schema } from "effect";
2
- declare const KeychainError_base: Schema.TaggedErrorClass<KeychainError, "KeychainError", {
3
- readonly _tag: Schema.tag<"KeychainError">;
4
- } & {
5
- message: typeof Schema.String;
6
- cause: Schema.optional<typeof Schema.Unknown>;
7
- }>;
8
- export declare class KeychainError extends KeychainError_base {
1
+ declare const KeychainError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "KeychainError";
3
+ } & Readonly<A>;
4
+ export declare class KeychainError extends KeychainError_base<{
5
+ readonly message: string;
6
+ readonly cause?: unknown;
7
+ }> {
9
8
  }
10
9
  export {};
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  keychainPlugin
3
- } from "./chunk-OFXK6TNJ.js";
3
+ } from "./chunk-AWJ4XIQJ.js";
4
4
 
5
5
  // src/promise.ts
6
6
  var keychainPlugin2 = (config) => keychainPlugin(config);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@executor-js/plugin-keychain",
3
3
  "type": "module",
4
- "version": "0.0.1-beta.3",
4
+ "version": "0.0.1-beta.4",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@napi-rs/keyring": "^1.2.0",
37
- "@executor-js/sdk": "0.0.1-beta.2",
37
+ "@executor-js/sdk": "0.0.1-beta.4",
38
38
  "effect": "^3.21.0"
39
39
  },
40
40
  "devDependencies": {
@@ -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-js/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 { Schema } from \"effect\";\n\nexport class KeychainError extends Schema.TaggedError<KeychainError>()(\n \"KeychainError\",\n {\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n },\n) {}\n","import { Effect } from \"effect\";\n\nimport type { SecretProvider } from \"@executor-js/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"]}