local-serverless-stack 0.17.2 → 1.0.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 (221) hide show
  1. package/CHANGELOG.md +327 -0
  2. package/README.md +1150 -221
  3. package/assets/icon.svg +37 -0
  4. package/assets/logo.svg +38 -0
  5. package/bin/cli.js +384 -217
  6. package/bin/i18n.js +498 -0
  7. package/dist/client/config-discovery.d.ts.map +1 -1
  8. package/dist/client/config-discovery.js +2 -1
  9. package/dist/client/config-discovery.js.map +1 -1
  10. package/dist/client/http.d.ts +7 -0
  11. package/dist/client/http.d.ts.map +1 -1
  12. package/dist/client/http.js +3 -2
  13. package/dist/client/http.js.map +1 -1
  14. package/dist/client/lifecycle.d.ts +1 -4
  15. package/dist/client/lifecycle.d.ts.map +1 -1
  16. package/dist/client/lifecycle.js +2 -8
  17. package/dist/client/lifecycle.js.map +1 -1
  18. package/dist/client/namespaces/health.d.ts +1 -1
  19. package/dist/client/namespaces/health.d.ts.map +1 -1
  20. package/dist/client/namespaces/queues.d.ts.map +1 -1
  21. package/dist/client/namespaces/queues.js +9 -0
  22. package/dist/client/namespaces/queues.js.map +1 -1
  23. package/dist/client/namespaces/seeds.d.ts +1 -1
  24. package/dist/client/namespaces/services.d.ts +34 -0
  25. package/dist/client/namespaces/services.d.ts.map +1 -1
  26. package/dist/client/namespaces/services.js +3 -0
  27. package/dist/client/namespaces/services.js.map +1 -1
  28. package/dist/client/types.d.ts +17 -5
  29. package/dist/client/types.d.ts.map +1 -1
  30. package/dist/mcp/http.d.ts +15 -0
  31. package/dist/mcp/http.d.ts.map +1 -0
  32. package/dist/mcp/http.js +86 -0
  33. package/dist/mcp/http.js.map +1 -0
  34. package/dist/mcp/protocol.d.ts +36 -0
  35. package/dist/mcp/protocol.d.ts.map +1 -0
  36. package/dist/mcp/protocol.js +96 -0
  37. package/dist/mcp/protocol.js.map +1 -0
  38. package/dist/mcp/server.d.ts +7 -0
  39. package/dist/mcp/server.d.ts.map +1 -0
  40. package/dist/mcp/server.js +41 -0
  41. package/dist/mcp/server.js.map +1 -0
  42. package/dist/mcp/tools.d.ts +18 -0
  43. package/dist/mcp/tools.d.ts.map +1 -0
  44. package/dist/mcp/tools.js +323 -0
  45. package/dist/mcp/tools.js.map +1 -0
  46. package/dist/server/dev/dynamo-proxy.d.ts.map +1 -1
  47. package/dist/server/dev/dynamo-proxy.js +16 -2
  48. package/dist/server/dev/dynamo-proxy.js.map +1 -1
  49. package/dist/server/engine/backends/self-backend.d.ts +11 -2
  50. package/dist/server/engine/backends/self-backend.d.ts.map +1 -1
  51. package/dist/server/engine/backends/self-backend.js +42 -1
  52. package/dist/server/engine/backends/self-backend.js.map +1 -1
  53. package/dist/server/engine/dispatch/dispatcher.js +2 -2
  54. package/dist/server/engine/dispatch/dispatcher.js.map +1 -1
  55. package/dist/server/engine/engine-manager.d.ts +6 -1
  56. package/dist/server/engine/engine-manager.d.ts.map +1 -1
  57. package/dist/server/engine/engine-manager.js +30 -27
  58. package/dist/server/engine/engine-manager.js.map +1 -1
  59. package/dist/server/engine/http/is-aws-request.d.ts +8 -0
  60. package/dist/server/engine/http/is-aws-request.d.ts.map +1 -0
  61. package/dist/server/engine/http/is-aws-request.js +53 -0
  62. package/dist/server/engine/http/is-aws-request.js.map +1 -0
  63. package/dist/server/engine/http/router.d.ts.map +1 -1
  64. package/dist/server/engine/http/router.js +7 -1
  65. package/dist/server/engine/http/router.js.map +1 -1
  66. package/dist/server/engine/store/engine-store.d.ts +1 -0
  67. package/dist/server/engine/store/engine-store.d.ts.map +1 -1
  68. package/dist/server/engine/store/engine-store.js +2 -1
  69. package/dist/server/engine/store/engine-store.js.map +1 -1
  70. package/dist/server/engine/store/memory-store.d.ts +16 -0
  71. package/dist/server/engine/store/memory-store.d.ts.map +1 -0
  72. package/dist/server/engine/store/memory-store.js +167 -0
  73. package/dist/server/engine/store/memory-store.js.map +1 -0
  74. package/dist/server/engine/store/wal.d.ts +3 -0
  75. package/dist/server/engine/store/wal.d.ts.map +1 -1
  76. package/dist/server/engine/store/wal.js +35 -1
  77. package/dist/server/engine/store/wal.js.map +1 -1
  78. package/dist/server/index.js +159 -44
  79. package/dist/server/index.js.map +1 -1
  80. package/dist/server/routes/config.d.ts.map +1 -1
  81. package/dist/server/routes/config.js +25 -52
  82. package/dist/server/routes/config.js.map +1 -1
  83. package/dist/server/routes/lambdas.d.ts.map +1 -1
  84. package/dist/server/routes/lambdas.js +65 -0
  85. package/dist/server/routes/lambdas.js.map +1 -1
  86. package/dist/server/routes/services.d.ts.map +1 -1
  87. package/dist/server/routes/services.js +275 -24
  88. package/dist/server/routes/services.js.map +1 -1
  89. package/dist/server/services/bind-host.d.ts +30 -0
  90. package/dist/server/services/bind-host.d.ts.map +1 -0
  91. package/dist/server/services/bind-host.js +182 -0
  92. package/dist/server/services/bind-host.js.map +1 -0
  93. package/dist/server/services/cache-manager.d.ts +2 -1
  94. package/dist/server/services/cache-manager.d.ts.map +1 -1
  95. package/dist/server/services/cache-manager.js +4 -14
  96. package/dist/server/services/cache-manager.js.map +1 -1
  97. package/dist/server/services/config-manager.d.ts +28 -35
  98. package/dist/server/services/config-manager.d.ts.map +1 -1
  99. package/dist/server/services/config-manager.js +475 -189
  100. package/dist/server/services/config-manager.js.map +1 -1
  101. package/dist/server/services/dynamo-explorer.d.ts +1 -0
  102. package/dist/server/services/dynamo-explorer.d.ts.map +1 -1
  103. package/dist/server/services/dynamo-explorer.js +28 -6
  104. package/dist/server/services/dynamo-explorer.js.map +1 -1
  105. package/dist/server/services/explorer-region.d.ts +2 -0
  106. package/dist/server/services/explorer-region.d.ts.map +1 -0
  107. package/dist/server/services/explorer-region.js +23 -0
  108. package/dist/server/services/explorer-region.js.map +1 -0
  109. package/dist/server/services/gateway-manager.d.ts.map +1 -1
  110. package/dist/server/services/gateway-manager.js +18 -5
  111. package/dist/server/services/gateway-manager.js.map +1 -1
  112. package/dist/server/services/invocation-activity.d.ts +45 -0
  113. package/dist/server/services/invocation-activity.d.ts.map +1 -0
  114. package/dist/server/services/invocation-activity.js +102 -0
  115. package/dist/server/services/invocation-activity.js.map +1 -0
  116. package/dist/server/services/lambda-runtime-manager.d.ts +7 -1
  117. package/dist/server/services/lambda-runtime-manager.d.ts.map +1 -1
  118. package/dist/server/services/lambda-runtime-manager.js +118 -10
  119. package/dist/server/services/lambda-runtime-manager.js.map +1 -1
  120. package/dist/server/services/opensearch-explorer.d.ts.map +1 -1
  121. package/dist/server/services/opensearch-explorer.js +14 -10
  122. package/dist/server/services/opensearch-explorer.js.map +1 -1
  123. package/dist/server/services/project-scope.d.ts +2 -0
  124. package/dist/server/services/project-scope.d.ts.map +1 -0
  125. package/dist/server/services/project-scope.js +23 -0
  126. package/dist/server/services/project-scope.js.map +1 -0
  127. package/dist/server/services/queue-inspector.d.ts.map +1 -1
  128. package/dist/server/services/queue-inspector.js +15 -6
  129. package/dist/server/services/queue-inspector.js.map +1 -1
  130. package/dist/server/services/resource-provisioner.d.ts +0 -2
  131. package/dist/server/services/resource-provisioner.d.ts.map +1 -1
  132. package/dist/server/services/resource-provisioner.js +24 -14
  133. package/dist/server/services/resource-provisioner.js.map +1 -1
  134. package/dist/server/services/s3-explorer.js +3 -3
  135. package/dist/server/services/s3-explorer.js.map +1 -1
  136. package/dist/server/services/secrets-explorer.d.ts.map +1 -1
  137. package/dist/server/services/secrets-explorer.js +10 -3
  138. package/dist/server/services/secrets-explorer.js.map +1 -1
  139. package/dist/server/services/seed-manager.d.ts.map +1 -1
  140. package/dist/server/services/seed-manager.js +17 -8
  141. package/dist/server/services/seed-manager.js.map +1 -1
  142. package/dist/server/services/serverless-state-parser.d.ts +10 -0
  143. package/dist/server/services/serverless-state-parser.d.ts.map +1 -1
  144. package/dist/server/services/serverless-state-parser.js +20 -1
  145. package/dist/server/services/serverless-state-parser.js.map +1 -1
  146. package/dist/server/services/service-registrar.d.ts.map +1 -1
  147. package/dist/server/services/service-registrar.js +19 -5
  148. package/dist/server/services/service-registrar.js.map +1 -1
  149. package/dist/server/services/service-scanner.d.ts +20 -0
  150. package/dist/server/services/service-scanner.d.ts.map +1 -0
  151. package/dist/server/services/service-scanner.js +173 -0
  152. package/dist/server/services/service-scanner.js.map +1 -0
  153. package/dist/server/services/source-watcher.d.ts.map +1 -1
  154. package/dist/server/services/source-watcher.js +31 -6
  155. package/dist/server/services/source-watcher.js.map +1 -1
  156. package/dist/ui/assets/ApisPage-BOuimwWz.js +1 -0
  157. package/dist/ui/assets/BucketDetailPage-vLYwhoQt.js +1 -0
  158. package/dist/ui/assets/BucketsPage-Cu5lU1Hp.js +1 -0
  159. package/dist/ui/assets/DynamoPage-y3TTEPUL.js +1 -0
  160. package/dist/ui/assets/DynamoTablePage-BnmSRZjc.js +3 -0
  161. package/dist/ui/assets/LambdaDetailPage-B5q_d27t.js +4 -0
  162. package/dist/ui/assets/LambdasPage-CJpRoEDx.js +1 -0
  163. package/dist/ui/assets/OnboardingPage-D02dymQi.js +1 -0
  164. package/dist/ui/assets/OpenSearchCollectionPage-B_wWTlfL.js +1 -0
  165. package/dist/ui/assets/OpenSearchPage-BLEgfF_g.js +1 -0
  166. package/dist/ui/assets/{OverviewPage-DS6XJ7kG.css → OverviewPage-C1pBJ8aP.css} +1 -1
  167. package/dist/ui/assets/OverviewPage-EdJWiAt6.js +1 -0
  168. package/dist/ui/assets/QueueDetailPage-ByEYHvHe.js +1 -0
  169. package/dist/ui/assets/QueuesPage-CvwYHSll.js +1 -0
  170. package/dist/ui/assets/SecretsPage-DASw8Ntf.js +1 -0
  171. package/dist/ui/assets/ServiceDetailPage-BMsUDg6L.js +2 -0
  172. package/dist/ui/assets/ServicesPage-2JuiIiRr.js +2 -0
  173. package/dist/ui/assets/SettingsPage-DStO4bgN.js +1 -0
  174. package/dist/ui/assets/engine-D0mFFNbL.js +1 -0
  175. package/dist/ui/assets/index-BIEznsi4.js +37 -0
  176. package/dist/ui/assets/index-BRMvNP3Y.css +1 -0
  177. package/dist/ui/assets/onboarding-DQmlvyWU.js +1 -0
  178. package/dist/ui/assets/resourceIcons-baecADXA.js +1 -0
  179. package/dist/ui/assets/triggerIcons-DIPWQkJ3.js +1 -0
  180. package/dist/ui/favicon.svg +37 -0
  181. package/dist/ui/index.html +5 -3
  182. package/package.json +11 -11
  183. package/dist/server/engine/aoss-sidecar.d.ts +0 -13
  184. package/dist/server/engine/aoss-sidecar.d.ts.map +0 -1
  185. package/dist/server/engine/aoss-sidecar.js +0 -93
  186. package/dist/server/engine/aoss-sidecar.js.map +0 -1
  187. package/dist/server/engine/backends/localstack-backend.d.ts +0 -25
  188. package/dist/server/engine/backends/localstack-backend.d.ts.map +0 -1
  189. package/dist/server/engine/backends/localstack-backend.js +0 -199
  190. package/dist/server/engine/backends/localstack-backend.js.map +0 -1
  191. package/dist/server/engine/engine-backend.d.ts +0 -17
  192. package/dist/server/engine/engine-backend.d.ts.map +0 -1
  193. package/dist/server/engine/engine-backend.js +0 -7
  194. package/dist/server/engine/engine-backend.js.map +0 -1
  195. package/dist/server/services/localstack-manager.d.ts +0 -17
  196. package/dist/server/services/localstack-manager.d.ts.map +0 -1
  197. package/dist/server/services/localstack-manager.js +0 -31
  198. package/dist/server/services/localstack-manager.js.map +0 -1
  199. package/dist/ui/assets/ApisPage-CXYcWDhm.js +0 -1
  200. package/dist/ui/assets/BucketDetailPage-BwS2--Pe.js +0 -1
  201. package/dist/ui/assets/BucketsPage-khuiYc9C.js +0 -1
  202. package/dist/ui/assets/DynamoPage-aYo0QC0N.js +0 -1
  203. package/dist/ui/assets/DynamoTablePage-rFuV2pgd.js +0 -3
  204. package/dist/ui/assets/LambdaDetailPage-CJmu8M_N.js +0 -4
  205. package/dist/ui/assets/LambdasPage-DniNyKMe.js +0 -1
  206. package/dist/ui/assets/OpenSearchCollectionPage-BBwjgbB9.js +0 -1
  207. package/dist/ui/assets/OpenSearchPage-D5RxJGRo.js +0 -1
  208. package/dist/ui/assets/OverviewPage-Cyt1Xdp8.js +0 -1
  209. package/dist/ui/assets/QueueDetailPage-3FPsowIp.js +0 -1
  210. package/dist/ui/assets/QueuesPage-CUoDDgHr.js +0 -1
  211. package/dist/ui/assets/SecretsPage-B_mTnUf3.js +0 -1
  212. package/dist/ui/assets/ServiceDetailPage-BcdSjA6e.js +0 -2
  213. package/dist/ui/assets/ServicesPage-CU6fb3f8.js +0 -2
  214. package/dist/ui/assets/SettingsPage-BG8cYxgC.js +0 -1
  215. package/dist/ui/assets/index-BxwA-UT0.css +0 -1
  216. package/dist/ui/assets/index-DGsXIPJ-.js +0 -37
  217. package/packages/serverless-plugin/README.md +0 -115
  218. package/packages/serverless-plugin/dist/index.d.ts +0 -2
  219. package/packages/serverless-plugin/dist/index.d.ts.map +0 -1
  220. package/packages/serverless-plugin/dist/index.js +0 -107
  221. package/packages/serverless-plugin/dist/index.js.map +0 -1
