@stacksjs/ts-cloud-core 0.1.1

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 (251) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +321 -0
  3. package/package.json +31 -0
  4. package/src/advanced-features.test.ts +465 -0
  5. package/src/aws/cloudformation.ts +421 -0
  6. package/src/aws/cloudfront.ts +158 -0
  7. package/src/aws/credentials.test.ts +132 -0
  8. package/src/aws/credentials.ts +545 -0
  9. package/src/aws/index.ts +87 -0
  10. package/src/aws/s3.test.ts +188 -0
  11. package/src/aws/s3.ts +1088 -0
  12. package/src/aws/signature.test.ts +670 -0
  13. package/src/aws/signature.ts +1155 -0
  14. package/src/backup/disaster-recovery.test.ts +726 -0
  15. package/src/backup/disaster-recovery.ts +500 -0
  16. package/src/backup/index.ts +34 -0
  17. package/src/backup/manager.test.ts +498 -0
  18. package/src/backup/manager.ts +432 -0
  19. package/src/cicd/circleci.ts +430 -0
  20. package/src/cicd/github-actions.ts +424 -0
  21. package/src/cicd/gitlab-ci.ts +255 -0
  22. package/src/cicd/index.ts +8 -0
  23. package/src/cli/history.ts +396 -0
  24. package/src/cli/index.ts +10 -0
  25. package/src/cli/progress.ts +458 -0
  26. package/src/cli/repl.ts +454 -0
  27. package/src/cli/suggestions.ts +327 -0
  28. package/src/cli/table.test.ts +319 -0
  29. package/src/cli/table.ts +332 -0
  30. package/src/cloudformation/builder.test.ts +327 -0
  31. package/src/cloudformation/builder.ts +378 -0
  32. package/src/cloudformation/builders/api-gateway.ts +449 -0
  33. package/src/cloudformation/builders/cache.ts +334 -0
  34. package/src/cloudformation/builders/cdn.ts +278 -0
  35. package/src/cloudformation/builders/compute.ts +485 -0
  36. package/src/cloudformation/builders/database.ts +392 -0
  37. package/src/cloudformation/builders/functions.ts +343 -0
  38. package/src/cloudformation/builders/messaging.ts +140 -0
  39. package/src/cloudformation/builders/monitoring.ts +300 -0
  40. package/src/cloudformation/builders/network.ts +264 -0
  41. package/src/cloudformation/builders/queue.ts +147 -0
  42. package/src/cloudformation/builders/security.ts +399 -0
  43. package/src/cloudformation/builders/storage.ts +285 -0
  44. package/src/cloudformation/index.ts +30 -0
  45. package/src/cloudformation/types.ts +173 -0
  46. package/src/compliance/aws-config.ts +543 -0
  47. package/src/compliance/cloudtrail.ts +376 -0
  48. package/src/compliance/compliance.test.ts +423 -0
  49. package/src/compliance/guardduty.ts +446 -0
  50. package/src/compliance/index.ts +66 -0
  51. package/src/compliance/security-hub.ts +456 -0
  52. package/src/containers/build-optimization.ts +416 -0
  53. package/src/containers/containers.test.ts +508 -0
  54. package/src/containers/image-scanning.ts +360 -0
  55. package/src/containers/index.ts +9 -0
  56. package/src/containers/registry.ts +293 -0
  57. package/src/containers/service-mesh.ts +520 -0
  58. package/src/database/database.test.ts +762 -0
  59. package/src/database/index.ts +9 -0
  60. package/src/database/migrations.ts +444 -0
  61. package/src/database/performance.ts +528 -0
  62. package/src/database/replicas.ts +534 -0
  63. package/src/database/users.ts +494 -0
  64. package/src/dependency-graph.ts +143 -0
  65. package/src/deployment/ab-testing.ts +582 -0
  66. package/src/deployment/blue-green.ts +452 -0
  67. package/src/deployment/canary.ts +500 -0
  68. package/src/deployment/deployment.test.ts +526 -0
  69. package/src/deployment/index.ts +61 -0
  70. package/src/deployment/progressive.ts +62 -0
  71. package/src/dns/dns.test.ts +641 -0
  72. package/src/dns/dnssec.ts +315 -0
  73. package/src/dns/index.ts +8 -0
  74. package/src/dns/resolver.ts +496 -0
  75. package/src/dns/routing.ts +593 -0
  76. package/src/email/advanced/analytics.ts +445 -0
  77. package/src/email/advanced/index.ts +11 -0
  78. package/src/email/advanced/rules.ts +465 -0
  79. package/src/email/advanced/scheduling.ts +352 -0
  80. package/src/email/advanced/search.ts +412 -0
  81. package/src/email/advanced/shared-mailboxes.ts +404 -0
  82. package/src/email/advanced/templates.ts +455 -0
  83. package/src/email/advanced/threading.ts +281 -0
  84. package/src/email/analytics.ts +467 -0
  85. package/src/email/bounce-handling.ts +425 -0
  86. package/src/email/email.test.ts +431 -0
  87. package/src/email/handlers/__tests__/inbound.test.ts +38 -0
  88. package/src/email/handlers/__tests__/outbound.test.ts +37 -0
  89. package/src/email/handlers/converter.ts +227 -0
  90. package/src/email/handlers/feedback.ts +228 -0
  91. package/src/email/handlers/inbound.ts +169 -0
  92. package/src/email/handlers/outbound.ts +178 -0
  93. package/src/email/index.ts +15 -0
  94. package/src/email/reputation.ts +303 -0
  95. package/src/email/templates.ts +352 -0
  96. package/src/errors/index.test.ts +434 -0
  97. package/src/errors/index.ts +416 -0
  98. package/src/health-checks/index.ts +40 -0
  99. package/src/index.ts +360 -0
  100. package/src/intrinsic-functions.ts +118 -0
  101. package/src/lambda/concurrency.ts +330 -0
  102. package/src/lambda/destinations.ts +345 -0
  103. package/src/lambda/dlq.ts +425 -0
  104. package/src/lambda/index.ts +11 -0
  105. package/src/lambda/lambda.test.ts +840 -0
  106. package/src/lambda/layers.ts +263 -0
  107. package/src/lambda/versions.ts +376 -0
  108. package/src/lambda/vpc.ts +399 -0
  109. package/src/local/config.ts +114 -0
  110. package/src/local/index.ts +6 -0
  111. package/src/local/mock-aws.ts +351 -0
  112. package/src/modules/ai.ts +340 -0
  113. package/src/modules/api.ts +478 -0
  114. package/src/modules/auth.ts +805 -0
  115. package/src/modules/cache.ts +417 -0
  116. package/src/modules/cdn.ts +1062 -0
  117. package/src/modules/communication.ts +1094 -0
  118. package/src/modules/compute.ts +3348 -0
  119. package/src/modules/database.ts +554 -0
  120. package/src/modules/deployment.ts +1079 -0
  121. package/src/modules/dns.ts +337 -0
  122. package/src/modules/email.ts +1538 -0
  123. package/src/modules/filesystem.ts +515 -0
  124. package/src/modules/index.ts +32 -0
  125. package/src/modules/messaging.ts +486 -0
  126. package/src/modules/monitoring.ts +2086 -0
  127. package/src/modules/network.ts +664 -0
  128. package/src/modules/parameter-store.ts +325 -0
  129. package/src/modules/permissions.ts +1081 -0
  130. package/src/modules/phone.ts +494 -0
  131. package/src/modules/queue.ts +1260 -0
  132. package/src/modules/redirects.ts +464 -0
  133. package/src/modules/registry.ts +699 -0
  134. package/src/modules/search.ts +401 -0
  135. package/src/modules/secrets.ts +416 -0
  136. package/src/modules/security.ts +731 -0
  137. package/src/modules/sms.ts +389 -0
  138. package/src/modules/storage.ts +1120 -0
  139. package/src/modules/workflow.ts +680 -0
  140. package/src/multi-account/config.ts +521 -0
  141. package/src/multi-account/index.ts +7 -0
  142. package/src/multi-account/manager.ts +427 -0
  143. package/src/multi-region/cross-region.ts +410 -0
  144. package/src/multi-region/index.ts +8 -0
  145. package/src/multi-region/manager.ts +483 -0
  146. package/src/multi-region/regions.ts +435 -0
  147. package/src/network-security/index.ts +48 -0
  148. package/src/observability/index.ts +9 -0
  149. package/src/observability/logs.ts +522 -0
  150. package/src/observability/metrics.ts +460 -0
  151. package/src/observability/observability.test.ts +782 -0
  152. package/src/observability/synthetics.ts +568 -0
  153. package/src/observability/xray.ts +358 -0
  154. package/src/phone/advanced/analytics.ts +349 -0
  155. package/src/phone/advanced/callbacks.ts +428 -0
  156. package/src/phone/advanced/index.ts +8 -0
  157. package/src/phone/advanced/ivr-builder.ts +504 -0
  158. package/src/phone/advanced/recording.ts +310 -0
  159. package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
  160. package/src/phone/handlers/incoming-call.ts +117 -0
  161. package/src/phone/handlers/missed-call.ts +116 -0
  162. package/src/phone/handlers/voicemail.ts +179 -0
  163. package/src/phone/index.ts +9 -0
  164. package/src/presets/api-backend.ts +134 -0
  165. package/src/presets/data-pipeline.ts +204 -0
  166. package/src/presets/extend.test.ts +295 -0
  167. package/src/presets/extend.ts +297 -0
  168. package/src/presets/fullstack-app.ts +144 -0
  169. package/src/presets/index.ts +27 -0
  170. package/src/presets/jamstack.ts +135 -0
  171. package/src/presets/microservices.ts +167 -0
  172. package/src/presets/ml-api.ts +208 -0
  173. package/src/presets/nodejs-server.ts +104 -0
  174. package/src/presets/nodejs-serverless.ts +114 -0
  175. package/src/presets/realtime-app.ts +184 -0
  176. package/src/presets/static-site.ts +64 -0
  177. package/src/presets/traditional-web-app.ts +339 -0
  178. package/src/presets/wordpress.ts +138 -0
  179. package/src/preview/github.test.ts +249 -0
  180. package/src/preview/github.ts +297 -0
  181. package/src/preview/index.ts +37 -0
  182. package/src/preview/manager.test.ts +440 -0
  183. package/src/preview/manager.ts +326 -0
  184. package/src/preview/notifications.test.ts +582 -0
  185. package/src/preview/notifications.ts +341 -0
  186. package/src/queue/batch-processing.ts +402 -0
  187. package/src/queue/dlq-monitoring.ts +402 -0
  188. package/src/queue/fifo.ts +342 -0
  189. package/src/queue/index.ts +9 -0
  190. package/src/queue/management.ts +428 -0
  191. package/src/queue/queue.test.ts +429 -0
  192. package/src/resource-mgmt/index.ts +39 -0
  193. package/src/resource-naming.ts +62 -0
  194. package/src/s3/index.ts +523 -0
  195. package/src/schema/cloud-config.schema.json +554 -0
  196. package/src/schema/index.ts +68 -0
  197. package/src/security/certificate-manager.ts +492 -0
  198. package/src/security/index.ts +9 -0
  199. package/src/security/scanning.ts +545 -0
  200. package/src/security/secrets-manager.ts +476 -0
  201. package/src/security/secrets-rotation.ts +456 -0
  202. package/src/security/security.test.ts +738 -0
  203. package/src/sms/advanced/ab-testing.ts +389 -0
  204. package/src/sms/advanced/analytics.ts +336 -0
  205. package/src/sms/advanced/campaigns.ts +523 -0
  206. package/src/sms/advanced/chatbot.ts +224 -0
  207. package/src/sms/advanced/index.ts +10 -0
  208. package/src/sms/advanced/link-tracking.ts +248 -0
  209. package/src/sms/advanced/mms.ts +308 -0
  210. package/src/sms/handlers/__tests__/send.test.ts +40 -0
  211. package/src/sms/handlers/delivery-status.ts +133 -0
  212. package/src/sms/handlers/receive.ts +162 -0
  213. package/src/sms/handlers/send.ts +174 -0
  214. package/src/sms/index.ts +9 -0
  215. package/src/stack-diff.ts +389 -0
  216. package/src/static-site/index.ts +85 -0
  217. package/src/template-builder.ts +110 -0
  218. package/src/template-validator.ts +574 -0
  219. package/src/utils/cache.ts +291 -0
  220. package/src/utils/diff.ts +269 -0
  221. package/src/utils/hash.ts +227 -0
  222. package/src/utils/index.ts +8 -0
  223. package/src/utils/parallel.ts +294 -0
  224. package/src/validators/credentials.test.ts +274 -0
  225. package/src/validators/credentials.ts +233 -0
  226. package/src/validators/quotas.test.ts +434 -0
  227. package/src/validators/quotas.ts +217 -0
  228. package/test/ai.test.ts +327 -0
  229. package/test/api.test.ts +511 -0
  230. package/test/auth.test.ts +632 -0
  231. package/test/cache.test.ts +406 -0
  232. package/test/cdn.test.ts +247 -0
  233. package/test/compute.test.ts +861 -0
  234. package/test/database.test.ts +523 -0
  235. package/test/deployment.test.ts +499 -0
  236. package/test/dns.test.ts +270 -0
  237. package/test/email.test.ts +439 -0
  238. package/test/filesystem.test.ts +382 -0
  239. package/test/integration.test.ts +350 -0
  240. package/test/messaging.test.ts +514 -0
  241. package/test/monitoring.test.ts +634 -0
  242. package/test/network.test.ts +425 -0
  243. package/test/permissions.test.ts +488 -0
  244. package/test/queue.test.ts +484 -0
  245. package/test/registry.test.ts +306 -0
  246. package/test/security.test.ts +462 -0
  247. package/test/storage.test.ts +463 -0
  248. package/test/template-validator.test.ts +559 -0
  249. package/test/workflow.test.ts +592 -0
  250. package/tsconfig.json +16 -0
  251. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,427 @@
