@appliance.sh/api-server 1.13.0 → 1.15.0

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/package.json CHANGED
@@ -1,73 +1,43 @@
1
1
  {
2
2
  "name": "@appliance.sh/api-server",
3
- "version": "1.13.0",
3
+ "version": "1.15.0",
4
4
  "description": "",
5
5
  "author": "Eliot Lim",
6
6
  "repository": "https://github.com/appliance-sh/appliance.sh",
7
7
  "license": "MIT",
8
8
  "scripts": {
9
- "build": "nest build",
9
+ "build": "tsc",
10
10
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11
- "start": "nest start",
12
- "start:dev": "nest start --watch",
13
- "start:debug": "nest start --debug --watch",
14
- "start:prod": "node dist/main",
11
+ "start": "node dist/src/main.js",
12
+ "start:dev": "tsx watch src/main.ts",
13
+ "start:debug": "tsx watch --inspect src/main.ts",
14
+ "start:prod": "node dist/src/main.js",
15
15
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16
- "test": "jest",
17
- "test:watch": "jest --watch",
18
- "test:cov": "jest --coverage",
19
- "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20
- "test:e2e": "jest --config ./test/jest-e2e.json"
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "test:cov": "vitest run --coverage",
19
+ "test:e2e": "vitest run --config vitest.e2e.config.ts"
21
20
  },
22
21
  "dependencies": {
23
- "@nestjs/common": "^11.0.1",
24
- "@nestjs/core": "^11.0.1",
25
- "@nestjs/platform-express": "^11.0.1",
26
22
  "@pulumi/aws": "^7.15.0",
27
23
  "@pulumi/pulumi": "^3.213.0",
28
- "reflect-metadata": "^0.2.2",
29
- "rxjs": "^7.8.1"
24
+ "express": "^5.2.1"
30
25
  },
31
26
  "devDependencies": {
32
27
  "@eslint/eslintrc": "^3.2.0",
33
28
  "@eslint/js": "^9.18.0",
34
- "@nestjs/cli": "^11.0.0",
35
- "@nestjs/schematics": "^11.0.0",
36
- "@nestjs/testing": "^11.0.1",
37
29
  "@types/express": "^5.0.0",
38
- "@types/jest": "^30.0.0",
39
30
  "@types/node": "^22.10.7",
40
31
  "@types/supertest": "^6.0.2",
41
32
  "eslint": "^9.18.0",
42
33
  "eslint-config-prettier": "^10.0.1",
43
34
  "eslint-plugin-prettier": "^5.2.2",
44
35
  "globals": "^16.0.0",
45
- "jest": "^30.0.0",
46
36
  "prettier": "^3.4.2",
47
- "source-map-support": "^0.5.21",
48
37
  "supertest": "^7.0.0",
49
- "ts-jest": "^29.2.5",
50
- "ts-loader": "^9.5.2",
51
- "ts-node": "^10.9.2",
52
- "tsconfig-paths": "^4.2.0",
38
+ "tsx": "^4.19.2",
53
39
  "typescript": "^5.7.3",
54
- "typescript-eslint": "^8.20.0"
55
- },
56
- "jest": {
57
- "moduleFileExtensions": [
58
- "js",
59
- "json",
60
- "ts"
61
- ],
62
- "rootDir": "src",
63
- "testRegex": ".*\\.spec\\.ts$",
64
- "transform": {
65
- "^.+\\.(t|j)s$": "ts-jest"
66
- },
67
- "collectCoverageFrom": [
68
- "**/*.(t|j)s"
69
- ],
70
- "coverageDirectory": "../coverage",
71
- "testEnvironment": "node"
40
+ "typescript-eslint": "^8.20.0",
41
+ "vitest": "^3.0.4"
72
42
  }
73
43
  }
