local-serverless-stack 0.17.1 → 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 (222) hide show
  1. package/CHANGELOG.md +327 -0
  2. package/README.md +1157 -224
  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 +164 -15
  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 +59 -35
  98. package/dist/server/services/config-manager.d.ts.map +1 -1
  99. package/dist/server/services/config-manager.js +787 -131
  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-C7JlCyW1.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 +12 -12
  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-9Lk0_ZLj.js +0 -1
  200. package/dist/ui/assets/BucketDetailPage-CdLGW5em.js +0 -1
  201. package/dist/ui/assets/BucketsPage-CDP95vp8.js +0 -1
  202. package/dist/ui/assets/DynamoPage-CV7omZpi.js +0 -1
  203. package/dist/ui/assets/DynamoTablePage-C8v42fy7.js +0 -3
  204. package/dist/ui/assets/LambdaDetailPage-DkGxePSD.js +0 -4
  205. package/dist/ui/assets/LambdasPage-Bg7_taxW.js +0 -1
  206. package/dist/ui/assets/OpenSearchCollectionPage-Ci1hHyy2.js +0 -1
  207. package/dist/ui/assets/OpenSearchPage-CBKqZeim.js +0 -1
  208. package/dist/ui/assets/OverviewPage-D8lrE9rQ.js +0 -1
  209. package/dist/ui/assets/QueueDetailPage-D0DSIGZ2.js +0 -1
  210. package/dist/ui/assets/QueuesPage-BXebf6st.js +0 -1
  211. package/dist/ui/assets/SecretsPage-Be2Nw9BM.js +0 -1
  212. package/dist/ui/assets/SecretsPage-D3XYogv-.css +0 -1
  213. package/dist/ui/assets/ServiceDetailPage-DZpczZ-G.js +0 -2
  214. package/dist/ui/assets/ServicesPage-CdzxEqs3.js +0 -2
  215. package/dist/ui/assets/_plugin-vue_export-helper-DlAUqK2U.js +0 -1
  216. package/dist/ui/assets/index-C1Wb35Y8.css +0 -1
  217. package/dist/ui/assets/index-CGpxa55R.js +0 -37
  218. package/packages/serverless-plugin/README.md +0 -115
  219. package/packages/serverless-plugin/dist/index.d.ts +0 -2
  220. package/packages/serverless-plugin/dist/index.d.ts.map +0 -1
  221. package/packages/serverless-plugin/dist/index.js +0 -107
  222. 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 q,o as E,m as u,e as d,W as t,t as p,$ as e,j as n,y as J,z as w,J as W,i,V as s,f as y,v as X,B as N,g as T,F as I,n as Y,u as G,C as P,A as S,w as v,q as c,R as H,s as _,x as K,D as O,r as z,b as Q,a as x,c as Z}from"./index-CGpxa55R.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"}],$=Q(()=>({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 M(r){return r==="ANY"?"info":"neutral"}return q(()=>{A(),b=window.setInterval(A,1e4)}),E(()=>{b&&window.clearInterval(b)}),(r,l)=>(u(),d(t(p),{direction:"vertical",gap:"1.25rem"},{default:e(()=>[n(t(J),{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(W),{key:0,variant:"danger",dismissible:"",onDismiss:l[0]||(l[0]=o=>g.value=null)},{default:e(()=>[i(s(g.value),1)]),_:1})):y("",!0),h.value&&!f.value.length?(u(),d(t(p),{key:1,direction:"horizontal",justify:"center",align:"center"},{default:e(()=>[n(t(X),{label:"Loading APIs..."})]),_:1})):f.value.length?y("",!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,Y(f.value,o=>(u(),d(t(G),{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(O),{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)):y("",!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"])):y("",!0),o.stage?(u(),d(t(v),{key:2,size:"sm",variant:"soft"},{default:e(()=>[i("stage: "+s(o.stage),1)]),_:2},1024)):y("",!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:M(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(H),{to:`/lambdas/${encodeURIComponent(String(a.functionName))}`,style:{"text-decoration":"none"}},{default:e(()=>[n(t(v),{size:"sm",variant:"soft",clickable:""},{default:e(()=>[i(s(a.functionName),1)]),_:2},1024)]),_:2},1032,["to"])]),"cell-eventType":e(({row:a})=>[n(t(v),{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(v),{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(v),{size:"sm",variant:"soft"},{default:e(()=>[i(s(a.type),1)]),_:2},1024)]),"cell-payloadVersion":e(({row:a})=>[n(t(v),{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)):y("",!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 L,l as P,_ as W,e as f,W as t,t as r,$ as a,a as g,m as c,j as l,A as p,p as Y,i,q as $,V as b,s as Z,f as M,J as Q,v as F,g as X,z as x,y as ee,I as U,a0 as te,Z as ae,d as T,u as _,B as le,C as ne,D as oe,a1 as ie,F as ue,c as re,r as s,b as se,Y as de}from"./index-CGpxa55R.js";const ce=["href"],fe=L({__name:"BucketDetail",props:{bucketName:{}},emits:["back"],setup(z,{emit:N}){const d=z,S=N,v=re(),u=s(null),k=s([]),V=s(""),K=s(!0),B=s(!1),y=s(null),j=s(""),w=s(""),h=s("text/plain"),C=s(!1),q=[{key:"key",label:"Key"},{key:"size",label:"Size",align:"right"},{key:"lastModified",label:"Modified"},{key:"actions",label:"",align:"right"}],A=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 E(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(){B.value=!0;try{const o=await g.listBucketObjects(d.bucketName,{prefix:V.value||void 0,maxKeys:200});k.value=o.objects}catch(o){v.add({title:"Failed to load objects",description:o.message,variant:"danger"})}finally{B.value=!1}}function R(o){return g.bucketObjectContentUrl(d.bucketName,o,!1)}function G(o){return g.bucketObjectContentUrl(d.bucketName,o,!0)}async function H(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}C.value=!0;try{await g.putBucketObject(d.bucketName,{key:j.value,body:w.value,contentType:h.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{C.value=!1}}return P(()=>{D(),m()}),W(()=>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]=J=>S("back"))},{default:a(()=>[l(t(Y),{name:"arrow-left"}),e[9]||(e[9]=i(" Buckets",-1))]),_:1}),l(t($),{size:"lg",weight:"semibold"},{default:a(()=>[i(b(z.bucketName),1)]),_:1}),(n=u.value)!=null&&n.versioning?(c(),f(t(Z),{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:B.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(Q),{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(),X(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($),{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:h.value,"onUpdate:modelValue":e[4]||(e[4]=n=>h.value=n),placeholder:"text/plain",label:"Content-Type"},null,8,["modelValue"]),l(t($),{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:C.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($),{weight:"semibold"},{default:a(()=>[i("Objects ("+b(k.value.length)+" · "+b(O(A.value))+")",1)]),_:1}),l(t(r),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:a(()=>[l(t(U),{modelValue:V.value,"onUpdate:modelValue":e[6]||(e[6]=n=>V.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(()=>[B.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:q,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(E(n.lastModified)),1)]),"cell-actions":a(({row:n})=>[l(t(r),{direction:"horizontal",gap:"0.25rem",justify:"flex-end"},{default:a(()=>[T("a",{href:G(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:J=>H(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=L({__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,Y as N,l as V,o as D,m as i,e as u,W as a,t as b,$ as t,j as o,y as I,z as p,J as O,i as s,V as c,f as T,u as U,v as L,B as q,C as F,A as P,s as _,R as A,w as E,q as y,D as G,r as f,b as S,a as w}from"./index-CGpxa55R.js";const J=C({__name:"BucketsView",setup(j){const $=N(),r=f([]),B=f({}),d=f(!0),v=f(null);let m=null;const R=[{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"}],x=S(()=>r.value.map(n=>({...n,service:B.value[n.name]||""}))),g=S(()=>({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 z(){try{const[n,l]=await Promise.all([w.listBuckets(),w.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 M(n){$.push(`/buckets/${encodeURIComponent(n)}`)}return V(()=>{z(),m=window.setInterval(z,1e4)}),D(()=>{m&&window.clearInterval(m)}),(n,l)=>(i(),u(a(b),{direction:"vertical",gap:"1.25rem"},{default:t(()=>[o(a(I),{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(O),{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:R,rows:x.value,"aria-label":"S3 buckets"},{"cell-name":t(({row:e})=>[o(a(G),{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(A),{key:0,to:`/services/${encodeURIComponent(String(e.service))}`,style:{"text-decoration":"none"}},{default:t(()=>[o(a(E),{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(P),{size:"sm",variant:"ghost",onClick:k=>M(String(e.name))},{default:t(()=>[...l[4]||(l[4]=[s(" Open ",-1)])]),_:1},8,["onClick"])]),_:1},8,["rows"])):(i(),u(a(q),{key:1,title:"No buckets found",description:"Register a microservice that defines S3 resources or create buckets directly in LocalStack."}))]),_:1})]),_:1}))}}),W=C({__name:"BucketsPage",setup(j){return($,r)=>(i(),u(J))}});export{W as default};
@@ -1 +0,0 @@
1
- import{k as A,l as U,o as j,m as n,e as l,W as a,t as v,$ as s,j as u,y as q,z as D,J as F,i as o,V as r,f as b,u as W,v as H,B as G,C as J,A as Y,q as m,w as c,s as R,R as Q,I as X,r as p,b as S,a as L,Y as Z}from"./index-CGpxa55R.js";const ee=A({__name:"DynamoTablesList",emits:["open"],setup(K,{emit:z}){const N=z,d=p([]),k=p([]),_=p({}),y=p(!0),C=p(null),$=p("");let I=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"}],h=S(()=>{const i=d.value.map(e=>{var P,V;const t=(P=e.keySchema.find(x=>x.KeyType==="HASH"))==null?void 0:P.AttributeName,f=(V=e.keySchema.find(x=>x.KeyType==="RANGE"))==null?void 0:V.AttributeName,w=f?`PK: ${t} · SK: ${f}`:`PK: ${t??"—"}`,E=k.value.find(x=>x.tableName===e.name);return{name:e.name,status:e.status,itemCount:e.itemCount||0,keyDescriptor:w,billingMode:e.billingMode,ttlOn:e.ttl.enabled,streamOn:e.streamEnabled,hasGsi:e.hasGsi,hasLsi:e.hasLsi,service:_.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:_.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?h.value.filter(e=>e.name.toLowerCase().includes(i)||(e.service||"").toLowerCase().includes(i)):h.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 B(){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 w of t.tables)f[w.name]=w.service;_.value=f,C.value=null}catch(i){C.value=i.message||"Failed to load DynamoDB tables"}finally{y.value=!1}}function O(i){i.exists&&N("open",i.name)}return U(()=>{B(),I=window.setInterval(B,15e3)}),j(()=>{I&&window.clearInterval(I)}),(i,e)=>(n(),l(a(v),{direction:"vertical",gap:"1.25rem"},{default:s(()=>[u(a(q),{columns:4,gap:"1rem"},{default:s(()=>[u(a(D),{label:"Tables",value:g.value.tables,tone:"info",loading:y.value},null,8,["value","loading"]),u(a(D),{label:"Total items",value:g.value.items,tone:"success",loading:y.value},null,8,["value","loading"]),u(a(D),{label:"Seeds pending",value:g.value.seedsPending,tone:g.value.seedsPending>0?"warning":"neutral",loading:y.value},null,8,["value","tone","loading"]),u(a(D),{label:"Warnings",value:g.value.warnings,tone:g.value.warnings>0?"warning":"neutral",loading:y.value},null,8,["value","tone","loading"])]),_:1}),C.value?(n(),l(a(F),{key:0,variant:"danger",dismissible:"",onDismiss:e[0]||(e[0]=t=>C.value=null)},{default:s(()=>[o(r(C.value),1)]),_:1})):b("",!0),u(a(W),{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(X),{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(H),{label:"Loading tables..."})]),_:1})):h.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=>O(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(Q),{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(Y),{key:0,size:"sm",variant:"soft",onClick:f=>O(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(G),{key:2,title:"No matching tables",description:`No tables match "${$.value}".`},null,8,["description"])):(n(),l(a(G),{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 z=Z();function N(d){z.push(`/dynamo/${encodeURIComponent(d)}`)}return(d,k)=>(n(),l(ee,{onOpen:N}))}});export{ae as default};
@@ -1,3 +0,0 @@
1
- import{k as X,_ as fe,m as d,e as b,W as e,E as et,$ as t,j as a,t as s,J as ie,i as r,V as y,f as C,q as k,s as F,N as tt,A as D,g as J,F as M,r as c,b as j,a as R,c as be,u as L,d as W,S as at,H as q,O as ne,x as xe,I as O,T as lt,D as Ve,a2 as Se,p as ce,n as G,v as ze,B as Ae,C as nt,h as it,G as ke,y as Ne,z as de,U as ut,w as $e,l as rt,P as ot,L as me,K as st,M as ve,X as dt,Y as Ce}from"./index-CGpxa55R.js";const mt=X({__name:"DynamoItemEditor",props:{open:{type:Boolean},tableName:{},mode:{},item:{},originalKey:{}},emits:["update:open","saved","request-edit","request-clone","request-delete"],setup(A,{emit:$}){const o=A,T=$,S=be(),V=c(""),f=c(null),w=c(!1),_=j({get:()=>o.open,set:i=>T("update:open",i)}),h=j(()=>o.mode==="create"?`Create item · ${o.tableName}`:o.mode==="view"?`View item · ${o.tableName}`:`Edit item · ${o.tableName}`),E=j(()=>o.mode==="view");fe(()=>[o.open,o.item,o.mode],([i])=>{i&&(V.value=o.item&&Object.keys(o.item).length?JSON.stringify(o.item,null,2):`{
2
-
3
- }`,f.value=null)},{immediate:!0});function z(){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 N(){const i=z();if(i){w.value=!0;try{o.mode==="edit"&&o.originalKey&&Object.entries(o.originalKey).some(([p,x])=>JSON.stringify(i[p])!==JSON.stringify(x))&&await R.deleteDynamoItem(o.tableName,o.originalKey),await R.putDynamoItem(o.tableName,i),S.add({title:o.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=z();i&&(V.value=JSON.stringify(i,null,2))}return(i,m)=>(d(),b(e(et),{open:_.value,"onUpdate:open":m[5]||(m[5]=p=>_.value=p),title:h.value,size:"lg"},{footer:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",justify:"space-between"},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem"},{default:t(()=>[E.value?C("",!0):(d(),b(e(D),{key:0,size:"sm",variant:"ghost",onClick:g},{default:t(()=>[...m[8]||(m[8]=[r(" Format JSON ",-1)])]),_:1})),E.value?(d(),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)):C("",!0)]),_:1}),a(e(s),{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?C("",!0):(d(),b(e(D),{key:0,size:"sm",variant:"solid",loading:w.value,disabled:!!f.value,onClick:N},{default:t(()=>[r(y(A.mode==="create"?"Create":"Save"),1)]),_:1},8,["loading","disabled"]))]),_:1})]),_:1})]),default:t(()=>[a(e(s),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[f.value?(d(),b(e(ie),{key:0,variant:"danger"},{default:t(()=>[r(y(f.value),1)]),_:1})):C("",!0),a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(k),{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?(d(),b(e(F),{key:0,tone:"neutral",variant:"soft"},{default:t(()=>[...m[7]||(m[7]=[r("read-only",-1)])]),_:1})):C("",!0)]),_:1}),a(e(tt),{modelValue:V.value,"onUpdate:modelValue":m[0]||(m[0]=p=>V.value=p),rows:18,readonly:E.value,spellcheck:"false",class:"mono",onBlur:z},null,8,["modelValue","readonly"])]),_:1})]),_:1},8,["open","title"]))}}),vt={style:{width:"100%"}},ft=X({__name:"DynamoItemsExplorer",props:{table:{}},setup(A){const $=A,o=be(),T=c("scan"),S=c(""),V=c(50),f=c(""),w=c("="),_=c(""),h=c(""),E=c(!1),z=c([]),N=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"),U=c(null),te=c(null),ue=c(!1),re=c(null),Te=[{value:"scan",label:"Scan"},{value:"query",label:"Query"}],he=[{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"}],Ie=[{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"}],De=[{value:"String",label:"String"},{value:"Number",label:"Number"},{value:"Boolean",label:"Boolean"},{value:"Null",label:"Null"}],Ee=j(()=>{const u=[{value:"",label:`Table - ${$.table.name}`}];for(const l of $.table.gsis||[])l.IndexName&&u.push({value:l.IndexName,label:`Index - ${l.IndexName}`});for(const l of $.table.lsis||[])l.IndexName&&u.push({value:l.IndexName,label:`Index - ${l.IndexName}`});return u}),pe=j(()=>{if(!S.value)return $.table.keySchema;const u=$.table.gsis.find(l=>l.IndexName===S.value)||$.table.lsis.find(l=>l.IndexName===S.value);return(u==null?void 0:u.KeySchema)||$.table.keySchema}),ae=j(()=>{var u,l;return((l=(u=pe.value)==null?void 0:u.find(n=>n.KeyType==="HASH"))==null?void 0:l.AttributeName)||""}),P=j(()=>{var u,l;return((l=(u=pe.value)==null?void 0:u.find(n=>n.KeyType==="RANGE"))==null?void 0:l.AttributeName)||""}),oe=j(()=>(pe.value||[]).map(u=>u.AttributeName).filter(u=>!!u)),ge=j(()=>{const u=new Set;for(const l of g.value)Object.keys(l).forEach(n=>{oe.value.includes(n)||u.add(n)});return Array.from(u).sort()});function je(u){const l=$.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 qe=j(()=>{const u=oe.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]}),Re=j(()=>g.value.map((u,l)=>{const n={__id:l,__raw:u};for(const v of oe.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 Be(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=$.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 Ue(){const u={},l={},n=[];return z.value.forEach((v,I)=>{if(!v.attr)return;const K=`#fn${I}`,se=`:fv${I}`;if(u[K]=v.attr,v.op==="attribute_exists"){n.push(`attribute_exists(${K})`);return}if(v.op==="attribute_not_exists"){n.push(`attribute_not_exists(${K})`);return}l[se]=Be(v.value,v.type),v.op==="begins_with"?n.push(`begins_with(${K}, ${se})`):v.op==="contains"?n.push(`contains(${K}, ${se})`):n.push(`${K} ${v.op} ${se}`)}),{expr:n.join(" AND "),names:u,values:l}}function Oe(u){const l=Ue(),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 K=Ke();n.keyConditionExpression=K.keyExpr,v={...v,...K.names},I={...I,...K.values},E.value&&(n.scanIndexForward=!1)}return Object.keys(v).length&&(n.expressionAttributeNames=v),Object.keys(I).length&&(n.expressionAttributeValues=I),n}async function H(u){x.value=!0,B.value=null;try{const l=Oe(u),n=T.value==="scan"?await R.scanDynamoTable($.table.name,l):await R.queryDynamoTable($.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 Le(){f.value="",w.value="=",_.value="",h.value="",E.value=!1,z.value=[],g.value=[],i.value=void 0,m.value=void 0,Y.value=!1,B.value=null}function Pe(){i.value&&H(i.value)}function Fe(){z.value.push({attr:"",op:"=",type:"String",value:""}),N.value=!0}function Je(u){z.value.splice(u,1)}function _e(u){const l={};for(const n of $.table.keySchema)n.AttributeName&&(l[n.AttributeName]=u[n.AttributeName]);return l}function Me(){const u={};for(const l of $.table.keySchema){if(!l.AttributeName)continue;const n=$.table.attributeDefinitions.find(v=>v.AttributeName===l.AttributeName);u[l.AttributeName]=(n==null?void 0:n.AttributeType)==="N"?0:""}return u}function Ge(){ee.value="create",U.value=Me(),te.value=null,Z.value=!0}function We(u){ee.value="view",U.value=u,te.value=null,Z.value=!0}function He(){U.value&&(te.value=_e(U.value),ee.value="edit")}function Qe(){if(!U.value)return;const u={...U.value};for(const l of $.table.keySchema){if(!l.AttributeName)continue;const n=$.table.attributeDefinitions.find(v=>v.AttributeName===l.AttributeName);u[l.AttributeName]=(n==null?void 0:n.AttributeType)==="N"?0:""}U.value=u,te.value=null,ee.value="create"}function Xe(){U.value&&(re.value=_e(U.value),ue.value=!0)}async function Ye(){if(re.value)try{await R.deleteDynamoItem($.table.name,re.value),o.add({title:"Item deleted",variant:"info"}),Z.value=!1,await H()}catch(u){o.add({title:"Delete failed",description:u.message,variant:"danger"})}finally{ue.value=!1,re.value=null}}function Ze(){H()}const Q=j(()=>{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 H(),fe(()=>[T.value,S.value],()=>{g.value=[],i.value=void 0,m.value=void 0,Y.value=!1}),(u,l)=>(d(),b(e(s),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e(L),{variant:"outline"},{header:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...l[15]||(l[15]=[r("Scan or query items",-1)])]),_:1})]),footer:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e(D),{variant:"solid",loading:x.value,onClick:l[8]||(l[8]=n=>H())},{default:t(()=>[...l[21]||(l[21]=[r("Run",-1)])]),_:1},8,["loading"]),a(e(D),{variant:"ghost",onClick:Le},{default:t(()=>[...l[22]||(l[22]=[r("Reset",-1)])]),_:1})]),_:1}),a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e(k),{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(s),{direction:"vertical",gap:"1rem"},{default:t(()=>[W("div",vt,[a(e(at),{modelValue:T.value,"onUpdate:modelValue":l[0]||(l[0]=n=>T.value=n),options:Te,size:"md"},null,8,["modelValue"])]),a(e(s),{direction:"horizontal",gap:"1rem"},{default:t(()=>[a(e(q),{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:Ee.value},null,8,["modelValue","options"])]),_:1}),a(e(q),{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"?(d(),J(M,{key:0},[a(e(xe)),a(e(s),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(k),{weight:"semibold",style:{"font-size":"0.9rem"}},{default:t(()=>[...l[16]||(l[16]=[r("Partition key",-1)])]),_:1}),a(e(s),{direction:"horizontal",gap:"1rem"},{default:t(()=>[a(e(q),{label:"Attribute",style:{flex:"1"}},{default:t(()=>[a(e(O),{"model-value":ae.value||"—",disabled:""},null,8,["model-value"])]),_:1}),a(e(q),{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?(d(),b(e(s),{key:0,direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(k),{weight:"semibold",style:{"font-size":"0.9rem"}},{default:t(()=>[...l[17]||(l[17]=[r("Sort key – optional",-1)])]),_:1}),a(e(s),{direction:"horizontal",gap:"0.75rem",align:"end"},{default:t(()=>[a(e(q),{label:"Attribute",style:{flex:"1.4"}},{default:t(()=>[a(e(O),{"model-value":P.value,disabled:""},null,8,["model-value"])]),_:1}),a(e(q),{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:he},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"?(d(),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"])):C("",!0),a(e(lt),{modelValue:E.value,"onUpdate:modelValue":l[6]||(l[6]=n=>E.value=n),label:"Sort descending"},null,8,["modelValue"])]),_:1})]),_:1})):C("",!0)],64)):C("",!0),a(e(xe)),a(e(s),{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=>N.value=!N.value,["prevent"]))},{default:t(()=>[a(e(ce),{name:N.value?"chevron-down":"chevron-right"},null,8,["name"]),l[18]||(l[18]=r(" Filters – optional ",-1))]),_:1}),N.value?(d(),b(e(s),{key:0,direction:"vertical",gap:"0.5rem"},{default:t(()=>[(d(!0),J(M,null,G(z.value,(n,v)=>(d(),b(e(s),{key:`f-${v}`,direction:"horizontal",gap:"0.5rem",align:"end"},{default:t(()=>[a(e(q),{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(q),{label:"Condition",style:{flex:"1.4"}},{default:t(()=>[a(e(ne),{modelValue:n.op,"onUpdate:modelValue":I=>n.op=I,options:Ie},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),a(e(q),{label:"Type",style:{flex:"0.9"}},{default:t(()=>[a(e(ne),{modelValue:n.type,"onUpdate:modelValue":I=>n.type=I,options:De},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),a(e(q),{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=>Je(v)},{default:t(()=>[...l[19]||(l[19]=[r("Remove",-1)])]),_:1},8,["onClick"])]),_:2},1024))),128)),W("div",null,[a(e(D),{size:"sm",variant:"outline",onClick:Fe},{default:t(()=>[...l[20]||(l[20]=[r("Add filter",-1)])]),_:1})])]),_:1})):C("",!0)]),_:1})]),_:1})]),_:1}),B.value?(d(),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})):C("",!0),Y.value&&!B.value?(d(),b(e(ie),{key:1,variant:Q.value.finished?"success":"warning",dismissible:"",onDismiss:l[11]||(l[11]=n=>Y.value=!1)},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[W("span",null,[a(e(k),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(Q.value.finished?"Completed":"Stopped"),1)]),_:1}),l[24]||(l[24]=r(" · Items returned: ",-1)),a(e(k),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(Q.value.returned),1)]),_:1}),l[25]||(l[25]=r(" · Items scanned: ",-1)),a(e(k),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(Q.value.scanned),1)]),_:1}),l[26]||(l[26]=r(" · Efficiency: ",-1)),a(e(k),{as:"strong",weight:"semibold"},{default:t(()=>[r(y(Q.value.efficiency)+"%",1)]),_:1})]),Q.value.finished?C("",!0):(d(),b(e(D),{key:0,size:"sm",variant:"outline",loading:x.value,onClick:Pe},{default:t(()=>[...l[27]||(l[27]=[r(" Retrieve next page ",-1)])]),_:1},8,["loading"]))]),_:1})]),_:1},8,["variant"])):C("",!0),a(e(L),{variant:"outline"},{header:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(s),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[r(y(S.value?`Index: ${S.value} (${$.table.name})`:`Table: ${$.table.name}`)+" – Items returned ("+y(g.value.length)+") ",1)]),_:1}),a(e(k),{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(s),{direction:"horizontal",gap:"0.5rem"},{default:t(()=>[a(e(D),{size:"sm",variant:"ghost",loading:x.value,onClick:l[12]||(l[12]=n=>H())},{default:t(()=>[...l[28]||(l[28]=[r("Refresh",-1)])]),_:1},8,["loading"]),a(e(D),{size:"sm",variant:"outline",onClick:Ge},{default:t(()=>[...l[29]||(l[29]=[r("Create item",-1)])]),_:1})]),_:1})]),_:1})]),default:t(()=>[x.value&&!g.value.length?(d(),b(e(s),{key:0,direction:"horizontal",justify:"center",align:"center"},{default:t(()=>[a(e(ze),{label:"Running..."})]),_:1})):g.value.length?(d(),b(e(nt),{key:2,columns:qe.value,rows:Re.value,"aria-label":"Scan and query results"},it({_:2},[G(oe.value,(n,v)=>({name:`cell-__attr__${n}`,fn:t(({row:I})=>[v===0?(d(),b(e(Ve),{key:0,href:"#",class:"mono",onClick:Se(K=>We(I.__raw),["prevent"])},{default:t(()=>[r(y(ye(I[`__attr__${n}`])),1)]),_:2},1032,["onClick"])):(d(),b(e(k),{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(k),{family:"mono",size:"sm"},{default:t(()=>[r(y(ye(v[`__attr__${n}`])),1)]),_:2},1024)])}))]),1032,["columns","rows"])):(d(),b(e(Ae),{key:1,title:"No items",description:"Run the operation to load items."}))]),_:1}),a(mt,{open:Z.value,"onUpdate:open":l[13]||(l[13]=n=>Z.value=n),"table-name":$.table.name,mode:ee.value,item:U.value,"original-key":te.value,onSaved:Ze,onRequestEdit:He,onRequestClone:Qe,onRequestDelete:Xe},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 ${$.table.name}? This cannot be undone.`,"confirm-label":"Delete","cancel-label":"Cancel",tone:"danger",onConfirm:Ye},null,8,["open","description"])]),_:1}))}}),bt=X({__name:"DynamoTableSettings",props:{table:{}},emits:["refresh"],setup(A,{emit:$}){const o=A,T=$,S=be(),V=c(o.table.ttl.enabled),f=c(o.table.ttl.attributeName||""),w=c(!1),_=c(null);fe(()=>[o.table.ttl.enabled,o.table.ttl.attributeName],([z,N])=>{V.value=z,f.value=N||""});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(o.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(z){_.value=z.message||"Failed to update TTL"}finally{w.value=!1}}function E(z){return z<1024?`${z} B`:z<1024*1024?`${(z/1024).toFixed(1)} KB`:`${(z/(1024*1024)).toFixed(1)} MB`}return(z,N)=>(d(),b(e(s),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e(Ne),{columns:4,gap:"0.75rem"},{default:t(()=>[a(e(de),{label:"Items",value:o.table.itemCount,tone:"info"},null,8,["value"]),a(e(de),{label:"Size",value:E(o.table.sizeBytes),tone:"neutral"},null,8,["value"]),a(e(de),{label:"Status",value:o.table.status||"UNKNOWN",tone:o.table.status==="ACTIVE"?"success":"warning"},null,8,["value","tone"]),a(e(de),{label:"Billing",value:o.table.billingMode||"—",tone:"neutral"},null,8,["value"])]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...N[3]||(N[3]=[r("Time to Live (TTL)",-1)])]),_:1})]),default:t(()=>[_.value?(d(),b(e(ie),{key:0,variant:"danger",dismissible:"",onDismiss:N[0]||(N[0]=g=>_.value=null)},{default:t(()=>[r(y(_.value),1)]),_:1})):C("",!0),a(e(s),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[a(e(k),{tone:"muted",size:"sm"},{default:t(()=>[...N[4]||(N[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(q),{label:"Enable TTL"},{default:t(()=>[a(e(ut),{modelValue:V.value,"onUpdate:modelValue":N[1]||(N[1]=g=>V.value=g)},null,8,["modelValue"])]),_:1}),a(e(q),{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":N[2]||(N[2]=g=>f.value=g),placeholder:"e.g. expiresAt",disabled:!V.value},null,8,["modelValue","disabled"])]),_:1},8,["hint"]),a(e(s),{direction:"horizontal",justify:"flex-end"},{default:t(()=>[a(e(D),{size:"sm",variant:"solid",loading:w.value,onClick:h},{default:t(()=>[...N[5]||(N[5]=[r(" Apply ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...N[6]||(N[6]=[r("Streams",-1)])]),_:1})]),default:t(()=>[a(e(s),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:t(()=>[a(e(F),{tone:o.table.streamEnabled?"success":"neutral",variant:"soft"},{default:t(()=>[r(y(o.table.streamEnabled?"Enabled":"Disabled"),1)]),_:1},8,["tone"]),o.table.streamViewType?(d(),b(e($e),{key:0,size:"sm",variant:"soft"},{default:t(()=>[r(y(o.table.streamViewType),1)]),_:1})):C("",!0)]),_:1}),o.table.streamArn?(d(),b(e(k),{key:0,tone:"muted",family:"mono",style:{"font-size":"0.7rem"}},{default:t(()=>[r(y(o.table.streamArn),1)]),_:1})):(d(),b(e(k),{key:1,tone:"muted",size:"xs"},{default:t(()=>[...N[7]||(N[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(k),{weight:"semibold"},{default:t(()=>[...N[8]||(N[8]=[r("Identifier",-1)])]),_:1})]),default:t(()=>[a(e(s),{direction:"vertical",gap:"0.25rem"},{default:t(()=>[a(e(k),{tone:"muted",family:"mono",size:"xs"},{default:t(()=>[r(" ARN: "+y(o.table.arn||"—"),1)]),_:1}),a(e(k),{tone:"muted",size:"xs"},{default:t(()=>[r(" Created: "+y(o.table.createdAt?new Date(o.table.createdAt).toLocaleString():"—"),1)]),_:1})]),_:1})]),_:1})]),_:1}))}}),pt=X({__name:"DynamoSeedPanel",props:{tableName:{},seedFile:{},seedItemCount:{},tableItemCount:{}},emits:["refresh"],setup(A,{emit:$}){const o=A,T=$,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(o.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:`${o.tableName}: ${m.reason||"unknown reason"}`,variant:"warning"}):S.add({title:"Seed applied",description:`${i} item(s) inserted into ${o.tableName}`,variant:"success"}),T("refresh")}catch(g){S.add({title:"Seed failed",description:g.message,variant:"danger"})}finally{V.value=!1}}}async function z(){if(!w.value){w.value=!0;try{const i=(await R.clearSeed(o.tableName)).results.reduce((m,p)=>m+(p.deleted||0),0);S.add({title:"Table purged",description:`${i} item(s) removed from ${o.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 N(){if(!f.value){f.value=!0;try{const i=(await R.clearSeed(o.tableName)).results.reduce((x,B)=>x+(B.deleted||0),0),p=(await R.runSeed(o.tableName)).results.reduce((x,B)=>x+(B.inserted||0),0);S.add({title:"Seed redone",description:`${i} removed, ${p} inserted in ${o.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)=>(d(),b(e(s),{direction:"vertical",gap:"1rem"},{default:t(()=>[a(e(L),{variant:"outline"},{header:t(()=>[a(e(s),{direction:"horizontal",justify:"space-between",align:"center"},{default:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...i[4]||(i[4]=[r("Seed file",-1)])]),_:1}),a(e(F),{tone:"info",variant:"soft"},{default:t(()=>[r(y(A.seedItemCount)+" item"+y(A.seedItemCount===1?"":"s"),1)]),_:1})]),_:1})]),default:t(()=>[a(e(s),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(s),{direction:"horizontal",justify:"space-between",align:"center"},{default:t(()=>[a(e(k),{tone:"muted"},{default:t(()=>[...i[5]||(i[5]=[r("Path",-1)])]),_:1}),a(e(k),{family:"mono",size:"sm"},{default:t(()=>[r(y(A.seedFile),1)]),_:1})]),_:1}),a(e(s),{direction:"horizontal",justify:"space-between",align:"center"},{default:t(()=>[a(e(k),{tone:"muted"},{default:t(()=>[...i[6]||(i[6]=[r("Current rows in table",-1)])]),_:1}),a(e(k),{family:"mono"},{default:t(()=>[r(y(A.tableItemCount),1)]),_:1})]),_:1})]),_:1})]),_:1}),a(e(L),{variant:"outline"},{header:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...i[7]||(i[7]=[r("Actions",-1)])]),_:1})]),default:t(()=>[a(e(s),{direction:"vertical",gap:"0.75rem"},{default:t(()=>[a(e(s),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(s),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...i[8]||(i[8]=[r("Apply seed",-1)])]),_:1}),a(e(k),{tone:"muted",size:"sm"},{default:t(()=>[...i[9]||(i[9]=[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:A.seedItemCount<=0,onClick:E},{default:t(()=>[...i[10]||(i[10]=[r(" Apply ",-1)])]),_:1},8,["loading","disabled"])]),_:1}),a(e(s),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(s),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...i[11]||(i[11]=[r("Redo seed",-1)])]),_:1}),a(e(k),{tone:"muted",size:"sm"},{default:t(()=>[...i[12]||(i[12]=[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:A.seedItemCount<=0,onClick:i[0]||(i[0]=m=>h.value=!0)},{default:t(()=>[...i[13]||(i[13]=[r(" Redo ",-1)])]),_:1},8,["loading","disabled"])]),_:1}),a(e(s),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:t(()=>[a(e(s),{direction:"vertical",gap:"0.125rem"},{default:t(()=>[a(e(k),{weight:"semibold"},{default:t(()=>[...i[14]||(i[14]=[r("Purge table",-1)])]),_:1}),a(e(k),{tone:"muted",size:"sm"},{default:t(()=>[...i[15]||(i[15]=[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[16]||(i[16]=[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 ${A.tableName}?`,description:`This deletes all ${A.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:z},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 ${A.tableName}?`,description:`This purges all ${A.tableItemCount} current item(s), then re-applies ${A.seedItemCount} seeded item(s).`,"confirm-label":"Redo","cancel-label":"Cancel","confirm-variant":"danger",onConfirm:N},null,8,["open","title","description"])]),_:1}))}}),gt={style:{"padding-top":"1rem"}},yt={style:{"padding-top":"1rem"}},ct={style:{"padding-top":"1rem"}},kt={style:{"padding-top":"1rem"}},Nt=X({__name:"DynamoTableDetail",props:{tableName:{}},emits:["back"],setup(A,{emit:$}){const o=A,T=$,S=dt(),V=Ce(),f=c(null),w=c(null),_=c(!0),h=c(null),E=["items","indexes","settings","seed"],z=j({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 N(){_.value=!0;try{const[g,i]=await Promise.all([R.describeDynamoTable(o.tableName),R.listSeeds().catch(()=>({seedsDir:"",entries:[]}))]);f.value=g,w.value=i.entries.find(m=>m.tableName===o.tableName)||null,h.value=null}catch(g){h.value=g.message||"Failed to load table",f.value=null}finally{_.value=!1}}return rt(N),fe(()=>o.tableName,N),(g,i)=>(d(),b(e(s),{direction:"vertical",gap:"1rem"},{default:t(()=>{var m;return[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(s),{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(k),{size:"lg",weight:"semibold"},{default:t(()=>[r(y(A.tableName),1)]),_:1}),(p=f.value)!=null&&p.status?(d(),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"])):C("",!0),w.value?(d(),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})):C("",!0)]}),_:1}),a(e(D),{size:"sm",variant:"ghost",loading:_.value,onClick:N},{default:t(()=>[...i[4]||(i[4]=[r("Refresh",-1)])]),_:1},8,["loading"])]),_:1}),(m=f.value)!=null&&m.warnings.length?(d(),b(e(s),{key:0,direction:"horizontal",gap:"0.375rem",wrap:""},{default:t(()=>[(d(!0),J(M,null,G(f.value.warnings,p=>(d(),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})):C("",!0),h.value?(d(),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})):C("",!0),_.value&&!f.value?(d(),b(e(s),{key:2,direction:"horizontal",justify:"center",align:"center"},{default:t(()=>[a(e(ze),{label:"Loading table..."})]),_:1})):f.value?(d(),b(e(ot),{key:3,modelValue:z.value,"onUpdate:modelValue":i[2]||(i[2]=p=>z.value=p)},{default:t(()=>[a(e(st),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?(d(),b(e(me),{key:0,value:"seed"},{default:t(()=>[...i[8]||(i[8]=[r("Seed",-1)])]),_:1})):C("",!0)]),_:1}),a(e(ve),{value:"items"},{default:t(()=>[W("div",gt,[a(ft,{table:f.value},null,8,["table"])])]),_:1}),a(e(ve),{value:"indexes"},{default:t(()=>[W("div",yt,[!f.value.gsis.length&&!f.value.lsis.length?(d(),b(e(Ae),{key:0,title:"No secondary indexes",description:"This table has only the primary key."})):(d(),b(e(s),{key:1,direction:"vertical",gap:"1rem"},{default:t(()=>[f.value.gsis.length?(d(),b(e(Ne),{key:0,columns:2,gap:"0.75rem"},{default:t(()=>[(d(!0),J(M,null,G(f.value.gsis,p=>(d(),b(e(L),{key:p.IndexName,variant:"outline"},{header:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(k),{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(s),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",wrap:""},{default:t(()=>[(d(!0),J(M,null,G(p.KeySchema||[],x=>(d(),b(e($e),{key:x.AttributeName,size:"sm",variant:"soft"},{default:t(()=>[r(y(x.AttributeName)+" ("+y(x.KeyType)+") ",1)]),_:2},1024))),128))]),_:2},1024),a(e(k),{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})):C("",!0),f.value.lsis.length?(d(),b(e(Ne),{key:1,columns:2,gap:"0.75rem"},{default:t(()=>[(d(!0),J(M,null,G(f.value.lsis,p=>(d(),b(e(L),{key:p.IndexName,variant:"outline"},{header:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:t(()=>[a(e(k),{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(s),{direction:"vertical",gap:"0.5rem"},{default:t(()=>[a(e(s),{direction:"horizontal",gap:"0.5rem",wrap:""},{default:t(()=>[(d(!0),J(M,null,G(p.KeySchema||[],x=>(d(),b(e($e),{key:x.AttributeName,size:"sm",variant:"soft"},{default:t(()=>[r(y(x.AttributeName)+" ("+y(x.KeyType)+") ",1)]),_:2},1024))),128))]),_:2},1024),a(e(k),{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})):C("",!0)]),_:1}))])]),_:1}),a(e(ve),{value:"settings"},{default:t(()=>[W("div",ct,[a(bt,{table:f.value,onRefresh:N},null,8,["table"])])]),_:1}),w.value?(d(),b(e(ve),{key:0,value:"seed"},{default:t(()=>[W("div",kt,[a(pt,{"table-name":f.value.name,"seed-file":w.value.file,"seed-item-count":w.value.itemCount,"table-item-count":f.value.itemCount,onRefresh:N},null,8,["table-name","seed-file","seed-item-count","table-item-count"])])]),_:1})):C("",!0)]),_:1},8,["modelValue"])):C("",!0)]}),_:1}))}}),wt=X({__name:"DynamoTablePage",props:{tableName:{}},setup(A){const $=Ce();function o(){$.push("/dynamo")}return(T,S)=>(d(),b(Nt,{"table-name":A.tableName,onBack:o},null,8,["table-name"]))}});export{wt as default};