@griffin-app/griffin-executor 0.1.0 → 0.1.2

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.
Files changed (40) hide show
  1. package/dist/executor.d.ts.map +1 -1
  2. package/dist/executor.js +55 -10
  3. package/dist/executor.js.map +1 -1
  4. package/dist/executor.test.js +83 -0
  5. package/dist/executor.test.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/secrets/factory.d.ts +3 -99
  11. package/dist/secrets/factory.d.ts.map +1 -1
  12. package/dist/secrets/factory.js +3 -117
  13. package/dist/secrets/factory.js.map +1 -1
  14. package/dist/secrets/index.d.ts +5 -3
  15. package/dist/secrets/index.d.ts.map +1 -1
  16. package/dist/secrets/index.js +4 -2
  17. package/dist/secrets/index.js.map +1 -1
  18. package/dist/secrets/providers/aws.d.ts +10 -12
  19. package/dist/secrets/providers/aws.d.ts.map +1 -1
  20. package/dist/secrets/providers/aws.js +44 -58
  21. package/dist/secrets/providers/aws.js.map +1 -1
  22. package/dist/secrets/providers/index.d.ts +0 -2
  23. package/dist/secrets/providers/index.d.ts.map +1 -1
  24. package/dist/secrets/providers/index.js +0 -2
  25. package/dist/secrets/providers/index.js.map +1 -1
  26. package/dist/secrets/resolver.d.ts.map +1 -1
  27. package/dist/secrets/resolver.js +1 -1
  28. package/dist/secrets/resolver.js.map +1 -1
  29. package/dist/secrets/secrets.test.js.map +1 -1
  30. package/package.json +3 -3
  31. package/src/executor.test.ts +90 -0
  32. package/src/executor.ts +84 -12
  33. package/src/index.ts +0 -8
  34. package/src/secrets/factory.ts +5 -211
  35. package/src/secrets/index.ts +3 -9
  36. package/src/secrets/providers/index.ts +0 -10
  37. package/src/secrets/resolver.ts +5 -1
  38. package/src/secrets/secrets.test.ts +1 -0
  39. package/tsconfig.tsbuildinfo +1 -0
  40. package/src/secrets/providers/aws.ts +0 -178
