@executor-js/plugin-file-secrets 0.0.1-beta.6 → 0.0.1

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.
@@ -4,7 +4,13 @@ import { definePlugin } from "@executor-js/sdk";
4
4
  import * as fs from "fs";
5
5
  import * as path from "path";
6
6
  var APP_NAME = "executor";
7
- var xdgDataHome = () => process.env.XDG_DATA_HOME?.trim() || path.join(process.env.HOME || process.env.USERPROFILE || "~", ".local", "share");
7
+ var xdgDataHome = () => {
8
+ if (process.env.XDG_DATA_HOME?.trim()) return process.env.XDG_DATA_HOME.trim();
9
+ if (process.platform === "win32") {
10
+ return process.env.LOCALAPPDATA || process.env.APPDATA || path.join(process.env.USERPROFILE || "~", "AppData", "Local");
11
+ }
12
+ return path.join(process.env.HOME || "~", ".local", "share");
13
+ };
8
14
  var authDir = (overrideDir) => overrideDir ?? path.join(xdgDataHome(), APP_NAME);
9
15
  var authFilePath = (overrideDir) => path.join(authDir(overrideDir), "auth.json");
10
16
  var ScopedAuthFile = Schema.Record({
@@ -74,6 +80,7 @@ var fileSecretsPlugin = (config) => definePlugin({
74
80
  });
75
81
 
76
82
  export {
83
+ xdgDataHome,
77
84
  fileSecretsPlugin
78
85
  };
79
- //# sourceMappingURL=chunk-PBQRMQCD.js.map
86
+ //# sourceMappingURL=chunk-PBFXEL43.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport { definePlugin, type ExecutorPlugin, type SecretProvider } from \"@executor/sdk\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// XDG data dir resolution\n// ---------------------------------------------------------------------------\n\nconst APP_NAME = \"executor\";\n\nexport const xdgDataHome = (): string => {\n if (process.env.XDG_DATA_HOME?.trim()) return process.env.XDG_DATA_HOME.trim();\n if (process.platform === \"win32\") {\n return process.env.LOCALAPPDATA || process.env.APPDATA || path.join(process.env.USERPROFILE || \"~\", \"AppData\", \"Local\");\n }\n return path.join(process.env.HOME || \"~\", \".local\", \"share\");\n};\n\nconst authDir = (overrideDir?: string): string => overrideDir ?? path.join(xdgDataHome(), APP_NAME);\n\nconst authFilePath = (overrideDir?: string): string => path.join(authDir(overrideDir), \"auth.json\");\n\n// ---------------------------------------------------------------------------\n// Schema for the auth file\n//\n// Top-level keys are scope IDs, values are { secretId: secretValue } maps.\n// { \"web-a1b2c3d4\": { \"github-token\": \"ghp_xxx\" } }\n// ---------------------------------------------------------------------------\n\nconst ScopedAuthFile = Schema.Record({\n key: Schema.String,\n value: Schema.Record({ key: Schema.String, value: Schema.String }),\n});\nconst decodeScopedAuthFile = Schema.decodeUnknownSync(ScopedAuthFile);\n\n// ---------------------------------------------------------------------------\n// File I/O with restricted permissions\n// ---------------------------------------------------------------------------\n\nconst readFullFile = (filePath: string): Record<string, Record<string, string>> => {\n try {\n if (!fs.existsSync(filePath)) return {};\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return decodeScopedAuthFile(JSON.parse(raw));\n } catch {\n return {};\n }\n};\n\nconst readScopeSecrets = (filePath: string, scopeId: string): Record<string, string> =>\n readFullFile(filePath)[scopeId] ?? {};\n\nconst writeScopeSecrets = (\n filePath: string,\n scopeId: string,\n secrets: Record<string, string>,\n): void => {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n const full = readFullFile(filePath);\n if (Object.keys(secrets).length === 0) {\n delete full[scopeId];\n } else {\n full[scopeId] = secrets;\n }\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(full, null, 2), { mode: 0o600 });\n fs.renameSync(tmp, filePath);\n};\n\n// ---------------------------------------------------------------------------\n// Plugin config\n// ---------------------------------------------------------------------------\n\nexport interface FileSecretsPluginConfig {\n /** Override the directory for auth.json (default: XDG data dir) */\n readonly directory?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin extension — public API on executor.fileSecrets\n// ---------------------------------------------------------------------------\n\nexport interface FileSecretsExtension {\n /** Path to the auth file */\n readonly filePath: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider factory (internal)\n// ---------------------------------------------------------------------------\n\nconst makeScopedProvider = (filePath: string, scopeId: string): SecretProvider => ({\n key: \"file\",\n writable: true,\n\n get: (secretId) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n return data[secretId] ?? null;\n }),\n\n set: (secretId, value) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n data[secretId] = value;\n writeScopeSecrets(filePath, scopeId, data);\n }),\n\n delete: (secretId) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n const had = secretId in data;\n delete data[secretId];\n if (had) writeScopeSecrets(filePath, scopeId, data);\n return had;\n }),\n\n list: () =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n return Object.keys(data).map((k) => ({ id: k, name: k }));\n }),\n});\n\n// ---------------------------------------------------------------------------\n// Plugin definition\n// ---------------------------------------------------------------------------\n\nconst PLUGIN_KEY = \"fileSecrets\";\n\nexport const fileSecretsPlugin = (\n config?: FileSecretsPluginConfig,\n): ExecutorPlugin<typeof PLUGIN_KEY, FileSecretsExtension> =>\n definePlugin({\n key: PLUGIN_KEY,\n init: (ctx) =>\n Effect.gen(function* () {\n const filePath = authFilePath(config?.directory);\n\n yield* ctx.secrets.addProvider(makeScopedProvider(filePath, ctx.scope.id));\n\n return {\n extension: { filePath },\n };\n }),\n });\n"],"mappings":"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","names":[]}
package/dist/core.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import {
2
- fileSecretsPlugin
3
- } from "./chunk-PBQRMQCD.js";
2
+ fileSecretsPlugin,
3
+ xdgDataHome
4
+ } from "./chunk-PBFXEL43.js";
4
5
  export {
5
- fileSecretsPlugin
6
+ fileSecretsPlugin,
7
+ xdgDataHome
6
8
  };
7
9
  //# sourceMappingURL=core.js.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type ExecutorPlugin } from "@executor-js/sdk";
2
+ export declare const xdgDataHome: () => string;
2
3
  export interface FileSecretsPluginConfig {
3
4
  /** Override the directory for auth.json (default: XDG data dir) */
4
5
  readonly directory?: string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fileSecretsPlugin
3
- } from "./chunk-PBQRMQCD.js";
3
+ } from "./chunk-PBFXEL43.js";
4
4
 