@@ -1,22 +1,12 @@
1
- import { Test, TestingModule } from '@nestjs/testing';
2
- import { AppController } from './app.controller';
3
- import { AppService } from './app.service';
4
-
5
- describe('AppController', () => {
6
- let appController: AppController;
7
-
8
- beforeEach(async () => {
9
- const app: TestingModule = await Test.createTestingModule({
10
- controllers: [AppController],
11
- providers: [AppService],
12
- }).compile();
13
-
14
- appController = app.get<AppController>(AppController);
15
- });
16
-
17
- describe('root', () => {
18
- it('should return "Hello World!"', () => {
19
- expect(appController.getHello()).toBe('Hello World!');
20
- });
1
+ import { describe, it, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import { createApp } from './main';
4
+
5
+ describe('Index Route', () => {
6
+ it('should return "Hello World!"', async () => {
7
+ const app = createApp();
8
+ const response = await request(app).get('/');
9
+ expect(response.status).toBe(200);
10
+ expect(response.text).toBe('Hello World!');
21
11
  });
22
12
  });
package/src/main.ts CHANGED
@@ -1,8 +1,26 @@
1
- import { NestFactory } from '@nestjs/core';
2
- import { AppModule } from './app.module';
1
+ import express from 'express';
2
+ import { indexRoutes } from './routes';
3
+ import { infraRoutes } from './routes/infra';
4
+
5
+ export function createApp() {
6
+ const app = express();
7
+
8
+ app.use(express.json());
9
+
10
+ // Set up routes
11
+ app.use('/', indexRoutes);
12
+ app.use('/infra', infraRoutes);
13
+
14
+ return app;
15
+ }
3
16
 
4
17
  async function bootstrap() {
5
- const app = await NestFactory.create(AppModule);
6
- await app.listen(process.env.PORT ?? 3000);
18
+ const app = createApp();
19
+ const port = process.env.PORT ?? 3000;
20
+
21
+ app.listen(port, () => {
22
+ console.log(`Server is running on http://localhost:${port}`);
23
+ });
7
24
  }
25
+
8
26
  bootstrap();
@@ -0,0 +1,7 @@
1
+ import { Router } from 'express';
2
+
3
+ export const indexRoutes = Router();
4
+
5
+ indexRoutes.get('/', (_req, res) => {
6
+ res.send('Hello World!');
7
+ });
@@ -0,0 +1,24 @@
1
+ import { Router } from 'express';
2
+ import { pulumiService } from '../../services/pulumi.service';
3
+
4
+ export const infraRoutes = Router();
5
+
6
+ infraRoutes.post('/deploy', async (_req, res) => {
7
+ try {
8
+ const result = await pulumiService.deploy();
9
+ res.json(result);
10
+ } catch (error) {
11
+ console.error('Deploy error:', error);
12
+ res.status(500).json({ error: 'Deploy failed', message: String(error) });
13
+ }
14
+ });
15
+
16
+ infraRoutes.post('/destroy', async (_req, res) => {
17
+ try {
18
+ const result = await pulumiService.destroy();
19
+ res.json(result);
20
+ } catch (error) {
21
+ console.error('Destroy error:', error);
22
+ res.status(500).json({ error: 'Destroy failed', message: String(error) });
23
+ }
24
+ });
@@ -0,0 +1,176 @@
1
+ import * as pulumi from '@pulumi/pulumi';
2
+ import * as aws from '@pulumi/aws';
3
+ import * as awsNative from '@pulumi/aws-native';
4
+ import type { ApplianceBaseConfig } from '@appliance.sh/sdk';
5
+
6
+ export interface ApplianceStackArgs {
7
+ tags?: Record<string, string>;
8
+ config: ApplianceBaseConfig;
9
+ }
10
+
11
+ export interface ApplianceStackOpts extends pulumi.ComponentResourceOptions {
12
+ globalProvider: aws.Provider;
13
+ provider: aws.Provider;
14
+ nativeProvider: awsNative.Provider;
15
+ nativeGlobalProvider: awsNative.Provider;
16
+ }
17
+
18
+ export class ApplianceStack extends pulumi.ComponentResource {
19
+ lambdaRole: aws.iam.Role;
20
+ lambdaRolePolicy: aws.iam.Policy;
21
+ lambda: aws.lambda.Function;
22
+ lambdaUrl: aws.lambda.FunctionUrl;
23
+ dnsRecord: pulumi.Output<string>;
24
+
25
+ constructor(name: string, args: ApplianceStackArgs, opts: ApplianceStackOpts) {
26
+ super('appliance:aws:ApplianceStack', name, args, opts);
27
+
28
+ const defaultOpts = { parent: this, provider: opts.provider };
29
+ const defaultNativeOpts = { parent: this, provider: opts.nativeProvider };
30
+ const defaultTags = { stack: name, managed: 'appliance', ...args.tags };
31
+
32
+ this.lambdaRole = new aws.iam.Role(`${name}-role`, {
33
+ path: `/appliance/${name}/`,
34
+ assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: 'lambda.amazonaws.com' }),
35
+ tags: defaultTags,
36
+ });
37
+
38
+ this.lambdaRolePolicy = new aws.iam.Policy(`${name}-policy`, {
39
+ path: `/appliance/${name}/`,
40
+ policy: {
41
+ Version: '2012-10-17',
42
+ Statement: [{ Effect: 'Allow', Action: 'logs:CreateLogGroup', Resource: '*' }],
43
+ },
44
+ });
45
+
46
+ new aws.iam.RolePolicyAttachment(`${name}-role-policy-attachment`, {
47
+ role: this.lambdaRole.name,
48
+ policyArn: this.lambdaRolePolicy.arn,
49
+ });
50
+
51
+ this.lambda = new aws.lambda.CallbackFunction(
52
+ `${name}-handler`,
53
+ {
54
+ runtime: 'nodejs22.x',
55
+ callback: async () => {
56
+ return { statusCode: 200, body: JSON.stringify({ message: 'Hello world!' }) };
57
+ },
58
+ tags: defaultTags,
59
+ },
60
+ defaultOpts
61
+ );
62
+
63
+ // lambda url
64
+ this.lambdaUrl = new aws.lambda.FunctionUrl(
65
+ `${name}-url`,
66
+ {
67
+ functionName: this.lambda.name,
68
+ authorizationType: args.config.aws.cloudfrontDistributionId ? 'AWS_IAM' : 'NONE',
69
+ },
70
+ defaultOpts
71
+ );
72
+
73
+ this.dnsRecord = pulumi.interpolate`${name}.${args.config.domainName ?? ''}`;
74
+
75
+ if (args.config.aws.cloudfrontDistributionId) {
76
+ new aws.lambda.Permission(
77
+ `${name}-url-invoke-url-permission`,
78
+ {
79
+ function: this.lambda.name,
80
+ action: 'lambda:InvokeFunctionUrl',
81
+ principal: 'cloudfront.amazonaws.com',
82
+ functionUrlAuthType: 'AWS_IAM',
83
+ sourceArn: pulumi.interpolate`arn:aws:cloudfront::${
84
+ aws.getCallerIdentityOutput({}, { provider: opts.provider }).accountId
85
+ }:distribution/${args.config.aws.cloudfrontDistributionId}`,
86
+ statementId: 'FunctionURLAllowCloudFrontAccess',
87
+ },
88
+ defaultOpts
89
+ );
90
+
91
+ // Grant the edge router role permission to invoke the Lambda Function URL
92
+ // The edge router role is the execution role of the Lambda@Edge function that signs requests
93
+ if (args.config.aws.edgeRouterRoleArn) {
94
+ new aws.lambda.Permission(
95
+ `${name}-invoke-url-edge-router-permission`,
96
+ {
97
+ function: this.lambda.name,
98
+ action: 'lambda:InvokeFunctionUrl',
99
+ principal: args.config.aws.edgeRouterRoleArn,
100
+ functionUrlAuthType: 'AWS_IAM',
101
+ statementId: 'FunctionURLAllowEdgeRouterRoleAccess',
102
+ },
103
+ defaultOpts
104
+ );
105
+
106
+ new awsNative.lambda.Permission(
107
+ `${name}-invoke-edge-router-permission`,
108
+ {
109
+ action: 'lambda:InvokeFunction',
110
+ principal: args.config.aws.edgeRouterRoleArn,
111
+ functionName: this.lambda.name,
112
+ invokedViaFunctionUrl: true,
113
+ },
114
+ defaultNativeOpts
115
+ );
116
+ }
117
+ } else {
118
+ new aws.lambda.Permission(
119
+ `${name}-url-invoke-url-permission`,
120
+ {
121
+ function: this.lambda.name,
122
+ action: 'lambda:InvokeFunctionUrl',
123
+ principal: '*',
124
+ functionUrlAuthType: 'NONE',
125
+ statementId: 'FunctionURLAllowPublicAccess',
126
+ },
127
+ defaultOpts
128
+ );
129
+ }
130
+
131
+ if (args.config.aws.cloudfrontDistributionId && args.config.aws.cloudfrontDistributionDomainName) {
132
+ new awsNative.lambda.Permission(
133
+ `${name}-url-invoke-lambda-native-permission`,
134
+ {
135
+ action: 'lambda:InvokeFunction',
136
+ principal: 'cloudfront.amazonaws.com',
137
+ sourceArn: pulumi.interpolate`arn:aws:cloudfront::${
138
+ aws.getCallerIdentityOutput({}, { provider: opts.provider }).accountId
139
+ }:distribution/${args.config.aws.cloudfrontDistributionId}`,
140
+ functionName: this.lambda.name,
141
+ invokedViaFunctionUrl: true,
142
+ },
143
+ defaultNativeOpts
144
+ );
145
+
146
+ new aws.route53.Record(
147
+ `${name}-cname-record`,
148
+ {
149
+ zoneId: args.config.aws.zoneId,
150
+ name: pulumi.interpolate`${name}.${args.config.domainName ?? ''}`,
151
+ type: 'CNAME',
152
+ ttl: 60,
153
+ records: [args.config.aws.cloudfrontDistributionDomainName],
154
+ },
155
+ { parent: this, provider: opts.globalProvider }
156
+ );
157
+
158
+ new aws.route53.Record(
159
+ `${name}-txt-record`,
160
+ {
161
+ zoneId: args.config.aws.zoneId,
162
+ name: pulumi.interpolate`origin.${name}.${args.config.domainName ?? ''}`,
163
+ type: 'TXT',
164
+ ttl: 60,
165
+ records: [this.lambdaUrl.functionUrl],
166
+ },
167
+ { parent: this, provider: opts.globalProvider }
168
+ );
169
+ }
170
+
171
+ this.registerOutputs({
172
+ lambda: this.lambda,
173
+ lambdaUrl: this.lambdaUrl,
174
+ });
175
+ }
176
+ }
@@ -1,6 +1,6 @@
1
- import { Injectable, Logger } from '@nestjs/common';
2
1
  import * as auto from '@pulumi/pulumi/automation';
3
2
  import * as aws from '@pulumi/aws';
3
+ import * as awsNative from '@pulumi/aws-native';
4
4
  import { ApplianceStack } from './ApplianceStack';
5
5
  import { applianceBaseConfig } from '@appliance.sh/sdk';
6
6
 
@@ -14,34 +14,47 @@ export interface PulumiResult {
14
14
  stackName: string;
15
15
  }
16
16
 
17
- @Injectable()
18
- export class PulumiService {
19
- private readonly logger = new Logger(PulumiService.name);
20
- private readonly region = process.env.AWS_REGION || 'us-east-1';
17
+ class PulumiService {
21
18
  private readonly projectName = 'appliance-api-managed-proj';
22
19
 
23
20
  private readonly baseConfig = process.env.APPLIANCE_BASE_CONFIG
24
21
  ? applianceBaseConfig.parse(JSON.parse(process.env.APPLIANCE_BASE_CONFIG))
25
22
  : undefined;
23
+ private readonly region = this.baseConfig?.aws.region || 'us-east-1';
26
24
 
27
25
  private inlineProgram() {
28
26
  return async () => {
29
27
  const name = 'appliance';
28
+
29
+ if (!this.baseConfig) {
30
+ throw new Error('Missing base config');
31
+ }
32
+
30
33
  const regionalProvider = new aws.Provider(`${name}-regional`, {
31
- region: this.baseConfig?.region ?? 'ap-southeast-1',
34
+ region: (this.baseConfig?.aws.region as aws.Region) ?? 'ap-southeast-1',
32
35
  });
33
36
  const globalProvider = new aws.Provider(`${name}-global`, {
34
37
  region: 'us-east-1',
35
38
  });
39
+ const nativeRegionalProvider = new awsNative.Provider(`${name}-native-regional`, {
40
+ region: (this.baseConfig?.aws.region as awsNative.Region) ?? 'ap-southeast-1',
41
+ });
42
+
43
+ const nativeGlobalProvider = new awsNative.Provider(`${name}-native-global`, {
44
+ region: 'us-east-1',
45
+ });
36
46
 
37
47
  const applianceStack = new ApplianceStack(
38
48
  `${name}-stack`,
39
49
  {
40
50
  tags: { project: name },
51
+ config: this.baseConfig,
41
52
  },
42
53
  {
43
54
  globalProvider,
44
55
  provider: regionalProvider,
56
+ nativeProvider: nativeRegionalProvider,
57
+ nativeGlobalProvider: nativeGlobalProvider,
45
58
  }
46
59
  );
47
60
 
@@ -67,7 +80,7 @@ export class PulumiService {
67
80
  { projectName: this.projectName, stackName, program },
68
81
  { envVars }
69
82
  );
70
- await stack.setConfig('aws:region', { value: this.region });
83
+ await stack.setConfig('aws:region', { value: this.baseConfig.aws.region });
71
84
  return stack;
72
85
  }
73
86
 
@@ -92,7 +105,7 @@ export class PulumiService {
92
105
 
93
106
  async deploy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
94
107
  const stack = await this.getOrCreateStack(stackName);
95
- const result = await stack.up({ onOutput: (m) => this.logger.log(m) });
108
+ const result = await stack.up({ onOutput: (m) => console.log(m) });
96
109
  const changes = result.summary.resourceChanges || {};
97
110
  const totalChanges = Object.entries(changes)
98
111
  .filter(([k]) => k !== 'same')
@@ -110,7 +123,7 @@ export class PulumiService {
110
123
  async destroy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
111
124
  try {
112
125
  const stack = await this.selectExistingStack(stackName);
113
- await stack.destroy({ onOutput: (m) => this.logger.log(m) });
126
+ await stack.destroy({ onOutput: (m) => console.log(m) });
114
127
  return { action: 'destroy', ok: true, idempotentNoop: false, message: 'Stack resources deleted', stackName };
115
128
  } catch (e) {
116
129
  if (!(e instanceof Error)) throw e;
@@ -128,3 +141,6 @@ export class PulumiService {
128
141
  }
129
142
  }
130
143
  }
144
+
145
+ // Export a singleton instance
146
+ export const pulumiService = new PulumiService();
@@ -1,22 +1,18 @@
1
- import { Test, TestingModule } from '@nestjs/testing';
2
- import { INestApplication } from '@nestjs/common';
1
+ import { describe, it, expect, beforeAll } from 'vitest';
3
2
  import request from 'supertest';
4
- import { App } from 'supertest/types';
5
- import { AppModule } from '../src/app.module';
3
+ import { createApp } from '../src/main';
4
+ import type { Express } from 'express';
6
5
 
7
- describe('AppController (e2e)', () => {
8
- let app: INestApplication<App>;
6
+ describe('App (e2e)', () => {
7
+ let app: Express;
9
8
 
10
- beforeEach(async () => {
11
- const moduleFixture: TestingModule = await Test.createTestingModule({
12
- imports: [AppModule],
13
- }).compile();
14
-
15
- app = moduleFixture.createNestApplication();
16
- await app.init();
9
+ beforeAll(() => {
10
+ app = createApp();
17
11
  });
18
12
 
19
- it('/ (GET)', () => {
20
- return request(app.getHttpServer()).get('/').expect(200).expect('Hello World!');
13
+ it('/ (GET)', async () => {
14
+ const response = await request(app).get('/');
15
+ expect(response.status).toBe(200);
16
+ expect(response.text).toBe('Hello World!');
21
17
  });
22
18
  });
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['src/**/*.spec.ts'],
6
+ globals: false,
7
+ },
8
+ });
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['test/**/*.e2e-spec.ts'],
6
+ globals: false,
7
+ },
8
+ });
package/nest-cli.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/nest-cli",
3
- "collection": "@nestjs/schematics",
4
- "sourceRoot": "src",
5
- "compilerOptions": {
6
- "deleteOutDir": true
7
- }
8
- }
@@ -1,12 +0,0 @@
1
- import { Controller, Get } from '@nestjs/common';
2
- import { AppService } from './app.service';
3
-
4
- @Controller()
5
- export class AppController {
6
- constructor(private readonly appService: AppService) {}
7
-
8
- @Get()
9
- getHello(): string {
10
- return this.appService.getHello();
11
- }
12
- }
package/src/app.module.ts DELETED
@@ -1,11 +0,0 @@
1
- import { Module } from '@nestjs/common';
2
- import { AppController } from './app.controller';
3
- import { AppService } from './app.service';
4
- import { PulumiModule } from './pulumi/pulumi.module';
5
-
6
- @Module({
7
- imports: [PulumiModule],
8
- controllers: [AppController],
9
- providers: [AppService],
10
- })
11
- export class AppModule {}
@@ -1,8 +0,0 @@
1
- import { Injectable } from '@nestjs/common';
2
-
3
- @Injectable()
4
- export class AppService {
5
- getHello(): string {
6
- return 'Hello World!';
7
- }
8
- }
@@ -1,86 +0,0 @@
1
- import * as pulumi from '@pulumi/pulumi';
2
- import * as aws from '@pulumi/aws';
3
-
4
- export interface ApplianceStackArgs {
5
- tags?: Record<string, string>;
6
- }
7
-
8
- export interface ApplianceStackOpts extends pulumi.ComponentResourceOptions {
9
- globalProvider: aws.Provider;
10
- provider: aws.Provider;
11
- }
12
-
13
- export class ApplianceStack extends pulumi.ComponentResource {
14
- lambdaRole: aws.iam.Role;
15
- lambdaRolePolicy: aws.iam.Policy;
16
- lambda: aws.lambda.Function;
17
- lambdaUrl: aws.lambda.FunctionUrl;
18
-
19
- constructor(name: string, args: ApplianceStackArgs, opts: ApplianceStackOpts) {
20
- super('appliance:aws:ApplianceStack', name, args, opts);
21
-
22
- const defaultOpts = { parent: this, provider: opts.provider };
23
- const defaultTags = { stack: name, managed: 'appliance', ...args.tags };
24
-
25
- this.lambdaRole = new aws.iam.Role(`${name}-role`, {
26
- path: `/appliance/${name}/`,
27
- assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: 'lambda.amazonaws.com' }),
28
- tags: defaultTags,
29
- });
30
-
31
- this.lambdaRolePolicy = new aws.iam.Policy(`${name}-policy`, {
32
- path: `/appliance/${name}/`,
33
- policy: {
34
- Version: '2012-10-17',
35
- Statement: [{ Effect: 'Allow', Action: 'logs:CreateLogGroup', Resource: '*' }],
36
- },
37
- });
38
-
39
- new aws.iam.RolePolicyAttachment(`${name}-role-policy-attachment`, {
40
- role: this.lambdaRole.name,
41
- policyArn: this.lambdaRolePolicy.arn,
42
- });
43
-
44
- this.lambda = new aws.lambda.CallbackFunction(
45
- `${name}-handler`,
46
- {
47
- runtime: 'nodejs22.x',
48
- callback: async () => {
49
- return { statusCode: 200, body: JSON.stringify({ message: 'Hello world!' }) };
50
- },
51
- tags: defaultTags,
52
- },
53
- defaultOpts
54
- );
55
-
56
- // lambda url
57
- this.lambdaUrl = new aws.lambda.FunctionUrl(
58
- `${name}-url`,
59
- {
60
- functionName: this.lambda.name,
61
- authorizationType: 'NONE',
62
- },
63
- defaultOpts
64
- );
65
-
66
- new aws.lambda.Permission(`${name}-url-invoke-url-permission`, {
67
- function: this.lambda.name,
68
- action: 'lambda:InvokeFunctionUrl',
69
- principal: '*',
70
- functionUrlAuthType: 'NONE',
71
- statementId: 'FunctionURLAllowPublicAccess',
72
- });
73
-
74
- new aws.lambda.Permission(`${name}-url-invoke-lambda-permission`, {
75
- function: this.lambda.name,
76
- action: 'lambda:InvokeFunction',
77
- principal: '*',
78
- statementId: 'FunctionURLAllowInvokeAction',
79
- });
80
-
81
- this.registerOutputs({
82
- lambda: this.lambda,
83
- lambdaUrl: this.lambdaUrl,
84
- });
85
- }
86
- }
@@ -1,19 +0,0 @@
1
- import { Controller, HttpCode, Post } from '@nestjs/common';
2
- import { PulumiService } from './pulumi.service';
3
-
4
- @Controller('infra')
5
- export class PulumiController {
6
- constructor(private readonly pulumi: PulumiService) {}
7
-
8
- @Post('deploy')
9
- @HttpCode(200)
10
- async deploy() {
11
- return await this.pulumi.deploy();
12
- }
13
-
14
- @Post('destroy')
15
- @HttpCode(200)
16
- async destroy() {
17
- return await this.pulumi.destroy();
18
- }
19
- }
@@ -1,9 +0,0 @@
1
- import { Module } from '@nestjs/common';
2
- import { PulumiService } from './pulumi.service';
3
- import { PulumiController } from './pulumi.controller';
4
-
5
- @Module({
6
- providers: [PulumiService],
7
- controllers: [PulumiController],
8
- })
9
- export class PulumiModule {}
@@ -1,9 +0,0 @@
1
- {
2
- "moduleFileExtensions": ["js", "json", "ts"],
3
- "rootDir": ".",
4
- "testEnvironment": "node",
5
- "testRegex": ".e2e-spec.ts$",
6
- "transform": {
7
- "^.+\\.(t|j)s$": "ts-jest"
8
- }
9
- }