1
+ /**
2
+ * Multi-Account Manager
3
+ * Manages deployments across multiple AWS accounts
4
+ */
5
+
6
+ export interface AWSAccount {
7
+ id: string
8
+ alias?: string
9
+ email: string
10
+ role: 'management' | 'production' | 'staging' | 'development' | 'security' | 'shared-services'
11
+ organizationalUnit?: string
12
+ assumeRoleArn?: string
13
+ }
14
+
15
+ export interface CrossAccountRole {
16
+ roleArn: string
17
+ roleName: string
18
+ sourceAccountId: string
19
+ targetAccountId: string
20
+ permissions: string[]
21
+ externalId?: string
22
+ sessionDuration?: number
23
+ }
24
+
25
+ export interface AccountMapping {
26
+ environment: string
27
+ accountId: string
28
+ region: string
29
+ }
30
+
31
+ /**
32
+ * Multi-account deployment manager
33
+ */
34
+ export class MultiAccountManager {
35
+ private accounts: Map<string, AWSAccount> = new Map()
36
+ private crossAccountRoles: CrossAccountRole[] = []
37
+ private accountMappings: AccountMapping[] = []
38
+
39
+ /**
40
+ * Register an AWS account
41
+ */
42
+ registerAccount(account: AWSAccount): void {
43
+ this.accounts.set(account.id, account)
44
+ }
45
+
46
+ /**
47
+ * Get account by ID
48
+ */
49
+ getAccount(accountId: string): AWSAccount | undefined {
50
+ return this.accounts.get(accountId)
51
+ }
52
+
53
+ /**
54
+ * Get account by alias
55
+ */
56
+ getAccountByAlias(alias: string): AWSAccount | undefined {
57
+ return Array.from(this.accounts.values()).find(acc => acc.alias === alias)
58
+ }
59
+
60
+ /**
61
+ * List all accounts
62
+ */
63
+ listAccounts(): AWSAccount[] {
64
+ return Array.from(this.accounts.values())
65
+ }
66
+
67
+ /**
68
+ * Get accounts by role
69
+ */
70
+ getAccountsByRole(role: AWSAccount['role']): AWSAccount[] {
71
+ return Array.from(this.accounts.values()).filter(acc => acc.role === role)
72
+ }
73
+
74
+ /**
75
+ * Create cross-account role for deployment
76
+ */
77
+ createCrossAccountRole(
78
+ sourceAccountId: string,
79
+ targetAccountId: string,
80
+ roleName: string,
81
+ permissions: string[],
82
+ options?: {
83
+ externalId?: string
84
+ sessionDuration?: number
85
+ },
86
+ ): CrossAccountRole {
87
+ const role: CrossAccountRole = {
88
+ roleArn: `arn:aws:iam::${targetAccountId}:role/${roleName}`,
89
+ roleName,
90
+ sourceAccountId,
91
+ targetAccountId,
92
+ permissions,
93
+ externalId: options?.externalId,
94
+ sessionDuration: options?.sessionDuration || 3600,
95
+ }
96
+
97
+ this.crossAccountRoles.push(role)
98
+
99
+ return role
100
+ }
101
+
102
+ /**
103
+ * Get assume role policy document
104
+ */
105
+ getAssumeRolePolicyDocument(sourceAccountId: string, externalId?: string): any {
106
+ const policy: any = {
107
+ Version: '2012-10-17',
108
+ Statement: [
109
+ {
110
+ Effect: 'Allow',
111
+ Principal: {
112
+ AWS: `arn:aws:iam::${sourceAccountId}:root`,
113
+ },
114
+ Action: 'sts:AssumeRole',
115
+ },
116
+ ],
117
+ }
118
+
119
+ // Add external ID condition for enhanced security
120
+ if (externalId) {
121
+ policy.Statement[0].Condition = {
122
+ StringEquals: {
123
+ 'sts:ExternalId': externalId,
124
+ },
125
+ }
126
+ }
127
+
128
+ return policy
129
+ }
130
+
131
+ /**
132
+ * Generate IAM policy for cross-account access
133
+ */
134
+ generateCrossAccountPolicy(permissions: string[]): any {
135
+ return {
136
+ Version: '2012-10-17',
137
+ Statement: [
138
+ {
139
+ Effect: 'Allow',
140
+ Action: permissions,
141
+ Resource: '*',
142
+ },
143
+ ],
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Map environment to account
149
+ */
150
+ mapEnvironmentToAccount(
151
+ environment: string,
152
+ accountId: string,
153
+ region: string,
154
+ ): void {
155
+ this.accountMappings.push({
156
+ environment,
157
+ accountId,
158
+ region,
159
+ })
160
+ }
161
+
162
+ /**
163
+ * Get account for environment
164
+ */
165
+ getAccountForEnvironment(environment: string): AccountMapping | undefined {
166
+ return this.accountMappings.find(mapping => mapping.environment === environment)
167
+ }
168
+
169
+ /**
170
+ * Assume role in target account
171
+ */
172
+ async assumeRole(
173
+ roleArn: string,
174
+ sessionName: string,
175
+ externalId?: string,
176
+ ): Promise<{
177
+ accessKeyId: string
178
+ secretAccessKey: string
179
+ sessionToken: string
180
+ expiration: Date
181
+ }> {
182
+ // This would use AWS STS AssumeRole API
183
+ // Placeholder implementation
184
+ console.log(`Assuming role: ${roleArn} with session: ${sessionName}`)
185
+
186
+ return {
187
+ accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
188
+ secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
189
+ sessionToken: 'token',
190
+ expiration: new Date(Date.now() + 3600000),
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Get credentials for account
196
+ */
197
+ async getCredentialsForAccount(accountId: string): Promise<{
198
+ accessKeyId: string
199
+ secretAccessKey: string
200
+ sessionToken?: string
201
+ }> {
202
+ const account = this.accounts.get(accountId)
203
+
204
+ if (!account) {
205
+ throw new Error(`Account not found: ${accountId}`)
206
+ }
207
+
208
+ // If account has assume role ARN, assume the role
209
+ if (account.assumeRoleArn) {
210
+ const credentials = await this.assumeRole(
211
+ account.assumeRoleArn,
212
+ `ts-cloud-${Date.now()}`,
213
+ )
214
+
215
+ return {
216
+ accessKeyId: credentials.accessKeyId,
217
+ secretAccessKey: credentials.secretAccessKey,
218
+ sessionToken: credentials.sessionToken,
219
+ }
220
+ }
221
+
222
+ // Otherwise, return default credentials
223
+ // In real implementation, would fetch from environment/credentials file
224
+ throw new Error('No credentials available for account')
225
+ }
226
+
227
+ /**
228
+ * List cross-account roles
229
+ */
230
+ listCrossAccountRoles(): CrossAccountRole[] {
231
+ return [...this.crossAccountRoles]
232
+ }
233
+
234
+ /**
235
+ * Get cross-account roles for account
236
+ */
237
+ getCrossAccountRolesForAccount(accountId: string): CrossAccountRole[] {
238
+ return this.crossAccountRoles.filter(
239
+ role => role.sourceAccountId === accountId || role.targetAccountId === accountId,
240
+ )
241
+ }
242
+
243
+ /**
244
+ * Validate account access
245
+ */
246
+ async validateAccountAccess(accountId: string): Promise<boolean> {
247
+ try {
248
+ const credentials = await this.getCredentialsForAccount(accountId)
249
+
250
+ // Would use STS GetCallerIdentity to validate credentials
251
+ console.log(`Validating access to account: ${accountId}`)
252
+
253
+ return true
254
+ }
255
+ catch {
256
+ return false
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Get consolidated billing summary
262
+ */
263
+ async getConsolidatedBilling(): Promise<{
264
+ totalCost: number
265
+ byAccount: Record<string, number>
266
+ }> {
267
+ // Would use AWS Cost Explorer API
268
+ // Placeholder implementation
269
+ const byAccount: Record<string, number> = {}
270
+
271
+ for (const account of this.accounts.values()) {
272
+ byAccount[account.id] = Math.random() * 1000 // Placeholder cost
273
+ }
274
+
275
+ const totalCost = Object.values(byAccount).reduce((sum, cost) => sum + cost, 0)
276
+
277
+ return {
278
+ totalCost,
279
+ byAccount,
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Clear all data
285
+ */
286
+ clear(): void {
287
+ this.accounts.clear()
288
+ this.crossAccountRoles = []
289
+ this.accountMappings = []
290
+ }
291
+ }
292
+
293
+ /**
294
+ * AWS Organizations helper
295
+ */
296
+ export class OrganizationManager {
297
+ private organizationId?: string
298
+ private organizationalUnits: Map<string, OrganizationalUnit> = new Map()
299
+
300
+ /**
301
+ * Get organization ID
302
+ */
303
+ getOrganizationId(): string | undefined {
304
+ return this.organizationId
305
+ }
306
+
307
+ /**
308
+ * Set organization ID
309
+ */
310
+ setOrganizationId(id: string): void {
311
+ this.organizationId = id
312
+ }
313
+
314
+ /**
315
+ * Create organizational unit
316
+ */
317
+ createOrganizationalUnit(name: string, parentId?: string): OrganizationalUnit {
318
+ const ou: OrganizationalUnit = {
319
+ id: `ou-${Date.now()}`,
320
+ name,
321
+ parentId,
322
+ accounts: [],
323
+ }
324
+
325
+ this.organizationalUnits.set(ou.id, ou)
326
+
327
+ return ou
328
+ }
329
+
330
+ /**
331
+ * Get organizational unit
332
+ */
333
+ getOrganizationalUnit(id: string): OrganizationalUnit | undefined {
334
+ return this.organizationalUnits.get(id)
335
+ }
336
+
337
+ /**
338
+ * List organizational units
339
+ */
340
+ listOrganizationalUnits(): OrganizationalUnit[] {
341
+ return Array.from(this.organizationalUnits.values())
342
+ }
343
+
344
+ /**
345
+ * Add account to organizational unit
346
+ */
347
+ addAccountToOU(ouId: string, accountId: string): void {
348
+ const ou = this.organizationalUnits.get(ouId)
349
+
350
+ if (!ou) {
351
+ throw new Error(`Organizational unit not found: ${ouId}`)
352
+ }
353
+
354
+ if (!ou.accounts.includes(accountId)) {
355
+ ou.accounts.push(accountId)
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Remove account from organizational unit
361
+ */
362
+ removeAccountFromOU(ouId: string, accountId: string): void {
363
+ const ou = this.organizationalUnits.get(ouId)
364
+
365
+ if (!ou) {
366
+ throw new Error(`Organizational unit not found: ${ouId}`)
367
+ }
368
+
369
+ ou.accounts = ou.accounts.filter(id => id !== accountId)
370
+ }
371
+
372
+ /**
373
+ * Get accounts in organizational unit
374
+ */
375
+ getAccountsInOU(ouId: string): string[] {
376
+ const ou = this.organizationalUnits.get(ouId)
377
+
378
+ if (!ou) {
379
+ return []
380
+ }
381
+
382
+ return [...ou.accounts]
383
+ }
384
+
385
+ /**
386
+ * Apply service control policy
387
+ */
388
+ applyServiceControlPolicy(
389
+ targetId: string,
390
+ policyDocument: any,
391
+ ): ServiceControlPolicy {
392
+ return {
393
+ id: `scp-${Date.now()}`,
394
+ name: 'Custom SCP',
395
+ targetId,
396
+ policyDocument,
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Clear all data
402
+ */
403
+ clear(): void {
404
+ this.organizationId = undefined
405
+ this.organizationalUnits.clear()
406
+ }
407
+ }
408
+
409
+ export interface OrganizationalUnit {
410
+ id: string
411
+ name: string
412
+ parentId?: string
413
+ accounts: string[]
414
+ }
415
+
416
+ export interface ServiceControlPolicy {
417
+ id: string
418
+ name: string
419
+ targetId: string
420
+ policyDocument: any
421
+ }
422
+
423
+ /**
424
+ * Global instances
425
+ */
426
+ export const multiAccountManager: MultiAccountManager = new MultiAccountManager()
427
+ export const organizationManager: OrganizationManager = new OrganizationManager()