5
5
  // src/promise.ts
6
6
  var fileSecretsPlugin2 = (config) => fileSecretsPlugin(config);
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@executor-js/plugin-file-secrets",
3
- "version": "0.0.1-beta.6",
3
+ "version": "0.0.1",
4
4
  "homepage": "https://github.com/RhysSullivan/executor/tree/main/packages/plugins/file-secrets",
5
5
  "bugs": {
6
6
  "url": "https://github.com/RhysSullivan/executor/issues"
@@ -40,7 +40,7 @@
40
40
  "typecheck:slow": "bunx tsc --noEmit -p tsconfig.json"
41
41
  },
42
42
  "dependencies": {
43
- "@executor-js/sdk": "0.0.1-beta.6",
43
+ "@executor-js/sdk": "0.0.1",
44
44
  "effect": "^3.21.0"
45
45
  },
46
46
  "devDependencies": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport { definePlugin, type ExecutorPlugin, type SecretProvider } from \"@executor/sdk\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// XDG data dir resolution\n// ---------------------------------------------------------------------------\n\nconst APP_NAME = \"executor\";\n\nconst xdgDataHome = (): string =>\n process.env.XDG_DATA_HOME?.trim() ||\n path.join(process.env.HOME || process.env.USERPROFILE || \"~\", \".local\", \"share\");\n\nconst authDir = (overrideDir?: string): string => overrideDir ?? path.join(xdgDataHome(), APP_NAME);\n\nconst authFilePath = (overrideDir?: string): string => path.join(authDir(overrideDir), \"auth.json\");\n\n// ---------------------------------------------------------------------------\n// Schema for the auth file\n//\n// Top-level keys are scope IDs, values are { secretId: secretValue } maps.\n// { \"web-a1b2c3d4\": { \"github-token\": \"ghp_xxx\" } }\n// ---------------------------------------------------------------------------\n\nconst ScopedAuthFile = Schema.Record({\n key: Schema.String,\n value: Schema.Record({ key: Schema.String, value: Schema.String }),\n});\nconst decodeScopedAuthFile = Schema.decodeUnknownSync(ScopedAuthFile);\n\n// ---------------------------------------------------------------------------\n// File I/O with restricted permissions\n// ---------------------------------------------------------------------------\n\nconst readFullFile = (filePath: string): Record<string, Record<string, string>> => {\n try {\n if (!fs.existsSync(filePath)) return {};\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return decodeScopedAuthFile(JSON.parse(raw));\n } catch {\n return {};\n }\n};\n\nconst readScopeSecrets = (filePath: string, scopeId: string): Record<string, string> =>\n readFullFile(filePath)[scopeId] ?? {};\n\nconst writeScopeSecrets = (\n filePath: string,\n scopeId: string,\n secrets: Record<string, string>,\n): void => {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n const full = readFullFile(filePath);\n if (Object.keys(secrets).length === 0) {\n delete full[scopeId];\n } else {\n full[scopeId] = secrets;\n }\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(full, null, 2), { mode: 0o600 });\n fs.renameSync(tmp, filePath);\n};\n\n// ---------------------------------------------------------------------------\n// Plugin config\n// ---------------------------------------------------------------------------\n\nexport interface FileSecretsPluginConfig {\n /** Override the directory for auth.json (default: XDG data dir) */\n readonly directory?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin extension — public API on executor.fileSecrets\n// ---------------------------------------------------------------------------\n\nexport interface FileSecretsExtension {\n /** Path to the auth file */\n readonly filePath: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider factory (internal)\n// ---------------------------------------------------------------------------\n\nconst makeScopedProvider = (filePath: string, scopeId: string): SecretProvider => ({\n key: \"file\",\n writable: true,\n\n get: (secretId) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n return data[secretId] ?? null;\n }),\n\n set: (secretId, value) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n data[secretId] = value;\n writeScopeSecrets(filePath, scopeId, data);\n }),\n\n delete: (secretId) =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n const had = secretId in data;\n delete data[secretId];\n if (had) writeScopeSecrets(filePath, scopeId, data);\n return had;\n }),\n\n list: () =>\n Effect.sync(() => {\n const data = readScopeSecrets(filePath, scopeId);\n return Object.keys(data).map((k) => ({ id: k, name: k }));\n }),\n});\n\n// ---------------------------------------------------------------------------\n// Plugin definition\n// ---------------------------------------------------------------------------\n\nconst PLUGIN_KEY = \"fileSecrets\";\n\nexport const fileSecretsPlugin = (\n config?: FileSecretsPluginConfig,\n): ExecutorPlugin<typeof PLUGIN_KEY, FileSecretsExtension> =>\n definePlugin({\n key: PLUGIN_KEY,\n init: (ctx) =>\n Effect.gen(function* () {\n const filePath = authFilePath(config?.directory);\n\n yield* ctx.secrets.addProvider(makeScopedProvider(filePath, ctx.scope.id));\n\n return {\n extension: { filePath },\n };\n }),\n });\n"],"mappings":"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","names":[]}