@@ -1,93 +0,0 @@
1
- // OpenSearch Serverless (aoss) sidecar: the self-engine OpenSearch emulator
2
- // served in-process behind the engine router, on its own port next to a
3
- // LocalStack engine. No LocalStack edition provides aoss, so LSS fills the
4
- // gap itself — the control plane (X-Amz-Target OpenSearchServerless.*) and
5
- // the data plane (/_aoss/<collection>/...) both answer on this listener,
6
- // persisted under the sidecar's own data dir. Never started in self-engine
7
- // mode, where aoss is native.
8
- import http from 'http';
9
- import { EngineBus } from './bus.js';
10
- import { createEngineStore } from './store/engine-store.js';
11
- import { createEngineRequestHandler } from './http/router.js';
12
- import { OpenSearchEmulator } from './emulators/opensearch/index.js';
13
- // Same residency defaults as the self engine (config-manager.ts) — the
14
- // sidecar hosts one emulator, so there is no reason to expose knobs for them.
15
- const IDLE_UNLOAD_MS = 300_000;
16
- const MEMORY_BUDGET_MB = 128;
17
- export async function startAossSidecar(opts) {
18
- const store = createEngineStore({
19
- dataDir: opts.dataDir,
20
- idleUnloadMs: IDLE_UNLOAD_MS,
21
- memoryBudgetMb: MEMORY_BUDGET_MB,
22
- fsync: false,
23
- });
24
- // The emulator resolves collectionEndpoint through ctx.endpoint() at request
25
- // time; a closure over the mutable port keeps it correct once listen() has
26
- // picked the real port (port 0 case).
27
- let boundPort = opts.port;
28
- const ctx = {
29
- config: {
30
- port: opts.port,
31
- dataDir: opts.dataDir,
32
- account: opts.account ?? '000000000000',
33
- region: opts.region,
34
- idleUnloadMs: IDLE_UNLOAD_MS,
35
- memoryBudgetMb: MEMORY_BUDGET_MB,
36
- fsync: false,
37
- fallbackEndpoint: null,
38
- persistence: true,
39
- },
40
- store,
41
- bus: new EngineBus(),
42
- // The OpenSearch emulator never invokes functions; the stub keeps the
43
- // context honest without dragging the dispatcher (and the Lambda runtime)
44
- // into the sidecar.
45
- dispatcher: { invokeFunction: async () => ({ ok: true }) },
46
- endpoint: () => `http://localhost:${boundPort}`,
47
- };
48
- const emulator = new OpenSearchEmulator(ctx);
49
- const handler = createEngineRequestHandler({ ctx, emulators: [emulator] });
50
- const server = http.createServer(handler);
51
- // Keep-alive sockets must be destroyed for server.close() not to hang.
52
- const sockets = new Set();
53
- server.on('connection', socket => {
54
- sockets.add(socket);
55
- socket.on('close', () => sockets.delete(socket));
56
- });
57
- await new Promise((resolve, reject) => {
58
- const onError = (err) => {
59
- server.removeListener('listening', onListening);
60
- if (err.code === 'EADDRINUSE') {
61
- reject(new Error(`aoss sidecar could not bind port ${opts.port}: address already in use. ` +
62
- 'Stop the conflicting process or set aossSidecar.port to a free port.'));
63
- }
64
- else {
65
- reject(err);
66
- }
67
- };
68
- const onListening = () => {
69
- server.removeListener('error', onError);
70
- resolve();
71
- };
72
- server.once('error', onError);
73
- server.once('listening', onListening);
74
- server.listen(opts.port, '0.0.0.0');
75
- });
76
- boundPort = server.address().port;
77
- store.startSweeper();
78
- return {
79
- port: boundPort,
80
- endpoint: `http://localhost:${boundPort}`,
81
- async close() {
82
- await store.flushAll();
83
- store.stopSweeper();
84
- await new Promise(resolve => {
85
- server.close(() => resolve());
86
- for (const socket of sockets)
87
- socket.destroy();
88
- sockets.clear();
89
- });
90
- },
91
- };
92
- }
93
- //# sourceMappingURL=aoss-sidecar.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aoss-sidecar.js","sourceRoot":"","sources":["../../../src/server/engine/aoss-sidecar.ts"],"names":[],"mappings":"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"}
@@ -1,25 +0,0 @@
1
- import type { EngineBackend } from '../engine-backend.js';
2
- export declare class LocalStackBackend implements EngineBackend {
3
- readonly kind: "localstack";
4
- private process;
5
- private _isRunning;
6
- private endpoint;
7
- private readonly containerName;
8
- private readonly configManager;
9
- constructor();
10
- start(): Promise<void>;
11
- stop(): Promise<void>;
12
- private waitForReady;
13
- isRunning(): boolean;
14
- getEndpoint(): string;
15
- getConfig(): {
16
- endpoint: string;
17
- region: string;
18
- credentials: {
19
- accessKeyId: string;
20
- secretAccessKey: string;
21
- };
22
- };
23
- healthDetail(): Record<string, unknown>;
24
- }
25
- //# sourceMappingURL=localstack-backend.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localstack-backend.d.ts","sourceRoot":"","sources":["../../../../src/server/engine/backends/localstack-backend.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IAKzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;;IASxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+HtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAwBb,YAAY;IAmB1B,SAAS,IAAI,OAAO;IAIpB,WAAW,IAAI,MAAM;IAIrB,SAAS;;;;;;;;IAWT,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQxC"}
@@ -1,199 +0,0 @@
1
- // LocalStack lifecycle backend (docker container, managed/external). This is
2
- // the code that used to live in services/localstack-manager.ts — that module
3
- // is now a thin facade over EngineManager so existing call sites keep working
4
- // regardless of the active engine.
5
- import { spawn, exec } from 'child_process';
6
- import { promisify } from 'util';
7
- import { ConfigManager } from '../../services/config-manager.js';
8
- const execAsync = promisify(exec);
9
- export class LocalStackBackend {
10
- kind = 'localstack';
11
- process = null;
12
- _isRunning = false;
13
- endpoint;
14
- // Container name is scoped to the LocalStack port so multiple LSS instances
15
- // (one per example/project) can launch their own container side by side.
16
- // Falls back to "lss-localstack" when the default 4566 is in use to preserve
17
- // existing teardown scripts that look for that name.
18
- containerName;
19
- configManager;
20
- constructor() {
21
- this.configManager = ConfigManager.getInstance();
22
- this.endpoint = this.configManager.getLocalStackEndpoint();
23
- const port = this.configManager.getLocalStackPort();
24
- this.containerName = port === 4566 ? 'lss-localstack' : `lss-localstack-${port}`;
25
- }
26
- async start() {
27
- if (this._isRunning) {
28
- console.log('⚠️ LocalStack already running');
29
- return;
30
- }
31
- if (this.configManager.isExternal()) {
32
- console.log(`🔗 Using external LocalStack at ${this.endpoint}`);
33
- await this.waitForReady(30);
34
- this._isRunning = true;
35
- console.log('✅ Connected to external LocalStack');
36
- return;
37
- }
38
- try {
39
- // Check if docker is available
40
- await execAsync('docker ps -q', { timeout: 5000 });
41
- }
42
- catch {
43
- throw new Error('Docker is not available or not running. Please start Docker first.');
44
- }
45
- const edition = this.configManager.getLocalStackEdition();
46
- const image = this.configManager.getLocalStackImage();
47
- const authToken = this.configManager.getLocalStackAuthToken();
48
- if (edition === 'pro' && !authToken) {
49
- throw new Error('LocalStack Pro requires LOCALSTACK_AUTH_TOKEN. Set the env var or "localstackAuthToken" in your config.');
50
- }
51
- if (edition === 'community' && !authToken) {
52
- console.warn('⚠️ LOCALSTACK_AUTH_TOKEN not set. Recent localstack/localstack images (>= 2026.5) require a token even for the community edition.');
53
- }
54
- return new Promise((resolve, reject) => {
55
- console.log(`🔄 Starting LocalStack (${image})...`);
56
- const port = this.configManager.getLocalStackPort();
57
- const services = this.configManager.getServices().join(',');
58
- const persistence = this.configManager.isPersistence() ? '1' : '0';
59
- const debug = this.configManager.isDebug() ? '1' : '0';
60
- // Persistence volume is scoped to the container so two LSS instances
61
- // don't share (and corrupt) the same on-disk state.
62
- const volumeName = this.containerName === 'lss-localstack'
63
- ? 'lss-localstack-data'
64
- : `${this.containerName}-data`;
65
- const dockerArgs = [
66
- 'run',
67
- '--rm',
68
- '-p',
69
- `${port}:4566`,
70
- '-v',
71
- `${volumeName}:/var/lib/localstack`,
72
- '-v',
73
- '/var/run/docker.sock:/var/run/docker.sock',
74
- // host.docker.internal resolves natively on Docker Desktop but not on
75
- // Linux; the generated Lambda proxies target it to reach the invoke
76
- // listeners on the host, so map it explicitly (no-op elsewhere).
77
- '--add-host',
78
- 'host.docker.internal:host-gateway',
79
- '--name',
80
- this.containerName,
81
- '-e',
82
- `SERVICES=${services}`,
83
- '-e',
84
- 'LAMBDA_EXECUTOR=local',
85
- // Lambda containers spawned BY LocalStack (which run the proxies) need
86
- // the same host mapping.
87
- '-e',
88
- 'LAMBDA_DOCKER_FLAGS=--add-host host.docker.internal:host-gateway',
89
- '-e',
90
- `PERSISTENCE=${persistence}`,
91
- '-e',
92
- `DEBUG=${debug}`,
93
- ];
94
- if (authToken) {
95
- dockerArgs.push('-e', `LOCALSTACK_AUTH_TOKEN=${authToken}`);
96
- }
97
- dockerArgs.push(image);
98
- this.process = spawn('docker', dockerArgs);
99
- let stderr = '';
100
- let stdout = '';
101
- this.process.stderr?.on('data', data => {
102
- stderr += data.toString();
103
- console.log(`[LocalStack stderr] ${data.toString().trim()}`);
104
- });
105
- this.process.stdout?.on('data', data => {
106
- stdout += data.toString();
107
- console.log(`[LocalStack stdout] ${data.toString().trim()}`);
108
- });
109
- this.process.on('error', error => {
110
- console.error('❌ Failed to start LocalStack process:', error);
111
- reject(error);
112
- });
113
- this.process.on('close', code => {
114
- if (code !== 0) {
115
- console.error(`Container exited with code ${code}`);
116
- console.error('stderr:', stderr);
117
- console.error('stdout:', stdout);
118
- }
119
- });
120
- // Wait for LocalStack to be ready
121
- this.waitForReady()
122
- .then(() => {
123
- this._isRunning = true;
124
- console.log('✅ LocalStack ready');
125
- resolve();
126
- })
127
- .catch(err => {
128
- console.error('LocalStack startup error:', err.message);
129
- this.process?.kill();
130
- reject(err);
131
- });
132
- });
133
- }
134
- async stop() {
135
- if (!this._isRunning) {
136
- return;
137
- }
138
- if (this.configManager.isExternal()) {
139
- console.log('🔗 External LocalStack — leaving container untouched');
140
- this._isRunning = false;
141
- return;
142
- }
143
- console.log('🛑 Stopping LocalStack...');
144
- try {
145
- await execAsync(`docker stop ${this.containerName}`, { timeout: 10000 });
146
- this._isRunning = false;
147
- this.process = null;
148
- console.log('✅ LocalStack stopped');
149
- }
150
- catch (error) {
151
- console.error('⚠️ Error stopping LocalStack:', error instanceof Error ? error.message : 'Unknown error');
152
- this._isRunning = false;
153
- }
154
- }
155
- async waitForReady(maxAttempts = 120) {
156
- for (let i = 0; i < maxAttempts; i++) {
157
- try {
158
- const response = await fetch(`${this.endpoint}/_localstack/health`);
159
- if (response.ok) {
160
- console.log(`✓ LocalStack is responsive (attempt ${i + 1}/${maxAttempts})`);
161
- return;
162
- }
163
- }
164
- catch {
165
- // Ignore fetch errors during startup
166
- if (i % 20 === 0) {
167
- console.log(`⏳ Waiting for LocalStack... (attempt ${i + 1}/${maxAttempts})`);
168
- }
169
- }
170
- await new Promise(resolve => setTimeout(resolve, 1000));
171
- }
172
- throw new Error('LocalStack failed to start in time (120s timeout). Check Docker and container logs.');
173
- }
174
- isRunning() {
175
- return this._isRunning;
176
- }
177
- getEndpoint() {
178
- return this.endpoint;
179
- }
180
- getConfig() {
181
- return {
182
- endpoint: this.endpoint,
183
- region: this.configManager.getRegion(),
184
- credentials: {
185
- accessKeyId: process.env.LOCALSTACK_ACCESS_KEY_ID || 'test',
186
- secretAccessKey: process.env.LOCALSTACK_SECRET_ACCESS_KEY || 'test',
187
- },
188
- };
189
- }
190
- healthDetail() {
191
- return {
192
- endpoint: this.endpoint,
193
- running: this._isRunning,
194
- mode: this.configManager.getMode(),
195
- image: this.configManager.isExternal() ? undefined : this.configManager.getLocalStackImage(),
196
- };
197
- }
198
- }
199
- //# sourceMappingURL=localstack-backend.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localstack-backend.js","sourceRoot":"","sources":["../../../../src/server/engine/backends/localstack-backend.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- export interface EngineBackend {
2
- readonly kind: 'localstack' | 'self';
3
- start(): Promise<void>;
4
- stop(): Promise<void>;
5
- isRunning(): boolean;
6
- getEndpoint(): string;
7
- getConfig(): {
8
- endpoint: string;
9
- region: string;
10
- credentials: {
11
- accessKeyId: string;
12
- secretAccessKey: string;
13
- };
14
- };
15
- healthDetail(): Record<string, unknown>;
16
- }
17
- //# sourceMappingURL=engine-backend.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine-backend.d.ts","sourceRoot":"","sources":["../../../src/server/engine/engine-backend.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,SAAS,IAAI,OAAO,CAAC;IACrB,WAAW,IAAI,MAAM,CAAC;IACtB,SAAS,IAAI;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,eAAe,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/D,CAAC;IACF,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC"}
@@ -1,7 +0,0 @@
1
- // Lifecycle seam between the orchestrator and whichever AWS provider is
2
- // active. Provisioning is NOT part of this interface on purpose: both engines
3
- // are driven through the AWS wire API by the existing SDK-based code
4
- // (provisioner, explorers, seeds), so the only thing that varies is lifecycle
5
- // and endpoint. See docs/PRD_SELF_ENGINE.md §5.1.
6
- export {};
7
- //# sourceMappingURL=engine-backend.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine-backend.js","sourceRoot":"","sources":["../../../src/server/engine/engine-backend.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAC9E,kDAAkD"}
@@ -1,17 +0,0 @@
1
- export declare class LocalStackManager {
2
- private static instance;
3
- static getInstance(): LocalStackManager;
4
- start(): Promise<void>;
5
- stop(): Promise<void>;
6
- isRunning(): boolean;
7
- getEndpoint(): string;
8
- getConfig(): {
9
- endpoint: string;
10
- region: string;
11
- credentials: {
12
- accessKeyId: string;
13
- secretAccessKey: string;
14
- };
15
- };
16
- }
17
- //# sourceMappingURL=localstack-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localstack-manager.d.ts","sourceRoot":"","sources":["../../../src/server/services/localstack-manager.ts"],"names":[],"mappings":"AAQA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAE3C,MAAM,CAAC,WAAW,IAAI,iBAAiB;IAOjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,SAAS,IAAI,OAAO;IAIpB,WAAW,IAAI,MAAM;IAIrB,SAAS,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,eAAe,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAGjH"}
@@ -1,31 +0,0 @@
1
- // Deprecated facade kept so the ~10 existing call sites (provisioner,
2
- // explorers, seeds, dynamo-proxy, routes) stay untouched: they keep importing
3
- // LocalStackManager, but the active provider may be the LocalStack container
4
- // OR the in-process self engine — EngineManager decides from the config.
5
- // New code should use EngineManager directly.
6
- import { EngineManager } from '../engine/engine-manager.js';
7
- export class LocalStackManager {
8
- static instance;
9
- static getInstance() {
10
- if (!LocalStackManager.instance) {
11
- LocalStackManager.instance = new LocalStackManager();
12
- }
13
- return LocalStackManager.instance;
14
- }
15
- async start() {
16
- return EngineManager.getInstance().start();
17
- }
18
- async stop() {
19
- return EngineManager.getInstance().stop();
20
- }
21
- isRunning() {
22
- return EngineManager.getInstance().isRunning();
23
- }
24
- getEndpoint() {
25
- return EngineManager.getInstance().getEndpoint();
26
- }
27
- getConfig() {
28
- return EngineManager.getInstance().getConfig();
29
- }
30
- }
31
- //# sourceMappingURL=localstack-manager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"localstack-manager.js","sourceRoot":"","sources":["../../../src/server/services/localstack-manager.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,8CAA8C;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAC,QAAQ,CAAoB;IAE3C,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAChC,iBAAiB,CAAC,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACvD,CAAC;QACD,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,SAAS;QACP,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC;IACjD,CAAC;IAED,WAAW;QACT,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;IAED,SAAS;QACP,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC;IACjD,CAAC;CACF"}
@@ -1 +0,0 @@
1
- import{k as R,l as M,o as q,m as u,e as d,$ as t,t as p,a4 as e,j as n,D as G,E as w,O as H,i,_ as s,f as v,x as O,G as N,g as T,F as I,q as X,w as Y,H as P,C as S,A as y,u as c,R as J,v as _,B as K,I as Q,n as z,b as W,a as x,c as Z}from"./index-DGsXIPJ-.js";const ee=R({__name:"ApisView",setup(V){const k=Z(),f=z([]),h=z(!0),g=z(null),m=z({});let b=null;const F=[{key:"method",label:"Method"},{key:"path",label:"Path"},{key:"functionName",label:"→ Function"},{key:"eventType",label:"Type"},{key:"authorizerName",label:"Auth"},{key:"actions",label:"",align:"right"}],j=[{key:"name",label:"Name"},{key:"type",label:"Type"},{key:"payloadVersion",label:"Payload"},{key:"resultTtlInSeconds",label:"TTL",align:"right"},{key:"identitySource",label:"Identity source"},{key:"target",label:"Function / ARN"}],$=W(()=>({services:f.value.length,routes:f.value.reduce((r,l)=>r+l.routes.length,0),online:f.value.filter(r=>r.status==="online").length}));function B(r){return r.routes.map(l=>({...l}))}function L(r){return r.authorizers.map(l=>({...l,identitySource:l.identitySource.join(", "),target:l.functionName||l.arn||""}))}async function A(){try{f.value=await x.listApis(),g.value=null}catch(r){g.value=r.message||"Failed to load APIs"}finally{h.value=!1}}async function D(r){if(!m.value[r]){m.value={...m.value,[r]:!0};try{const l=await x.clearAuthorizerCache({service:r});k.add({title:"Authorizer cache cleared",description:`${l.removed} cached result${l.removed===1?"":"s"} removed`,variant:"success"})}catch(l){k.add({title:"Failed to clear authorizer cache",description:l.message,variant:"danger"})}finally{m.value={...m.value,[r]:!1}}}}function U(r,l){var a;const o=`curl -X ${l.method} http://localhost:${r.apiPort}${l.path}`;(a=navigator.clipboard)==null||a.writeText(o).then(()=>{k.add({title:"curl command copied",description:o,variant:"success"})})}function C(r){switch(r){case"online":return"success";case"port-conflict":return"warning";default:return"neutral"}}function E(r){return r==="ANY"?"info":"neutral"}return M(()=>{A(),b=window.setInterval(A,1e4)}),q(()=>{b&&window.clearInterval(b)}),(r,l)=>(u(),d(t(p),{direction:"vertical",gap:"1.25rem"},{default:e(()=>[n(t(G),{columns:3,gap:"1rem"},{default:e(()=>[n(t(w),{label:"Services with APIs",value:$.value.services,tone:"info",loading:h.value},null,8,["value","loading"]),n(t(w),{label:"Routes",value:$.value.routes,tone:"info",loading:h.value},null,8,["value","loading"]),n(t(w),{label:"Listeners online",value:$.value.online,tone:"success",loading:h.value},null,8,["value","loading"])]),_:1}),g.value?(u(),d(t(H),{key:0,variant:"danger",dismissible:"",onDismiss:l[0]||(l[0]=o=>g.value=null)},{default:e(()=>[i(s(g.value),1)]),_:1})):v("",!0),h.value&&!f.value.length?(u(),d(t(p),{key:1,direction:"horizontal",justify:"center",align:"center"},{default:e(()=>[n(t(O),{label:"Loading APIs..."})]),_:1})):f.value.length?v("",!0):(u(),d(t(N),{key:2,title:"No APIs registered",description:"Register a microservice that defines http or httpApi events to see its routes here."})),(u(!0),T(I,null,X(f.value,o=>(u(),d(t(Y),{key:o.service,variant:"outline"},{header:e(()=>[n(t(p),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between",wrap:""},{default:e(()=>[n(t(p),{direction:"horizontal",gap:"0.5rem",align:"center",wrap:""},{default:e(()=>[n(t(Q),{to:`/services/${encodeURIComponent(o.service)}`},{default:e(()=>[n(t(c),{weight:"semibold"},{default:e(()=>[i(s(o.service),1)]),_:2},1024)]),_:2},1032,["to"]),o.apiPort?(u(),d(t(_),{key:0,tone:"info",variant:"soft"},{default:e(()=>[i(":"+s(o.apiPort),1)]),_:2},1024)):v("",!0),n(t(_),{tone:C(o.status),variant:"soft"},{default:e(()=>[i(s(o.status),1)]),_:2},1032,["tone"]),o.invokePort?(u(),d(t(_),{key:1,tone:C(o.invokeStatus),variant:"soft"},{default:e(()=>[i(" invoke :"+s(o.invokePort),1)]),_:2},1032,["tone"])):v("",!0),o.stage?(u(),d(t(y),{key:2,size:"sm",variant:"soft"},{default:e(()=>[i("stage: "+s(o.stage),1)]),_:2},1024)):v("",!0)]),_:2},1024),n(t(S),{size:"sm",variant:"ghost",loading:m.value[o.service],onClick:a=>D(o.service)},{default:e(()=>[...l[1]||(l[1]=[i(" Clear authorizer cache ",-1)])]),_:1},8,["loading","onClick"])]),_:2},1024)]),default:e(()=>[n(t(p),{direction:"vertical",gap:"0.75rem"},{default:e(()=>[o.routes.length?(u(),d(t(P),{key:0,columns:F,rows:B(o),"aria-label":"API routes"},{"cell-method":e(({row:a})=>[n(t(_),{tone:E(String(a.method)),variant:"soft"},{default:e(()=>[i(s(a.method),1)]),_:2},1032,["tone"])]),"cell-path":e(({row:a})=>[n(t(c),{family:"mono"},{default:e(()=>[i(s(a.path),1)]),_:2},1024)]),"cell-functionName":e(({row:a})=>[n(t(J),{to:`/lambdas/${encodeURIComponent(String(a.functionName))}`,style:{"text-decoration":"none"}},{default:e(()=>[n(t(y),{size:"sm",variant:"soft",clickable:""},{default:e(()=>[i(s(a.functionName),1)]),_:2},1024)]),_:2},1032,["to"])]),"cell-eventType":e(({row:a})=>[n(t(y),{size:"sm",variant:"soft"},{default:e(()=>[i(s(a.payloadVersion==="2.0"?"v2":"v1"),1)]),_:2},1024)]),"cell-authorizerName":e(({row:a})=>[a.authorizerName?(u(),d(t(y),{key:0,size:"sm",variant:"soft"},{default:e(()=>[i(s(a.authorizerName),1)]),_:2},1024)):(u(),d(t(c),{key:1,tone:"muted"},{default:e(()=>[...l[2]||(l[2]=[i("—",-1)])]),_:1}))]),"cell-actions":e(({row:a})=>[n(t(p),{direction:"horizontal",gap:"0.375rem",justify:"flex-end"},{default:e(()=>[n(t(S),{size:"sm",variant:"ghost",onClick:te=>U(o,a)},{default:e(()=>[...l[3]||(l[3]=[i(" Copy curl ",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:2},1032,["rows"])):(u(),d(t(N),{key:1,title:"No routes",description:"This service exposes no http or httpApi routes."})),o.authorizers.length?(u(),T(I,{key:2},[n(t(K)),n(t(c),{weight:"semibold",size:"sm"},{default:e(()=>[...l[4]||(l[4]=[i("Authorizers",-1)])]),_:1}),n(t(P),{columns:j,rows:L(o),"aria-label":"Authorizers"},{"cell-name":e(({row:a})=>[n(t(c),{family:"mono",size:"sm"},{default:e(()=>[i(s(a.name),1)]),_:2},1024)]),"cell-type":e(({row:a})=>[n(t(y),{size:"sm",variant:"soft"},{default:e(()=>[i(s(a.type),1)]),_:2},1024)]),"cell-payloadVersion":e(({row:a})=>[n(t(y),{size:"sm",variant:"soft"},{default:e(()=>[i(s(a.payloadVersion==="2.0"?"v2":"v1"),1)]),_:2},1024)]),"cell-resultTtlInSeconds":e(({row:a})=>[n(t(c),{family:"mono",size:"sm"},{default:e(()=>[i(s(a.resultTtlInSeconds)+"s",1)]),_:2},1024)]),"cell-identitySource":e(({row:a})=>[n(t(c),{family:"mono",size:"xs"},{default:e(()=>[i(s(a.identitySource||"—"),1)]),_:2},1024)]),"cell-target":e(({row:a})=>[a.target?(u(),d(t(c),{key:0,family:"mono",size:"xs"},{default:e(()=>[i(s(a.target),1)]),_:2},1024)):(u(),d(t(c),{key:1,tone:"muted"},{default:e(()=>[...l[5]||(l[5]=[i("—",-1)])]),_:1}))]),_:1},8,["rows"])],64)):v("",!0)]),_:2},1024)]),_:2},1024))),128))]),_:1}))}}),le=R({__name:"ApisPage",setup(V){return(k,f)=>(u(),d(ee))}});export{le as default};
@@ -1 +0,0 @@
1
- import{k as E,l as J,a3 as Q,e as f,$ as t,t as r,a4 as a,a as g,m as c,j as l,C as p,s as W,i,u as B,_ as b,v as X,f as M,O as Y,x as F,g as Z,E as x,D as ee,N as U,a5 as te,a2 as ae,d as T,w as _,G as le,H as ne,I as oe,a6 as ie,F as ue,c as re,n as s,b as se,a1 as de}from"./index-DGsXIPJ-.js";const ce=["href"],fe=E({__name:"BucketDetail",props:{bucketName:{}},emits:["back"],setup(z,{emit:N}){const d=z,S=N,v=re(),u=s(null),k=s([]),h=s(""),K=s(!0),$=s(!1),y=s(null),j=s(""),w=s(""),C=s("text/plain"),V=s(!1),L=[{key:"key",label:"Key"},{key:"size",label:"Size",align:"right"},{key:"lastModified",label:"Modified"},{key:"actions",label:"",align:"right"}],G=se(()=>k.value.reduce((o,e)=>o+(e.size||0),0));function O(o){if(o==null)return"—";if(o===0)return"0 B";const e=["B","KB","MB","GB","TB"],n=Math.floor(Math.log(o)/Math.log(1024));return`${(o/Math.pow(1024,n)).toFixed(n===0?0:1)} ${e[n]}`}function H(o){return o?new Date(o).toLocaleString():"—"}async function D(){try{u.value=await g.getBucket(d.bucketName),y.value=null}catch(o){y.value=o.message||"Failed to load bucket",u.value=null}finally{K.value=!1}}async function m(){$.value=!0;try{const o=await g.listBucketObjects(d.bucketName,{prefix:h.value||void 0,maxKeys:200});k.value=o.objects}catch(o){v.add({title:"Failed to load objects",description:o.message,variant:"danger"})}finally{$.value=!1}}function R(o){return g.bucketObjectContentUrl(d.bucketName,o,!1)}function q(o){return g.bucketObjectContentUrl(d.bucketName,o,!0)}async function A(o){if(confirm(`Delete object "${o}"?`))try{await g.deleteBucketObject(d.bucketName,o),v.add({title:"Object deleted",variant:"info"}),await m()}catch(e){v.add({title:"Failed to delete object",description:e.message,variant:"danger"})}}async function I(){if(!j.value||!w.value){v.add({title:"Key and body are required",variant:"warning"});return}V.value=!0;try{await g.putBucketObject(d.bucketName,{key:j.value,body:w.value,contentType:C.value||void 0}),v.add({title:"Object uploaded",variant:"info"}),j.value="",w.value="",await m(),await D()}catch(o){v.add({title:"Failed to upload object",description:o.message,variant:"danger"})}finally{V.value=!1}}return J(()=>{D(),m()}),Q(()=>d.bucketName,()=>{D(),m()}),(o,e)=>(c(),f(t(r),{direction:"vertical",gap:"1rem"},{default:a(()=>[l(t(r),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:a(()=>[l(t(r),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:a(()=>{var n;return[l(t(p),{size:"sm",variant:"ghost",onClick:e[0]||(e[0]=P=>S("back"))},{default:a(()=>[l(t(W),{name:"arrow-left"}),e[9]||(e[9]=i(" Buckets",-1))]),_:1}),l(t(B),{size:"lg",weight:"semibold"},{default:a(()=>[i(b(z.bucketName),1)]),_:1}),(n=u.value)!=null&&n.versioning?(c(),f(t(X),{key:0,tone:"info",variant:"soft"},{default:a(()=>[...e[10]||(e[10]=[i("Versioning",-1)])]),_:1})):M("",!0)]}),_:1}),l(t(p),{size:"sm",variant:"ghost",loading:$.value,onClick:e[1]||(e[1]=n=>m())},{default:a(()=>[...e[11]||(e[11]=[i("Refresh",-1)])]),_:1},8,["loading"])]),_:1}),y.value?(c(),f(t(Y),{key:0,variant:"danger",dismissible:"",onDismiss:e[2]||(e[2]=n=>y.value=null)},{default:a(()=>[i(b(y.value),1)]),_:1})):M("",!0),K.value&&!u.value?(c(),f(t(r),{key:1,direction:"horizontal",justify:"center",align:"center"},{default:a(()=>[l(t(F),{label:"Loading bucket..."})]),_:1})):u.value?(c(),Z(ue,{key:2},[l(t(ee),{columns:4,gap:"0.75rem"},{default:a(()=>[l(t(x),{label:"Objects",value:u.value.objectCount??0,tone:"info"},null,8,["value"]),l(t(x),{label:"Size",value:O(u.value.totalSize),tone:"neutral"},null,8,["value"]),l(t(x),{label:"Versioning",value:u.value.versioning?"Enabled":"Disabled",tone:u.value.versioning?"success":"neutral"},null,8,["value","tone"]),l(t(x),{label:"Notifications",value:u.value.notifications??0,tone:(u.value.notifications??0)>0?"info":"neutral"},null,8,["value","tone"])]),_:1}),l(t(_),{variant:"outline"},{header:a(()=>[l(t(B),{weight:"semibold"},{default:a(()=>[...e[12]||(e[12]=[i("Upload object",-1)])]),_:1})]),default:a(()=>[l(t(r),{direction:"vertical",gap:"0.5rem"},{default:a(()=>[l(t(U),{modelValue:j.value,"onUpdate:modelValue":e[3]||(e[3]=n=>j.value=n),placeholder:"object/key.txt",label:"Key"},null,8,["modelValue"]),l(t(U),{modelValue:C.value,"onUpdate:modelValue":e[4]||(e[4]=n=>C.value=n),placeholder:"text/plain",label:"Content-Type"},null,8,["modelValue"]),l(t(B),{as:"label",tone:"muted",size:"sm"},{default:a(()=>[...e[13]||(e[13]=[i("Body",-1)])]),_:1}),te(T("textarea",{"onUpdate:modelValue":e[5]||(e[5]=n=>w.value=n),rows:"4",style:{width:"100%","font-family":"var(--tree-font-mono, monospace)",padding:"0.5rem"},placeholder:"Hello, world!"},null,512),[[ae,w.value]]),l(t(r),{direction:"horizontal",justify:"flex-end"},{default:a(()=>[l(t(p),{size:"sm",loading:V.value,onClick:I},{default:a(()=>[...e[14]||(e[14]=[i("Upload",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),l(t(_),{variant:"outline"},{header:a(()=>[l(t(r),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:a(()=>[l(t(B),{weight:"semibold"},{default:a(()=>[i("Objects ("+b(k.value.length)+" · "+b(O(G.value))+")",1)]),_:1}),l(t(r),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:a(()=>[l(t(U),{modelValue:h.value,"onUpdate:modelValue":e[6]||(e[6]=n=>h.value=n),placeholder:"prefix filter",size:"sm",onKeyup:e[7]||(e[7]=ie(n=>m(),["enter"]))},null,8,["modelValue"]),l(t(p),{size:"sm",variant:"ghost",onClick:e[8]||(e[8]=n=>m())},{default:a(()=>[...e[15]||(e[15]=[i("Apply",-1)])]),_:1})]),_:1})]),_:1})]),default:a(()=>[$.value?(c(),f(t(r),{key:0,direction:"horizontal",justify:"center",align:"center"},{default:a(()=>[l(t(F),{label:"Loading objects..."})]),_:1})):k.value.length?(c(),f(t(ne),{key:2,columns:L,rows:k.value,"aria-label":"Bucket objects"},{"cell-key":a(({row:n})=>[l(t(oe),{href:R(String(n.key)),external:"",style:{"font-weight":"500"}},{default:a(()=>[i(b(n.key),1)]),_:2},1032,["href"])]),"cell-size":a(({row:n})=>[i(b(O(Number(n.size))),1)]),"cell-lastModified":a(({row:n})=>[i(b(H(n.lastModified)),1)]),"cell-actions":a(({row:n})=>[l(t(r),{direction:"horizontal",gap:"0.25rem",justify:"flex-end"},{default:a(()=>[T("a",{href:q(String(n.key)),target:"_blank",rel:"noopener noreferrer",style:{"text-decoration":"none"}},[l(t(p),{size:"sm",variant:"ghost"},{default:a(()=>[...e[16]||(e[16]=[i("Download",-1)])]),_:1})],8,ce),l(t(p),{size:"sm",variant:"ghost",tone:"danger",onClick:P=>A(String(n.key))},{default:a(()=>[...e[17]||(e[17]=[i(" Delete ",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:1},8,["rows"])):(c(),f(t(le),{key:1,title:"No objects",description:"This bucket is empty (or the prefix filter excluded everything)."}))]),_:1})],64)):M("",!0)]),_:1}))}}),me=E({__name:"BucketDetailPage",props:{bucketName:{}},setup(z){const N=de();function d(){N.push("/buckets")}return(S,v)=>(c(),f(fe,{"bucket-name":z.bucketName,onBack:d},null,8,["bucket-name"]))}});export{me as default};
@@ -1 +0,0 @@
1
- import{k as C,a1 as M,l as N,o as D,m as i,e as u,$ as a,t as b,a4 as t,j as o,D as O,E as p,O as V,i as s,_ as c,f as T,w as U,x as L,G as E,H as F,C as G,v as _,R as P,A as q,u as y,I as A,n as f,b as w,a as z}from"./index-DGsXIPJ-.js";const H=C({__name:"BucketsView",setup(j){const $=M(),r=f([]),B=f({}),d=f(!0),v=f(null);let m=null;const x=[{key:"name",label:"Bucket"},{key:"service",label:"Service"},{key:"objectCount",label:"Objects",align:"right"},{key:"totalSize",label:"Size",align:"right"},{key:"versioning",label:"Versioning"},{key:"notifications",label:"Notifications",align:"right"},{key:"actions",label:"",align:"right"}],R=w(()=>r.value.map(n=>({...n,service:B.value[n.name]||""}))),g=w(()=>({buckets:r.value.length,objects:r.value.reduce((n,l)=>n+(l.objectCount||0),0),size:r.value.reduce((n,l)=>n+(l.totalSize||0),0)}));function h(n){if(n==null)return"—";if(n===0)return"0 B";const l=["B","KB","MB","GB","TB"],e=Math.floor(Math.log(n)/Math.log(1024));return`${(n/Math.pow(1024,e)).toFixed(e===0?0:1)} ${l[e]}`}async function S(){try{const[n,l]=await Promise.all([z.listBuckets(),z.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);r.value=n;const e={};for(const k of l.buckets||[])e[k.name]=k.service;B.value=e,v.value=null}catch(n){v.value=n.message||"Failed to load buckets"}finally{d.value=!1}}function I(n){$.push(`/buckets/${encodeURIComponent(n)}`)}return N(()=>{S(),m=window.setInterval(S,1e4)}),D(()=>{m&&window.clearInterval(m)}),(n,l)=>(i(),u(a(b),{direction:"vertical",gap:"1.25rem"},{default:t(()=>[o(a(O),{columns:3,gap:"1rem"},{default:t(()=>[o(a(p),{label:"Buckets",value:g.value.buckets,tone:"info",loading:d.value},null,8,["value","loading"]),o(a(p),{label:"Objects",value:g.value.objects,tone:"success",loading:d.value},null,8,["value","loading"]),o(a(p),{label:"Total size",value:h(g.value.size),tone:"neutral",loading:d.value},null,8,["value","loading"])]),_:1}),v.value?(i(),u(a(V),{key:0,variant:"danger",dismissible:"",onDismiss:l[0]||(l[0]=e=>v.value=null)},{default:t(()=>[s(c(v.value),1)]),_:1})):T("",!0),o(a(U),{variant:"outline"},{header:t(()=>[o(a(b),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[o(a(y),{weight:"semibold"},{default:t(()=>[...l[1]||(l[1]=[s("S3 Buckets",-1)])]),_:1}),o(a(y),{tone:"muted"},{default:t(()=>[...l[2]||(l[2]=[s("Refreshes every 10s",-1)])]),_:1})]),_:1})]),default:t(()=>[d.value?(i(),u(a(b),{key:0,direction:"horizontal",justify:"center",align:"center"},{default:t(()=>[o(a(L),{label:"Loading buckets..."})]),_:1})):r.value.length?(i(),u(a(F),{key:2,columns:x,rows:R.value,"aria-label":"S3 buckets"},{"cell-name":t(({row:e})=>[o(a(A),{to:`/buckets/${encodeURIComponent(String(e.name))}`,style:{"font-weight":"600"}},{default:t(()=>[s(c(e.name),1)]),_:2},1032,["to"])]),"cell-service":t(({row:e})=>[e.service?(i(),u(a(P),{key:0,to:`/services/${encodeURIComponent(String(e.service))}`,style:{"text-decoration":"none"}},{default:t(()=>[o(a(q),{size:"sm",variant:"soft",clickable:""},{default:t(()=>[s(c(e.service),1)]),_:2},1024)]),_:2},1032,["to"])):(i(),u(a(y),{key:1,tone:"muted",size:"xs"},{default:t(()=>[...l[3]||(l[3]=[s("unmanaged",-1)])]),_:1}))]),"cell-objectCount":t(({row:e})=>[o(a(_),{tone:"info",variant:"soft"},{default:t(()=>[s(c(e.objectCount??0),1)]),_:2},1024)]),"cell-totalSize":t(({row:e})=>[s(c(h(e.totalSize)),1)]),"cell-versioning":t(({row:e})=>[o(a(_),{tone:e.versioning?"success":"neutral",variant:"soft"},{default:t(()=>[s(c(e.versioning?"Enabled":"Disabled"),1)]),_:2},1032,["tone"])]),"cell-notifications":t(({row:e})=>[o(a(_),{tone:Number(e.notifications)>0?"info":"neutral",variant:"soft"},{default:t(()=>[s(c(e.notifications??0),1)]),_:2},1032,["tone"])]),"cell-actions":t(({row:e})=>[o(a(G),{size:"sm",variant:"ghost",onClick:k=>I(String(e.name))},{default:t(()=>[...l[4]||(l[4]=[s(" Open ",-1)])]),_:1},8,["onClick"])]),_:1},8,["rows"])):(i(),u(a(E),{key:1,title:"No buckets found",description:"Register a microservice that defines S3 resources or create buckets directly in LocalStack."}))]),_:1})]),_:1}))}}),J=C({__name:"BucketsPage",setup(j){return($,r)=>(i(),u(H))}});export{J as default};
@@ -1 +0,0 @@
1
- import{k as A,l as U,o as j,m as n,e as l,$ as a,t as v,a4 as s,j as u,D as F,E as w,O as H,i as o,_ as r,f as b,w as q,x as W,G as V,H as J,C as Q,u as m,A as c,v as R,R as X,N as Y,n as p,b as S,a as L,a1 as Z}from"./index-DGsXIPJ-.js";const ee=A({__name:"DynamoTablesList",emits:["open"],setup(K,{emit:N}){const _=N,d=p([]),k=p([]),z=p({}),y=p(!0),x=p(null),$=p("");let h=null;const M=[{key:"name",label:"Table"},{key:"service",label:"Service"},{key:"status",label:"Status"},{key:"itemCount",label:"Items",align:"right"},{key:"seed",label:"Seed"},{key:"features",label:"Features"},{key:"actions",label:"",align:"right"}],I=S(()=>{const i=d.value.map(e=>{var G,P;const t=(G=e.keySchema.find(C=>C.KeyType==="HASH"))==null?void 0:G.AttributeName,f=(P=e.keySchema.find(C=>C.KeyType==="RANGE"))==null?void 0:P.AttributeName,D=f?`PK: ${t} · SK: ${f}`:`PK: ${t??"—"}`,E=k.value.find(C=>C.tableName===e.name);return{name:e.name,status:e.status,itemCount:e.itemCount||0,keyDescriptor:D,billingMode:e.billingMode,ttlOn:e.ttl.enabled,streamOn:e.streamEnabled,hasGsi:e.hasGsi,hasLsi:e.hasLsi,service:z.value[e.name]||"",seedItemCount:E?E.itemCount:null,exists:!0}});for(const e of k.value)!e.tableExists&&!i.some(t=>t.name===e.tableName)&&i.push({name:e.tableName,status:"PENDING",itemCount:0,keyDescriptor:"—",ttlOn:!1,streamOn:!1,hasGsi:!1,hasLsi:!1,service:z.value[e.tableName]||"",seedItemCount:e.itemCount,exists:!1});return i.sort((e,t)=>e.name.localeCompare(t.name))}),T=S(()=>{const i=$.value.trim().toLowerCase();return i?I.value.filter(e=>e.name.toLowerCase().includes(i)||(e.service||"").toLowerCase().includes(i)):I.value}),g=S(()=>({tables:d.value.length,items:d.value.reduce((i,e)=>i+(e.itemCount||0),0),warnings:d.value.reduce((i,e)=>{var t;return i+(((t=e.warnings)==null?void 0:t.length)||0)},0),seedsPending:k.value.filter(i=>!i.tableExists).length}));async function O(){try{const[i,e,t]=await Promise.all([L.listDynamoTables(),L.listSeeds().catch(()=>({seedsDir:"",entries:[]})),L.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);d.value=i.tables,k.value=e.entries;const f={};for(const D of t.tables)f[D.name]=D.service;z.value=f,x.value=null}catch(i){x.value=i.message||"Failed to load DynamoDB tables"}finally{y.value=!1}}function B(i){i.exists&&_("open",i.name)}return U(()=>{O(),h=window.setInterval(O,15e3)}),j(()=>{h&&window.clearInterval(h)}),(i,e)=>(n(),l(a(v),{direction:"vertical",gap:"1.25rem"},{default:s(()=>[u(a(F),{columns:4,gap:"1rem"},{default:s(()=>[u(a(w),{label:"Tables",value:g.value.tables,tone:"info",loading:y.value},null,8,["value","loading"]),u(a(w),{label:"Total items",value:g.value.items,tone:"success",loading:y.value},null,8,["value","loading"]),u(a(w),{label:"Seeds pending",value:g.value.seedsPending,tone:g.value.seedsPending>0?"warning":"neutral",loading:y.value},null,8,["value","tone","loading"]),u(a(w),{label:"Warnings",value:g.value.warnings,tone:g.value.warnings>0?"warning":"neutral",loading:y.value},null,8,["value","tone","loading"])]),_:1}),x.value?(n(),l(a(H),{key:0,variant:"danger",dismissible:"",onDismiss:e[0]||(e[0]=t=>x.value=null)},{default:s(()=>[o(r(x.value),1)]),_:1})):b("",!0),u(a(q),{variant:"outline"},{header:s(()=>[u(a(v),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:s(()=>[u(a(m),{weight:"semibold"},{default:s(()=>[...e[2]||(e[2]=[o("DynamoDB tables",-1)])]),_:1}),u(a(v),{direction:"horizontal",align:"center",gap:"1rem"},{default:s(()=>[u(a(Y),{modelValue:$.value,"onUpdate:modelValue":e[1]||(e[1]=t=>$.value=t),placeholder:"Filter tables...",style:{"min-width":"16rem"}},null,8,["modelValue"]),u(a(m),{tone:"muted",size:"xs"},{default:s(()=>[...e[3]||(e[3]=[o(" Rows with reduced opacity exist only as a seed file ",-1)])]),_:1})]),_:1})]),_:1})]),default:s(()=>[y.value?(n(),l(a(v),{key:0,direction:"horizontal",justify:"center",align:"center"},{default:s(()=>[u(a(W),{label:"Loading tables..."})]),_:1})):I.value.length?T.value.length?(n(),l(a(J),{key:3,columns:M,rows:T.value,"row-key":"name","row-state":t=>t.exists?"default":"muted","aria-label":"DynamoDB tables"},{"cell-name":s(({row:t})=>[u(a(v),{direction:"vertical",gap:"0.125rem"},{default:s(()=>[t.exists?(n(),l(a(m),{key:0,weight:"semibold",style:{cursor:"pointer","text-decoration":"underline","text-decoration-style":"dotted","text-underline-offset":"3px"},onClick:f=>B(t)},{default:s(()=>[o(r(t.name),1)]),_:2},1032,["onClick"])):(n(),l(a(v),{key:1,direction:"horizontal",gap:"0.375rem",align:"center"},{default:s(()=>[u(a(m),{weight:"semibold"},{default:s(()=>[o(r(t.name),1)]),_:2},1024),u(a(c),{size:"sm",variant:"soft"},{default:s(()=>[...e[4]||(e[4]=[o("seed only",-1)])]),_:1})]),_:2},1024)),u(a(m),{tone:"muted",family:"mono",size:"xs"},{default:s(()=>[o(r(t.keyDescriptor),1)]),_:2},1024)]),_:2},1024)]),"cell-service":s(({row:t})=>[t.service?(n(),l(a(X),{key:0,to:`/services/${encodeURIComponent(String(t.service))}`,style:{"text-decoration":"none"}},{default:s(()=>[u(a(c),{size:"sm",variant:"soft",clickable:""},{default:s(()=>[o(r(t.service),1)]),_:2},1024)]),_:2},1032,["to"])):(n(),l(a(m),{key:1,tone:"muted",size:"xs"},{default:s(()=>[...e[5]||(e[5]=[o("—",-1)])]),_:1}))]),"cell-status":s(({row:t})=>[t.exists?(n(),l(a(R),{key:0,tone:t.status==="ACTIVE"?"success":"warning",variant:"soft"},{default:s(()=>[o(r(t.status||"UNKNOWN"),1)]),_:2},1032,["tone"])):(n(),l(a(R),{key:1,tone:"warning",variant:"outline"},{default:s(()=>[...e[6]||(e[6]=[o("Not created",-1)])]),_:1}))]),"cell-itemCount":s(({row:t})=>[o(r(t.exists?t.itemCount:"—"),1)]),"cell-seed":s(({row:t})=>[t.seedItemCount!==null?(n(),l(a(R),{key:0,tone:t.exists?"info":"warning",variant:"soft"},{default:s(()=>[o(r(t.seedItemCount)+" seeded item"+r(t.seedItemCount===1?"":"s"),1)]),_:2},1032,["tone"])):(n(),l(a(m),{key:1,tone:"muted",size:"xs"},{default:s(()=>[...e[7]||(e[7]=[o("no seed",-1)])]),_:1}))]),"cell-features":s(({row:t})=>[u(a(v),{direction:"horizontal",gap:"0.25rem",wrap:""},{default:s(()=>[t.billingMode?(n(),l(a(c),{key:0,size:"sm",variant:"soft"},{default:s(()=>[o(r(t.billingMode),1)]),_:2},1024)):b("",!0),t.ttlOn?(n(),l(a(c),{key:1,size:"sm",variant:"solid"},{default:s(()=>[...e[8]||(e[8]=[o("TTL",-1)])]),_:1})):b("",!0),t.streamOn?(n(),l(a(c),{key:2,size:"sm",variant:"solid"},{default:s(()=>[...e[9]||(e[9]=[o("Streams",-1)])]),_:1})):b("",!0),t.hasGsi?(n(),l(a(c),{key:3,size:"sm",variant:"soft"},{default:s(()=>[...e[10]||(e[10]=[o("GSI",-1)])]),_:1})):b("",!0),t.hasLsi?(n(),l(a(c),{key:4,size:"sm",variant:"soft"},{default:s(()=>[...e[11]||(e[11]=[o("LSI",-1)])]),_:1})):b("",!0)]),_:2},1024)]),"cell-actions":s(({row:t})=>[t.exists?(n(),l(a(Q),{key:0,size:"sm",variant:"soft",onClick:f=>B(t)},{default:s(()=>[...e[12]||(e[12]=[o(" Explore ",-1)])]),_:1},8,["onClick"])):(n(),l(a(m),{key:1,tone:"muted",size:"xs"},{default:s(()=>[...e[13]||(e[13]=[o(" Register service to provision ",-1)])]),_:1}))]),_:1},8,["rows","row-state"])):(n(),l(a(V),{key:2,title:"No matching tables",description:`No tables match "${$.value}".`},null,8,["description"])):(n(),l(a(V),{key:1,title:"No DynamoDB tables",description:"Register a microservice with DynamoDB resources or drop a seed file into the seeds directory."}))]),_:1})]),_:1}))}}),ae=A({__name:"DynamoPage",setup(K){const N=Z();function _(d){N.push(`/dynamo/${encodeURIComponent(d)}`)}return(d,k)=>(n(),l(ee,{onOpen:_}))}});export{ae as default};
@@ -1,3 +0,0 @@
1
- import{k as X,a3 as fe,m as o,e as b,$ as e,J as tt,a4 as t,j as a,t as d,O as ie,i as r,_ as y,f as z,u as $,v as F,T as at,C as D,g as J,F as M,n as c,b as q,a as R,c as be,w as L,d as Q,X as lt,M as j,U as ne,B as xe,N as O,Y as nt,I as Ve,a7 as Se,s as ce,q as G,x as Ce,G as ze,H as it,h as ut,L as ke,D as $e,E as de,Z as rt,A as Ne,y as st,z as Ae,l as ot,V as dt,Q as me,P as mt,S as ve,a0 as vt,a1 as Te}from"./index-DGsXIPJ-.js";const ft=X({__name:"DynamoItemEditor",props:{open:{type:Boolean},tableName:{},mode:{},item:{},originalKey:{}},emits:["update:open","saved","request-edit","request-clone","request-delete"],setup(C,{emit:N}){const s=C,T=N,S=be(),V=c(""),f=c(null),w=c(!1),_=q({get:()=>s.open,set:i=>T("update:open",i)}),h=q(()=>s.mode==="create"?`Create item · ${s.tableName}`:s.mode==="view"?`View item · ${s.tableName}`:`Edit item · ${s.tableName}`),E=q(()=>s.mode==="view");fe(()=>[s.open,s.item,s.mode],([i])=>{i&&(V.value=s.item&&Object.keys(s.item).length?JSON.stringify(s.item,null,2):`{
2
-
3
- }`,f.value=null)},{immediate:!0});function A(){try{const i=JSON.parse(V.value);return i===null||typeof i!="object"||Array.isArray(i)?(f.value="Item must be a JSON object",null):(f.value=null,i)}catch(i){return f.value=i.message,null}}async function k(){const i=A();if(i){w.value=!0;try{s.mode==="edit"&&s.originalKey&&Object.entries(s.originalKey).some(([p,x])=>JSON.stringify(i[p])!==JSON.stringify(x))&&await R.deleteDynamoItem(s.tableName,s.originalKey),await R.putDynamoItem(s.tableName,i),S.add({title:s.mode==="create"?"Item created":"Item saved",variant:"success"}),T("saved"),_.value=!1}catch(m){S.add({title:"Save failed",description:m.message,variant:"danger"})}finally{w.value=!1}}}function g(){const i=A();i&&(V.value=JSON.stringify(i,null,2))}return(i,m)=>(o(),b(e(tt),{open:_.value,"onUpdate:open":m[5]||(m[5]=p=>_.value=p),title:h.value,size:"lg"},{footer:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",justify:"space-between"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem"},{default:t(()=>[E.value?z("",!0):(o(),b(e(D),{key:0,size:"sm",variant:"ghost",onClick:g},{default:t(()=>[...m[8]||(m[8]=[r(" Format JSON ",-1)])]),_:1})),E.value?(o(),J(M,{key:1},[a(e(D),{size:"sm",variant:"soft",onClick:m[1]||(m[1]=p=>T("request-edit"))},{default:t(()=>[...m[9]||(m[9]=[r("Edit",-1)])]),_:1}),a(e(D),{size:"sm",variant:"ghost",onClick:m[2]||(m[2]=p=>T("request-clone"))},{default:t(()=>[...m[10]||(m[10]=[r("Clone",-1)])]),_:1}),a(e(D),{size:"sm",variant:"ghost",tone:"danger",onClick:m[3]||(m[3]=p=>T("request-delete"))},{default:t(()=>[...m[11]||(m[11]=[r("Delete",-1)])]),_:1})],64)):z("",!0)]),_:1}),a(e(d),{direction:"horizontal",gap:"0.5rem"},{default:t(()=>[a(e(D),{size:"sm",variant:"ghost",onClick:m[4]||(m[4]=p=>_.value=!1)},{default:t(()=>[r(y(E.value?"Close":"Cancel"),1)]),_:1}),E.value?z("",!0):(o(),b(e(D),{key:0,size:"sm",variant:"solid",loading:w.value,disabled:!!f.value,onClick:k},{default:t(()=>[r(y(C.mode==="create"?"Create":"Save"),1)]),_:1},8,["loading","disabled"]))]),_:1})]),_:1})]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[f.value?(o(),b(e(ie),{key:0,variant:"danger"},{default:t(()=>[r(y(f.value),1)]),_:1})):z("",!0),a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e($),{tone:"muted",size:"xs"},{default:t(()=>[...m[6]||(m[6]=[r(" JSON object. Types are inferred — numbers, booleans, strings, arrays, nested objects are all supported. ",-1)])]),_:1}),E.value?(o(),b(e(F),{key:0,tone:"neutral",variant:"soft"},{default:t(()=>[...m[7]||(m[7]=[r("read-only",-1)])]),_:1})):z("",!0)]),_:1}),a(e(at),{modelValue:V.value,"onUpdate:modelValue":m[0]||(m[0]=p=>V.value=p),rows:18,readonly:E.value,spellcheck:"false",class:"mono",onBlur:A},null,8,["modelValue","readonly"])]),_:1})]),_:1},8,["open","title"]))}}),bt={style:{width:"100%"}},pt=X({__name:"DynamoItemsExplorer",props:{table:{}},setup(C){const N=C,s=be(),T=c("scan"),S=c(""),V=c(50),f=c(""),w=c("="),_=c(""),h=c(""),E=c(!1),A=c([]),k=c(!1),g=c([]),i=c(void 0),m=c(void 0),p=c(null),x=c(!1),B=c(null),Y=c(!1),Z=c(!1),ee=c("view"),K=c(null),te=c(null),ue=c(!1),re=c(null),he=[{value:"scan",label:"Scan"},{value:"query",label:"Query"}],Ie=[{value:"=",label:"Equal to"},{value:"<=",label:"Less than or equal to"},{value:"<",label:"Less than"},{value:">=",label:"Greater than or equal to"},{value:">",label:"Greater than"},{value:"between",label:"Between"},{value:"begins_with",label:"Begins with"}],De=[{value:"=",label:"Equal to"},{value:"<>",label:"Not equal to"},{value:"<",label:"Less than"},{value:"<=",label:"Less than or equal to"},{value:">",label:"Greater than"},{value:">=",label:"Greater than or equal to"},{value:"begins_with",label:"Begins with"},{value:"contains",label:"Contains"},{value:"attribute_exists",label:"Exists"},{value:"attribute_not_exists",label:"Does not exist"}],Ee=[{value:"String",label:"String"},{value:"Number",label:"Number"},{value:"Boolean",label:"Boolean"},{value:"Null",label:"Null"}],qe=q(()=>{const u=[{value:"",label:`Table - ${N.table.name}`}];for(const l of N.table.gsis||[])l.IndexName&&u.push({value:l.IndexName,label:`Index - ${l.IndexName}`});for(const l of N.table.lsis||[])l.IndexName&&u.push({value:l.IndexName,label:`Index - ${l.IndexName}`});return u}),pe=q(()=>{if(!S.value)return N.table.keySchema;const u=N.table.gsis.find(l=>l.IndexName===S.value)||N.table.lsis.find(l=>l.IndexName===S.value);return(u==null?void 0:u.KeySchema)||N.table.keySchema}),ae=q(()=>{var u,l;return((l=(u=pe.value)==null?void 0:u.find(n=>n.KeyType==="HASH"))==null?void 0:l.AttributeName)||""}),P=q(()=>{var u,l;return((l=(u=pe.value)==null?void 0:u.find(n=>n.KeyType==="RANGE"))==null?void 0:l.AttributeName)||""}),se=q(()=>(pe.value||[]).map(u=>u.AttributeName).filter(u=>!!u)),ge=q(()=>{const u=new Set;for(const l of g.value)Object.keys(l).forEach(n=>{se.value.includes(n)||u.add(n)});return Array.from(u).sort()});function je(u){const l=N.table.attributeDefinitions.find(n=>n.AttributeName===u);return l!=null&&l.AttributeType?l.AttributeType==="S"?"String":l.AttributeType==="N"?"Number":l.AttributeType==="B"?"Binary":l.AttributeType:null}function we(u,l,n){const v=je(u);return l?v?`${u} (${v}, PK)`:`${u} (PK)`:n?v?`${u} (${v}, SK)`:`${u} (SK)`:v?`${u} (${v})`:u}const Re=q(()=>{const u=se.value.map((n,v)=>({key:`__attr__${n}`,label:we(n,v===0,v===1)})),l=ge.value.map(n=>({key:`__attr__${n}`,label:we(n)}));return[...u,...l]}),Be=q(()=>g.value.map((u,l)=>{const n={__id:l,__raw:u};for(const v of se.value)n[`__attr__${v}`]=u[v];for(const v of ge.value)n[`__attr__${v}`]=u[v];return n}));function ye(u){return u===void 0?"—":u===null?"null":typeof u=="boolean"?u?"true":"false":typeof u=="object"?JSON.stringify(u).slice(0,80):String(u).slice(0,80)}function Ue(u,l){switch(l){case"Number":{const n=Number(u);if(Number.isNaN(n))throw new Error(`"${u}" is not a number`);return n}case"Boolean":return u==="true"||u==="1";case"Null":return null;case"String":default:return u}}function le(u,l){const n=N.table.attributeDefinitions.find(v=>v.AttributeName===l);if((n==null?void 0:n.AttributeType)==="N"){const v=Number(u);if(Number.isNaN(v))throw new Error(`"${u}" is not a number for ${l}`);return v}return u}function Ke(){const u={},l={};if(!ae.value)throw new Error("No partition key on the selected table or index");if(!f.value)throw new Error(`Partition key value (${ae.value}) is required`);u["#pk"]=ae.value,l[":pkv"]=le(f.value,ae.value);let n="#pk = :pkv";if(P.value&&_.value)if(u["#sk"]=P.value,w.value==="between"){if(!h.value)throw new Error("BETWEEN requires two values");l[":skv1"]=le(_.value,P.value),l[":skv2"]=le(h.value,P.value),n+=" AND #sk BETWEEN :skv1 AND :skv2"}else w.value==="begins_with"?(l[":skv"]=le(_.value,P.value),n+=" AND begins_with(#sk, :skv)"):(l[":skv"]=le(_.value,P.value),n+=` AND #sk ${w.value} :skv`);return{keyExpr:n,names:u,values:l}}function Oe(){const u={},l={},n=[];return A.value.forEach((v,I)=>{if(!v.attr)return;const U=`#fn${I}`,oe=`:fv${I}`;if(u[U]=v.attr,v.op==="attribute_exists"){n.push(`attribute_exists(${U})`);return}if(v.op==="attribute_not_exists"){n.push(`attribute_not_exists(${U})`);return}l[oe]=Ue(v.value,v.type),v.op==="begins_with"?n.push(`begins_with(${U}, ${oe})`):v.op==="contains"?n.push(`contains(${U}, ${oe})`):n.push(`${U} ${v.op} ${oe}`)}),{expr:n.join(" AND "),names:u,values:l}}function Le(u){const l=Oe(),n={indexName:S.value||void 0,limit:V.value>0?V.value:void 0,exclusiveStartKey:u};let v=l.names,I=l.values;if(l.expr&&(n.filterExpression=l.expr),T.value==="query"){const U=Ke();n.keyConditionExpression=U.keyExpr,v={...v,...U.names},I={...I,...U.values},E.value&&(n.scanIndexForward=!1)}return Object.keys(v).length&&(n.expressionAttributeNames=v),Object.keys(I).length&&(n.expressionAttributeValues=I),n}async function W(u){x.value=!0,B.value=null;try{const l=Le(u),n=T.value==="scan"?await R.scanDynamoTable(N.table.name,l):await R.queryDynamoTable(N.table.name,l);u?g.value=[...g.value,...n.items]:(g.value=n.items,p.value=new Date),i.value=n.lastEvaluatedKey,m.value=n.scannedCount,Y.value=!0}catch(l){B.value=l.message||"Request failed"}finally{x.value=!1}}function Pe(){f.value="",w.value="=",_.value="",h.value="",E.value=!1,A.value=[],g.value=[],i.value=void 0,m.value=void 0,Y.value=!1,B.value=null}function Fe(){i.value&&W(i.value)}function Je(){A.value.push({attr:"",op:"=",type:"String",value:""}),k.value=!0}function Me(u){A.value.splice(u,1)}function _e(u){const l={};for(const n of N.table.keySchema)n.AttributeName&&(l[n.AttributeName]=u[n.AttributeName]);return l}function Ge(){const u={};for(const l of N.table.keySchema){if(!l.AttributeName)continue;const n=N.table.attributeDefinitions.find(v=>v.AttributeName===l.AttributeName);u[l.AttributeName]=(n==null?void 0:n.AttributeType)==="N"?0:""}return u}function Qe(){ee.value="create",K.value=Ge(),te.value=null,Z.value=!0}function We(u){ee.value="view",K.value=u,te.value=null,Z.value=!0}function He(){K.value&&(te.value=_e(K.value),ee.value="edit")}function Xe(){if(!K.value)return;const u={...K.value};for(const l of N.table.keySchema){if(!l.AttributeName)continue;const n=N.table.attributeDefinitions.find(v=>v.AttributeName===l.AttributeName);u[l.AttributeName]=(n==null?void 0:n.AttributeType)==="N"?0:""}K.value=u,te.value=null,ee.value="create"}function Ye(){K.value&&(re.value=_e(K.value),ue.value=!0)}async function Ze(){if(re.value)try{await R.deleteDynamoItem(N.table.name,re.value),s.add({title:"Item deleted",variant:"info"}),Z.value=!1,await W()}catch(u){s.add({title:"Delete failed",description:u.message,variant:"danger"})}finally{ue.value=!1,re.value=null}}function et(){W()}const H=q(()=>{const u=g.value.length,l=m.value??u,n=l>0?Math.round(u/l*100):100;return{returned:u,scanned:l,efficiency:n,finished:!i.value}});return W(),fe(()=>[T.value,S.value],()=>{g.value=[],i.value=void 0,m.value=void 0,Y.value=!1}),(u,l)=>(o(),b(e(d),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e(L),{variant:"outline"},{header:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...l[15]||(l[15]=[r("Scan or query items",-1)])]),_:1})]),footer:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e(D),{variant:"solid",loading:x.value,onClick:l[8]||(l[8]=n=>W())},{default:t(()=>[...l[21]||(l[21]=[r("Run",-1)])]),_:1},8,["loading"]),a(e(D),{variant:"ghost",onClick:Pe},{default:t(()=>[...l[22]||(l[22]=[r("Reset",-1)])]),_:1})]),_:1}),a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e($),{tone:"muted"},{default:t(()=>[...l[23]||(l[23]=[r("Limit",-1)])]),_:1}),a(e(O),{modelValue:V.value,"onUpdate:modelValue":l[9]||(l[9]=n=>V.value=n),modelModifiers:{number:!0},type:"number",size:"sm",style:{width:"6rem"}},null,8,["modelValue"])]),_:1})]),_:1})]),default:t(()=>[a(e(d),{direction:"vertical",gap:"1rem"},{default:t(()=>[Q("div",bt,[a(e(lt),{modelValue:T.value,"onUpdate:modelValue":l[0]||(l[0]=n=>T.value=n),options:he,size:"md"},null,8,["modelValue"])]),a(e(d),{direction:"horizontal",gap:"1rem"},{default:t(()=>[a(e(j),{label:"Select a table or index",style:{flex:"1"}},{default:t(()=>[a(e(ne),{modelValue:S.value,"onUpdate:modelValue":l[1]||(l[1]=n=>S.value=n),options:qe.value},null,8,["modelValue","options"])]),_:1}),a(e(j),{label:"Select attribute projection",style:{flex:"1"}},{default:t(()=>[a(e(ne),{"model-value":"All attributes",options:[{value:"All attributes",label:"All attributes"}],disabled:""})]),_:1})]),_:1}),T.value==="query"?(o(),J(M,{key:0},[a(e(xe)),a(e(d),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e($),{weight:"semibold",style:{"font-size":"0.9rem"}},{default:t(()=>[...l[16]||(l[16]=[r("Partition key",-1)])]),_:1}),a(e(d),{direction:"horizontal",gap:"1rem"},{default:t(()=>[a(e(j),{label:"Attribute",style:{flex:"1"}},{default:t(()=>[a(e(O),{"model-value":ae.value||"—",disabled:""},null,8,["model-value"])]),_:1}),a(e(j),{label:"Value",style:{flex:"2"}},{default:t(()=>[a(e(O),{modelValue:f.value,"onUpdate:modelValue":l[2]||(l[2]=n=>f.value=n),placeholder:"Enter attribute value"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1}),P.value?(o(),b(e(d),{key:0,direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e($),{weight:"semibold",style:{"font-size":"0.9rem"}},{default:t(()=>[...l[17]||(l[17]=[r("Sort key – optional",-1)])]),_:1}),a(e(d),{direction:"horizontal",gap:"0.75rem",align:"end"},{default:t(()=>[a(e(j),{label:"Attribute",style:{flex:"1.4"}},{default:t(()=>[a(e(O),{"model-value":P.value,disabled:""},null,8,["model-value"])]),_:1}),a(e(j),{label:"Value",style:{flex:"1.2","min-width":"11rem"}},{default:t(()=>[a(e(ne),{modelValue:w.value,"onUpdate:modelValue":l[3]||(l[3]=n=>w.value=n),options:Ie},null,8,["modelValue"])]),_:1}),a(e(O),{modelValue:_.value,"onUpdate:modelValue":l[4]||(l[4]=n=>_.value=n),placeholder:"Enter attribute value",style:{flex:"2"}},null,8,["modelValue"]),w.value==="between"?(o(),b(e(O),{key:0,modelValue:h.value,"onUpdate:modelValue":l[5]||(l[5]=n=>h.value=n),placeholder:"and value",style:{flex:"2"}},null,8,["modelValue"])):z("",!0),a(e(nt),{modelValue:E.value,"onUpdate:modelValue":l[6]||(l[6]=n=>E.value=n),label:"Sort descending"},null,8,["modelValue"])]),_:1})]),_:1})):z("",!0)],64)):z("",!0),a(e(xe)),a(e(d),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(Ve),{href:"#",style:{"font-weight":"600","font-size":"0.9rem"},onClick:l[7]||(l[7]=Se(n=>k.value=!k.value,["prevent"]))},{default:t(()=>[a(e(ce),{name:k.value?"chevron-down":"chevron-right"},null,8,["name"]),l[18]||(l[18]=r(" Filters – optional ",-1))]),_:1}),k.value?(o(),b(e(d),{key:0,direction:"vertical",gap:"0.5rem"},{default:t(()=>[(o(!0),J(M,null,G(A.value,(n,v)=>(o(),b(e(d),{key:`f-${v}`,direction:"horizontal",gap:"0.5rem",align:"end"},{default:t(()=>[a(e(j),{label:"Attribute name",style:{flex:"1.4"}},{default:t(()=>[a(e(O),{modelValue:n.attr,"onUpdate:modelValue":I=>n.attr=I,placeholder:"Enter attribute name"},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),a(e(j),{label:"Condition",style:{flex:"1.4"}},{default:t(()=>[a(e(ne),{modelValue:n.op,"onUpdate:modelValue":I=>n.op=I,options:De},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),a(e(j),{label:"Type",style:{flex:"0.9"}},{default:t(()=>[a(e(ne),{modelValue:n.type,"onUpdate:modelValue":I=>n.type=I,options:Ee},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),a(e(j),{label:"Value",style:{flex:"1.7"}},{default:t(()=>[a(e(O),{modelValue:n.value,"onUpdate:modelValue":I=>n.value=I,disabled:n.op==="attribute_exists"||n.op==="attribute_not_exists",placeholder:"Enter attribute value"},null,8,["modelValue","onUpdate:modelValue","disabled"])]),_:2},1024),a(e(D),{size:"sm",variant:"outline",onClick:I=>Me(v)},{default:t(()=>[...l[19]||(l[19]=[r("Remove",-1)])]),_:1},8,["onClick"])]),_:2},1024))),128)),Q("div",null,[a(e(D),{size:"sm",variant:"outline",onClick:Je},{default:t(()=>[...l[20]||(l[20]=[r("Add filter",-1)])]),_:1})])]),_:1})):z("",!0)]),_:1})]),_:1})]),_:1}),B.value?(o(),b(e(ie),{key:0,variant:"danger",dismissible:"",onDismiss:l[10]||(l[10]=n=>B.value=null)},{default:t(()=>[r(y(B.value),1)]),_:1})):z("",!0),Y.value&&!B.value?(o(),b(e(ie),{key:1,variant:H.value.finished?"success":"warning",dismissible:"",onDismiss:l[11]||(l[11]=n=>Y.value=!1)},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[Q("span",null,[a(e($),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(H.value.finished?"Completed":"Stopped"),1)]),_:1}),l[24]||(l[24]=r(" · Items returned: ",-1)),a(e($),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(H.value.returned),1)]),_:1}),l[25]||(l[25]=r(" · Items scanned: ",-1)),a(e($),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(H.value.scanned),1)]),_:1}),l[26]||(l[26]=r(" · Efficiency: ",-1)),a(e($),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(H.value.efficiency)+"%",1)]),_:1})]),H.value.finished?z("",!0):(o(),b(e(D),{key:0,size:"sm",variant:"outline",loading:x.value,onClick:Fe},{default:t(()=>[...l[27]||(l[27]=[r(" Retrieve next page ",-1)])]),_:1},8,["loading"]))]),_:1})]),_:1},8,["variant"])):z("",!0),a(e(L),{variant:"outline"},{header:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(d),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[r(y(S.value?`Index: ${S.value} (${N.table.name})`:`Table: ${N.table.name}`)+" – Items returned ("+y(g.value.length)+") ",1)]),_:1}),a(e($),{tone:"muted",size:"xs"},{default:t(()=>[r(y(T.value==="scan"?"Scan":"Query")+" started on "+y(p.value?p.value.toLocaleString():"—"),1)]),_:1})]),_:1}),a(e(d),{direction:"horizontal",gap:"0.5rem"},{default:t(()=>[a(e(D),{size:"sm",variant:"ghost",loading:x.value,onClick:l[12]||(l[12]=n=>W())},{default:t(()=>[...l[28]||(l[28]=[r("Refresh",-1)])]),_:1},8,["loading"]),a(e(D),{size:"sm",variant:"outline",onClick:Qe},{default:t(()=>[...l[29]||(l[29]=[r("Create item",-1)])]),_:1})]),_:1})]),_:1})]),default:t(()=>[x.value&&!g.value.length?(o(),b(e(d),{key:0,direction:"horizontal",justify:"center",align:"center"},{default:t(()=>[a(e(Ce),{label:"Running..."})]),_:1})):g.value.length?(o(),b(e(it),{key:2,columns:Re.value,rows:Be.value,"aria-label":"Scan and query results"},ut({_:2},[G(se.value,(n,v)=>({name:`cell-__attr__${n}`,fn:t(({row:I})=>[v===0?(o(),b(e(Ve),{key:0,href:"#",class:"mono",onClick:Se(U=>We(I.__raw),["prevent"])},{default:t(()=>[r(y(ye(I[`__attr__${n}`])),1)]),_:2},1032,["onClick"])):(o(),b(e($),{key:1,family:"mono"},{default:t(()=>[r(y(ye(I[`__attr__${n}`])),1)]),_:2},1024))])})),G(ge.value,n=>({name:`cell-__attr__${n}`,fn:t(({row:v})=>[a(e($),{family:"mono",size:"sm"},{default:t(()=>[r(y(ye(v[`__attr__${n}`])),1)]),_:2},1024)])}))]),1032,["columns","rows"])):(o(),b(e(ze),{key:1,title:"No items",description:"Run the operation to load items."}))]),_:1}),a(ft,{open:Z.value,"onUpdate:open":l[13]||(l[13]=n=>Z.value=n),"table-name":N.table.name,mode:ee.value,item:K.value,"original-key":te.value,onSaved:et,onRequestEdit:He,onRequestClone:Xe,onRequestDelete:Ye},null,8,["open","table-name","mode","item","original-key"]),a(e(ke),{open:ue.value,"onUpdate:open":l[14]||(l[14]=n=>ue.value=n),title:"Delete item",description:`Delete this item from ${N.table.name}? This cannot be undone.`,"confirm-label":"Delete","cancel-label":"Cancel",tone:"danger",onConfirm:Ze},null,8,["open","description"])]),_:1}))}}),gt=X({__name:"DynamoTableSettings",props:{table:{}},emits:["refresh"],setup(C,{emit:N}){const s=C,T=N,S=be(),V=c(s.table.ttl.enabled),f=c(s.table.ttl.attributeName||""),w=c(!1),_=c(null);fe(()=>[s.table.ttl.enabled,s.table.ttl.attributeName],([A,k])=>{V.value=A,f.value=k||""});async function h(){if(V.value&&!f.value.trim()){_.value="Attribute name is required to enable TTL";return}w.value=!0,_.value=null;try{await R.setDynamoTtl(s.table.name,V.value,f.value.trim()||void 0),S.add({title:V.value?"TTL enabled":"TTL disabled",description:V.value?`Attribute: ${f.value}`:void 0,variant:"success"}),T("refresh")}catch(A){_.value=A.message||"Failed to update TTL"}finally{w.value=!1}}function E(A){return A<1024?`${A} B`:A<1024*1024?`${(A/1024).toFixed(1)} KB`:`${(A/(1024*1024)).toFixed(1)} MB`}return(A,k)=>(o(),b(e(d),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e($e),{columns:4,gap:"0.75rem"},{default:t(()=>[a(e(de),{label:"Items",value:s.table.itemCount,tone:"info"},null,8,["value"]),a(e(de),{label:"Size",value:E(s.table.sizeBytes),tone:"neutral"},null,8,["value"]),a(e(de),{label:"Status",value:s.table.status||"UNKNOWN",tone:s.table.status==="ACTIVE"?"success":"warning"},null,8,["value","tone"]),a(e(de),{label:"Billing",value:s.table.billingMode||"—",tone:"neutral"},null,8,["value"])]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...k[3]||(k[3]=[r("Time to Live (TTL)",-1)])]),_:1})]),default:t(()=>[_.value?(o(),b(e(ie),{key:0,variant:"danger",dismissible:"",onDismiss:k[0]||(k[0]=g=>_.value=null)},{default:t(()=>[r(y(_.value),1)]),_:1})):z("",!0),a(e(d),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[a(e($),{tone:"muted",size:"sm"},{default:t(()=>[...k[4]||(k[4]=[r(" When TTL is enabled, items are automatically deleted by DynamoDB after the timestamp in the configured attribute (epoch seconds). Items are eventually consistent and may take time to be removed. ",-1)])]),_:1}),a(e(j),{label:"Enable TTL"},{default:t(()=>[a(e(rt),{modelValue:V.value,"onUpdate:modelValue":k[1]||(k[1]=g=>V.value=g)},null,8,["modelValue"])]),_:1}),a(e(j),{label:"Attribute name",hint:V.value?"Required when enabling TTL":"Disabled — value retained for reference"},{default:t(()=>[a(e(O),{modelValue:f.value,"onUpdate:modelValue":k[2]||(k[2]=g=>f.value=g),placeholder:"e.g. expiresAt",disabled:!V.value},null,8,["modelValue","disabled"])]),_:1},8,["hint"]),a(e(d),{direction:"horizontal",justify:"flex-end"},{default:t(()=>[a(e(D),{size:"sm",variant:"solid",loading:w.value,onClick:h},{default:t(()=>[...k[5]||(k[5]=[r(" Apply ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...k[6]||(k[6]=[r("Streams",-1)])]),_:1})]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e(F),{tone:s.table.streamEnabled?"success":"neutral",variant:"soft"},{default:t(()=>[r(y(s.table.streamEnabled?"Enabled":"Disabled"),1)]),_:1},8,["tone"]),s.table.streamViewType?(o(),b(e(Ne),{key:0,size:"sm",variant:"soft"},{default:t(()=>[r(y(s.table.streamViewType),1)]),_:1})):z("",!0)]),_:1}),s.table.streamArn?(o(),b(e($),{key:0,tone:"muted",family:"mono",style:{"font-size":"0.7rem"}},{default:t(()=>[r(y(s.table.streamArn),1)]),_:1})):(o(),b(e($),{key:1,tone:"muted",size:"xs"},{default:t(()=>[...k[7]||(k[7]=[r(" Streams configuration is set at table creation time and cannot be changed from here. ",-1)])]),_:1}))]),_:1})]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...k[8]||(k[8]=[r("Identifier",-1)])]),_:1})]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.25rem"},{default:t(()=>[a(e($),{tone:"muted",family:"mono",size:"xs"},{default:t(()=>[r(" ARN: "+y(s.table.arn||"—"),1)]),_:1}),a(e($),{tone:"muted",size:"xs"},{default:t(()=>[r(" Created: "+y(s.table.createdAt?new Date(s.table.createdAt).toLocaleString():"—"),1)]),_:1})]),_:1})]),_:1})]),_:1}))}}),yt=X({__name:"DynamoSeedPanel",props:{tableName:{},seedFile:{},seedItemCount:{},tableItemCount:{}},emits:["refresh"],setup(C,{emit:N}){const s=C,T=N,S=be(),V=c(!1),f=c(!1),w=c(!1),_=c(!1),h=c(!1);async function E(){if(!V.value){V.value=!0;try{const g=await R.runSeed(s.tableName),i=g.results.reduce((p,x)=>p+(x.inserted||0),0),m=g.results.find(p=>p.skipped);m?S.add({title:"Seed skipped",description:`${s.tableName}: ${m.reason||"unknown reason"}`,variant:"warning"}):S.add({title:"Seed applied",description:`${i} item(s) inserted into ${s.tableName}`,variant:"success"}),T("refresh")}catch(g){S.add({title:"Seed failed",description:g.message,variant:"danger"})}finally{V.value=!1}}}async function A(){if(!w.value){w.value=!0;try{const i=(await R.clearSeed(s.tableName)).results.reduce((m,p)=>m+(p.deleted||0),0);S.add({title:"Table purged",description:`${i} item(s) removed from ${s.tableName}`,variant:"info"}),T("refresh")}catch(g){S.add({title:"Purge failed",description:g.message,variant:"danger"})}finally{w.value=!1,_.value=!1}}}async function k(){if(!f.value){f.value=!0;try{const i=(await R.clearSeed(s.tableName)).results.reduce((x,B)=>x+(B.deleted||0),0),p=(await R.runSeed(s.tableName)).results.reduce((x,B)=>x+(B.inserted||0),0);S.add({title:"Seed redone",description:`${i} removed, ${p} inserted in ${s.tableName}`,variant:"success"}),T("refresh")}catch(g){S.add({title:"Redo failed",description:g.message,variant:"danger"})}finally{f.value=!1,h.value=!1}}}return(g,i)=>(o(),b(e(d),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e(L),{variant:"outline"},{header:t(()=>[a(e(d),{direction:"horizontal",justify:"space-between",align:"center"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...i[4]||(i[4]=[r("Seed file",-1)])]),_:1}),a(e(F),{tone:"info",variant:"soft"},{default:t(()=>[r(y(C.seedItemCount)+" item"+y(C.seedItemCount===1?"":"s"),1)]),_:1})]),_:1})]),default:t(()=>[a(e(st),null,{default:t(()=>[a(e(Ae),{label:"Path"},{default:t(()=>[a(e($),{family:"mono",size:"sm"},{default:t(()=>[r(y(C.seedFile),1)]),_:1})]),_:1}),a(e(Ae),{label:"Current rows in table"},{default:t(()=>[a(e($),{family:"mono"},{default:t(()=>[r(y(C.tableItemCount),1)]),_:1})]),_:1})]),_:1})]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...i[5]||(i[5]=[r("Actions",-1)])]),_:1})]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[a(e(d),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(d),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...i[6]||(i[6]=[r("Apply seed",-1)])]),_:1}),a(e($),{tone:"muted",size:"sm"},{default:t(()=>[...i[7]||(i[7]=[r(" Inserts every item from the seed file. Existing items with the same key are overwritten. ",-1)])]),_:1})]),_:1}),a(e(D),{variant:"solid",loading:V.value,disabled:C.seedItemCount<=0,onClick:E},{default:t(()=>[...i[8]||(i[8]=[r(" Apply ",-1)])]),_:1},8,["loading","disabled"])]),_:1}),a(e(d),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(d),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...i[9]||(i[9]=[r("Redo seed",-1)])]),_:1}),a(e($),{tone:"muted",size:"sm"},{default:t(()=>[...i[10]||(i[10]=[r(" Purges the table first, then re-applies the seed file. Use when stale rows are blocking a fresh load. ",-1)])]),_:1})]),_:1}),a(e(D),{variant:"soft",loading:f.value,disabled:C.seedItemCount<=0,onClick:i[0]||(i[0]=m=>h.value=!0)},{default:t(()=>[...i[11]||(i[11]=[r(" Redo ",-1)])]),_:1},8,["loading","disabled"])]),_:1}),a(e(d),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(d),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[...i[12]||(i[12]=[r("Purge table",-1)])]),_:1}),a(e($),{tone:"muted",size:"sm"},{default:t(()=>[...i[13]||(i[13]=[r(" Deletes every item currently in this table. The seed file is not touched. ",-1)])]),_:1})]),_:1}),a(e(D),{variant:"danger",loading:w.value,onClick:i[1]||(i[1]=m=>_.value=!0)},{default:t(()=>[...i[14]||(i[14]=[r(" Purge ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),a(e(ke),{open:_.value,"onUpdate:open":i[2]||(i[2]=m=>_.value=m),title:`Purge ${C.tableName}?`,description:`This deletes all ${C.tableItemCount} item(s) currently in the table. The seed file on disk is not affected.`,"confirm-label":"Purge","cancel-label":"Cancel","confirm-variant":"danger",onConfirm:A},null,8,["open","title","description"]),a(e(ke),{open:h.value,"onUpdate:open":i[3]||(i[3]=m=>h.value=m),title:`Redo seed for ${C.tableName}?`,description:`This purges all ${C.tableItemCount} current item(s), then re-applies ${C.seedItemCount} seeded item(s).`,"confirm-label":"Redo","cancel-label":"Cancel","confirm-variant":"danger",onConfirm:k},null,8,["open","title","description"])]),_:1}))}}),ct={style:{"padding-top":"1rem"}},kt={style:{"padding-top":"1rem"}},$t={style:{"padding-top":"1rem"}},Nt={style:{"padding-top":"1rem"}},wt=X({__name:"DynamoTableDetail",props:{tableName:{}},emits:["back"],setup(C,{emit:N}){const s=C,T=N,S=vt(),V=Te(),f=c(null),w=c(null),_=c(!0),h=c(null),E=["items","indexes","settings","seed"],A=q({get(){const g=String(S.query.tab||"");return E.includes(g)?g:"items"},set(g){V.replace({query:{...S.query,tab:g==="items"?void 0:g}})}});async function k(){_.value=!0;try{const[g,i]=await Promise.all([R.describeDynamoTable(s.tableName),R.listSeeds().catch(()=>({seedsDir:"",entries:[]}))]);f.value=g,w.value=i.entries.find(m=>m.tableName===s.tableName)||null,h.value=null}catch(g){h.value=g.message||"Failed to load table",f.value=null}finally{_.value=!1}}return ot(k),fe(()=>s.tableName,k),(g,i)=>(o(),b(e(d),{direction:"vertical",gap:"1rem"},{default:t(()=>{var m;return[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>{var p;return[a(e(D),{size:"sm",variant:"ghost",onClick:i[0]||(i[0]=x=>T("back"))},{default:t(()=>[a(e(ce),{name:"arrow-left"}),i[3]||(i[3]=r(" Tables",-1))]),_:1}),a(e($),{size:"lg",weight:"semibold"},{default:t(()=>[r(y(C.tableName),1)]),_:1}),(p=f.value)!=null&&p.status?(o(),b(e(F),{key:0,tone:f.value.status==="ACTIVE"?"success":"warning",variant:"soft"},{default:t(()=>[r(y(f.value.status),1)]),_:1},8,["tone"])):z("",!0),w.value?(o(),b(e(F),{key:1,tone:"info",variant:"soft"},{default:t(()=>[r(" Seed: "+y(w.value.itemCount)+" item"+y(w.value.itemCount===1?"":"s"),1)]),_:1})):z("",!0)]}),_:1}),a(e(D),{size:"sm",variant:"ghost",loading:_.value,onClick:k},{default:t(()=>[...i[4]||(i[4]=[r("Refresh",-1)])]),_:1},8,["loading"])]),_:1}),(m=f.value)!=null&&m.warnings.length?(o(),b(e(d),{key:0,direction:"horizontal",gap:"0.375rem",wrap:""},{default:t(()=>[(o(!0),J(M,null,G(f.value.warnings,p=>(o(),b(e(F),{key:p,tone:"warning",variant:"soft"},{default:t(()=>[a(e(ce),{name:"triangle-alert"}),r(" "+y(p),1)]),_:2},1024))),128))]),_:1})):z("",!0),h.value?(o(),b(e(ie),{key:1,variant:"danger",dismissible:"",onDismiss:i[1]||(i[1]=p=>h.value=null)},{default:t(()=>[r(y(h.value),1)]),_:1})):z("",!0),_.value&&!f.value?(o(),b(e(d),{key:2,direction:"horizontal",justify:"center",align:"center"},{default:t(()=>[a(e(Ce),{label:"Loading table..."})]),_:1})):f.value?(o(),b(e(dt),{key:3,modelValue:A.value,"onUpdate:modelValue":i[2]||(i[2]=p=>A.value=p)},{default:t(()=>[a(e(mt),null,{default:t(()=>[a(e(me),{value:"items"},{default:t(()=>[...i[5]||(i[5]=[r("Items",-1)])]),_:1}),a(e(me),{value:"indexes"},{default:t(()=>[...i[6]||(i[6]=[r("Indexes",-1)])]),_:1}),a(e(me),{value:"settings"},{default:t(()=>[...i[7]||(i[7]=[r("Settings",-1)])]),_:1}),w.value?(o(),b(e(me),{key:0,value:"seed"},{default:t(()=>[...i[8]||(i[8]=[r("Seed",-1)])]),_:1})):z("",!0)]),_:1}),a(e(ve),{value:"items"},{default:t(()=>[Q("div",ct,[a(pt,{table:f.value},null,8,["table"])])]),_:1}),a(e(ve),{value:"indexes"},{default:t(()=>[Q("div",kt,[!f.value.gsis.length&&!f.value.lsis.length?(o(),b(e(ze),{key:0,title:"No secondary indexes",description:"This table has only the primary key."})):(o(),b(e(d),{key:1,direction:"vertical",gap:"1rem"},{default:t(()=>[f.value.gsis.length?(o(),b(e($e),{key:0,columns:2,gap:"0.75rem"},{default:t(()=>[(o(!0),J(M,null,G(f.value.gsis,p=>(o(),b(e(L),{key:p.IndexName,variant:"outline"},{header:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[r(y(p.IndexName),1)]),_:2},1024),a(e(F),{tone:"info",variant:"soft"},{default:t(()=>[...i[9]||(i[9]=[r("GSI",-1)])]),_:1})]),_:2},1024)]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",wrap:""},{default:t(()=>[(o(!0),J(M,null,G(p.KeySchema||[],x=>(o(),b(e(Ne),{key:x.AttributeName,size:"sm",variant:"soft"},{default:t(()=>[r(y(x.AttributeName)+" ("+y(x.KeyType)+") ",1)]),_:2},1024))),128))]),_:2},1024),a(e($),{tone:"muted",size:"xs"},{default:t(()=>{var x;return[r(" Projection: "+y(((x=p.Projection)==null?void 0:x.ProjectionType)||"—")+" · Items: "+y(p.ItemCount??"—")+" · Status: "+y(p.IndexStatus||"—"),1)]}),_:2},1024)]),_:2},1024)]),_:2},1024))),128))]),_:1})):z("",!0),f.value.lsis.length?(o(),b(e($e),{key:1,columns:2,gap:"0.75rem"},{default:t(()=>[(o(!0),J(M,null,G(f.value.lsis,p=>(o(),b(e(L),{key:p.IndexName,variant:"outline"},{header:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e($),{weight:"semibold"},{default:t(()=>[r(y(p.IndexName),1)]),_:2},1024),a(e(F),{tone:"neutral",variant:"soft"},{default:t(()=>[...i[10]||(i[10]=[r("LSI",-1)])]),_:1})]),_:2},1024)]),default:t(()=>[a(e(d),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(d),{direction:"horizontal",gap:"0.5rem",wrap:""},{default:t(()=>[(o(!0),J(M,null,G(p.KeySchema||[],x=>(o(),b(e(Ne),{key:x.AttributeName,size:"sm",variant:"soft"},{default:t(()=>[r(y(x.AttributeName)+" ("+y(x.KeyType)+") ",1)]),_:2},1024))),128))]),_:2},1024),a(e($),{tone:"muted",size:"xs"},{default:t(()=>{var x;return[r(" Projection: "+y(((x=p.Projection)==null?void 0:x.ProjectionType)||"—"),1)]}),_:2},1024)]),_:2},1024)]),_:2},1024))),128))]),_:1})):z("",!0)]),_:1}))])]),_:1}),a(e(ve),{value:"settings"},{default:t(()=>[Q("div",$t,[a(gt,{table:f.value,onRefresh:k},null,8,["table"])])]),_:1}),w.value?(o(),b(e(ve),{key:0,value:"seed"},{default:t(()=>[Q("div",Nt,[a(yt,{"table-name":f.value.name,"seed-file":w.value.file,"seed-item-count":w.value.itemCount,"table-item-count":f.value.itemCount,onRefresh:k},null,8,["table-name","seed-file","seed-item-count","table-item-count"])])]),_:1})):z("",!0)]),_:1},8,["modelValue"])):z("",!0)]}),_:1}))}}),xt=X({__name:"DynamoTablePage",props:{tableName:{}},setup(C){const N=Te();function s(){N.push("/dynamo")}return(T,S)=>(o(),b(wt,{"table-name":C.tableName,onBack:s},null,8,["table-name"]))}});export{xt as default};