@kirschbaum-development/sst-laravel 0.1.5 → 0.2.7

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.
@@ -12,3 +12,10 @@ export declare function extractSstProjectName(configPath: string): string | null
12
12
  export declare function extractLaravelComponents(configPath: string): string[];
13
13
  export declare function extractEnvironmentFile(configPath: string, stage: string): string | null;
14
14
  export declare function validateDeployment(stage: string): void;
15
+ /**
16
+ * Extract RemoteEnvVault secrets configuration from SST config
17
+ * Returns the custom path if specified, or null if no RemoteEnvVault is used
18
+ */
19
+ export declare function extractSecretsConfig(configPath: string): {
20
+ path?: string;
21
+ } | null;
@@ -88,7 +88,9 @@ export function validateDeployment(stage) {
88
88
  throw new Error('Could not find sst.config.ts or sst.config.js in current directory.');
89
89
  }
90
90
  const envFile = extractEnvironmentFile(configPath, stage);
91
- if (envFile) {
91
+ const secretsConfig = extractSecretsConfig(configPath);
92
+ // Only validate env file if secrets are not configured
93
+ if (envFile && !secretsConfig) {
92
94
  const cwd = process.cwd();
93
95
  const envFilePath = path.join(cwd, envFile);
94
96
  if (!fs.existsSync(envFilePath)) {
@@ -96,4 +98,26 @@ export function validateDeployment(stage) {
96
98
  }
97
99
  }
98
100
  }
101
+ /**
102
+ * Extract RemoteEnvVault secrets configuration from SST config
103
+ * Returns the custom path if specified, or null if no RemoteEnvVault is used
104
+ */
105
+ export function extractSecretsConfig(configPath) {
106
+ const content = fs.readFileSync(configPath, 'utf-8');
107
+ // Check if RemoteEnvVault is used
108
+ const laravelEnvMatch = content.match(/new\s+RemoteEnvVault\s*\(/);
109
+ if (!laravelEnvMatch) {
110
+ return null;
111
+ }
112
+ // Check if secrets is configured in environment
113
+ const secretsMatch = content.match(/secrets\s*:\s*(\w+)/);
114
+ if (!secretsMatch) {
115
+ return null;
116
+ }
117
+ // Try to extract custom path from RemoteEnvVault constructor
118
+ const pathMatch = content.match(/new\s+RemoteEnvVault\s*\([^)]*path\s*:\s*['"`]([^'"`]+)['"`]/);
119
+ return {
120
+ path: pathMatch ? pathMatch[1] : undefined,
121
+ };
122
+ }
99
123
  //# sourceMappingURL=sst-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sst-config.js","sourceRoot":"","sources":["../../../bin/utils/sst-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sst-config.js","sourceRoot":"","sources":["../../../bin/utils/sst-config.ts"],"names":[],"mappings":"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"}
package/laravel-sst.ts CHANGED
@@ -9,7 +9,12 @@ import { Input } from "../../../.sst/platform/src/components/input.js";
9
9
  import { ClusterArgs } from "../../../.sst/platform/src/components/aws/cluster.js";
10
10
  import { ServiceArgs } from "../../../.sst/platform/src/components/aws/service.js";
11
11
  import { Dns } from "../../../.sst/platform/src/components/dns.js";
12
- import { applyLinkedResourcesEnv, EnvCallback, EnvCallbacks } from "./src/laravel-env";
12
+ import { applyLinkedResourcesEnv, EnvCallback, EnvCallbacks, extractSecrets } from "./src/laravel-env";
13
+ import { RemoteEnvVault, RemoteEnvVaultArgs } from "./src/laravel-env-manager";
14
+ import { getPackagePath } from "./src/config";
15
+
16
+ // Re-export RemoteEnvVault for external use
17
+ export { RemoteEnvVault, RemoteEnvVaultArgs };
13
18
 
14
19
  // duplicate from cluster.ts
15
20
  type Port = `${number}/${"http" | "https" | "tcp" | "udp" | "tcp_udp" | "tls"}`;
@@ -181,20 +186,39 @@ export interface LaravelArgs extends ClusterArgs {
181
186
  autoInject?: Input<boolean>,
182
187
 
183
188
  /**
184
- * Custom environment variables that will be automatically injected into your application.
185
- *
186
- * @example
187
- * ```js
188
- * environment: {
189
- * vars: {
190
- * SESSION_DRIVER: 'redis',
191
- * QUEUE_CONNECTION: 'redis',
192
- * }
193
- * }
194
- * ```
195
- */
196
- vars?: FunctionArgs["environment"],
197
- };
189
+ * Custom environment variables that will be automatically injected into your application.
190
+ *
191
+ * @example
192
+ * ```js
193
+ * environment: {
194
+ * vars: {
195
+ * SESSION_DRIVER: 'redis',
196
+ * QUEUE_CONNECTION: 'redis',
197
+ * }
198
+ * }
199
+ * ```
200
+ */
201
+ vars?: FunctionArgs["environment"],
202
+
203
+ /**
204
+ * Use a `RemoteEnvVault` component to manage environment variables in AWS Secrets Manager.
205
+ * When provided, secrets will be fetched from AWS Secrets Manager at build time.
206
+ *
207
+ * @example
208
+ * ```js
209
+ * const env = new RemoteEnvVault("Env");
210
+ *
211
+ * new LaravelService("Laravel", {
212
+ * config: {
213
+ * environment: {
214
+ * secrets: env,
215
+ * },
216
+ * },
217
+ * });
218
+ * ```
219
+ */
220
+ secrets?: RemoteEnvVault,
221
+ };
198
222
 
199
223
  /**
200
224
  * Custom deployment configurations.
@@ -223,7 +247,7 @@ export class LaravelService extends Component {
223
247
  args.config = args.config ?? {};
224
248
  const sitePath = args.path ?? '.';
225
249
  const absSitePath = path.resolve(sitePath.toString());
226
- const nodeModulePath = path.resolve(__dirname, '../../node_modules/@kirschbaum-development/sst-laravel');
250
+ const nodeModulePath = getPackagePath();
227
251
 
228
252
  // Determine the path where our plugin will save build files.
229
253
  // SST sets __dirname to the .sst/platform directory.
@@ -287,6 +311,19 @@ export class LaravelService extends Component {
287
311
  dev: {
288
312
  command: `php ${sitePath}/artisan serve`,
289
313
  },
314
+
315
+ transform: {
316
+ taskDefinition: (args) => {
317
+ args.containerDefinitions = (args.containerDefinitions as $util.Output<string>).apply(a => {
318
+ return JSON.stringify([{
319
+ ...JSON.parse(a)[0],
320
+ linuxParameters: {
321
+ initProcessEnabled: false,
322
+ }
323
+ }]);
324
+ })
325
+ }
326
+ }
290
327
  });
291
328
  }
292
329
 
@@ -516,6 +553,13 @@ export class LaravelService extends Component {
516
553
  fs.appendFileSync(envFilePath, '\n' + envContent);
517
554
  }
518
555
  });
556
+
557
+ const secrets = extractSecrets(resources);
558
+ secrets.forEach(secret => {
559
+ all([secret.name, secret.value]).apply(([name, value]) => {
560
+ fs.appendFileSync(envFilePath, `\n${name}=${value}`);
561
+ });
562
+ });
519
563
  };
520
564
 
521
565
  /**
@@ -533,8 +577,31 @@ export class LaravelService extends Component {
533
577
 
534
578
  function prepareEnvironmentFile() {
535
579
  const envFile = args.config?.environment?.file as string | undefined;
580
+ const secrets = args.config?.environment?.secrets;
581
+
582
+ // If secrets are configured, the deploy command will have already
583
+ // fetched them and created the .env file in .sst/laravel/deploy/
584
+ if (secrets) {
585
+ // Check if the .env file was created by the deploy command
586
+ if (fs.existsSync(envFilePath)) {
587
+ // Secrets were fetched, append auto-inject variables
588
+ if (args.config?.environment?.autoInject !== false) {
589
+ applyLinkedResourcesToEnvironment();
590
+ }
591
+ } else {
592
+ // Secrets not fetched yet - this happens during `sst dev` or direct `sst deploy`
593
+ // Create an empty file and add a warning comment
594
+ fs.writeFileSync(envFilePath, '# WARNING: RemoteEnvVault secrets not loaded. Use `sst-laravel deploy` to fetch secrets.\n');
595
+
596
+ if (args.config?.environment?.autoInject !== false) {
597
+ applyLinkedResourcesToEnvironment();
598
+ }
599
+ }
600
+ return;
601
+ }
536
602
 
537
- if (! envFile) {
603
+ // Handle traditional env file configuration
604
+ if (!envFile) {
538
605
  return;
539
606
  }
540
607
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kirschbaum-development/sst-laravel",
3
- "version": "0.1.5",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "description": "An unofficial extension of SST to deploy containerized Laravel applications to AWS Fargate.",
6
6
  "main": "laravel-sst.ts",
@@ -21,7 +21,8 @@
21
21
  "images",
22
22
  "Dockerfile.web",
23
23
  "Dockerfile.worker",
24
- ".dockerignore"
24
+ ".dockerignore",
25
+ "skills"
25
26
  ],
26
27
  "scripts": {
27
28
  "build": "tsc",
@@ -52,6 +53,7 @@
52
53
  "dependencies": {
53
54
  "@aws-sdk/client-ecs": "^3.0.0",
54
55
  "@aws-sdk/client-iam": "^3.0.0",
56
+ "@aws-sdk/client-secrets-manager": "^3.0.0",
55
57
  "@aws-sdk/client-sts": "^3.0.0",
56
58
  "@inquirer/prompts": "^7.0.0",
57
59
  "@pulumi/aws": "^7.8.0",
package/src/config.ts ADDED
@@ -0,0 +1,24 @@
1
+ import * as path from 'path';
2
+
3
+ /**
4
+ * Environment variables set by the CLI to pass configuration to the SST component.
5
+ * These are prefixed with SST_LARAVEL_ to avoid collisions.
6
+ */
7
+ export const SST_LARAVEL_ENV = {
8
+ PACKAGE_ROOT: 'SST_LARAVEL_PACKAGE_ROOT',
9
+ } as const;
10
+
11
+ /**
12
+ * Get the root path of the @kirschbaum-development/sst-laravel package.
13
+ *
14
+ * When invoked via the CLI, this reads from the SST_LARAVEL_PACKAGE_ROOT env var.
15
+ * Otherwise, falls back to resolving from node_modules relative to __dirname
16
+ * (which SST sets to .sst/platform/).
17
+ */
18
+ export function getPackagePath(): string {
19
+ if (process.env[SST_LARAVEL_ENV.PACKAGE_ROOT]) {
20
+ return process.env[SST_LARAVEL_ENV.PACKAGE_ROOT]!;
21
+ }
22
+
23
+ return path.resolve(__dirname, '../../node_modules/@kirschbaum-development/sst-laravel');
24
+ }
@@ -0,0 +1,109 @@
1
+ /// <reference path="./../../../../.sst/platform/config.d.ts" />
2
+
3
+ import { Component } from "../../../../.sst/platform/src/components/component.js";
4
+ import { ComponentResourceOptions, Output, output } from "@pulumi/pulumi";
5
+ import { Input } from "../../../../.sst/platform/src/components/input.js";
6
+
7
+ export interface RemoteEnvVaultArgs {
8
+ /**
9
+ * The path in AWS Secrets Manager where environment variables will be stored.
10
+ * Defaults to `/{app-name}/{stage}/env`.
11
+ *
12
+ * @example
13
+ * ```js
14
+ * new RemoteEnvVault("Env", {
15
+ * path: "/my-app/production/env",
16
+ * });
17
+ * ```
18
+ */
19
+ path?: Input<string>;
20
+ }
21
+
22
+ /**
23
+ * The `RemoteEnvVault` component manages environment variables for your Laravel application
24
+ * using AWS Secrets Manager.
25
+ *
26
+ * The secrets are managed via CLI commands:
27
+ * - `sst-laravel env:push` - Push local .env file to AWS Secrets Manager
28
+ * - `sst-laravel env:pull` - Pull secrets from AWS Secrets Manager to local file
29
+ *
30
+ * Large environment files are automatically split into multiple chunks to handle
31
+ * AWS Secrets Manager's 64KB limit per secret.
32
+ *
33
+ * @example
34
+ * ### Basic usage
35
+ * ```js
36
+ * const env = new RemoteEnvVault("Env");
37
+ *
38
+ * new LaravelService("Laravel", {
39
+ * config: {
40
+ * environment: {
41
+ * secrets: env,
42
+ * },
43
+ * },
44
+ * });
45
+ * ```
46
+ *
47
+ * @example
48
+ * ### Custom path
49
+ * ```js
50
+ * const env = new RemoteEnvVault("Env", {
51
+ * path: "/custom/path/env",
52
+ * });
53
+ * ```
54
+ *
55
+ * @example
56
+ * ### CLI workflow
57
+ * ```bash
58
+ * # Push secrets to AWS
59
+ * sst-laravel env:push --stage production --input .env.production
60
+ *
61
+ * # Pull secrets from AWS
62
+ * sst-laravel env:pull --stage production
63
+ *
64
+ * # Deploy (automatically fetches secrets)
65
+ * sst-laravel deploy --stage production
66
+ * ```
67
+ */
68
+ export class RemoteEnvVault extends Component {
69
+ private readonly _path: Output<string>;
70
+
71
+ /**
72
+ * RemoteEnvVault is a component provided by the sst-laravel package
73
+ * to manage environment variables for your Laravel application using AWS Secrets Manager,
74
+ * making it simple to manage your environment variables in a remote way that also works well with CI/CD pipelines.
75
+ */
76
+ constructor(
77
+ name: string,
78
+ args: RemoteEnvVaultArgs = {},
79
+ opts: ComponentResourceOptions = {},
80
+ ) {
81
+ super(__pulumiType, name, args, opts);
82
+
83
+ // Build the secret path: /{app-name}/{stage}/env
84
+ const secretPath = args.path
85
+ ? output(args.path)
86
+ : output(`/${$app.name}/${$app.stage}/env`);
87
+
88
+ this._path = secretPath;
89
+
90
+ // Note: We don't create the secret here. Secrets are managed via CLI commands
91
+ // (env:push, env:pull) which handle chunking for large environment files.
92
+ // The deploy command fetches secrets before building the Docker image.
93
+
94
+ this.registerOutputs({
95
+ path: this._path,
96
+ });
97
+ }
98
+
99
+ /**
100
+ * The path in AWS Secrets Manager where environment variables are stored.
101
+ */
102
+ public get path(): Output<string> {
103
+ return this._path;
104
+ }
105
+ }
106
+
107
+ const __pulumiType = "sst:aws:RemoteEnvVault";
108
+ // @ts-expect-error
109
+ RemoteEnvVault.__pulumiType = __pulumiType;
@@ -7,10 +7,11 @@ import * as pulumiAws from "@pulumi/aws";
7
7
  import { Queue } from "../../../../.sst/platform/src/components/aws/queue.js";
8
8
  import { Aurora } from "../../../../.sst/platform/src/components/aws/aurora.js";
9
9
  import { Bucket } from "../../../../.sst/platform/src/components/aws/bucket.js";
10
+ import { Secret } from "../../../../.sst/platform/src/components/secret.js";
10
11
 
11
12
  type EnvType = Record<string, string | Output<string>>|Record<string, string | Output<string | undefined> | undefined>;
12
13
  type Database = Postgres | Mysql | Aurora | pulumiAws.rds.Instance;
13
- type LinkSupportedTypes = Database | Email | Queue | Redis | Bucket;
14
+ type LinkSupportedTypes = Database | Email | Queue | Redis | Bucket | Secret;
14
15
 
15
16
  export type EnvCallback = (resource: any) => EnvType;
16
17
  export type EnvCallbacks = {
@@ -73,11 +74,16 @@ export function applyLinkedResourcesEnv(links: LinkSupportedTypes[], callbacks?:
73
74
  ...defaultEnv,
74
75
  };
75
76
  }
77
+
76
78
  });
77
79
 
78
80
  return environment;
79
81
  }
80
82
 
83
+ export function extractSecrets(links: LinkSupportedTypes[]): Secret[] {
84
+ return links.filter((link): link is Secret => link instanceof Secret);
85
+ }
86
+
81
87
  function applyDatabaseEnv(database: Database, callbacks?: EnvCallbacks): EnvType {
82
88
  let port: number | undefined;
83
89
  database.port.apply(value => port = value);
package/sst-env.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  /* tslint:disable */
3
3
  /* eslint-disable */
4
4
  /* deno-fmt-ignore-file */
5
+ /* biome-ignore-all lint: auto-generated */
5
6
 
6
7
  /// <reference path="../../../sst-env.d.ts" />
7
8
 
@@ -1,10 +1,23 @@
1
- const { LaravelService } = await import("@kirschbaum-development/sst-laravel");
1
+ const { LaravelService, RemoteEnvVault } = await import("@kirschbaum-development/sst-laravel");
2
2
  const vpc = new sst.aws.Vpc("MyVpc");
3
3
  // you can also use an existing VPC
4
4
  // const vpc = sst.aws.Vpc.get("DefaultVpc", "vpc-12345678901234567");
5
5
 
6
6
  const database = new sst.aws.Postgres('MyDB', { vpc });
7
7
 
8
+ /**
9
+ * With RemoteEnvVault, SST-Laravel will use the environment variables stored in the remote vault (AWS Secrets Manager)
10
+ * This makes it easy to manage env with teams, and especially makes it ready for CI/CD
11
+ *
12
+ * To get started, create the environment file first, and push it to the remote vault. Examples:
13
+ * - `cp .env.example .env.dev`
14
+ * - `php artisan key:generate --env .env.dev`
15
+ * - `npx sst-laravel env:push --stage dev`
16
+ *
17
+ * Replace `dev` with the stage you want to set up
18
+ */
19
+ const env = new RemoteEnvVault("Env");
20
+
8
21
  const app = new LaravelService("MyLaravelApp", {
9
22
  vpc,
10
23
  link: [database],
@@ -12,7 +25,7 @@
12
25
  config: {
13
26
  php: 8.4,
14
27
  environment: {
15
- file: `.env.${$app.stage}`,
28
+ secrets: env,
16
29
  },
17
30
  deployment: {
18
31
  script: 'infra/deploy.sh',
@@ -33,10 +46,13 @@
33
46
  }
34
47
  },
35
48
 
36
- workers: [{
37
- horizon: true,
38
- scheduler: true,
39
- }]
49
+ // this configuration will create one worker container, which will run horizon and the laravel scheduler as background jobs
50
+ workers: [
51
+ {
52
+ horizon: true,
53
+ scheduler: true,
54
+ }
55
+ ]
40
56
  });
41
57
 
42
58
  return {