@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.
Files changed (160) hide show
  1. package/.gitattributes +1 -0
  2. package/README.md +108 -8
  3. package/README.zh-CN.md +52 -8
  4. package/dist/package.json +37 -35
  5. package/dist/src/commands/deploy.js +17 -7
  6. package/dist/src/commands/destroy.js +27 -4
  7. package/dist/src/commands/forceUnlock.js +61 -0
  8. package/dist/src/commands/index.js +86 -14
  9. package/dist/src/commands/local.js +10 -1
  10. package/dist/src/commands/plan.js +33 -0
  11. package/dist/src/commands/template.js +3 -1
  12. package/dist/src/commands/validate.js +2 -1
  13. package/dist/src/common/aliyunClient/apigwOperations.js +652 -0
  14. package/dist/src/common/aliyunClient/dnsOperations.js +90 -0
  15. package/dist/src/common/aliyunClient/ecsOperations.js +141 -0
  16. package/dist/src/common/aliyunClient/esOperations.js +219 -0
  17. package/dist/src/common/aliyunClient/fc3Operations.js +270 -0
  18. package/dist/src/common/aliyunClient/index.js +141 -0
  19. package/dist/src/common/aliyunClient/nasOperations.js +233 -0
  20. package/dist/src/common/aliyunClient/ossOperations.js +237 -0
  21. package/dist/src/common/aliyunClient/ramOperations.js +205 -0
  22. package/dist/src/common/aliyunClient/rdsOperations.js +206 -0
  23. package/dist/src/common/aliyunClient/slsOperations.js +218 -0
  24. package/dist/src/common/aliyunClient/tablestoreOperations.js +199 -0
  25. package/dist/src/common/aliyunClient/types.js +2 -0
  26. package/dist/src/common/constants.js +7 -1
  27. package/dist/src/common/context.js +32 -14
  28. package/dist/src/common/credentials.js +39 -0
  29. package/dist/src/common/dependencyGraph/graph.js +280 -0
  30. package/dist/src/common/dependencyGraph/index.js +18 -0
  31. package/dist/src/common/dependencyGraph/types.js +2 -0
  32. package/dist/src/common/fileUtils.js +16 -0
  33. package/dist/src/common/hashUtils.js +121 -0
  34. package/dist/src/common/iacHelper.js +25 -97
  35. package/dist/src/common/imsClient.js +4 -0
  36. package/dist/src/common/index.js +7 -2
  37. package/dist/src/common/lockManager.js +212 -0
  38. package/dist/src/common/logger.js +89 -6
  39. package/dist/src/common/providerEnum.js +2 -3
  40. package/dist/src/common/runtimeMapper.js +160 -0
  41. package/dist/src/common/scfClient.js +84 -0
  42. package/dist/src/common/stateManager.js +107 -0
  43. package/dist/src/common/tencentClient/cosOperations.js +287 -0
  44. package/dist/src/common/tencentClient/esOperations.js +156 -0
  45. package/dist/src/common/tencentClient/index.js +116 -0
  46. package/dist/src/common/tencentClient/scfOperations.js +141 -0
  47. package/dist/src/common/tencentClient/tdsqlcOperations.js +211 -0
  48. package/dist/src/common/tencentClient/types.js +17 -0
  49. package/dist/src/lang/en.js +254 -0
  50. package/dist/src/lang/index.js +28 -8
  51. package/dist/src/lang/zh-CN.js +229 -0
  52. package/dist/src/parser/bucketParser.js +25 -12
  53. package/dist/src/parser/databaseParser.js +14 -10
  54. package/dist/src/parser/functionParser.js +19 -6
  55. package/dist/src/parser/parseUtils.js +74 -0
  56. package/dist/src/parser/tableParser.js +19 -17
  57. package/dist/src/stack/aliyunStack/apigwExecutor.js +84 -0
  58. package/dist/src/stack/aliyunStack/apigwPlanner.js +118 -0
  59. package/dist/src/stack/aliyunStack/apigwResource.js +339 -0
  60. package/dist/src/stack/aliyunStack/apigwTypes.js +125 -0
  61. package/dist/src/stack/aliyunStack/databaseExecutor.js +112 -0
  62. package/dist/src/stack/aliyunStack/databasePlanner.js +128 -0
  63. package/dist/src/stack/aliyunStack/databaseResource.js +228 -0
  64. package/dist/src/stack/aliyunStack/deployer.js +133 -0
  65. package/dist/src/stack/aliyunStack/destroyer.js +114 -0
  66. package/dist/src/stack/aliyunStack/esServerlessTypes.js +141 -0
  67. package/dist/src/stack/aliyunStack/fc3Executor.js +91 -0
  68. package/dist/src/stack/aliyunStack/fc3Planner.js +77 -0
  69. package/dist/src/stack/aliyunStack/fc3Resource.js +511 -0
  70. package/dist/src/stack/aliyunStack/fc3Types.js +76 -0
  71. package/dist/src/stack/aliyunStack/index.js +40 -0
  72. package/dist/src/stack/aliyunStack/ossExecutor.js +91 -0
  73. package/dist/src/stack/aliyunStack/ossPlanner.js +76 -0
  74. package/dist/src/stack/aliyunStack/ossResource.js +196 -0
  75. package/dist/src/stack/aliyunStack/ossTypes.js +50 -0
  76. package/dist/src/stack/aliyunStack/planner.js +37 -0
  77. package/dist/src/stack/aliyunStack/rdsTypes.js +217 -0
  78. package/dist/src/stack/aliyunStack/tablestoreExecutor.js +92 -0
  79. package/dist/src/stack/aliyunStack/tablestorePlanner.js +94 -0
  80. package/dist/src/stack/aliyunStack/tablestoreResource.js +120 -0
  81. package/dist/src/stack/aliyunStack/tablestoreTypes.js +77 -0
  82. package/dist/src/stack/bucketTypes.js +17 -0
  83. package/dist/src/stack/deploy.js +24 -77
  84. package/dist/src/stack/localStack/bucket.js +11 -6
  85. package/dist/src/stack/localStack/event.js +10 -5
  86. package/dist/src/stack/localStack/function.js +13 -7
  87. package/dist/src/stack/localStack/functionRunner.js +1 -1
  88. package/dist/src/stack/localStack/localServer.js +7 -6
  89. package/dist/src/stack/scfStack/cosExecutor.js +91 -0
  90. package/dist/src/stack/scfStack/cosPlanner.js +76 -0
  91. package/dist/src/stack/scfStack/cosResource.js +126 -0
  92. package/dist/src/stack/scfStack/cosTypes.js +46 -0
  93. package/dist/src/stack/scfStack/deployer.js +91 -0
  94. package/dist/src/stack/scfStack/destroyer.js +88 -0
  95. package/dist/src/stack/scfStack/esServerlessExecutor.js +105 -0
  96. package/dist/src/stack/scfStack/esServerlessPlanner.js +86 -0
  97. package/dist/src/stack/scfStack/esServerlessResource.js +94 -0
  98. package/dist/src/stack/scfStack/esServerlessTypes.js +48 -0
  99. package/dist/src/stack/scfStack/index.js +35 -0
  100. package/dist/src/stack/scfStack/planner.js +91 -0
  101. package/dist/src/stack/scfStack/scfExecutor.js +91 -0
  102. package/dist/src/stack/scfStack/scfPlanner.js +78 -0
  103. package/dist/src/stack/scfStack/scfResource.js +216 -0
  104. package/dist/src/stack/scfStack/scfTypes.js +41 -0
  105. package/dist/src/stack/scfStack/tdsqlcExecutor.js +105 -0
  106. package/dist/src/stack/scfStack/tdsqlcPlanner.js +90 -0
  107. package/dist/src/stack/scfStack/tdsqlcResource.js +146 -0
  108. package/dist/src/stack/scfStack/tdsqlcTypes.js +59 -0
  109. package/dist/src/types/domains/lock.js +2 -0
  110. package/dist/src/types/domains/resolvable.js +2 -0
  111. package/dist/src/types/domains/state.js +19 -0
  112. package/dist/src/types/index.js +4 -0
  113. package/dist/src/validator/bucketSchema.js +4 -10
  114. package/dist/src/validator/databaseSchema.js +36 -36
  115. package/dist/src/validator/eventSchema.js +3 -2
  116. package/dist/src/validator/functionSchema.js +51 -46
  117. package/dist/src/validator/iacSchema.js +52 -3
  118. package/dist/src/validator/rootSchema.js +47 -1
  119. package/dist/src/validator/tableschema.js +9 -8
  120. package/dist/src/validator/templateRefSchema.js +23 -0
  121. package/dist/tsconfig.tsbuildinfo +1 -1
  122. package/package.json +37 -35
  123. package/samples/README_TENCENT_COS.md +486 -0
  124. package/samples/README_TENCENT_SCF.md +272 -0
  125. package/samples/aliyun-poc-api.yml +1 -1
  126. package/samples/aliyun-poc-bucket.yml +0 -1
  127. package/samples/aliyun-poc-domain.yml +0 -1
  128. package/samples/aliyun-poc-es.yml +14 -13
  129. package/samples/aliyun-poc-rds.yml +0 -2
  130. package/samples/aliyun-poc-table.yml +1 -3
  131. package/samples/tencent-poc-cos.yml +20 -0
  132. package/samples/tencent-poc-scf.yml +36 -0
  133. package/dist/src/commands/index.d.ts +0 -2
  134. package/dist/src/common/index.d.ts +0 -11
  135. package/dist/src/common/rosAssets.js +0 -178
  136. package/dist/src/common/rosClient.js +0 -198
  137. package/dist/src/index.d.ts +0 -1
  138. package/dist/src/lang/index.d.ts +0 -3
  139. package/dist/src/parser/index.d.ts +0 -3
  140. package/dist/src/stack/index.d.ts +0 -1
  141. package/dist/src/stack/localStack/index.d.ts +0 -5
  142. package/dist/src/stack/rfsStack/index.d.ts +0 -9
  143. package/dist/src/stack/rosStack/bootstrap.js +0 -187
  144. package/dist/src/stack/rosStack/bucket.js +0 -127
  145. package/dist/src/stack/rosStack/database.js +0 -313
  146. package/dist/src/stack/rosStack/event.js +0 -143
  147. package/dist/src/stack/rosStack/function.js +0 -259
  148. package/dist/src/stack/rosStack/index.d.ts +0 -7
  149. package/dist/src/stack/rosStack/index.js +0 -75
  150. package/dist/src/stack/rosStack/stage.js +0 -46
  151. package/dist/src/stack/rosStack/table.js +0 -95
  152. package/dist/src/stack/rosStack/tag.js +0 -11
  153. package/dist/src/stack/rosStack/vars.js +0 -49
  154. package/dist/src/types/index.d.ts +0 -55
  155. package/dist/src/types/localStack/index.d.ts +0 -81
  156. package/dist/src/validator/index.d.ts +0 -1
  157. package/layers/si-bootstrap-sdk/Dockerfile-aliyuncli +0 -12
  158. package/layers/si-bootstrap-sdk/README.md +0 -1
  159. package/layers/si-bootstrap-sdk/package-lock.json +0 -875
  160. package/layers/si-bootstrap-sdk/package.json +0 -33
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeDatabasePlan = void 0;
4
+ const databaseResource_1 = require("./databaseResource");
5
+ const common_1 = require("../../common");
6
+ const stateManager_1 = require("../../common/stateManager");
7
+ const lang_1 = require("../../lang");
8
+ const getResourceTypeName = (resourceType) => resourceType === 'ALIYUN_ES_SERVERLESS' ? 'Elasticsearch Serverless' : 'RDS Serverless';
9
+ const executeCreateAction = async (context, database, resourceType, currentState) => {
10
+ const resourceTypeName = getResourceTypeName(resourceType);
11
+ common_1.logger.info(`Creating ${resourceTypeName} database: ${database.name}`);
12
+ const newState = await (0, databaseResource_1.createDatabaseResource)(context, database, currentState);
13
+ common_1.logger.info(`Successfully created ${resourceTypeName} database: ${database.name}`);
14
+ return newState;
15
+ };
16
+ const executeUpdateAction = async (context, database, instanceId, resourceType, currentState) => {
17
+ const resourceTypeName = getResourceTypeName(resourceType);
18
+ common_1.logger.info(`Updating ${resourceTypeName} database: ${database.name}`);
19
+ const newState = await (0, databaseResource_1.updateDatabaseResource)(context, database, instanceId, resourceType, currentState);
20
+ common_1.logger.info(`Successfully updated ${resourceTypeName} database: ${database.name}`);
21
+ return newState;
22
+ };
23
+ const executeDeleteAction = async (context, instanceId, resourceType, logicalId, currentState) => {
24
+ const resourceTypeName = getResourceTypeName(resourceType);
25
+ common_1.logger.info(`Deleting ${resourceTypeName} database: ${instanceId}`);
26
+ const newState = await (0, databaseResource_1.deleteDatabaseResource)(context, instanceId, resourceType, logicalId, currentState);
27
+ common_1.logger.info(`Successfully deleted ${resourceTypeName} database: ${instanceId}`);
28
+ return newState;
29
+ };
30
+ const executeSingleItem = async (context, item, databasesMap, currentState) => {
31
+ if (item.resourceType !== 'ALIYUN_RDS_SERVERLESS' &&
32
+ item.resourceType !== 'ALIYUN_ES_SERVERLESS') {
33
+ return null;
34
+ }
35
+ switch (item.action) {
36
+ case 'noop':
37
+ common_1.logger.info(`No changes for ${item.logicalId}`);
38
+ return null;
39
+ case 'create': {
40
+ const database = databasesMap.get(item.logicalId);
41
+ if (!database) {
42
+ throw new Error(`Database not found for logical ID: ${item.logicalId}`);
43
+ }
44
+ return executeCreateAction(context, database, item.resourceType, currentState);
45
+ }
46
+ case 'update': {
47
+ const database = databasesMap.get(item.logicalId);
48
+ if (!database) {
49
+ throw new Error(`Database not found for logical ID: ${item.logicalId}`);
50
+ }
51
+ const state = (0, stateManager_1.getResource)(currentState, item.logicalId);
52
+ if (!state) {
53
+ throw new Error(`State not found for ${item.logicalId}`);
54
+ }
55
+ const instanceId = state.metadata?.instanceId || state.instances?.[0]?.id;
56
+ const resourceType = state.metadata?.resourceType || item.resourceType;
57
+ if (!instanceId) {
58
+ throw new Error(`Instance ID not found in state for ${item.logicalId}`);
59
+ }
60
+ return executeUpdateAction(context, database, instanceId, resourceType, currentState);
61
+ }
62
+ case 'delete': {
63
+ const state = (0, stateManager_1.getResource)(currentState, item.logicalId);
64
+ if (!state) {
65
+ common_1.logger.warn(`State not found for ${item.logicalId}, skipping deletion`);
66
+ return null;
67
+ }
68
+ const instanceId = state.metadata?.instanceId || state.instances?.[0]?.id;
69
+ const resourceType = state.metadata?.resourceType || item.resourceType;
70
+ if (!instanceId) {
71
+ throw new Error(`Instance ID not found in state for ${item.logicalId}`);
72
+ }
73
+ return executeDeleteAction(context, instanceId, resourceType, item.logicalId, currentState);
74
+ }
75
+ default:
76
+ common_1.logger.warn(`Unknown action: ${item.action} for ${item.logicalId}`);
77
+ return null;
78
+ }
79
+ };
80
+ const executeDatabasePlan = async (context, plan, databases, initialState, onStateChange) => {
81
+ const databasesMap = new Map(databases?.map((database) => [`databases.${database.key}`, database]) ?? []);
82
+ const successfulItems = [];
83
+ let currentState = initialState;
84
+ for (const item of plan.items) {
85
+ try {
86
+ const newState = await executeSingleItem(context, item, databasesMap, currentState);
87
+ if (newState !== null) {
88
+ currentState = newState;
89
+ successfulItems.push(item);
90
+ if (onStateChange) {
91
+ onStateChange(currentState);
92
+ common_1.logger.debug(lang_1.lang.__('STATE_PERSISTED_AFTER_OPERATION', {
93
+ action: item.action,
94
+ resourceId: item.logicalId,
95
+ }));
96
+ }
97
+ }
98
+ }
99
+ catch (error) {
100
+ return {
101
+ state: currentState,
102
+ partialFailure: {
103
+ failedItem: item,
104
+ error: error instanceof Error ? error : new Error(String(error)),
105
+ successfulItems,
106
+ },
107
+ };
108
+ }
109
+ }
110
+ return { state: currentState };
111
+ };
112
+ exports.executeDatabasePlan = executeDatabasePlan;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDatabasePlan = void 0;
4
+ const aliyunClient_1 = require("../../common/aliyunClient");
5
+ const rdsTypes_1 = require("./rdsTypes");
6
+ const esServerlessTypes_1 = require("./esServerlessTypes");
7
+ const stateManager_1 = require("../../common/stateManager");
8
+ const hashUtils_1 = require("../../common/hashUtils");
9
+ const planDatabaseDeletion = (logicalId, definition, resourceType) => ({
10
+ logicalId,
11
+ action: 'delete',
12
+ resourceType,
13
+ changes: { before: definition },
14
+ });
15
+ const getResourceType = (database) => {
16
+ if (database.type === "ELASTICSEARCH_SERVERLESS" /* DatabaseEnum.ELASTICSEARCH_SERVERLESS */) {
17
+ return 'ALIYUN_ES_SERVERLESS';
18
+ }
19
+ else if ([
20
+ "RDS_MYSQL_SERVERLESS" /* DatabaseEnum.RDS_MYSQL_SERVERLESS */,
21
+ "RDS_PGSQL_SERVERLESS" /* DatabaseEnum.RDS_PGSQL_SERVERLESS */,
22
+ "RDS_MSSQL_SERVERLESS" /* DatabaseEnum.RDS_MSSQL_SERVERLESS */,
23
+ ].includes(database.type)) {
24
+ return 'ALIYUN_RDS_SERVERLESS';
25
+ }
26
+ throw new Error(`Unsupported database type: ${database.type}`);
27
+ };
28
+ const getDesiredDefinition = (database) => {
29
+ if (database.type === "ELASTICSEARCH_SERVERLESS" /* DatabaseEnum.ELASTICSEARCH_SERVERLESS */) {
30
+ const config = (0, esServerlessTypes_1.databaseToEsConfig)(database);
31
+ return (0, esServerlessTypes_1.extractEsDefinition)(config);
32
+ }
33
+ else if ([
34
+ "RDS_MYSQL_SERVERLESS" /* DatabaseEnum.RDS_MYSQL_SERVERLESS */,
35
+ "RDS_PGSQL_SERVERLESS" /* DatabaseEnum.RDS_PGSQL_SERVERLESS */,
36
+ "RDS_MSSQL_SERVERLESS" /* DatabaseEnum.RDS_MSSQL_SERVERLESS */,
37
+ ].includes(database.type)) {
38
+ const config = (0, rdsTypes_1.databaseToRdsConfig)(database);
39
+ return (0, rdsTypes_1.extractRdsDefinition)(config);
40
+ }
41
+ throw new Error(`Unsupported database type: ${database.type}`);
42
+ };
43
+ const generateDatabasePlan = async (context, state, databases) => {
44
+ // Filter databases for Aliyun RDS and ES Serverless
45
+ const aliyunDatabases = databases?.filter((db) => db.type === "ELASTICSEARCH_SERVERLESS" /* DatabaseEnum.ELASTICSEARCH_SERVERLESS */ ||
46
+ db.type === "RDS_MYSQL_SERVERLESS" /* DatabaseEnum.RDS_MYSQL_SERVERLESS */ ||
47
+ db.type === "RDS_PGSQL_SERVERLESS" /* DatabaseEnum.RDS_PGSQL_SERVERLESS */ ||
48
+ db.type === "RDS_MSSQL_SERVERLESS" /* DatabaseEnum.RDS_MSSQL_SERVERLESS */);
49
+ if (!aliyunDatabases || aliyunDatabases.length === 0) {
50
+ const allStates = (0, stateManager_1.getAllResources)(state);
51
+ const items = Object.entries(allStates)
52
+ .filter(([logicalId, resourceState]) => {
53
+ const resourceType = resourceState.metadata?.resourceType;
54
+ return (logicalId.startsWith('databases.') &&
55
+ (resourceType === 'ALIYUN_RDS_SERVERLESS' || resourceType === 'ALIYUN_ES_SERVERLESS'));
56
+ })
57
+ .map(([logicalId, resourceState]) => planDatabaseDeletion(logicalId, resourceState.definition, resourceState.metadata?.resourceType || 'ALIYUN_RDS_SERVERLESS'));
58
+ return { items };
59
+ }
60
+ const desiredLogicalIds = new Set(aliyunDatabases.map((db) => `databases.${db.key}`));
61
+ const client = (0, aliyunClient_1.createAliyunClient)(context);
62
+ const databaseItems = await Promise.all(aliyunDatabases.map(async (database) => {
63
+ const logicalId = `databases.${database.key}`;
64
+ const currentState = (0, stateManager_1.getResource)(state, logicalId);
65
+ const resourceType = getResourceType(database);
66
+ const desiredDefinition = getDesiredDefinition(database);
67
+ if (!currentState) {
68
+ return {
69
+ logicalId,
70
+ action: 'create',
71
+ resourceType,
72
+ changes: { after: desiredDefinition },
73
+ };
74
+ }
75
+ const instanceId = currentState.metadata?.instanceId ||
76
+ currentState.instances?.[0]?.id;
77
+ try {
78
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+ let remoteInstance = null;
80
+ if (resourceType === 'ALIYUN_ES_SERVERLESS') {
81
+ remoteInstance = instanceId ? await client.es.getApp(instanceId) : null;
82
+ }
83
+ else if (resourceType === 'ALIYUN_RDS_SERVERLESS') {
84
+ remoteInstance = instanceId ? await client.rds.getInstance(instanceId) : null;
85
+ }
86
+ if (!remoteInstance) {
87
+ return {
88
+ logicalId,
89
+ action: 'create',
90
+ resourceType,
91
+ changes: { before: currentState.definition, after: desiredDefinition },
92
+ drifted: true,
93
+ };
94
+ }
95
+ const currentDefinition = currentState.definition || {};
96
+ const definitionChanged = !(0, hashUtils_1.attributesEqual)(currentDefinition, desiredDefinition);
97
+ if (definitionChanged) {
98
+ return {
99
+ logicalId,
100
+ action: 'update',
101
+ resourceType,
102
+ changes: { before: currentDefinition, after: desiredDefinition },
103
+ drifted: true,
104
+ };
105
+ }
106
+ return { logicalId, action: 'noop', resourceType };
107
+ }
108
+ catch {
109
+ return {
110
+ logicalId,
111
+ action: 'create',
112
+ resourceType,
113
+ changes: { before: currentState.definition, after: desiredDefinition },
114
+ };
115
+ }
116
+ }));
117
+ const allStates = (0, stateManager_1.getAllResources)(state);
118
+ const deletionItems = Object.entries(allStates)
119
+ .filter(([logicalId, resourceState]) => {
120
+ const resourceType = resourceState.metadata?.resourceType;
121
+ return (logicalId.startsWith('databases.') &&
122
+ !desiredLogicalIds.has(logicalId) &&
123
+ (resourceType === 'ALIYUN_RDS_SERVERLESS' || resourceType === 'ALIYUN_ES_SERVERLESS'));
124
+ })
125
+ .map(([logicalId, resourceState]) => planDatabaseDeletion(logicalId, resourceState.definition, resourceState.metadata?.resourceType || 'ALIYUN_RDS_SERVERLESS'));
126
+ return { items: [...databaseItems, ...deletionItems] };
127
+ };
128
+ exports.generateDatabasePlan = generateDatabasePlan;
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteDatabaseResource = exports.updateDatabaseResource = exports.readDatabaseResource = exports.createDatabaseResource = void 0;
4
+ const aliyunClient_1 = require("../../common/aliyunClient");
5
+ const rdsTypes_1 = require("./rdsTypes");
6
+ const esServerlessTypes_1 = require("./esServerlessTypes");
7
+ const stateManager_1 = require("../../common/stateManager");
8
+ const buildRdsInstanceFromProvider = (info, arn) => {
9
+ return {
10
+ arn,
11
+ id: info.dbInstanceId ?? '',
12
+ dbInstanceId: info.dbInstanceId ?? null,
13
+ dbInstanceDescription: info.dbInstanceDescription ?? null,
14
+ engine: info.engine ?? null,
15
+ engineVersion: info.engineVersion ?? null,
16
+ dbInstanceClass: info.dbInstanceClass ?? null,
17
+ dbInstanceStorage: info.dbInstanceStorage ?? null,
18
+ category: info.category ?? null,
19
+ dbInstanceStorageType: info.dbInstanceStorageType ?? null,
20
+ serverlessConfig: info.serverlessConfig
21
+ ? {
22
+ minCapacity: info.serverlessConfig.minCapacity ?? null,
23
+ maxCapacity: info.serverlessConfig.maxCapacity ?? null,
24
+ autoPause: info.serverlessConfig.autoPause ?? null,
25
+ switchForce: info.serverlessConfig.switchForce ?? null,
26
+ }
27
+ : {},
28
+ masterUsername: info.masterUsername ?? null,
29
+ vpcId: info.vpcId ?? null,
30
+ vSwitchId: info.vSwitchId ?? null,
31
+ zoneId: info.zoneId ?? null,
32
+ connectionString: info.connectionString ?? null,
33
+ port: info.port ?? null,
34
+ dbInstanceStatus: info.dbInstanceStatus ?? null,
35
+ createTime: info.createTime ?? null,
36
+ regionId: info.regionId ?? null,
37
+ securityIPList: info.securityIPList ?? null,
38
+ multiAZ: info.multiAZ ?? null,
39
+ };
40
+ };
41
+ const buildEsInstanceFromProvider = (info, arn) => {
42
+ return {
43
+ arn,
44
+ id: info.appId ?? '',
45
+ appId: info.appId ?? null,
46
+ appName: info.appName ?? null,
47
+ appType: info.appType ?? null,
48
+ status: info.status ?? null,
49
+ description: info.description ?? null,
50
+ createTime: info.createTime ?? null,
51
+ modifiedTime: info.modifiedTime ?? null,
52
+ regionId: info.regionId ?? null,
53
+ version: info.version ?? null,
54
+ ownerId: info.ownerId ?? null,
55
+ instanceId: info.instanceId ?? null,
56
+ chargeType: info.chargeType ?? null,
57
+ scenario: info.scenario ?? null,
58
+ network: info.network
59
+ ? info.network.map((n) => ({
60
+ type: n.type ?? null,
61
+ enabled: n.enabled ?? null,
62
+ domain: n.domain ?? null,
63
+ port: n.port ?? null,
64
+ whiteIpGroup: n.whiteIpGroup
65
+ ? n.whiteIpGroup.map((w) => ({
66
+ groupName: w.groupName ?? null,
67
+ ips: w.ips ?? [],
68
+ }))
69
+ : [],
70
+ }))
71
+ : [],
72
+ privateNetwork: info.privateNetwork
73
+ ? info.privateNetwork.map((n) => ({
74
+ type: n.type ?? null,
75
+ enabled: n.enabled ?? null,
76
+ domain: n.domain ?? null,
77
+ port: n.port ?? null,
78
+ vpcId: n.vpcId ?? null,
79
+ pvlEndpointId: n.pvlEndpointId ?? null,
80
+ whiteIpGroup: n.whiteIpGroup
81
+ ? n.whiteIpGroup.map((w) => ({
82
+ groupName: w.groupName ?? null,
83
+ ips: w.ips ?? [],
84
+ }))
85
+ : [],
86
+ }))
87
+ : [],
88
+ tags: info.tags
89
+ ? info.tags.map((t) => ({
90
+ key: t.key ?? null,
91
+ value: t.value ?? null,
92
+ }))
93
+ : [],
94
+ };
95
+ };
96
+ const createDatabaseResource = async (context, database, state) => {
97
+ const client = (0, aliyunClient_1.createAliyunClient)(context);
98
+ let instanceId;
99
+ let definition;
100
+ let instance;
101
+ let arn;
102
+ let resourceType;
103
+ if (database.type === "ELASTICSEARCH_SERVERLESS" /* DatabaseEnum.ELASTICSEARCH_SERVERLESS */) {
104
+ // Create Elasticsearch Serverless app
105
+ const config = (0, esServerlessTypes_1.databaseToEsConfig)(database);
106
+ instanceId = await client.es.createApp(config);
107
+ // Refresh state from provider to get all attributes
108
+ const appInfo = await client.es.getApp(instanceId);
109
+ if (!appInfo) {
110
+ throw new Error(`Failed to refresh state for ES app: ${instanceId}`);
111
+ }
112
+ definition = (0, esServerlessTypes_1.extractEsDefinition)(config);
113
+ arn = `arn:acs:elasticsearch:${context.region}:${context.accountId}:serverless:${instanceId}`;
114
+ instance = buildEsInstanceFromProvider(appInfo, arn);
115
+ resourceType = 'ALIYUN_ES_SERVERLESS';
116
+ }
117
+ else if ([
118
+ "RDS_MYSQL_SERVERLESS" /* DatabaseEnum.RDS_MYSQL_SERVERLESS */,
119
+ "RDS_PGSQL_SERVERLESS" /* DatabaseEnum.RDS_PGSQL_SERVERLESS */,
120
+ "RDS_MSSQL_SERVERLESS" /* DatabaseEnum.RDS_MSSQL_SERVERLESS */,
121
+ ].includes(database.type)) {
122
+ // Create RDS Serverless instance
123
+ const config = (0, rdsTypes_1.databaseToRdsConfig)(database);
124
+ instanceId = await client.rds.createInstance(config);
125
+ // Refresh state from provider to get all attributes
126
+ const rdsInfo = await client.rds.getInstance(instanceId);
127
+ if (!rdsInfo) {
128
+ throw new Error(`Failed to refresh state for RDS instance: ${instanceId}`);
129
+ }
130
+ definition = (0, rdsTypes_1.extractRdsDefinition)(config);
131
+ arn = `arn:acs:rds:${context.region}:${context.accountId}:dbinstance:${instanceId}`;
132
+ instance = buildRdsInstanceFromProvider(rdsInfo, arn);
133
+ resourceType = 'ALIYUN_RDS_SERVERLESS';
134
+ }
135
+ else {
136
+ throw new Error(`Unsupported database type: ${database.type}`);
137
+ }
138
+ const resourceState = {
139
+ mode: 'managed',
140
+ region: context.region,
141
+ definition,
142
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
+ instances: [instance],
144
+ lastUpdated: new Date().toISOString(),
145
+ metadata: {
146
+ databaseName: database.name,
147
+ instanceId,
148
+ resourceType,
149
+ },
150
+ };
151
+ const logicalId = `databases.${database.key}`;
152
+ return (0, stateManager_1.setResource)(state, logicalId, resourceState);
153
+ };
154
+ exports.createDatabaseResource = createDatabaseResource;
155
+ const readDatabaseResource = async (context, instanceId, resourceType) => {
156
+ const client = (0, aliyunClient_1.createAliyunClient)(context);
157
+ if (resourceType === 'ALIYUN_ES_SERVERLESS') {
158
+ return await client.es.getApp(instanceId);
159
+ }
160
+ else if (resourceType === 'ALIYUN_RDS_SERVERLESS') {
161
+ return await client.rds.getInstance(instanceId);
162
+ }
163
+ throw new Error(`Unsupported resource type: ${resourceType}`);
164
+ };
165
+ exports.readDatabaseResource = readDatabaseResource;
166
+ const updateDatabaseResource = async (context, database, instanceId, resourceType, state) => {
167
+ const client = (0, aliyunClient_1.createAliyunClient)(context);
168
+ let definition;
169
+ let instance;
170
+ let arn;
171
+ if (resourceType === 'ALIYUN_ES_SERVERLESS') {
172
+ const config = (0, esServerlessTypes_1.databaseToEsConfig)(database);
173
+ await client.es.updateApp(instanceId, config);
174
+ // Refresh state from provider to get all attributes
175
+ const appInfo = await client.es.getApp(instanceId);
176
+ if (!appInfo) {
177
+ throw new Error(`Failed to refresh state for ES app: ${instanceId}`);
178
+ }
179
+ definition = (0, esServerlessTypes_1.extractEsDefinition)(config);
180
+ arn = `arn:acs:elasticsearch:${context.region}:${context.accountId}:serverless:${instanceId}`;
181
+ instance = buildEsInstanceFromProvider(appInfo, arn);
182
+ }
183
+ else if (resourceType === 'ALIYUN_RDS_SERVERLESS') {
184
+ const config = (0, rdsTypes_1.databaseToRdsConfig)(database);
185
+ await client.rds.updateInstance(instanceId, config);
186
+ // Refresh state from provider to get all attributes
187
+ const rdsInfo = await client.rds.getInstance(instanceId);
188
+ if (!rdsInfo) {
189
+ throw new Error(`Failed to refresh state for RDS instance: ${instanceId}`);
190
+ }
191
+ definition = (0, rdsTypes_1.extractRdsDefinition)(config);
192
+ arn = `arn:acs:rds:${context.region}:${context.accountId}:dbinstance:${instanceId}`;
193
+ instance = buildRdsInstanceFromProvider(rdsInfo, arn);
194
+ }
195
+ else {
196
+ throw new Error(`Unsupported resource type: ${resourceType}`);
197
+ }
198
+ const resourceState = {
199
+ mode: 'managed',
200
+ region: context.region,
201
+ definition,
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ instances: [instance],
204
+ lastUpdated: new Date().toISOString(),
205
+ metadata: {
206
+ databaseName: database.name,
207
+ instanceId,
208
+ resourceType,
209
+ },
210
+ };
211
+ const logicalId = `databases.${database.key}`;
212
+ return (0, stateManager_1.setResource)(state, logicalId, resourceState);
213
+ };
214
+ exports.updateDatabaseResource = updateDatabaseResource;
215
+ const deleteDatabaseResource = async (context, instanceId, resourceType, logicalId, state) => {
216
+ const client = (0, aliyunClient_1.createAliyunClient)(context);
217
+ if (resourceType === 'ALIYUN_ES_SERVERLESS') {
218
+ await client.es.deleteApp(instanceId);
219
+ }
220
+ else if (resourceType === 'ALIYUN_RDS_SERVERLESS') {
221
+ await client.rds.deleteInstance(instanceId);
222
+ }
223
+ else {
224
+ throw new Error(`Unsupported resource type: ${resourceType}`);
225
+ }
226
+ return (0, stateManager_1.removeResource)(state, logicalId);
227
+ };
228
+ exports.deleteDatabaseResource = deleteDatabaseResource;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deployAliyunStack = void 0;
4
+ const common_1 = require("../../common");
5
+ const lang_1 = require("../../lang");
6
+ const fc3Planner_1 = require("./fc3Planner");
7
+ const fc3Executor_1 = require("./fc3Executor");
8
+ const ossPlanner_1 = require("./ossPlanner");
9
+ const ossExecutor_1 = require("./ossExecutor");
10
+ const databasePlanner_1 = require("./databasePlanner");
11
+ const databaseExecutor_1 = require("./databaseExecutor");
12
+ const tablestorePlanner_1 = require("./tablestorePlanner");
13
+ const tablestoreExecutor_1 = require("./tablestoreExecutor");
14
+ const apigwPlanner_1 = require("./apigwPlanner");
15
+ const apigwExecutor_1 = require("./apigwExecutor");
16
+ const createSaveStateFn = (baseDir) => (state) => {
17
+ (0, common_1.saveState)(state, baseDir);
18
+ };
19
+ const handlePartialFailure = (failure) => {
20
+ const error = failure.error;
21
+ error.isPartialFailure = true;
22
+ common_1.logger.error(`${lang_1.lang.__('FAILED_TO_EXECUTE_ACTION', {
23
+ action: failure.failedItem.action,
24
+ logicalId: failure.failedItem.logicalId,
25
+ error: error.message,
26
+ })}\n\n${lang_1.lang.__('PARTIAL_DEPLOYMENT_FAILURE', {
27
+ successCount: String(failure.successfulItems.length),
28
+ failedResource: failure.failedItem.logicalId,
29
+ })}\n${lang_1.lang.__('PARTIAL_FAILURE_STATE_SAVED')}\n${lang_1.lang.__('PARTIAL_FAILURE_NEXT_STEPS')}`);
30
+ throw error;
31
+ };
32
+ const collectSuccessfulItems = (results) => results.flatMap((result) => result.partialFailure?.successfulItems ?? []);
33
+ const logDependencyGraph = (orderedItems, dotGraph) => {
34
+ common_1.logger.info(lang_1.lang.__('DEPENDENCY_GRAPH_GENERATED'));
35
+ common_1.logger.info(` ${lang_1.lang.__('EXECUTION_ORDER')}:`);
36
+ orderedItems.forEach((item, index) => {
37
+ common_1.logger.info(` ${index + 1}. ${item.logicalId} (${item.resourceType}) - ${item.action}`);
38
+ });
39
+ common_1.logger.debug(`${lang_1.lang.__('DOT_GRAPH_OUTPUT')}:\n${dotGraph}`);
40
+ };
41
+ const deployAliyunStack = async (iac) => {
42
+ const context = (0, common_1.getContext)();
43
+ const baseDir = process.cwd();
44
+ // Cache IAC for access throughout the deployment
45
+ (0, common_1.setIac)(iac);
46
+ common_1.logger.info(lang_1.lang.__('DEPLOYING_STACK_PUBLISHING_ASSETS'));
47
+ let state = (0, common_1.loadState)(iac.provider.name, baseDir);
48
+ const onStateChange = createSaveStateFn(baseDir);
49
+ common_1.logger.info(lang_1.lang.__('GENERATING_PLAN'));
50
+ const functionPlan = await (0, fc3Planner_1.generateFunctionPlan)(context, state, iac.functions);
51
+ const bucketPlan = await (0, ossPlanner_1.generateBucketPlan)(context, state, iac.buckets);
52
+ const databasePlan = await (0, databasePlanner_1.generateDatabasePlan)(context, state, iac.databases);
53
+ const tablePlan = await (0, tablestorePlanner_1.generateTablePlan)(context, state, iac.tables);
54
+ const eventPlan = await (0, apigwPlanner_1.generateApigwPlan)(context, state, iac.events, iac.service);
55
+ const allItems = [
56
+ ...functionPlan.items,
57
+ ...bucketPlan.items,
58
+ ...databasePlan.items,
59
+ ...tablePlan.items,
60
+ ...eventPlan.items,
61
+ ];
62
+ // Build dependency graph for validation (e.g. cycle detection) and logging
63
+ const dependencyInfo = (0, common_1.getDependencyInfo)(allItems);
64
+ if (dependencyInfo.cycleError) {
65
+ throw new Error(`${lang_1.lang.__('CYCLE_DETECTED')}: ${dependencyInfo.cycleError.cycle.join(' -> ')}`);
66
+ }
67
+ const orderedItems = dependencyInfo.order;
68
+ const dotGraph = (0, common_1.toDotFormat)(dependencyInfo.graph);
69
+ logDependencyGraph(orderedItems, dotGraph);
70
+ // NOTE: The dependency graph is currently used only for validation (e.g. cycle detection).
71
+ // Plan execution below still follows the fixed per-resource ordering.
72
+ common_1.logger.info(`${lang_1.lang.__('PLAN_GENERATED')}: ${allItems.length} ${lang_1.lang.__('ACTIONS')}`);
73
+ allItems.forEach((item) => {
74
+ common_1.logger.info(` - ${item.action.toUpperCase()}: ${item.logicalId} (${item.resourceType})`);
75
+ });
76
+ common_1.logger.info(lang_1.lang.__('EXECUTING_PLAN'));
77
+ // Execute plans per resource type in a fixed order.
78
+ // The dependency graph above does not yet drive the execution sequence.
79
+ const functionResult = await (0, fc3Executor_1.executeFunctionPlan)(context, functionPlan, iac.functions, state, onStateChange);
80
+ state = functionResult.state;
81
+ if (functionResult.partialFailure) {
82
+ handlePartialFailure(functionResult.partialFailure);
83
+ }
84
+ const bucketResult = await (0, ossExecutor_1.executeBucketPlan)(context, bucketPlan, iac.buckets, state, onStateChange);
85
+ state = bucketResult.state;
86
+ if (bucketResult.partialFailure) {
87
+ handlePartialFailure({
88
+ ...bucketResult.partialFailure,
89
+ successfulItems: [
90
+ ...collectSuccessfulItems([functionResult]),
91
+ ...bucketResult.partialFailure.successfulItems,
92
+ ],
93
+ });
94
+ }
95
+ const databaseResult = await (0, databaseExecutor_1.executeDatabasePlan)(context, databasePlan, iac.databases, state, onStateChange);
96
+ state = databaseResult.state;
97
+ if (databaseResult.partialFailure) {
98
+ handlePartialFailure({
99
+ ...databaseResult.partialFailure,
100
+ successfulItems: [
101
+ ...collectSuccessfulItems([functionResult, bucketResult]),
102
+ ...databaseResult.partialFailure.successfulItems,
103
+ ],
104
+ });
105
+ }
106
+ const tableResult = await (0, tablestoreExecutor_1.executeTablePlan)(context, tablePlan, iac.tables, state, onStateChange);
107
+ state = tableResult.state;
108
+ if (tableResult.partialFailure) {
109
+ handlePartialFailure({
110
+ ...tableResult.partialFailure,
111
+ successfulItems: [
112
+ ...collectSuccessfulItems([functionResult, bucketResult, databaseResult]),
113
+ ...tableResult.partialFailure.successfulItems,
114
+ ],
115
+ });
116
+ }
117
+ // Execute event plan after functions are created (events depend on functions)
118
+ const roleArn = (0, common_1.getRoleArnFromState)(state);
119
+ const eventResult = await (0, apigwExecutor_1.executeApigwPlan)(context, eventPlan, iac.events, iac.service, roleArn, state, onStateChange);
120
+ state = eventResult.state;
121
+ if (eventResult.partialFailure) {
122
+ handlePartialFailure({
123
+ ...eventResult.partialFailure,
124
+ successfulItems: [
125
+ ...collectSuccessfulItems([functionResult, bucketResult, databaseResult, tableResult]),
126
+ ...eventResult.partialFailure.successfulItems,
127
+ ],
128
+ });
129
+ }
130
+ (0, common_1.saveState)(state, baseDir);
131
+ common_1.logger.info(lang_1.lang.__('STACK_DEPLOYED'));
132
+ };
133
+ exports.deployAliyunStack = deployAliyunStack;