@@ -1,178 +0,0 @@
1
- /**
2
- * AWS Secrets Manager secret provider.
3
- *
4
- * Reads secrets from AWS Secrets Manager. Supports JSON secrets
5
- * with field extraction and version staging.
6
- *
7
- * Usage in DSL:
8
- * secret("aws:my-secret")
9
- * secret("aws:prod/api-keys", { field: "stripe" })
10
- * secret("aws:my-secret", { version: "AWSPREVIOUS" })
11
- */
12
-
13
- import type { SecretProvider, SecretResolveOptions } from "../types.js";
14
- import { SecretResolutionError } from "../types.js";
15
-
16
- /**
17
- * Interface for AWS Secrets Manager client.
18
- * This allows dependency injection of the actual AWS SDK client.
19
- */
20
- export interface AwsSecretsManagerClient {
21
- getSecretValue(params: { SecretId: string; VersionStage?: string }): Promise<{
22
- SecretString?: string;
23
- SecretBinary?: Uint8Array;
24
- }>;
25
- }
26
-
27
- export interface AwsSecretsManagerProviderOptions {
28
- /**
29
- * AWS Secrets Manager client instance.
30
- * Should be pre-configured with region and credentials.
31
- */
32
- client: AwsSecretsManagerClient;
33
-
34
- /**
35
- * Optional prefix for secret names.
36
- * For example, if prefix is "myapp/", then secret("aws:api-key")
37
- * will look for "myapp/api-key" in Secrets Manager.
38
- */
39
- prefix?: string;
40
-
41
- /**
42
- * Default version stage to use if not specified.
43
- * Defaults to "AWSCURRENT".
44
- */
45
- defaultVersionStage?: string;
46
- }
47
-
48
- export class AwsSecretsManagerProvider implements SecretProvider {
49
- readonly name = "aws";
50
- private readonly client: AwsSecretsManagerClient;
51
- private readonly prefix: string;
52
- private readonly defaultVersionStage: string;
53
-
54
- // Simple in-memory cache with TTL
55
- private cache = new Map<string, { value: string; expires: number }>();
56
- private readonly cacheTtlMs = 5 * 60 * 1000; // 5 minutes
57
-
58
- constructor(options: AwsSecretsManagerProviderOptions) {
59
- this.client = options.client;
60
- this.prefix = options.prefix ?? "";
61
- this.defaultVersionStage = options.defaultVersionStage ?? "AWSCURRENT";
62
- }
63
-
64
- async resolve(ref: string, options?: SecretResolveOptions): Promise<string> {
65
- const secretId = this.prefix + ref;
66
- const versionStage = options?.version ?? this.defaultVersionStage;
67
- const cacheKey = `${secretId}:${versionStage}`;
68
-
69
- // Check cache
70
- const cached = this.cache.get(cacheKey);
71
- if (cached && cached.expires > Date.now()) {
72
- return this.extractField(cached.value, options?.field, ref);
73
- }
74
-
75
- try {
76
- const response = await this.client.getSecretValue({
77
- SecretId: secretId,
78
- VersionStage: versionStage,
79
- });
80
-
81
- if (!response.SecretString) {
82
- throw new SecretResolutionError(
83
- `Secret "${secretId}" does not contain a string value (binary secrets are not supported)`,
84
- { ref },
85
- );
86
- }
87
-
88
- // Cache the raw value
89
- this.cache.set(cacheKey, {
90
- value: response.SecretString,
91
- expires: Date.now() + this.cacheTtlMs,
92
- });
93
-
94
- return this.extractField(response.SecretString, options?.field, ref);
95
- } catch (error) {
96
- if (error instanceof SecretResolutionError) {
97
- throw error;
98
- }
99
-
100
- // Handle common AWS errors
101
- const awsError = error as { name?: string; message?: string };
102
- let message = `Failed to retrieve secret "${secretId}"`;
103
-
104
- if (awsError.name === "ResourceNotFoundException") {
105
- message = `Secret "${secretId}" not found in AWS Secrets Manager`;
106
- } else if (awsError.name === "AccessDeniedException") {
107
- message = `Access denied to secret "${secretId}". Check IAM permissions.`;
108
- } else if (awsError.message) {
109
- message = `${message}: ${awsError.message}`;
110
- }
111
-
112
- throw new SecretResolutionError(message, {
113
- ref,
114
- cause: error,
115
- });
116
- }
117
- }
118
-
119
- /**
120
- * Extract a field from a JSON secret string.
121
- */
122
- private extractField(
123
- secretValue: string,
124
- field: string | undefined,
125
- ref: string,
126
- ): string {
127
- if (!field) {
128
- return secretValue;
129
- }
130
-
131
- try {
132
- const parsed = JSON.parse(secretValue);
133
-
134
- if (typeof parsed !== "object" || parsed === null) {
135
- throw new SecretResolutionError(
136
- `Secret "${ref}" is not a JSON object, cannot extract field "${field}"`,
137
- { ref },
138
- );
139
- }
140
-
141
- const value = parsed[field];
142
-
143
- if (value === undefined) {
144
- throw new SecretResolutionError(
145
- `Field "${field}" not found in secret "${ref}"`,
146
- { ref },
147
- );
148
- }
149
-
150
- // Convert to string if not already
151
- return typeof value === "string" ? value : JSON.stringify(value);
152
- } catch (error) {
153
- if (error instanceof SecretResolutionError) {
154
- throw error;
155
- }
156
-
157
- throw new SecretResolutionError(
158
- `Failed to parse secret "${ref}" as JSON for field extraction: ${
159
- error instanceof Error ? error.message : String(error)
160
- }`,
161
- { ref, cause: error },
162
- );
163
- }
164
- }
165
-
166
- async validate(): Promise<void> {
167
- // Try a simple operation to verify credentials
168
- // This is a no-op if the client is properly configured
169
- // The actual validation happens on first secret access
170
- }
171
-
172
- /**
173
- * Clear the cache. Useful for testing or forced refresh.
174
- */
175
- clearCache(): void {
176
- this.cache.clear();
177
- }
178
- }