@appliance.sh/api-server 1.16.0 → 1.17.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@appliance.sh/api-server",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "",
5
5
  "author": "Eliot Lim",
6
6
  "repository": "https://github.com/appliance-sh/appliance.sh",
@@ -19,11 +19,8 @@
19
19
  "test:e2e": "vitest run --config vitest.e2e.config.ts"
20
20
  },
21
21
  "dependencies": {
22
- "@appliance.sh/infra": "1.16.0",
23
- "@appliance.sh/sdk": "1.16.0",
24
- "@pulumi/aws": "^7.16.0",
25
- "@pulumi/aws-native": "^1.48.0",
26
- "@pulumi/pulumi": "^3.216.0",
22
+ "@appliance.sh/infra": "1.17.0",
23
+ "@appliance.sh/sdk": "1.17.0",
27
24
  "express": "^5.2.1"
28
25
  },
29
26
  "devDependencies": {
@@ -1,146 +1,12 @@
1
- import * as auto from '@pulumi/pulumi/automation';
2
- import * as aws from '@pulumi/aws';
3
- import * as awsNative from '@pulumi/aws-native';
4
- import { ApplianceStack } from '@appliance.sh/infra';
5
- import { applianceBaseConfig } from '@appliance.sh/sdk';
1
+ import {
2
+ ApplianceDeploymentService,
3
+ createApplianceDeploymentService,
4
+ type PulumiAction,
5
+ type PulumiResult,
6
+ } from '@appliance.sh/infra';
6
7
 
7
- export type PulumiAction = 'deploy' | 'destroy';
8
-
9
- export interface PulumiResult {
10
- action: PulumiAction;
11
- ok: boolean;
12
- idempotentNoop: boolean;
13
- message: string;
14
- stackName: string;
15
- }
16
-
17
- class PulumiService {
18
- private readonly projectName = 'appliance-api-managed-proj';
19
-
20
- private readonly baseConfig = process.env.APPLIANCE_BASE_CONFIG
21
- ? applianceBaseConfig.parse(JSON.parse(process.env.APPLIANCE_BASE_CONFIG))
22
- : undefined;
23
- private readonly region = this.baseConfig?.aws.region || 'us-east-1';
24
-
25
- private inlineProgram() {
26
- return async () => {
27
- const name = 'appliance';
28
-
29
- if (!this.baseConfig) {
30
- throw new Error('Missing base config');
31
- }
32
-
33
- const regionalProvider = new aws.Provider(`${name}-regional`, {
34
- region: (this.baseConfig?.aws.region as aws.Region) ?? 'ap-southeast-1',
35
- });
36
- const globalProvider = new aws.Provider(`${name}-global`, {
37
- region: 'us-east-1',
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
- });
46
-
47
- const applianceStack = new ApplianceStack(
48
- `${name}-stack`,
49
- {
50
- tags: { project: name },
51
- config: this.baseConfig,
52
- },
53
- {
54
- globalProvider,
55
- provider: regionalProvider,
56
- nativeProvider: nativeRegionalProvider,
57
- nativeGlobalProvider: nativeGlobalProvider,
58
- }
59
- );
60
-
61
- return {
62
- applianceStack,
63
- };
64
- };
65
- }
66
-
67
- private async getOrCreateStack(stackName: string): Promise<auto.Stack> {
68
- const program = this.inlineProgram();
69
- const envVars: Record<string, string> = {
70
- AWS_REGION: this.region,
71
- };
72
- if (!this.baseConfig) {
73
- throw new Error('Missing base config');
74
- }
75
- if (this.baseConfig) {
76
- envVars['PULUMI_BACKEND_URL'] = this.baseConfig.stateBackendUrl;
77
- }
78
-
79
- const stack = await auto.LocalWorkspace.createOrSelectStack(
80
- { projectName: this.projectName, stackName, program },
81
- { envVars }
82
- );
83
- await stack.setConfig('aws:region', { value: this.baseConfig.aws.region });
84
- return stack;
85
- }
86
-
87
- private async selectExistingStack(stackName: string): Promise<auto.Stack> {
88
- const envVars: Record<string, string> = {
89
- AWS_REGION: this.region,
90
- };
91
- if (!this.baseConfig) {
92
- throw new Error('Missing base config');
93
- }
94
- if (this.baseConfig) {
95
- envVars['PULUMI_BACKEND_URL'] = this.baseConfig.stateBackendUrl;
96
- }
97
-
98
- const ws = await auto.LocalWorkspace.create({
99
- projectSettings: { name: this.projectName, runtime: 'nodejs' },
100
- envVars,
101
- });
102
-
103
- return auto.Stack.createOrSelect(stackName, ws);
104
- }
105
-
106
- async deploy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
107
- const stack = await this.getOrCreateStack(stackName);
108
- const result = await stack.up({ onOutput: (m) => console.log(m) });
109
- const changes = result.summary.resourceChanges || {};
110
- const totalChanges = Object.entries(changes)
111
- .filter(([k]) => k !== 'same')
112
- .reduce((acc, [, v]) => acc + (v || 0), 0);
113
- const idempotentNoop = totalChanges === 0;
114
- return {
115
- action: 'deploy',
116
- ok: true,
117
- idempotentNoop,
118
- message: idempotentNoop ? 'No changes (idempotent)' : 'Stack updated',
119
- stackName,
120
- };
121
- }
122
-
123
- async destroy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
124
- try {
125
- const stack = await this.selectExistingStack(stackName);
126
- await stack.destroy({ onOutput: (m) => console.log(m) });
127
- return { action: 'destroy', ok: true, idempotentNoop: false, message: 'Stack resources deleted', stackName };
128
- } catch (e) {
129
- if (!(e instanceof Error)) throw e;
130
- const msg = String(e?.message || e);
131
- if (msg.includes('no stack named') || msg.includes('not found')) {
132
- return {
133
- action: 'destroy',
134
- ok: true,
135
- idempotentNoop: true,
136
- message: 'Stack not found (idempotent)',
137
- stackName,
138
- };
139
- }
140
- throw e;
141
- }
142
- }
143
- }
8
+ // Re-export types for consumers
9
+ export type { PulumiAction, PulumiResult };
144
10
 
145
11
  // Export a singleton instance
146
- export const pulumiService = new PulumiService();
12
+ export const pulumiService: ApplianceDeploymentService = createApplianceDeploymentService();