@geek-fun/serverlessinsight 0.4.0 → 0.5.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/.gitattributes +1 -0
- package/README.md +108 -8
- package/README.zh-CN.md +52 -8
- package/dist/package.json +37 -35
- package/dist/src/commands/deploy.js +17 -7
- package/dist/src/commands/destroy.js +27 -4
- package/dist/src/commands/forceUnlock.js +61 -0
- package/dist/src/commands/index.js +86 -14
- package/dist/src/commands/local.js +10 -1
- package/dist/src/commands/plan.js +33 -0
- package/dist/src/commands/template.js +3 -1
- package/dist/src/commands/validate.js +2 -1
- package/dist/src/common/aliyunClient/apigwOperations.js +652 -0
- package/dist/src/common/aliyunClient/dnsOperations.js +90 -0
- package/dist/src/common/aliyunClient/ecsOperations.js +141 -0
- package/dist/src/common/aliyunClient/esOperations.js +219 -0
- package/dist/src/common/aliyunClient/fc3Operations.js +270 -0
- package/dist/src/common/aliyunClient/index.js +141 -0
- package/dist/src/common/aliyunClient/nasOperations.js +233 -0
- package/dist/src/common/aliyunClient/ossOperations.js +237 -0
- package/dist/src/common/aliyunClient/ramOperations.js +205 -0
- package/dist/src/common/aliyunClient/rdsOperations.js +206 -0
- package/dist/src/common/aliyunClient/slsOperations.js +218 -0
- package/dist/src/common/aliyunClient/tablestoreOperations.js +199 -0
- package/dist/src/common/aliyunClient/types.js +2 -0
- package/dist/src/common/constants.js +7 -1
- package/dist/src/common/context.js +32 -14
- package/dist/src/common/credentials.js +39 -0
- package/dist/src/common/dependencyGraph/graph.js +280 -0
- package/dist/src/common/dependencyGraph/index.js +18 -0
- package/dist/src/common/dependencyGraph/types.js +2 -0
- package/dist/src/common/fileUtils.js +16 -0
- package/dist/src/common/hashUtils.js +121 -0
- package/dist/src/common/iacHelper.js +25 -97
- package/dist/src/common/imsClient.js +4 -0
- package/dist/src/common/index.js +7 -2
- package/dist/src/common/lockManager.js +212 -0
- package/dist/src/common/logger.js +89 -6
- package/dist/src/common/providerEnum.js +2 -3
- package/dist/src/common/runtimeMapper.js +160 -0
- package/dist/src/common/scfClient.js +84 -0
- package/dist/src/common/stateManager.js +107 -0
- package/dist/src/common/tencentClient/cosOperations.js +287 -0
- package/dist/src/common/tencentClient/esOperations.js +156 -0
- package/dist/src/common/tencentClient/index.js +116 -0
- package/dist/src/common/tencentClient/scfOperations.js +141 -0
- package/dist/src/common/tencentClient/tdsqlcOperations.js +211 -0
- package/dist/src/common/tencentClient/types.js +17 -0
- package/dist/src/lang/en.js +254 -0
- package/dist/src/lang/index.js +28 -8
- package/dist/src/lang/zh-CN.js +229 -0
- package/dist/src/parser/bucketParser.js +25 -12
- package/dist/src/parser/databaseParser.js +14 -10
- package/dist/src/parser/functionParser.js +19 -6
- package/dist/src/parser/parseUtils.js +74 -0
- package/dist/src/parser/tableParser.js +19 -17
- package/dist/src/stack/aliyunStack/apigwExecutor.js +84 -0
- package/dist/src/stack/aliyunStack/apigwPlanner.js +118 -0
- package/dist/src/stack/aliyunStack/apigwResource.js +339 -0
- package/dist/src/stack/aliyunStack/apigwTypes.js +125 -0
- package/dist/src/stack/aliyunStack/databaseExecutor.js +112 -0
- package/dist/src/stack/aliyunStack/databasePlanner.js +128 -0
- package/dist/src/stack/aliyunStack/databaseResource.js +228 -0
- package/dist/src/stack/aliyunStack/deployer.js +133 -0
- package/dist/src/stack/aliyunStack/destroyer.js +114 -0
- package/dist/src/stack/aliyunStack/esServerlessTypes.js +141 -0
- package/dist/src/stack/aliyunStack/fc3Executor.js +91 -0
- package/dist/src/stack/aliyunStack/fc3Planner.js +77 -0
- package/dist/src/stack/aliyunStack/fc3Resource.js +511 -0
- package/dist/src/stack/aliyunStack/fc3Types.js +76 -0
- package/dist/src/stack/aliyunStack/index.js +40 -0
- package/dist/src/stack/aliyunStack/ossExecutor.js +91 -0
- package/dist/src/stack/aliyunStack/ossPlanner.js +76 -0
- package/dist/src/stack/aliyunStack/ossResource.js +196 -0
- package/dist/src/stack/aliyunStack/ossTypes.js +50 -0
- package/dist/src/stack/aliyunStack/planner.js +37 -0
- package/dist/src/stack/aliyunStack/rdsTypes.js +217 -0
- package/dist/src/stack/aliyunStack/tablestoreExecutor.js +92 -0
- package/dist/src/stack/aliyunStack/tablestorePlanner.js +94 -0
- package/dist/src/stack/aliyunStack/tablestoreResource.js +120 -0
- package/dist/src/stack/aliyunStack/tablestoreTypes.js +77 -0
- package/dist/src/stack/bucketTypes.js +17 -0
- package/dist/src/stack/deploy.js +24 -77
- package/dist/src/stack/localStack/bucket.js +11 -6
- package/dist/src/stack/localStack/event.js +10 -5
- package/dist/src/stack/localStack/function.js +13 -7
- package/dist/src/stack/localStack/functionRunner.js +1 -1
- package/dist/src/stack/localStack/localServer.js +7 -6
- package/dist/src/stack/scfStack/cosExecutor.js +91 -0
- package/dist/src/stack/scfStack/cosPlanner.js +76 -0
- package/dist/src/stack/scfStack/cosResource.js +126 -0
- package/dist/src/stack/scfStack/cosTypes.js +46 -0
- package/dist/src/stack/scfStack/deployer.js +91 -0
- package/dist/src/stack/scfStack/destroyer.js +88 -0
- package/dist/src/stack/scfStack/esServerlessExecutor.js +105 -0
- package/dist/src/stack/scfStack/esServerlessPlanner.js +86 -0
- package/dist/src/stack/scfStack/esServerlessResource.js +94 -0
- package/dist/src/stack/scfStack/esServerlessTypes.js +48 -0
- package/dist/src/stack/scfStack/index.js +35 -0
- package/dist/src/stack/scfStack/planner.js +91 -0
- package/dist/src/stack/scfStack/scfExecutor.js +91 -0
- package/dist/src/stack/scfStack/scfPlanner.js +78 -0
- package/dist/src/stack/scfStack/scfResource.js +216 -0
- package/dist/src/stack/scfStack/scfTypes.js +41 -0
- package/dist/src/stack/scfStack/tdsqlcExecutor.js +105 -0
- package/dist/src/stack/scfStack/tdsqlcPlanner.js +90 -0
- package/dist/src/stack/scfStack/tdsqlcResource.js +146 -0
- package/dist/src/stack/scfStack/tdsqlcTypes.js +59 -0
- package/dist/src/types/domains/lock.js +2 -0
- package/dist/src/types/domains/resolvable.js +2 -0
- package/dist/src/types/domains/state.js +19 -0
- package/dist/src/types/index.js +4 -0
- package/dist/src/validator/bucketSchema.js +4 -10
- package/dist/src/validator/databaseSchema.js +36 -36
- package/dist/src/validator/eventSchema.js +3 -2
- package/dist/src/validator/functionSchema.js +51 -46
- package/dist/src/validator/iacSchema.js +52 -3
- package/dist/src/validator/rootSchema.js +47 -1
- package/dist/src/validator/tableschema.js +9 -8
- package/dist/src/validator/templateRefSchema.js +23 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +37 -35
- package/samples/README_TENCENT_COS.md +486 -0
- package/samples/README_TENCENT_SCF.md +272 -0
- package/samples/aliyun-poc-api.yml +1 -1
- package/samples/aliyun-poc-bucket.yml +0 -1
- package/samples/aliyun-poc-domain.yml +0 -1
- package/samples/aliyun-poc-es.yml +14 -13
- package/samples/aliyun-poc-rds.yml +0 -2
- package/samples/aliyun-poc-table.yml +1 -3
- package/samples/tencent-poc-cos.yml +20 -0
- package/samples/tencent-poc-scf.yml +36 -0
- package/dist/src/commands/index.d.ts +0 -2
- package/dist/src/common/index.d.ts +0 -11
- package/dist/src/common/rosAssets.js +0 -178
- package/dist/src/common/rosClient.js +0 -198
- package/dist/src/index.d.ts +0 -1
- package/dist/src/lang/index.d.ts +0 -3
- package/dist/src/parser/index.d.ts +0 -3
- package/dist/src/stack/index.d.ts +0 -1
- package/dist/src/stack/localStack/index.d.ts +0 -5
- package/dist/src/stack/rfsStack/index.d.ts +0 -9
- package/dist/src/stack/rosStack/bootstrap.js +0 -187
- package/dist/src/stack/rosStack/bucket.js +0 -127
- package/dist/src/stack/rosStack/database.js +0 -313
- package/dist/src/stack/rosStack/event.js +0 -143
- package/dist/src/stack/rosStack/function.js +0 -259
- package/dist/src/stack/rosStack/index.d.ts +0 -7
- package/dist/src/stack/rosStack/index.js +0 -75
- package/dist/src/stack/rosStack/stage.js +0 -46
- package/dist/src/stack/rosStack/table.js +0 -95
- package/dist/src/stack/rosStack/tag.js +0 -11
- package/dist/src/stack/rosStack/vars.js +0 -49
- package/dist/src/types/index.d.ts +0 -55
- package/dist/src/types/localStack/index.d.ts +0 -81
- package/dist/src/validator/index.d.ts +0 -1
- package/layers/si-bootstrap-sdk/Dockerfile-aliyuncli +0 -12
- package/layers/si-bootstrap-sdk/README.md +0 -1
- package/layers/si-bootstrap-sdk/package-lock.json +0 -875
- package/layers/si-bootstrap-sdk/package.json +0 -33
package/.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* text=auto eol=lf
|
package/README.md
CHANGED
|
@@ -47,14 +47,14 @@ Whether you're building on AWS, Alibaba Cloud, Huawei Cloud, or other providers,
|
|
|
47
47
|
|
|
48
48
|
ServerlessInsight supports the following cloud providers:
|
|
49
49
|
|
|
50
|
-
| Provider
|
|
51
|
-
|
|
52
|
-
| **Alibaba Cloud** | ✅ FC3
|
|
53
|
-
| **Huawei Cloud**
|
|
54
|
-
| **AWS**
|
|
55
|
-
| **Azure**
|
|
56
|
-
| **Google Cloud**
|
|
57
|
-
| **Tencent Cloud** | 🔜 Planned
|
|
50
|
+
| Provider | Functions | API Gateway | Storage | Databases | Status |
|
|
51
|
+
| ----------------- | ---------------- | -------------- | -------------- | ---------------- | ------- |
|
|
52
|
+
| **Alibaba Cloud** | ✅ FC3 | ✅ API Gateway | ✅ OSS | ✅ RDS, OTS, ESS | Stable |
|
|
53
|
+
| **Huawei Cloud** | ✅ FunctionGraph | 🚧 Coming Soon | 🚧 Coming Soon | 🚧 Coming Soon | Beta |
|
|
54
|
+
| **AWS** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
|
55
|
+
| **Azure** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
|
56
|
+
| **Google Cloud** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
|
57
|
+
| **Tencent Cloud** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
|
58
58
|
|
|
59
59
|
---
|
|
60
60
|
|
|
@@ -188,6 +188,105 @@ curl http://localhost:4567/si_buckets/<bucket_key>/subdir/
|
|
|
188
188
|
|
|
189
189
|
The bucket handler serves files from the directory specified in your bucket's `website.code` configuration.
|
|
190
190
|
|
|
191
|
+
### Architecture
|
|
192
|
+
|
|
193
|
+
ServerlessInsight follows a **functional client architecture** that cleanly separates cloud provider SDKs from business logic:
|
|
194
|
+
|
|
195
|
+
#### Layered Design
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
┌─────────────────────────────────────────┐
|
|
199
|
+
│ Resource / Planner / Executor Layer │ ← Provider-agnostic business logic
|
|
200
|
+
│ (Pure functions, no SDK imports) │
|
|
201
|
+
└─────────────────────────────────────────┘
|
|
202
|
+
↓
|
|
203
|
+
┌─────────────────────────────────────────┐
|
|
204
|
+
│ Functional Client Layer │ ← Encapsulated SDK operations
|
|
205
|
+
│ (aliyunClient.ts, tencentClient.ts) │
|
|
206
|
+
└─────────────────────────────────────────┘
|
|
207
|
+
↓
|
|
208
|
+
┌─────────────────────────────────────────┐
|
|
209
|
+
│ Cloud Provider SDKs │ ← @alicloud/*, tencentcloud-*
|
|
210
|
+
└─────────────────────────────────────────┘
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Key Principles
|
|
214
|
+
|
|
215
|
+
- **Functional & Pure**: All business logic uses pure functions with immutable data
|
|
216
|
+
- **SDK Encapsulation**: Provider SDKs are accessed ONLY through client modules
|
|
217
|
+
- **Operation Functions**: Clients expose high-level operation functions (e.g., `createFunction`, `getFunction`)
|
|
218
|
+
- **No Classes**: Prefer `type` over `interface`, and functional patterns over classes
|
|
219
|
+
- **Minimal Side Effects**: File I/O and other side effects are isolated at boundaries
|
|
220
|
+
|
|
221
|
+
#### Client Pattern Example
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// ✅ Client exposes operation functions, not raw SDKs
|
|
225
|
+
export type AliyunClient = {
|
|
226
|
+
fc3: {
|
|
227
|
+
createFunction: (config: Fc3FunctionConfig, codeBase64: string) => Promise<void>;
|
|
228
|
+
getFunction: (functionName: string) => Promise<Fc3FunctionInfo | null>;
|
|
229
|
+
// ... other operations
|
|
230
|
+
};
|
|
231
|
+
// ... other services
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// ✅ Resource layer uses clean client API
|
|
235
|
+
const client = createAliyunClient(context);
|
|
236
|
+
const codeBase64 = readFileAsBase64(codePath);
|
|
237
|
+
await client.fc3.createFunction(config, codeBase64);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
This architecture enables:
|
|
241
|
+
|
|
242
|
+
- **Better Testing**: Mock client operations instead of SDKs
|
|
243
|
+
- **Maintainability**: Provider changes isolated to client layer
|
|
244
|
+
- **Type Safety**: Strong typing throughout the stack
|
|
245
|
+
- **Code Reuse**: Shared client operations across resources
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 🗄️ State Management
|
|
250
|
+
|
|
251
|
+
ServerlessInsight uses a state-based deployment model that tracks all deployed resources in a local state file (`.serverlessinsight/state.json`). This enables:
|
|
252
|
+
|
|
253
|
+
- **Incremental deployments** - Only changed resources are updated
|
|
254
|
+
- **Drift detection** - Identifies differences between local state and cloud resources
|
|
255
|
+
- **Safe destruction** - Knows which resources to clean up
|
|
256
|
+
|
|
257
|
+
### Partial Failure Recovery
|
|
258
|
+
|
|
259
|
+
When deploying multiple resources, if one fails, ServerlessInsight ensures that:
|
|
260
|
+
|
|
261
|
+
1. **Successfully deployed resources are always saved to state** - Even if subsequent resources fail, your state file will contain all resources that were successfully created/updated/deleted
|
|
262
|
+
2. **Clear error reporting** - You'll see which resources succeeded and which failed
|
|
263
|
+
3. **Easy retry** - Simply run `deploy` again to continue from where you left off
|
|
264
|
+
|
|
265
|
+
Example partial failure output:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
⚠️ PARTIAL DEPLOYMENT FAILURE: 2 resource(s) succeeded, but functions.api_handler failed.
|
|
269
|
+
State has been saved for successfully deployed resources. Run deploy again to retry failed resources.
|
|
270
|
+
Next steps: 1) Review the error above, 2) Fix any configuration issues, 3) Run deploy again to continue.
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### State File Location
|
|
274
|
+
|
|
275
|
+
The state file is stored in `.serverlessinsight/state.json` in your project directory. This file:
|
|
276
|
+
|
|
277
|
+
- Should be committed to version control for team collaboration
|
|
278
|
+
- Contains resource metadata and identifiers
|
|
279
|
+
- Is automatically updated after each successful operation
|
|
280
|
+
|
|
281
|
+
### State Recovery
|
|
282
|
+
|
|
283
|
+
If you encounter state drift (cloud resources exist that aren't in your state file):
|
|
284
|
+
|
|
285
|
+
1. **Manual import** - Currently, resources must be manually added to the state file
|
|
286
|
+
2. **Clean start** - Delete the state file and resources in the cloud, then redeploy
|
|
287
|
+
|
|
288
|
+
> 💡 **Tip**: Always backup your state file before making manual modifications.
|
|
289
|
+
|
|
191
290
|
---
|
|
192
291
|
|
|
193
292
|
## 📘 Documentation
|
|
@@ -195,6 +294,7 @@ The bucket handler serves files from the directory specified in your bucket's `w
|
|
|
195
294
|
For comprehensive documentation, visit [serverlessinsight.geekfun.club](https://serverlessinsight.geekfun.club)
|
|
196
295
|
|
|
197
296
|
Additional resources:
|
|
297
|
+
|
|
198
298
|
- [Quick Start Guide](https://serverlessinsight.geekfun.club)
|
|
199
299
|
- [Configuration Reference](https://serverlessinsight.geekfun.club)
|
|
200
300
|
- [API Documentation](https://serverlessinsight.geekfun.club)
|
package/README.zh-CN.md
CHANGED
|
@@ -47,14 +47,14 @@ ServerlessInsight 是一个强大的 Serverless 框架,用于跨多个云服
|
|
|
47
47
|
|
|
48
48
|
ServerlessInsight 支持以下云服务商:
|
|
49
49
|
|
|
50
|
-
| 云服务商
|
|
51
|
-
|
|
52
|
-
| **阿里云**
|
|
53
|
-
| **华为云**
|
|
54
|
-
| **AWS**
|
|
55
|
-
| **Azure**
|
|
56
|
-
| **Google Cloud** | 🔜 计划中
|
|
57
|
-
| **腾讯云**
|
|
50
|
+
| 云服务商 | 函数 | API 网关 | 存储 | 数据库 | 状态 |
|
|
51
|
+
| ---------------- | ---------------- | ----------- | ----------- | ---------------- | ------ |
|
|
52
|
+
| **阿里云** | ✅ FC3 | ✅ API 网关 | ✅ OSS | ✅ RDS, OTS, ESS | 稳定 |
|
|
53
|
+
| **华为云** | ✅ FunctionGraph | 🚧 即将推出 | 🚧 即将推出 | 🚧 即将推出 | 测试版 |
|
|
54
|
+
| **AWS** | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 计划中 |
|
|
55
|
+
| **Azure** | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 计划中 |
|
|
56
|
+
| **Google Cloud** | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 计划中 |
|
|
57
|
+
| **腾讯云** | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 🔜 计划中 | 计划中 |
|
|
58
58
|
|
|
59
59
|
---
|
|
60
60
|
|
|
@@ -178,6 +178,7 @@ npm run lint:check
|
|
|
178
178
|
完整文档请访问 [serverlessinsight.geekfun.club](https://serverlessinsight.geekfun.club)
|
|
179
179
|
|
|
180
180
|
其他资源:
|
|
181
|
+
|
|
181
182
|
- [快速开始指南](https://serverlessinsight.geekfun.club)
|
|
182
183
|
- [配置参考](https://serverlessinsight.geekfun.club)
|
|
183
184
|
- [API 文档](https://serverlessinsight.geekfun.club)
|
|
@@ -185,6 +186,49 @@ npm run lint:check
|
|
|
185
186
|
|
|
186
187
|
---
|
|
187
188
|
|
|
189
|
+
## 🗄️ 状态管理
|
|
190
|
+
|
|
191
|
+
ServerlessInsight 使用基于状态的部署模型,在本地状态文件 (`.serverlessinsight/state.json`) 中跟踪所有已部署的资源。这使得:
|
|
192
|
+
|
|
193
|
+
- **增量部署** - 只有更改的资源才会被更新
|
|
194
|
+
- **漂移检测** - 识别本地状态与云资源之间的差异
|
|
195
|
+
- **安全销毁** - 知道要清理哪些资源
|
|
196
|
+
|
|
197
|
+
### 部分失败恢复
|
|
198
|
+
|
|
199
|
+
当部署多个资源时,如果其中一个失败,ServerlessInsight 确保:
|
|
200
|
+
|
|
201
|
+
1. **成功部署的资源始终保存到状态** - 即使后续资源失败,您的状态文件也将包含所有成功创建/更新/删除的资源
|
|
202
|
+
2. **清晰的错误报告** - 您将看到哪些资源成功,哪些资源失败
|
|
203
|
+
3. **轻松重试** - 只需再次运行 `deploy` 即可从中断的地方继续
|
|
204
|
+
|
|
205
|
+
部分失败输出示例:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
⚠️ 部署部分失败: 2 个资源成功,但 functions.api_handler 失败。
|
|
209
|
+
已成功部署的资源状态已保存。再次运行 deploy 以重试失败的资源。
|
|
210
|
+
后续步骤: 1) 查看上面的错误, 2) 修复配置问题, 3) 再次运行 deploy 继续。
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 状态文件位置
|
|
214
|
+
|
|
215
|
+
状态文件存储在项目目录的 `.serverlessinsight/state.json` 中。此文件:
|
|
216
|
+
|
|
217
|
+
- 应提交到版本控制以便团队协作
|
|
218
|
+
- 包含资源元数据和标识符
|
|
219
|
+
- 在每次成功操作后自动更新
|
|
220
|
+
|
|
221
|
+
### 状态恢复
|
|
222
|
+
|
|
223
|
+
如果遇到状态漂移(云资源存在但不在状态文件中):
|
|
224
|
+
|
|
225
|
+
1. **手动导入** - 目前,资源必须手动添加到状态文件
|
|
226
|
+
2. **重新开始** - 删除状态文件和云中的资源,然后重新部署
|
|
227
|
+
|
|
228
|
+
> 💡 **提示**:在进行手动修改之前,请始终备份您的状态文件。
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
188
232
|
## 🤝 贡献
|
|
189
233
|
|
|
190
234
|
我们欢迎社区的贡献!以下是您可以帮助的方式:
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geek-fun/serverlessinsight",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Full life cycle cross providers serverless application management for your fast-growing business.",
|
|
5
5
|
"homepage": "https://serverlessinsight.geekfun.club",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"si": "dist/src/commands/index.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "DEBUG=ServerlessInsight jest --runInBand --detectOpenHandles --coverage --coverageReporters json-summary text html lcov",
|
|
12
|
+
"test": "cross-env DEBUG=ServerlessInsight jest --runInBand --detectOpenHandles --coverage --coverageReporters json-summary text html lcov",
|
|
13
13
|
"test:ci": "jest --runInBand --ci --coverage --coverageReporters json-summary text html lcov",
|
|
14
14
|
"build": "tsc --build",
|
|
15
15
|
"lint:fix": "eslint --fix ./",
|
|
@@ -49,54 +49,56 @@
|
|
|
49
49
|
"function"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@alicloud/
|
|
52
|
+
"@alicloud/alidns20150109": "^4.3.1",
|
|
53
|
+
"@alicloud/cloudapi20160714": "^4.7.9",
|
|
54
|
+
"@alicloud/ecs20140526": "^7.6.0",
|
|
55
|
+
"@alicloud/es-serverless20230627": "^2.3.0",
|
|
56
|
+
"@alicloud/fc20230330": "^4.6.8",
|
|
57
|
+
"@alicloud/ims20190815": "^2.3.3",
|
|
58
|
+
"@alicloud/nas20170626": "^3.3.1",
|
|
53
59
|
"@alicloud/openapi-client": "^0.4.15",
|
|
54
|
-
"@alicloud/
|
|
55
|
-
"@alicloud/
|
|
56
|
-
"@alicloud/
|
|
57
|
-
"
|
|
58
|
-
"@alicloud/ros-cdk-elasticsearchserverless": "^1.11.0",
|
|
59
|
-
"@alicloud/ros-cdk-fc3": "^1.11.0",
|
|
60
|
-
"@alicloud/ros-cdk-nas": "^1.11.0",
|
|
61
|
-
"@alicloud/ros-cdk-oss": "^1.11.0",
|
|
62
|
-
"@alicloud/ros-cdk-ossdeployment": "^1.11.0",
|
|
63
|
-
"@alicloud/ros-cdk-ots": "^1.11.0",
|
|
64
|
-
"@alicloud/ros-cdk-ram": "^1.11.0",
|
|
65
|
-
"@alicloud/ros-cdk-rds": "^1.11.0",
|
|
66
|
-
"@alicloud/ros-cdk-ros": "^1.11.0",
|
|
67
|
-
"@alicloud/ros-cdk-sls": "^1.11.0",
|
|
68
|
-
"@alicloud/ros-cdk-vpc": "^1.11.0",
|
|
69
|
-
"@alicloud/ros20190910": "^3.6.0",
|
|
70
|
-
"ajv": "^8.17.1",
|
|
60
|
+
"@alicloud/ram20150501": "^1.2.0",
|
|
61
|
+
"@alicloud/rds20140815": "^15.5.1",
|
|
62
|
+
"@alicloud/sls20201230": "^5.9.0",
|
|
63
|
+
"ajv": "^8.18.0",
|
|
71
64
|
"ali-oss": "^6.23.0",
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"i": "^0.3.7",
|
|
65
|
+
"commander": "^14.0.3",
|
|
66
|
+
"cos-nodejs-sdk-v5": "^2.16.0-beta.8",
|
|
75
67
|
"i18n": "^0.15.3",
|
|
68
|
+
"iconv-lite": "^0.7.2",
|
|
76
69
|
"jszip": "^3.10.1",
|
|
77
|
-
"lodash": "^4.17.
|
|
78
|
-
"
|
|
79
|
-
"pino": "^10.1.0",
|
|
70
|
+
"lodash": "^4.17.23",
|
|
71
|
+
"pino": "^10.3.1",
|
|
80
72
|
"pino-pretty": "^13.1.3",
|
|
73
|
+
"tablestore": "^5.6.3",
|
|
74
|
+
"tencentcloud-sdk-nodejs-cynosdb": "^4.1.188",
|
|
75
|
+
"tencentcloud-sdk-nodejs-es": "^4.1.183",
|
|
76
|
+
"tencentcloud-sdk-nodejs-scf": "^4.1.168",
|
|
81
77
|
"yaml": "^2.8.2"
|
|
82
78
|
},
|
|
83
79
|
"devDependencies": {
|
|
84
|
-
"@
|
|
80
|
+
"@eslint/eslintrc": "^3.3.4",
|
|
81
|
+
"@eslint/js": "^10.0.1",
|
|
82
|
+
"@types/ali-oss": "^6.23.3",
|
|
85
83
|
"@types/i18n": "^0.13.12",
|
|
86
84
|
"@types/jest": "^30.0.0",
|
|
87
|
-
"@types/lodash": "^4.17.
|
|
88
|
-
"@types/node": "^25.
|
|
89
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
90
|
-
"@typescript-eslint/parser": "^8.
|
|
91
|
-
"
|
|
85
|
+
"@types/lodash": "^4.17.24",
|
|
86
|
+
"@types/node": "^25.3.2",
|
|
87
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
88
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
89
|
+
"cross-env": "^10.1.0",
|
|
90
|
+
"eslint": "^10.0.2",
|
|
92
91
|
"eslint-config-prettier": "^10.1.8",
|
|
93
|
-
"eslint-plugin-prettier": "^5.5.
|
|
94
|
-
"globals": "^
|
|
92
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
93
|
+
"globals": "^17.3.0",
|
|
95
94
|
"husky": "^9.1.7",
|
|
96
95
|
"jest": "^30.2.0",
|
|
97
|
-
"prettier": "^3.
|
|
96
|
+
"prettier": "^3.8.1",
|
|
98
97
|
"ts-jest": "^29.4.6",
|
|
99
98
|
"ts-node": "^10.9.2",
|
|
100
99
|
"typescript": "^5.9.3"
|
|
100
|
+
},
|
|
101
|
+
"overrides": {
|
|
102
|
+
"fast-xml-parser": ">=5.3.8"
|
|
101
103
|
}
|
|
102
104
|
}
|
|
@@ -4,13 +4,23 @@ exports.deploy = void 0;
|
|
|
4
4
|
const stack_1 = require("../stack");
|
|
5
5
|
const common_1 = require("../common");
|
|
6
6
|
const parser_1 = require("../parser");
|
|
7
|
+
const lang_1 = require("../lang");
|
|
7
8
|
const deploy = async (stackName, options) => {
|
|
8
|
-
common_1.logger.info('
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
common_1.
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
common_1.logger.info(lang_1.lang.__('VALIDATING_YAML'));
|
|
10
|
+
const iacLocation = (0, common_1.getIacLocation)(options.location);
|
|
11
|
+
const rawIac = (0, parser_1.parseYaml)(iacLocation);
|
|
12
|
+
common_1.logger.info(lang_1.lang.__('YAML_VALID'));
|
|
13
|
+
await (0, common_1.setContext)({ ...options, stackName, iacProvider: rawIac.provider, stages: rawIac.stages }, true);
|
|
14
|
+
const context = (0, common_1.getContext)();
|
|
15
|
+
const iac = (0, parser_1.revalYaml)(iacLocation, context);
|
|
16
|
+
// Store IAC in context for access by all functions
|
|
17
|
+
(0, common_1.setIac)(iac);
|
|
18
|
+
common_1.logger.info(lang_1.lang.__('DEPLOYING_STACK'));
|
|
19
|
+
// Acquire lock for the deployment operation
|
|
20
|
+
const statePath = (0, common_1.getStatePath)();
|
|
21
|
+
await (0, common_1.withLock)(statePath, 'deploy', async () => {
|
|
22
|
+
await (0, stack_1.deployStack)(stackName, iac);
|
|
23
|
+
});
|
|
24
|
+
common_1.logger.info(lang_1.lang.__('STACK_DEPLOYED'));
|
|
15
25
|
};
|
|
16
26
|
exports.deploy = deploy;
|
|
@@ -3,11 +3,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.destroyStack = void 0;
|
|
4
4
|
const common_1 = require("../common");
|
|
5
5
|
const parser_1 = require("../parser");
|
|
6
|
+
const lang_1 = require("../lang");
|
|
7
|
+
const scfStack_1 = require("../stack/scfStack");
|
|
8
|
+
const aliyunStack_1 = require("../stack/aliyunStack");
|
|
6
9
|
const destroyStack = async (stackName, options) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
10
|
+
const iacLocation = (0, common_1.getIacLocation)(options.location);
|
|
11
|
+
const rawIac = (0, parser_1.parseYaml)(iacLocation);
|
|
12
|
+
await (0, common_1.setContext)({ stackName, ...options, iacProvider: rawIac.provider, stages: rawIac.stages }, true);
|
|
9
13
|
const context = (0, common_1.getContext)();
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
const iac = (0, parser_1.revalYaml)(iacLocation, context);
|
|
15
|
+
// Store IAC in context for access by all functions
|
|
16
|
+
(0, common_1.setIac)(iac);
|
|
17
|
+
common_1.logger.info(lang_1.lang.__('DESTROYING_STACK', {
|
|
18
|
+
stackName,
|
|
19
|
+
provider: context.provider,
|
|
20
|
+
region: context.region,
|
|
21
|
+
}));
|
|
22
|
+
// Acquire lock for the destroy operation
|
|
23
|
+
const statePath = (0, common_1.getStatePath)();
|
|
24
|
+
await (0, common_1.withLock)(statePath, 'destroy', async () => {
|
|
25
|
+
if (iac.provider.name === common_1.ProviderEnum.TENCENT) {
|
|
26
|
+
await (0, scfStack_1.destroyTencentStack)();
|
|
27
|
+
}
|
|
28
|
+
else if (iac.provider.name === common_1.ProviderEnum.ALIYUN) {
|
|
29
|
+
await (0, aliyunStack_1.destroyAliyunStack)();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new Error(`Unsupported provider: ${iac.provider.name}`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
12
35
|
};
|
|
13
36
|
exports.destroyStack = destroyStack;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.forceUnlockCommand = void 0;
|
|
7
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
8
|
+
const common_1 = require("../common");
|
|
9
|
+
const lang_1 = require("../lang");
|
|
10
|
+
const askConfirmation = (question) => {
|
|
11
|
+
const rl = node_readline_1.default.createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout,
|
|
14
|
+
});
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
rl.question(question, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.toLowerCase().trim() === 'yes');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const forceUnlockCommand = async (lockId) => {
|
|
23
|
+
const statePath = (0, common_1.getStatePath)();
|
|
24
|
+
// Check if lock exists
|
|
25
|
+
const existingLock = (0, common_1.readLockFileForCommand)(statePath);
|
|
26
|
+
if (!existingLock) {
|
|
27
|
+
common_1.logger.error(lang_1.lang.__('NO_LOCK_FOUND'));
|
|
28
|
+
throw new Error(lang_1.lang.__('NO_LOCK_FOUND'));
|
|
29
|
+
}
|
|
30
|
+
// Verify lock ID matches
|
|
31
|
+
if (existingLock.id !== lockId) {
|
|
32
|
+
common_1.logger.error(lang_1.lang.__('LOCK_ID_MISMATCH', {
|
|
33
|
+
providedId: lockId,
|
|
34
|
+
actualId: existingLock.id,
|
|
35
|
+
}));
|
|
36
|
+
throw new Error(lang_1.lang.__('LOCK_ID_MISMATCH', {
|
|
37
|
+
providedId: lockId,
|
|
38
|
+
actualId: existingLock.id,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
// Show lock info
|
|
42
|
+
common_1.logger.info(lang_1.lang.__('CURRENT_LOCK_INFO'));
|
|
43
|
+
common_1.logger.info((0, common_1.formatLockInfo)(existingLock));
|
|
44
|
+
// Ask for confirmation
|
|
45
|
+
common_1.logger.warn(lang_1.lang.__('FORCE_UNLOCK_WARNING'));
|
|
46
|
+
const confirmed = await askConfirmation(lang_1.lang.__('FORCE_UNLOCK_CONFIRM'));
|
|
47
|
+
if (!confirmed) {
|
|
48
|
+
common_1.logger.info(lang_1.lang.__('FORCE_UNLOCK_CANCELLED'));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Force unlock
|
|
52
|
+
const success = (0, common_1.forceUnlock)(statePath, lockId);
|
|
53
|
+
if (success) {
|
|
54
|
+
common_1.logger.info(lang_1.lang.__('LOCK_RELEASED'));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
common_1.logger.error(lang_1.lang.__('FAILED_TO_RELEASE_LOCK'));
|
|
58
|
+
throw new Error(lang_1.lang.__('FAILED_TO_RELEASE_LOCK'));
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.forceUnlockCommand = forceUnlockCommand;
|
|
@@ -8,26 +8,92 @@ const deploy_1 = require("./deploy");
|
|
|
8
8
|
const template_1 = require("./template");
|
|
9
9
|
const destroy_1 = require("./destroy");
|
|
10
10
|
const local_1 = require("./local");
|
|
11
|
+
const plan_1 = require("./plan");
|
|
12
|
+
const forceUnlock_1 = require("./forceUnlock");
|
|
13
|
+
const lang_1 = require("../lang");
|
|
14
|
+
// Global error handler
|
|
15
|
+
const handleCommandError = (error, commandName) => {
|
|
16
|
+
// Skip logging if already logged by handlePartialFailure
|
|
17
|
+
if (!error?.isPartialFailure) {
|
|
18
|
+
// Log error message as string to preserve newlines
|
|
19
|
+
common_1.logger.error(lang_1.lang.__('COMMAND_FAILED', {
|
|
20
|
+
commandName,
|
|
21
|
+
error: error?.message || 'Unknown error occurred',
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
if (error?.stack && process.env.DEBUG) {
|
|
25
|
+
common_1.logger.debug(lang_1.lang.__('STACK_TRACE', { stack: error.stack }));
|
|
26
|
+
}
|
|
27
|
+
let exitCode = 1;
|
|
28
|
+
if (error?.code) {
|
|
29
|
+
if (typeof error.code === 'number') {
|
|
30
|
+
exitCode = error.code;
|
|
31
|
+
}
|
|
32
|
+
else if (typeof error.code === 'string') {
|
|
33
|
+
const errorCodeMap = {
|
|
34
|
+
ENOENT: 2,
|
|
35
|
+
EACCES: 3,
|
|
36
|
+
VALIDATION: 4,
|
|
37
|
+
NETWORK: 5,
|
|
38
|
+
};
|
|
39
|
+
exitCode = errorCodeMap[error.code] || 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
process.exit(exitCode);
|
|
43
|
+
};
|
|
44
|
+
const actionWrapper = (commandName, handler) => {
|
|
45
|
+
// Reset context before each command execution
|
|
46
|
+
(0, common_1.clearContext)();
|
|
47
|
+
return async (...args) => {
|
|
48
|
+
try {
|
|
49
|
+
await handler(...args);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
handleCommandError(error, commandName);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
};
|
|
11
56
|
const program = new commander_1.Command();
|
|
12
57
|
program.name('si').description('CLI for ServerlessInsight').version((0, common_1.getVersion)());
|
|
13
58
|
program
|
|
14
59
|
.command('show')
|
|
15
60
|
.description('show string')
|
|
16
|
-
.action(async (options) => {
|
|
61
|
+
.action(actionWrapper('show', async (options) => {
|
|
17
62
|
await (0, common_1.setContext)({ ...options });
|
|
18
63
|
const context = (0, common_1.getContext)();
|
|
19
64
|
const result = await (0, common_1.getIamInfo)(context);
|
|
20
|
-
console.log('
|
|
21
|
-
});
|
|
65
|
+
console.log(lang_1.lang.__('RESULT', { result: JSON.stringify(result) }));
|
|
66
|
+
}));
|
|
22
67
|
program
|
|
23
68
|
.command('validate [stackName]')
|
|
24
69
|
.description('validate serverless Iac yaml')
|
|
25
70
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
26
71
|
.option('-s, --stage <stage>', 'specify the stage')
|
|
27
|
-
.action(async (stackName, { file, stage }) => {
|
|
28
|
-
common_1.logger.debug('
|
|
72
|
+
.action(actionWrapper('validate', async (stackName, { file, stage }) => {
|
|
73
|
+
common_1.logger.debug(lang_1.lang.__('LOG_COMMAND_INFO'));
|
|
29
74
|
await (0, validate_1.validate)(stackName, { stage, location: file });
|
|
30
|
-
});
|
|
75
|
+
}));
|
|
76
|
+
program
|
|
77
|
+
.command('plan <stackName>')
|
|
78
|
+
.description('generate and show deployment plan (Tencent provider only)')
|
|
79
|
+
.option('-f, --file <path>', 'specify the yaml file')
|
|
80
|
+
.option('-s, --stage <stage>', 'specify the stage')
|
|
81
|
+
.option('-r, --region <region>', 'specify the region')
|
|
82
|
+
.option('-v, --provider <provider>', 'specify the provider')
|
|
83
|
+
.option('-k, --accessKeyId <accessKeyId>', 'specify the AccessKeyId')
|
|
84
|
+
.option('-x, --accessKeySecret <accessKeySecret>', 'specify the AccessKeySecret')
|
|
85
|
+
.option('-n, --securityToken <securityToken>', 'specify the SecurityToken')
|
|
86
|
+
.action(actionWrapper('plan', async (stackName, { stage, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
87
|
+
await (0, plan_1.plan)(stackName, {
|
|
88
|
+
stage,
|
|
89
|
+
location: file,
|
|
90
|
+
region,
|
|
91
|
+
provider,
|
|
92
|
+
accessKeyId,
|
|
93
|
+
accessKeySecret,
|
|
94
|
+
securityToken,
|
|
95
|
+
});
|
|
96
|
+
}));
|
|
31
97
|
program
|
|
32
98
|
.command('deploy <stackName>')
|
|
33
99
|
.description('deploy serverless Iac yaml')
|
|
@@ -43,7 +109,7 @@ program
|
|
|
43
109
|
previous[key] = val;
|
|
44
110
|
return previous;
|
|
45
111
|
}, {})
|
|
46
|
-
.action(async (stackName, { stage, parameter, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
112
|
+
.action(actionWrapper('deploy', async (stackName, { stage, parameter, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
47
113
|
await (0, deploy_1.deploy)(stackName, {
|
|
48
114
|
stage,
|
|
49
115
|
parameters: parameter,
|
|
@@ -54,16 +120,16 @@ program
|
|
|
54
120
|
accessKeySecret,
|
|
55
121
|
securityToken,
|
|
56
122
|
});
|
|
57
|
-
});
|
|
123
|
+
}));
|
|
58
124
|
program
|
|
59
125
|
.command('template <stackName>')
|
|
60
126
|
.description('print platform specific infrastructure as code template')
|
|
61
127
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
62
128
|
.option('-s, --stage <stage>', 'specify the stage')
|
|
63
129
|
.option('-t, --format <type>', 'output content type (JSON or YAML)', 'JSON')
|
|
64
|
-
.action(async (stackName, { format, file, stage }) => {
|
|
130
|
+
.action(actionWrapper('template', async (stackName, { format, file, stage }) => {
|
|
65
131
|
await (0, template_1.template)(stackName, { format, location: file, stage });
|
|
66
|
-
});
|
|
132
|
+
}));
|
|
67
133
|
program
|
|
68
134
|
.command('destroy <stackName>')
|
|
69
135
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
@@ -73,7 +139,7 @@ program
|
|
|
73
139
|
.option('-x, --accessKeySecret <accessKeySecret>', 'specify the AccessKeySecret')
|
|
74
140
|
.option('-n, --securityToken <securityToken>', 'specify the SecurityToken')
|
|
75
141
|
.description('destroy serverless stack')
|
|
76
|
-
.action(async (stackName, { file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
142
|
+
.action(actionWrapper('destroy', async (stackName, { file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
77
143
|
await (0, destroy_1.destroyStack)(stackName, {
|
|
78
144
|
location: file,
|
|
79
145
|
region,
|
|
@@ -82,7 +148,7 @@ program
|
|
|
82
148
|
accessKeySecret,
|
|
83
149
|
securityToken,
|
|
84
150
|
});
|
|
85
|
-
});
|
|
151
|
+
}));
|
|
86
152
|
program
|
|
87
153
|
.command('local <stackName>')
|
|
88
154
|
.description('run Serverless application locally for debugging')
|
|
@@ -91,7 +157,7 @@ program
|
|
|
91
157
|
.option('-p, --port <port>', 'specify the port', '3000')
|
|
92
158
|
.option('-d, --debug', 'enable debug mode')
|
|
93
159
|
.option('-w, --watch', 'enable file watch', true)
|
|
94
|
-
.action(async (stackName, { stage, port, debug, watch, file }) => {
|
|
160
|
+
.action(actionWrapper('local', async (stackName, { stage, port, debug, watch, file }) => {
|
|
95
161
|
await (0, local_1.runLocal)(stackName, {
|
|
96
162
|
stage,
|
|
97
163
|
port: Number(port) || 3000,
|
|
@@ -99,5 +165,11 @@ program
|
|
|
99
165
|
watch: typeof watch === 'boolean' ? watch : true,
|
|
100
166
|
location: file,
|
|
101
167
|
});
|
|
102
|
-
});
|
|
168
|
+
}));
|
|
169
|
+
program
|
|
170
|
+
.command('force-unlock <lockId>')
|
|
171
|
+
.description('manually remove a stuck lock (use with caution)')
|
|
172
|
+
.action(actionWrapper('force-unlock', async (lockId) => {
|
|
173
|
+
await (0, forceUnlock_1.forceUnlockCommand)(lockId);
|
|
174
|
+
}));
|
|
103
175
|
program.parse();
|
|
@@ -4,12 +4,21 @@ exports.runLocal = void 0;
|
|
|
4
4
|
const common_1 = require("../common");
|
|
5
5
|
const localStack_1 = require("../stack/localStack");
|
|
6
6
|
const parser_1 = require("../parser");
|
|
7
|
+
const lang_1 = require("../lang");
|
|
7
8
|
const runLocal = async (stackName, opts) => {
|
|
8
9
|
const { stage, port, debug, watch, location } = opts;
|
|
9
10
|
await (0, common_1.setContext)({ stage, location });
|
|
10
11
|
const ctx = (0, common_1.getContext)();
|
|
11
12
|
const iac = (0, parser_1.revalYaml)((0, common_1.getIacLocation)(location), ctx);
|
|
12
|
-
|
|
13
|
+
// Store IAC in context for access by all functions
|
|
14
|
+
(0, common_1.setIac)(iac);
|
|
15
|
+
common_1.logger.info(lang_1.lang.__('RUN_LOCAL_STARTING', {
|
|
16
|
+
stackName,
|
|
17
|
+
stage,
|
|
18
|
+
port: String(port),
|
|
19
|
+
debug: String(debug),
|
|
20
|
+
watch: String(watch),
|
|
21
|
+
}));
|
|
13
22
|
await (0, localStack_1.startLocalStack)(iac);
|
|
14
23
|
// if (watch) {
|
|
15
24
|
// const cwd = process.cwd();
|