local-serverless-stack 0.4.0 → 0.6.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 (112) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +8 -8
  3. package/bin/cli.js +38 -3
  4. package/dist/client/index.d.ts +7 -0
  5. package/dist/client/index.d.ts.map +1 -1
  6. package/dist/client/index.js +6 -0
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/client/namespaces/apis.d.ts +48 -0
  9. package/dist/client/namespaces/apis.d.ts.map +1 -0
  10. package/dist/client/namespaces/apis.js +12 -0
  11. package/dist/client/namespaces/apis.js.map +1 -0
  12. package/dist/client/namespaces/lambdas.d.ts +61 -0
  13. package/dist/client/namespaces/lambdas.d.ts.map +1 -0
  14. package/dist/client/namespaces/lambdas.js +13 -0
  15. package/dist/client/namespaces/lambdas.js.map +1 -0
  16. package/dist/client/namespaces/services.d.ts +40 -0
  17. package/dist/client/namespaces/services.d.ts.map +1 -1
  18. package/dist/client/namespaces/services.js +3 -0
  19. package/dist/client/namespaces/services.js.map +1 -1
  20. package/dist/client/types.d.ts +2 -0
  21. package/dist/client/types.d.ts.map +1 -1
  22. package/dist/server/index.js +25 -2
  23. package/dist/server/index.js.map +1 -1
  24. package/dist/server/routes/apis.d.ts +3 -0
  25. package/dist/server/routes/apis.d.ts.map +1 -0
  26. package/dist/server/routes/apis.js +54 -0
  27. package/dist/server/routes/apis.js.map +1 -0
  28. package/dist/server/routes/lambdas.d.ts +3 -0
  29. package/dist/server/routes/lambdas.d.ts.map +1 -0
  30. package/dist/server/routes/lambdas.js +85 -0
  31. package/dist/server/routes/lambdas.js.map +1 -0
  32. package/dist/server/routes/services.d.ts.map +1 -1
  33. package/dist/server/routes/services.js +91 -81
  34. package/dist/server/routes/services.js.map +1 -1
  35. package/dist/server/runtime/runtime-worker.d.ts +2 -0
  36. package/dist/server/runtime/runtime-worker.d.ts.map +1 -0
  37. package/dist/server/runtime/runtime-worker.js +230 -0
  38. package/dist/server/runtime/runtime-worker.js.map +1 -0
  39. package/dist/server/services/api-gateway-events.d.ts +44 -0
  40. package/dist/server/services/api-gateway-events.d.ts.map +1 -0
  41. package/dist/server/services/api-gateway-events.js +299 -0
  42. package/dist/server/services/api-gateway-events.js.map +1 -0
  43. package/dist/server/services/artifact-resolver.d.ts +2 -0
  44. package/dist/server/services/artifact-resolver.d.ts.map +1 -0
  45. package/dist/server/services/artifact-resolver.js +38 -0
  46. package/dist/server/services/artifact-resolver.js.map +1 -0
  47. package/dist/server/services/authorizer-service.d.ts +25 -0
  48. package/dist/server/services/authorizer-service.d.ts.map +1 -0
  49. package/dist/server/services/authorizer-service.js +0 -0
  50. package/dist/server/services/authorizer-service.js.map +1 -0
  51. package/dist/server/services/cache-manager.d.ts +6 -0
  52. package/dist/server/services/cache-manager.d.ts.map +1 -1
  53. package/dist/server/services/cache-manager.js.map +1 -1
  54. package/dist/server/services/cloudformation-parser.d.ts +15 -0
  55. package/dist/server/services/cloudformation-parser.d.ts.map +1 -1
  56. package/dist/server/services/cloudformation-parser.js +36 -3
  57. package/dist/server/services/cloudformation-parser.js.map +1 -1
  58. package/dist/server/services/config-manager.d.ts +36 -0
  59. package/dist/server/services/config-manager.d.ts.map +1 -1
  60. package/dist/server/services/config-manager.js +57 -0
  61. package/dist/server/services/config-manager.js.map +1 -1
  62. package/dist/server/services/function-registry.d.ts +33 -0
  63. package/dist/server/services/function-registry.d.ts.map +1 -0
  64. package/dist/server/services/function-registry.js +100 -0
  65. package/dist/server/services/function-registry.js.map +1 -0
  66. package/dist/server/services/gateway-manager.d.ts +31 -0
  67. package/dist/server/services/gateway-manager.d.ts.map +1 -0
  68. package/dist/server/services/gateway-manager.js +292 -0
  69. package/dist/server/services/gateway-manager.js.map +1 -0
  70. package/dist/server/services/lambda-runtime-manager.d.ts +52 -0
  71. package/dist/server/services/lambda-runtime-manager.d.ts.map +1 -0
  72. package/dist/server/services/lambda-runtime-manager.js +309 -0
  73. package/dist/server/services/lambda-runtime-manager.js.map +1 -0
  74. package/dist/server/services/localstack-manager.d.ts.map +1 -1
  75. package/dist/server/services/localstack-manager.js +9 -0
  76. package/dist/server/services/localstack-manager.js.map +1 -1
  77. package/dist/server/services/resource-provisioner.d.ts +1 -0
  78. package/dist/server/services/resource-provisioner.d.ts.map +1 -1
  79. package/dist/server/services/resource-provisioner.js +73 -11
  80. package/dist/server/services/resource-provisioner.js.map +1 -1
  81. package/dist/server/services/serverless-state-parser.d.ts +86 -0
  82. package/dist/server/services/serverless-state-parser.d.ts.map +1 -0
  83. package/dist/server/services/serverless-state-parser.js +245 -0
  84. package/dist/server/services/serverless-state-parser.js.map +1 -0
  85. package/dist/server/services/service-registrar.d.ts +34 -0
  86. package/dist/server/services/service-registrar.d.ts.map +1 -0
  87. package/dist/server/services/service-registrar.js +280 -0
  88. package/dist/server/services/service-registrar.js.map +1 -0
  89. package/dist/server/services/source-watcher.d.ts +24 -0
  90. package/dist/server/services/source-watcher.d.ts.map +1 -0
  91. package/dist/server/services/source-watcher.js +101 -0
  92. package/dist/server/services/source-watcher.js.map +1 -0
  93. package/dist/ui/assets/ApisPage-DdgKjEdS.js +1 -0
  94. package/dist/ui/assets/{BucketDetailPage-Hg4Gg3jC.js → BucketDetailPage-DZQGxm0y.js} +1 -1
  95. package/dist/ui/assets/{BucketsPage-BHkg7TQp.js → BucketsPage-xYXzxCvd.js} +1 -1
  96. package/dist/ui/assets/{DynamoPage-CH_TgPh_.js → DynamoPage-B1__Rjr2.js} +1 -1
  97. package/dist/ui/assets/{DynamoTablePage-BPvl5y6_.js → DynamoTablePage-BCoxPdXW.js} +1 -1
  98. package/dist/ui/assets/LambdaDetailPage-B85CA8tb.js +4 -0
  99. package/dist/ui/assets/LambdasPage-_TtxQMT_.js +1 -0
  100. package/dist/ui/assets/{OverviewPage-CwLnw4VW.css → OverviewPage-6jDXV1jr.css} +1 -1
  101. package/dist/ui/assets/OverviewPage-CqTKTY64.js +1 -0
  102. package/dist/ui/assets/{QueueDetailPage-DHDPgRDc.js → QueueDetailPage-BOr_sImA.js} +1 -1
  103. package/dist/ui/assets/{QueuesPage-D5YcEbUU.js → QueuesPage-DpByfcM5.js} +1 -1
  104. package/dist/ui/assets/{ServiceDetailPage-DxJ0t7HQ.js → ServiceDetailPage-DsWgV-ad.js} +1 -1
  105. package/dist/ui/assets/{ServicesPage-DWDaaOz9.js → ServicesPage-CGlpsj98.js} +1 -1
  106. package/dist/ui/assets/{index-D3WwZ4lY.js → index-BWlB542w.js} +11 -11
  107. package/dist/ui/index.html +1 -1
  108. package/package.json +1 -1
  109. package/packages/serverless-plugin/README.md +21 -3
  110. package/packages/serverless-plugin/dist/index.js +8 -3
  111. package/packages/serverless-plugin/dist/index.js.map +1 -1
  112. package/dist/ui/assets/OverviewPage-nhomNDqx.js +0 -1
@@ -0,0 +1,280 @@
1
+ // End-to-end service (re-)registration: read the `sls package` artifacts
2
+ // (CloudFormation template + serverless-state.json), parse resources, functions,
3
+ // routes and authorizers, persist to the cache, provision LocalStack resources,
4
+ // and activate the data plane (runtime worker + gateway/invoke listeners +
5
+ // watcher). Shared by the /register route, boot rehydration and hot reload.
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import { CloudFormationParser } from './cloudformation-parser.js';
9
+ import { ServerlessStateParser, sanitizeEnvironmentValues, } from './serverless-state-parser.js';
10
+ import { CacheManager } from './cache-manager.js';
11
+ import { ResourceProvisioner } from './resource-provisioner.js';
12
+ import { ConfigManager } from './config-manager.js';
13
+ import { FunctionRegistry } from './function-registry.js';
14
+ import { LambdaRuntimeManager } from './lambda-runtime-manager.js';
15
+ import { GatewayManager } from './gateway-manager.js';
16
+ import { SourceWatcher } from './source-watcher.js';
17
+ import { runServerlessPackage, ServerlessPackageError } from './serverless-packager.js';
18
+ const cfnParser = new CloudFormationParser();
19
+ const stateParser = new ServerlessStateParser();
20
+ export class ServiceRegistrar {
21
+ static instance;
22
+ cache = new CacheManager();
23
+ cacheReady = false;
24
+ static getInstance() {
25
+ if (!ServiceRegistrar.instance) {
26
+ ServiceRegistrar.instance = new ServiceRegistrar();
27
+ }
28
+ return ServiceRegistrar.instance;
29
+ }
30
+ async ensureCache() {
31
+ if (!this.cacheReady) {
32
+ await this.cache.init();
33
+ this.cacheReady = true;
34
+ }
35
+ return this.cache;
36
+ }
37
+ async register(input) {
38
+ const configManager = ConfigManager.getInstance();
39
+ const cache = await this.ensureCache();
40
+ const resolvedPath = path.resolve(input.servicePath);
41
+ const dirName = path.basename(resolvedPath);
42
+ const effectiveRegion = input.region || configManager.getConfig().region || 'us-east-1';
43
+ const template = await this.readTemplate(resolvedPath, dirName);
44
+ const resources = cfnParser.parse(template);
45
+ const templateHash = cfnParser.calculateHash(template);
46
+ // serverless-state.json is the declarative source for routes/authorizers.
47
+ // Missing state (older setups) degrades gracefully: functions still come
48
+ // from the CFN template, HTTP routes are just unavailable.
49
+ const state = await this.readState(resolvedPath);
50
+ const warnings = [];
51
+ let functions = [];
52
+ let routes = [];
53
+ let authorizers = [];
54
+ let stage = 'dev';
55
+ // The service's identity is the `service:` name from serverless.yml (via
56
+ // serverless-state.json), not the directory basename — two products can
57
+ // both live in a folder called "bff". The basename remains the fallback
58
+ // for stateless registrations.
59
+ let serviceName = dirName;
60
+ const cfnLambdas = resources.filter((r) => r.type === 'lambda');
61
+ if (state) {
62
+ const parsed = stateParser.parse(state);
63
+ if (parsed.serviceName)
64
+ serviceName = parsed.serviceName;
65
+ warnings.push(...parsed.warnings);
66
+ stage = parsed.stage;
67
+ routes = parsed.routes;
68
+ authorizers = parsed.authorizers;
69
+ // The CFN template carries the fully resolved function env (state may
70
+ // still hold unresolved refs) — prefer it when the names line up.
71
+ functions = parsed.functions.map(fn => {
72
+ const cfn = cfnLambdas.find(l => l.name === fn.fullName);
73
+ return cfn
74
+ ? { ...fn, environment: { ...fn.environment, ...sanitizeEnvironmentValues(cfn.environment) } }
75
+ : fn;
76
+ });
77
+ }
78
+ else {
79
+ warnings.push('serverless-state.json not found — functions registered from the CloudFormation template only (no HTTP routes).');
80
+ functions = cfnLambdas.map(l => ({
81
+ name: l.name,
82
+ fullName: l.name,
83
+ handler: l.handler,
84
+ runtime: l.runtime,
85
+ memorySize: l.memorySize,
86
+ timeout: l.timeout,
87
+ environment: sanitizeEnvironmentValues(l.environment),
88
+ triggers: [],
89
+ }));
90
+ }
91
+ // Port resolution: lss.config.json serviceRuntime > plugin payload >
92
+ // invokePortOffset rule (apiPort 30xx → invokePort 130xx).
93
+ const runtimeConfig = configManager.getRuntimeConfigForService(resolvedPath);
94
+ const apiPort = runtimeConfig.apiPort ?? input.apiPort;
95
+ const invokePort = runtimeConfig.invokePort
96
+ ?? input.invokePort
97
+ ?? (apiPort ? apiPort + configManager.getInvokePortOffset() : undefined);
98
+ // 0.5.x keyed the cache by directory basename. When the real service name
99
+ // differs, migrate: drop the legacy entry for this same root (data plane +
100
+ // cache) so re-registration doesn't leave a ghost service behind.
101
+ if (serviceName !== dirName) {
102
+ const legacy = await cache.getMetadata(dirName);
103
+ if (legacy && legacy.root === resolvedPath) {
104
+ await this.deactivate(dirName);
105
+ await cache.deleteService(dirName);
106
+ console.log(`♻️ Migrated cached service "${dirName}" → "${serviceName}"`);
107
+ }
108
+ }
109
+ const metadata = {
110
+ root: resolvedPath,
111
+ templateHash,
112
+ lastUpdated: Date.now(),
113
+ status: 'registered',
114
+ invokePort,
115
+ apiPort,
116
+ region: effectiveRegion,
117
+ stage,
118
+ functions,
119
+ routes,
120
+ authorizers,
121
+ };
122
+ await cache.saveTemplate(serviceName, template, metadata);
123
+ // Provision infra resources to LocalStack (unchanged behavior).
124
+ await ResourceProvisioner.getInstance().provisionResources(serviceName, resources, {
125
+ invokePort,
126
+ region: effectiveRegion,
127
+ });
128
+ await this.activate({ name: serviceName, ...metadata });
129
+ for (const warning of warnings) {
130
+ console.warn(`⚠️ [${serviceName}] ${warning}`);
131
+ }
132
+ return {
133
+ serviceName,
134
+ resources,
135
+ functionsCount: functions.length,
136
+ routesCount: routes?.length ?? 0,
137
+ warnings,
138
+ };
139
+ }
140
+ // Bring the data plane (registry, runtime worker, listeners, watcher) in line
141
+ // with a service's metadata. Also used at boot for every cached service.
142
+ async activate(metadata) {
143
+ const configManager = ConfigManager.getInstance();
144
+ const registry = FunctionRegistry.getInstance();
145
+ const runtime = LambdaRuntimeManager.getInstance();
146
+ const gateway = GatewayManager.getInstance();
147
+ const watcher = SourceWatcher.getInstance();
148
+ const entry = registry.registerService(metadata);
149
+ const runtimeConfig = configManager.getRuntimeConfigForService(metadata.root);
150
+ await runtime.syncService(entry);
151
+ await gateway.syncService(entry, runtimeConfig.enabled);
152
+ // Watch default depends on how handlers are loaded: source mode reloads are
153
+ // cheap (worker restart), artifact mode would need a re-package per save.
154
+ const resolvedMode = runtime.getRuntimeInfo(metadata.name).resolvedMode;
155
+ const watchEnabled = runtimeConfig.enabled
156
+ && (runtimeConfig.watch ?? resolvedMode === 'source')
157
+ && (metadata.functions?.length ?? 0) > 0;
158
+ if (watchEnabled) {
159
+ watcher.watch(metadata.name, metadata.root);
160
+ }
161
+ else {
162
+ watcher.unwatch(metadata.name);
163
+ }
164
+ }
165
+ async rehydrateAll() {
166
+ const cache = await this.ensureCache();
167
+ const services = await cache.listServices();
168
+ for (const metadata of services) {
169
+ try {
170
+ await this.activate(metadata);
171
+ }
172
+ catch (err) {
173
+ console.error(`❌ Failed to activate cached service "${metadata.name}":`, err);
174
+ }
175
+ }
176
+ if (services.length) {
177
+ console.log(`🔁 Reactivated ${services.length} cached service(s)`);
178
+ }
179
+ }
180
+ // Full reload for the watcher: re-package (when autoPackage allows) and
181
+ // re-register using the ports/region already on record.
182
+ async reregister(serviceName) {
183
+ const cache = await this.ensureCache();
184
+ const metadata = await cache.getMetadata(serviceName);
185
+ if (!metadata)
186
+ throw new Error(`Service ${serviceName} not found in cache`);
187
+ if (ConfigManager.getInstance().isAutoPackage()) {
188
+ const pkgConfig = ConfigManager.getInstance().getPackageConfigForService(metadata.root);
189
+ await runServerlessPackage({
190
+ command: pkgConfig.command,
191
+ args: pkgConfig.args,
192
+ cwd: metadata.root,
193
+ timeoutMs: pkgConfig.timeoutMs,
194
+ env: pkgConfig.env,
195
+ });
196
+ }
197
+ await this.register({
198
+ servicePath: metadata.root,
199
+ invokePort: metadata.invokePort,
200
+ apiPort: metadata.apiPort,
201
+ region: metadata.region,
202
+ });
203
+ }
204
+ async deactivate(serviceName) {
205
+ SourceWatcher.getInstance().unwatch(serviceName);
206
+ await LambdaRuntimeManager.getInstance().stopRuntime(serviceName);
207
+ await GatewayManager.getInstance().removeService(serviceName);
208
+ FunctionRegistry.getInstance().removeService(serviceName);
209
+ }
210
+ async readTemplate(resolvedPath, serviceName) {
211
+ const configManager = ConfigManager.getInstance();
212
+ const templatePath = path.join(resolvedPath, '.serverless', 'cloudformation-template-update-stack.json');
213
+ let templateContent;
214
+ try {
215
+ templateContent = await fs.readFile(templatePath, 'utf-8');
216
+ }
217
+ catch (err) {
218
+ const isENOENT = err?.code === 'ENOENT';
219
+ if (!isENOENT)
220
+ throw err;
221
+ if (!configManager.isAutoPackage()) {
222
+ throw new RegistrationError(400, `CloudFormation template not found at ${templatePath}. Run 'serverless package' in the service directory, or enable autoPackage in lss.config.json.`);
223
+ }
224
+ const pkgConfig = configManager.getPackageConfigForService(resolvedPath);
225
+ const displayCmd = [pkgConfig.command, ...pkgConfig.args].join(' ');
226
+ console.log(`📦 Template missing — running '${displayCmd}' in ${resolvedPath} (service: ${serviceName})`);
227
+ try {
228
+ const result = await runServerlessPackage({
229
+ command: pkgConfig.command,
230
+ args: pkgConfig.args,
231
+ cwd: resolvedPath,
232
+ timeoutMs: pkgConfig.timeoutMs,
233
+ env: pkgConfig.env,
234
+ });
235
+ console.log(`✅ Auto-package finished for ${resolvedPath} (exit 0)`);
236
+ if (result.stdout.trim()) {
237
+ console.log(`--- ${displayCmd} stdout ---\n${result.stdout.trimEnd()}\n--- end ---`);
238
+ }
239
+ }
240
+ catch (packageErr) {
241
+ if (packageErr instanceof ServerlessPackageError) {
242
+ console.error(`❌ Auto-package failed for ${resolvedPath}: ${packageErr.message}`);
243
+ if (packageErr.result.stdout.trim()) {
244
+ console.error(`--- ${displayCmd} stdout ---\n${packageErr.result.stdout.trimEnd()}\n--- end ---`);
245
+ }
246
+ if (packageErr.result.stderr.trim()) {
247
+ console.error(`--- ${displayCmd} stderr ---\n${packageErr.result.stderr.trimEnd()}\n--- end ---`);
248
+ }
249
+ }
250
+ else {
251
+ console.error(`❌ Auto-package failed for ${resolvedPath}:`, packageErr);
252
+ }
253
+ const detail = packageErr instanceof ServerlessPackageError
254
+ ? `${packageErr.message}\n${packageErr.result.stderr || packageErr.result.stdout}`.trim()
255
+ : packageErr instanceof Error ? packageErr.message : 'Unknown error';
256
+ throw new RegistrationError(500, `Auto-package failed for ${resolvedPath}: ${detail}. Full stderr/stdout is in the orchestrator log (/tmp/lss-orchestrator.log).`);
257
+ }
258
+ templateContent = await fs.readFile(templatePath, 'utf-8');
259
+ }
260
+ return JSON.parse(templateContent);
261
+ }
262
+ async readState(resolvedPath) {
263
+ try {
264
+ const statePath = path.join(resolvedPath, '.serverless', 'serverless-state.json');
265
+ return JSON.parse(await fs.readFile(statePath, 'utf-8'));
266
+ }
267
+ catch {
268
+ return null;
269
+ }
270
+ }
271
+ }
272
+ export class RegistrationError extends Error {
273
+ statusCode;
274
+ constructor(statusCode, message) {
275
+ super(message);
276
+ this.statusCode = statusCode;
277
+ this.name = 'RegistrationError';
278
+ }
279
+ }
280
+ //# sourceMappingURL=service-registrar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-registrar.js","sourceRoot":"","sources":["../../../src/server/services/service-registrar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface WatchStatus {
2
+ watching: boolean;
3
+ lastReloadAt?: number;
4
+ lastReloadKind?: 'runtime' | 'full';
5
+ lastError?: string;
6
+ }
7
+ export interface ReloadHandlers {
8
+ onRuntimeReload: (serviceName: string) => Promise<void>;
9
+ onFullReload: (serviceName: string) => Promise<void>;
10
+ }
11
+ export declare class SourceWatcher {
12
+ private static instance;
13
+ private watched;
14
+ private handlers?;
15
+ static getInstance(): SourceWatcher;
16
+ setHandlers(handlers: ReloadHandlers): void;
17
+ watch(serviceName: string, root: string): void;
18
+ unwatch(serviceName: string): void;
19
+ unwatchAll(): void;
20
+ getStatus(serviceName: string): WatchStatus;
21
+ private onChange;
22
+ private reload;
23
+ }
24
+ //# sourceMappingURL=source-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-watcher.d.ts","sourceRoot":"","sources":["../../../src/server/services/source-watcher.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,MAAM,WAAW,cAAc;IAE7B,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAMD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IACvC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAElC,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAI3C,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAsB9C,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQlC,UAAU,IAAI,IAAI;IAMlB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW;IAI3C,OAAO,CAAC,QAAQ;YAmBF,MAAM;CAiBrB"}
@@ -0,0 +1,101 @@
1
+ // Hot reload: watches a registered service's source tree and refreshes its
2
+ // Lambda runtime when files change. Handler-only changes just restart the
3
+ // service worker (flushing the module cache — cheap); serverless.yml changes
4
+ // need a re-package + re-registration, which the caller wires in.
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ const DEBOUNCE_MS = 500;
8
+ const IGNORED_SEGMENTS = new Set(['node_modules', '.serverless', '.esbuild', '.build', '.git', 'dist', '.lss']);
9
+ const FULL_RELOAD_FILES = new Set(['serverless.yml', 'serverless.yaml', 'serverless.json', 'package.json']);
10
+ export class SourceWatcher {
11
+ static instance;
12
+ watched = new Map();
13
+ handlers;
14
+ static getInstance() {
15
+ if (!SourceWatcher.instance) {
16
+ SourceWatcher.instance = new SourceWatcher();
17
+ }
18
+ return SourceWatcher.instance;
19
+ }
20
+ setHandlers(handlers) {
21
+ this.handlers = handlers;
22
+ }
23
+ watch(serviceName, root) {
24
+ this.unwatch(serviceName);
25
+ try {
26
+ const watcher = fs.watch(root, { recursive: true }, (_event, filename) => {
27
+ this.onChange(serviceName, filename ? String(filename) : '');
28
+ });
29
+ watcher.on('error', err => {
30
+ console.warn(`⚠️ Watcher for "${serviceName}" failed: ${err.message}`);
31
+ this.unwatch(serviceName);
32
+ });
33
+ this.watched.set(serviceName, {
34
+ root,
35
+ watcher,
36
+ pendingFullReload: false,
37
+ status: { watching: true },
38
+ });
39
+ console.log(`👀 Watching ${root} for changes (service "${serviceName}")`);
40
+ }
41
+ catch (err) {
42
+ console.warn(`⚠️ Could not watch ${root}: ${err instanceof Error ? err.message : err}`);
43
+ }
44
+ }
45
+ unwatch(serviceName) {
46
+ const watched = this.watched.get(serviceName);
47
+ if (!watched)
48
+ return;
49
+ if (watched.debounce)
50
+ clearTimeout(watched.debounce);
51
+ watched.watcher.close();
52
+ this.watched.delete(serviceName);
53
+ }
54
+ unwatchAll() {
55
+ for (const name of [...this.watched.keys()]) {
56
+ this.unwatch(name);
57
+ }
58
+ }
59
+ getStatus(serviceName) {
60
+ return this.watched.get(serviceName)?.status ?? { watching: false };
61
+ }
62
+ onChange(serviceName, filename) {
63
+ const watched = this.watched.get(serviceName);
64
+ if (!watched || !filename)
65
+ return;
66
+ const segments = filename.split(path.sep);
67
+ if (segments.some(s => IGNORED_SEGMENTS.has(s)))
68
+ return;
69
+ if (FULL_RELOAD_FILES.has(path.basename(filename)) && segments.length === 1) {
70
+ watched.pendingFullReload = true;
71
+ }
72
+ if (watched.debounce)
73
+ clearTimeout(watched.debounce);
74
+ watched.debounce = setTimeout(() => {
75
+ const kind = watched.pendingFullReload ? 'full' : 'runtime';
76
+ watched.pendingFullReload = false;
77
+ void this.reload(serviceName, watched, kind);
78
+ }, DEBOUNCE_MS);
79
+ }
80
+ async reload(serviceName, watched, kind) {
81
+ if (!this.handlers)
82
+ return;
83
+ try {
84
+ console.log(`♻️ Change detected in "${serviceName}" — ${kind === 'full' ? 're-registering service' : 'reloading runtime'}`);
85
+ if (kind === 'full') {
86
+ await this.handlers.onFullReload(serviceName);
87
+ }
88
+ else {
89
+ await this.handlers.onRuntimeReload(serviceName);
90
+ }
91
+ watched.status.lastReloadAt = Date.now();
92
+ watched.status.lastReloadKind = kind;
93
+ watched.status.lastError = undefined;
94
+ }
95
+ catch (err) {
96
+ watched.status.lastError = err instanceof Error ? err.message : String(err);
97
+ console.error(`❌ Reload failed for "${serviceName}": ${watched.status.lastError}`);
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=source-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-watcher.js","sourceRoot":"","sources":["../../../src/server/services/source-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{o as $,v as K,u as M,w as i,i as c,G as a,f as _,S as e,n as s,D as O,s as A,b as Y,m as u,E as r,j as f,k as p,R as G,J as T,F as S,z as X,K as q,V as I,A as P,B as h,a as R,h as y,_ as z,Y as H,y as b,g as Q,d as V,O as W}from"./index-BWlB542w.js";const Z={key:1,style:{display:"flex","justify-content":"center",padding:"2rem"}},ee={style:{"text-decoration":"underline","text-decoration-style":"dotted","text-underline-offset":"3px"}},te={class:"mono"},ae={key:1,class:"muted"},ne={class:"mono",style:{"font-size":"0.8rem"}},oe={class:"mono",style:{"font-size":"0.8rem"}},le={class:"mono",style:{"font-size":"0.75rem"}},se={key:0,class:"mono",style:{"font-size":"0.75rem"}},re={key:1,class:"muted"},ie=$({__name:"ApisView",setup(B){const k=W(),d=b([]),v=b(!0),g=b(null),m=b({});let w=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"}],N=Q(()=>({services:d.value.length,routes:d.value.reduce((l,n)=>l+n.routes.length,0),online:d.value.filter(l=>l.status==="online").length}));function L(l){return l.routes.map(n=>({...n}))}function D(l){return l.authorizers.map(n=>({...n,identitySource:n.identitySource.join(", "),target:n.functionName||n.arn||""}))}async function C(){try{d.value=await V.listApis(),g.value=null}catch(l){g.value=l.message||"Failed to load APIs"}finally{v.value=!1}}async function U(l){if(!m.value[l]){m.value={...m.value,[l]:!0};try{const n=await V.clearAuthorizerCache({service:l});k.add({title:"Authorizer cache cleared",description:`${n.removed} cached result${n.removed===1?"":"s"} removed`,variant:"success"})}catch(n){k.add({title:"Failed to clear authorizer cache",description:n.message,variant:"danger"})}finally{m.value={...m.value,[l]:!1}}}}function E(l,n){var t;const o=`curl -X ${n.method} http://localhost:${l.apiPort}${n.path}`;(t=navigator.clipboard)==null||t.writeText(o).then(()=>{k.add({title:"curl command copied",description:o,variant:"success"})})}function x(l){switch(l){case"online":return"success";case"port-conflict":return"warning";default:return"neutral"}}function J(l){return l==="ANY"?"info":"neutral"}return K(()=>{C(),w=window.setInterval(C,1e4)}),M(()=>{w&&window.clearInterval(w)}),(l,n)=>(i(),c(a(_),{direction:"vertical",gap:"1.25rem"},{default:e(()=>[s(a(O),{columns:3,gap:"1rem"},{default:e(()=>[s(a(A),{label:"Services with APIs",value:N.value.services,tone:"info",loading:v.value},null,8,["value","loading"]),s(a(A),{label:"Routes",value:N.value.routes,tone:"info",loading:v.value},null,8,["value","loading"]),s(a(A),{label:"Listeners online",value:N.value.online,tone:"success",loading:v.value},null,8,["value","loading"])]),_:1}),g.value?(i(),c(a(Y),{key:0,variant:"danger",dismissible:"",onDismiss:n[0]||(n[0]=o=>g.value=null)},{default:e(()=>[u(r(g.value),1)]),_:1})):f("",!0),v.value&&!d.value.length?(i(),p("div",Z,[s(a(G),{label:"Loading APIs..."})])):d.value.length?f("",!0):(i(),c(a(T),{key:2,title:"No APIs registered",description:"Register a microservice that defines http or httpApi events to see its routes here."})),(i(!0),p(S,null,X(d.value,o=>(i(),c(a(q),{key:o.service,variant:"outline"},{header:e(()=>[s(a(_),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between",wrap:""},{default:e(()=>[s(a(_),{direction:"horizontal",gap:"0.5rem",align:"center",wrap:""},{default:e(()=>[s(a(R),{to:`/services/${encodeURIComponent(o.service)}`,style:{color:"inherit","text-decoration":"none"}},{default:e(()=>[y("strong",ee,r(o.service),1)]),_:2},1032,["to"]),o.apiPort?(i(),c(a(z),{key:0,tone:"info",variant:"soft"},{default:e(()=>[u(":"+r(o.apiPort),1)]),_:2},1024)):f("",!0),s(a(z),{tone:x(o.status),variant:"soft"},{default:e(()=>[u(r(o.status),1)]),_:2},1032,["tone"]),o.invokePort?(i(),c(a(z),{key:1,tone:x(o.invokeStatus),variant:"soft"},{default:e(()=>[u(" invoke :"+r(o.invokePort),1)]),_:2},1032,["tone"])):f("",!0),o.stage?(i(),c(a(h),{key:2,size:"sm",variant:"soft"},{default:e(()=>[u("stage: "+r(o.stage),1)]),_:2},1024)):f("",!0)]),_:2},1024),s(a(P),{size:"sm",variant:"ghost",loading:m.value[o.service],onClick:t=>U(o.service)},{default:e(()=>[...n[1]||(n[1]=[u(" Clear authorizer cache ",-1)])]),_:1},8,["loading","onClick"])]),_:2},1024)]),default:e(()=>[s(a(_),{direction:"vertical",gap:"0.75rem"},{default:e(()=>[o.routes.length?(i(),c(a(I),{key:0,columns:F,rows:L(o)},{"cell-method":e(({row:t})=>[s(a(z),{tone:J(String(t.method)),variant:"soft"},{default:e(()=>[u(r(t.method),1)]),_:2},1032,["tone"])]),"cell-path":e(({row:t})=>[y("span",te,r(t.path),1)]),"cell-functionName":e(({row:t})=>[s(a(R),{to:`/lambdas/${encodeURIComponent(String(t.functionName))}`,style:{"text-decoration":"none"}},{default:e(()=>[s(a(h),{size:"sm",variant:"soft",clickable:""},{default:e(()=>[u(r(t.functionName),1)]),_:2},1024)]),_:2},1032,["to"])]),"cell-eventType":e(({row:t})=>[s(a(h),{size:"sm",variant:"soft"},{default:e(()=>[u(r(t.payloadVersion==="2.0"?"v2":"v1"),1)]),_:2},1024)]),"cell-authorizerName":e(({row:t})=>[t.authorizerName?(i(),c(a(h),{key:0,size:"sm",variant:"soft"},{default:e(()=>[u(r(t.authorizerName),1)]),_:2},1024)):(i(),p("span",ae,"—"))]),"cell-actions":e(({row:t})=>[s(a(_),{direction:"horizontal",gap:"0.375rem",justify:"flex-end"},{default:e(()=>[s(a(P),{size:"sm",variant:"ghost",onClick:ue=>E(o,t)},{default:e(()=>[...n[2]||(n[2]=[u(" Copy curl ",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:2},1032,["rows"])):(i(),c(a(T),{key:1,title:"No routes",description:"This service exposes no http or httpApi routes."})),o.authorizers.length?(i(),p(S,{key:2},[s(a(H)),n[3]||(n[3]=y("strong",{style:{"font-size":"0.85rem"}},"Authorizers",-1)),s(a(I),{columns:j,rows:D(o)},{"cell-name":e(({row:t})=>[y("span",ne,r(t.name),1)]),"cell-type":e(({row:t})=>[s(a(h),{size:"sm",variant:"soft"},{default:e(()=>[u(r(t.type),1)]),_:2},1024)]),"cell-payloadVersion":e(({row:t})=>[s(a(h),{size:"sm",variant:"soft"},{default:e(()=>[u(r(t.payloadVersion==="2.0"?"v2":"v1"),1)]),_:2},1024)]),"cell-resultTtlInSeconds":e(({row:t})=>[y("span",oe,r(t.resultTtlInSeconds)+"s",1)]),"cell-identitySource":e(({row:t})=>[y("span",le,r(t.identitySource||"—"),1)]),"cell-target":e(({row:t})=>[t.target?(i(),p("span",se,r(t.target),1)):(i(),p("span",re,"—"))]),_:1},8,["rows"])],64)):f("",!0)]),_:2},1024)]),_:2},1024))),128))]),_:1}))}}),de=$({__name:"ApisPage",setup(B){return(k,d)=>(i(),c(ie))}});export{de as default};
@@ -1 +1 @@
1
- import{o as R,v as Q,Q as W,i as k,G as t,f as c,S as n,d as b,w as d,n as o,A as g,m as r,h as m,E as p,_ as I,j as U,b as X,k as K,R as F,s as N,D as Y,p as S,U as Z,M as ee,K as T,J as te,V as ae,W as le,F as ne,O as oe,y as u,g as ie,L as re}from"./index-D3WwZ4lY.js";const ue={style:{"font-size":"1.1rem"}},se={key:1,style:{display:"flex","justify-content":"center",padding:"2rem"}},de={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},ce=["href"],fe=["href"],ve=R({__name:"BucketDetail",props:{bucketName:{}},emits:["back"],setup(z,{emit:V}){const s=z,$=V,f=oe(),i=u(null),y=u([]),h=u(""),_=u(!0),B=u(!1),j=u(null),w=u(""),x=u(""),C=u("text/plain"),O=u(!1),L=[{key:"key",label:"Key"},{key:"size",label:"Size",align:"right"},{key:"lastModified",label:"Modified"},{key:"actions",label:"",align:"right"}],E=ie(()=>y.value.reduce((l,e)=>l+(e.size||0),0));function D(l){if(l==null)return"—";if(l===0)return"0 B";const e=["B","KB","MB","GB","TB"],a=Math.floor(Math.log(l)/Math.log(1024));return`${(l/Math.pow(1024,a)).toFixed(a===0?0:1)} ${e[a]}`}function A(l){return l?new Date(l).toLocaleString():"—"}async function M(){try{i.value=await b.getBucket(s.bucketName),j.value=null}catch(l){j.value=l.message||"Failed to load bucket",i.value=null}finally{_.value=!1}}async function v(){B.value=!0;try{const l=await b.listBucketObjects(s.bucketName,{prefix:h.value||void 0,maxKeys:200});y.value=l.objects}catch(l){f.add({title:"Failed to load objects",description:l.message,variant:"danger"})}finally{B.value=!1}}function G(l){return b.bucketObjectContentUrl(s.bucketName,l,!1)}function J(l){return b.bucketObjectContentUrl(s.bucketName,l,!0)}async function q(l){if(confirm(`Delete object "${l}"?`))try{await b.deleteBucketObject(s.bucketName,l),f.add({title:"Object deleted",variant:"info"}),await v()}catch(e){f.add({title:"Failed to delete object",description:e.message,variant:"danger"})}}async function H(){if(!w.value||!x.value){f.add({title:"Key and body are required",variant:"warning"});return}O.value=!0;try{await b.putBucketObject(s.bucketName,{key:w.value,body:x.value,contentType:C.value||void 0}),f.add({title:"Object uploaded",variant:"info"}),w.value="",x.value="",await v(),await M()}catch(l){f.add({title:"Failed to upload object",description:l.message,variant:"danger"})}finally{O.value=!1}}return Q(()=>{M(),v()}),W(()=>s.bucketName,()=>{M(),v()}),(l,e)=>(d(),k(t(c),{direction:"vertical",gap:"1rem"},{default:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:n(()=>{var a;return[o(t(g),{size:"sm",variant:"ghost",onClick:e[0]||(e[0]=P=>$("back"))},{default:n(()=>[...e[9]||(e[9]=[r("← Buckets",-1)])]),_:1}),m("strong",ue,p(z.bucketName),1),(a=i.value)!=null&&a.versioning?(d(),k(t(I),{key:0,tone:"info",variant:"soft"},{default:n(()=>[...e[10]||(e[10]=[r("Versioning",-1)])]),_:1})):U("",!0)]}),_:1}),o(t(g),{size:"sm",variant:"ghost",loading:B.value,onClick:e[1]||(e[1]=a=>v())},{default:n(()=>[...e[11]||(e[11]=[r("Refresh",-1)])]),_:1},8,["loading"])]),_:1}),j.value?(d(),k(t(X),{key:0,variant:"danger",dismissible:"",onDismiss:e[2]||(e[2]=a=>j.value=null)},{default:n(()=>[r(p(j.value),1)]),_:1})):U("",!0),_.value&&!i.value?(d(),K("div",se,[o(t(F),{label:"Loading bucket..."})])):i.value?(d(),K(ne,{key:2},[o(t(Y),{columns:4,gap:"0.75rem"},{default:n(()=>[o(t(N),{label:"Objects",value:i.value.objectCount??0,tone:"info"},null,8,["value"]),o(t(N),{label:"Size",value:D(i.value.totalSize),tone:"neutral"},null,8,["value"]),o(t(N),{label:"Versioning",value:i.value.versioning?"Enabled":"Disabled",tone:i.value.versioning?"success":"neutral"},null,8,["value","tone"]),o(t(N),{label:"Notifications",value:i.value.notifications??0,tone:(i.value.notifications??0)>0?"info":"neutral"},null,8,["value","tone"])]),_:1}),o(t(T),{variant:"outline"},{header:n(()=>[...e[12]||(e[12]=[m("strong",null,"Upload object",-1)])]),default:n(()=>[o(t(c),{direction:"vertical",gap:"0.5rem"},{default:n(()=>[o(t(S),{modelValue:w.value,"onUpdate:modelValue":e[3]||(e[3]=a=>w.value=a),placeholder:"object/key.txt",label:"Key"},null,8,["modelValue"]),o(t(S),{modelValue:C.value,"onUpdate:modelValue":e[4]||(e[4]=a=>C.value=a),placeholder:"text/plain",label:"Content-Type"},null,8,["modelValue"]),e[14]||(e[14]=m("label",{class:"muted",style:{"font-size":"0.875rem"}},"Body",-1)),Z(m("textarea",{"onUpdate:modelValue":e[5]||(e[5]=a=>x.value=a),rows:"4",style:{width:"100%","font-family":"var(--tree-font-mono, monospace)",padding:"0.5rem"},placeholder:"Hello, world!"},null,512),[[ee,x.value]]),o(t(c),{direction:"horizontal",justify:"flex-end"},{default:n(()=>[o(t(g),{size:"sm",loading:O.value,onClick:H},{default:n(()=>[...e[13]||(e[13]=[r("Upload",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),o(t(T),{variant:"outline"},{header:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:n(()=>[m("strong",null,"Objects ("+p(y.value.length)+" · "+p(D(E.value))+")",1),o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:n(()=>[o(t(S),{modelValue:h.value,"onUpdate:modelValue":e[6]||(e[6]=a=>h.value=a),placeholder:"prefix filter",size:"sm",onKeyup:e[7]||(e[7]=le(a=>v(),["enter"]))},null,8,["modelValue"]),o(t(g),{size:"sm",variant:"ghost",onClick:e[8]||(e[8]=a=>v())},{default:n(()=>[...e[15]||(e[15]=[r("Apply",-1)])]),_:1})]),_:1})]),_:1})]),default:n(()=>[B.value?(d(),K("div",de,[o(t(F),{label:"Loading objects..."})])):y.value.length?(d(),k(t(ae),{key:2,columns:L,rows:y.value},{"cell-key":n(({row:a})=>[m("a",{href:G(String(a.key)),target:"_blank",rel:"noopener noreferrer",style:{"text-decoration":"none","font-weight":"500"}},p(a.key),9,ce)]),"cell-size":n(({row:a})=>[r(p(D(Number(a.size))),1)]),"cell-lastModified":n(({row:a})=>[r(p(A(a.lastModified)),1)]),"cell-actions":n(({row:a})=>[o(t(c),{direction:"horizontal",gap:"0.25rem",justify:"flex-end"},{default:n(()=>[m("a",{href:J(String(a.key)),target:"_blank",rel:"noopener noreferrer",style:{"text-decoration":"none"}},[o(t(g),{size:"sm",variant:"ghost"},{default:n(()=>[...e[16]||(e[16]=[r("Download",-1)])]),_:1})],8,fe),o(t(g),{size:"sm",variant:"ghost",tone:"danger",onClick:P=>q(String(a.key))},{default:n(()=>[...e[17]||(e[17]=[r(" Delete ",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:1},8,["rows"])):(d(),k(t(te),{key:1,title:"No objects",description:"This bucket is empty (or the prefix filter excluded everything)."}))]),_:1})],64)):U("",!0)]),_:1}))}}),pe=R({__name:"BucketDetailPage",props:{bucketName:{}},setup(z){const V=re();function s(){V.push("/buckets")}return($,f)=>(d(),k(ve,{"bucket-name":z.bucketName,onBack:s},null,8,["bucket-name"]))}});export{pe as default};
1
+ import{o as R,v as Q,Q as W,i as k,G as t,f as c,S as n,d as b,w as d,n as o,A as g,m as r,h as m,E as p,_ as I,j as U,b as X,k as K,R as F,s as N,D as Y,p as S,U as Z,M as ee,K as T,J as te,V as ae,W as le,F as ne,O as oe,y as u,g as ie,L as re}from"./index-BWlB542w.js";const ue={style:{"font-size":"1.1rem"}},se={key:1,style:{display:"flex","justify-content":"center",padding:"2rem"}},de={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},ce=["href"],fe=["href"],ve=R({__name:"BucketDetail",props:{bucketName:{}},emits:["back"],setup(z,{emit:V}){const s=z,$=V,f=oe(),i=u(null),y=u([]),h=u(""),_=u(!0),B=u(!1),j=u(null),w=u(""),x=u(""),C=u("text/plain"),O=u(!1),L=[{key:"key",label:"Key"},{key:"size",label:"Size",align:"right"},{key:"lastModified",label:"Modified"},{key:"actions",label:"",align:"right"}],E=ie(()=>y.value.reduce((l,e)=>l+(e.size||0),0));function D(l){if(l==null)return"—";if(l===0)return"0 B";const e=["B","KB","MB","GB","TB"],a=Math.floor(Math.log(l)/Math.log(1024));return`${(l/Math.pow(1024,a)).toFixed(a===0?0:1)} ${e[a]}`}function A(l){return l?new Date(l).toLocaleString():"—"}async function M(){try{i.value=await b.getBucket(s.bucketName),j.value=null}catch(l){j.value=l.message||"Failed to load bucket",i.value=null}finally{_.value=!1}}async function v(){B.value=!0;try{const l=await b.listBucketObjects(s.bucketName,{prefix:h.value||void 0,maxKeys:200});y.value=l.objects}catch(l){f.add({title:"Failed to load objects",description:l.message,variant:"danger"})}finally{B.value=!1}}function G(l){return b.bucketObjectContentUrl(s.bucketName,l,!1)}function J(l){return b.bucketObjectContentUrl(s.bucketName,l,!0)}async function q(l){if(confirm(`Delete object "${l}"?`))try{await b.deleteBucketObject(s.bucketName,l),f.add({title:"Object deleted",variant:"info"}),await v()}catch(e){f.add({title:"Failed to delete object",description:e.message,variant:"danger"})}}async function H(){if(!w.value||!x.value){f.add({title:"Key and body are required",variant:"warning"});return}O.value=!0;try{await b.putBucketObject(s.bucketName,{key:w.value,body:x.value,contentType:C.value||void 0}),f.add({title:"Object uploaded",variant:"info"}),w.value="",x.value="",await v(),await M()}catch(l){f.add({title:"Failed to upload object",description:l.message,variant:"danger"})}finally{O.value=!1}}return Q(()=>{M(),v()}),W(()=>s.bucketName,()=>{M(),v()}),(l,e)=>(d(),k(t(c),{direction:"vertical",gap:"1rem"},{default:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:n(()=>{var a;return[o(t(g),{size:"sm",variant:"ghost",onClick:e[0]||(e[0]=P=>$("back"))},{default:n(()=>[...e[9]||(e[9]=[r("← Buckets",-1)])]),_:1}),m("strong",ue,p(z.bucketName),1),(a=i.value)!=null&&a.versioning?(d(),k(t(I),{key:0,tone:"info",variant:"soft"},{default:n(()=>[...e[10]||(e[10]=[r("Versioning",-1)])]),_:1})):U("",!0)]}),_:1}),o(t(g),{size:"sm",variant:"ghost",loading:B.value,onClick:e[1]||(e[1]=a=>v())},{default:n(()=>[...e[11]||(e[11]=[r("Refresh",-1)])]),_:1},8,["loading"])]),_:1}),j.value?(d(),k(t(X),{key:0,variant:"danger",dismissible:"",onDismiss:e[2]||(e[2]=a=>j.value=null)},{default:n(()=>[r(p(j.value),1)]),_:1})):U("",!0),_.value&&!i.value?(d(),K("div",se,[o(t(F),{label:"Loading bucket..."})])):i.value?(d(),K(ne,{key:2},[o(t(Y),{columns:4,gap:"0.75rem"},{default:n(()=>[o(t(N),{label:"Objects",value:i.value.objectCount??0,tone:"info"},null,8,["value"]),o(t(N),{label:"Size",value:D(i.value.totalSize),tone:"neutral"},null,8,["value"]),o(t(N),{label:"Versioning",value:i.value.versioning?"Enabled":"Disabled",tone:i.value.versioning?"success":"neutral"},null,8,["value","tone"]),o(t(N),{label:"Notifications",value:i.value.notifications??0,tone:(i.value.notifications??0)>0?"info":"neutral"},null,8,["value","tone"])]),_:1}),o(t(T),{variant:"outline"},{header:n(()=>[...e[12]||(e[12]=[m("strong",null,"Upload object",-1)])]),default:n(()=>[o(t(c),{direction:"vertical",gap:"0.5rem"},{default:n(()=>[o(t(S),{modelValue:w.value,"onUpdate:modelValue":e[3]||(e[3]=a=>w.value=a),placeholder:"object/key.txt",label:"Key"},null,8,["modelValue"]),o(t(S),{modelValue:C.value,"onUpdate:modelValue":e[4]||(e[4]=a=>C.value=a),placeholder:"text/plain",label:"Content-Type"},null,8,["modelValue"]),e[14]||(e[14]=m("label",{class:"muted",style:{"font-size":"0.875rem"}},"Body",-1)),Z(m("textarea",{"onUpdate:modelValue":e[5]||(e[5]=a=>x.value=a),rows:"4",style:{width:"100%","font-family":"var(--tree-font-mono, monospace)",padding:"0.5rem"},placeholder:"Hello, world!"},null,512),[[ee,x.value]]),o(t(c),{direction:"horizontal",justify:"flex-end"},{default:n(()=>[o(t(g),{size:"sm",loading:O.value,onClick:H},{default:n(()=>[...e[13]||(e[13]=[r("Upload",-1)])]),_:1},8,["loading"])]),_:1})]),_:1})]),_:1}),o(t(T),{variant:"outline"},{header:n(()=>[o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:n(()=>[m("strong",null,"Objects ("+p(y.value.length)+" · "+p(D(E.value))+")",1),o(t(c),{direction:"horizontal",gap:"0.5rem",align:"center"},{default:n(()=>[o(t(S),{modelValue:h.value,"onUpdate:modelValue":e[6]||(e[6]=a=>h.value=a),placeholder:"prefix filter",size:"sm",onKeyup:e[7]||(e[7]=le(a=>v(),["enter"]))},null,8,["modelValue"]),o(t(g),{size:"sm",variant:"ghost",onClick:e[8]||(e[8]=a=>v())},{default:n(()=>[...e[15]||(e[15]=[r("Apply",-1)])]),_:1})]),_:1})]),_:1})]),default:n(()=>[B.value?(d(),K("div",de,[o(t(F),{label:"Loading objects..."})])):y.value.length?(d(),k(t(ae),{key:2,columns:L,rows:y.value},{"cell-key":n(({row:a})=>[m("a",{href:G(String(a.key)),target:"_blank",rel:"noopener noreferrer",style:{"text-decoration":"none","font-weight":"500"}},p(a.key),9,ce)]),"cell-size":n(({row:a})=>[r(p(D(Number(a.size))),1)]),"cell-lastModified":n(({row:a})=>[r(p(A(a.lastModified)),1)]),"cell-actions":n(({row:a})=>[o(t(c),{direction:"horizontal",gap:"0.25rem",justify:"flex-end"},{default:n(()=>[m("a",{href:J(String(a.key)),target:"_blank",rel:"noopener noreferrer",style:{"text-decoration":"none"}},[o(t(g),{size:"sm",variant:"ghost"},{default:n(()=>[...e[16]||(e[16]=[r("Download",-1)])]),_:1})],8,fe),o(t(g),{size:"sm",variant:"ghost",tone:"danger",onClick:P=>q(String(a.key))},{default:n(()=>[...e[17]||(e[17]=[r(" Delete ",-1)])]),_:1},8,["onClick"])]),_:2},1024)]),_:1},8,["rows"])):(d(),k(t(te),{key:1,title:"No objects",description:"This bucket is empty (or the prefix filter excluded everything)."}))]),_:1})],64)):U("",!0)]),_:1}))}}),pe=R({__name:"BucketDetailPage",props:{bucketName:{}},setup(z){const V=re();function s(){V.push("/buckets")}return($,f)=>(d(),k(ve,{"bucket-name":z.bucketName,onBack:s},null,8,["bucket-name"]))}});export{pe as default};
@@ -1 +1 @@
1
- import{o as x,L as N,v as D,u as I,w as o,i as u,G as n,f as C,S as a,n as l,D as L,s as b,b as O,m as c,E as r,j as T,K as E,k as z,R as K,J as U,V as F,A as G,_ as p,a as J,B as P,h as _,X as q,y as m,g as j,d as R}from"./index-D3WwZ4lY.js";const A={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},X=["onClick"],H={key:1,class:"muted",style:{"font-size":"0.75rem"}},Q=x({__name:"BucketsView",setup(V){const y=N(),i=m([]),h=m({}),d=m(!0),v=m(null);let g=null;const $=[{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"}],M=j(()=>i.value.map(t=>({...t,service:h.value[t.name]||""}))),k=j(()=>({buckets:i.value.length,objects:i.value.reduce((t,s)=>t+(s.objectCount||0),0),size:i.value.reduce((t,s)=>t+(s.totalSize||0),0)}));function B(t){if(t==null)return"—";if(t===0)return"0 B";const s=["B","KB","MB","GB","TB"],e=Math.floor(Math.log(t)/Math.log(1024));return`${(t/Math.pow(1024,e)).toFixed(e===0?0:1)} ${s[e]}`}async function S(){try{const[t,s]=await Promise.all([R.listBuckets(),R.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);i.value=t;const e={};for(const f of s.buckets||[])e[f.name]=f.service;h.value=e,v.value=null}catch(t){v.value=t.message||"Failed to load buckets"}finally{d.value=!1}}function w(t){y.push(`/buckets/${encodeURIComponent(t)}`)}return D(()=>{S(),g=window.setInterval(S,1e4)}),I(()=>{g&&window.clearInterval(g)}),(t,s)=>(o(),u(n(C),{direction:"vertical",gap:"1.25rem"},{default:a(()=>[l(n(L),{columns:3,gap:"1rem"},{default:a(()=>[l(n(b),{label:"Buckets",value:k.value.buckets,tone:"info",loading:d.value},null,8,["value","loading"]),l(n(b),{label:"Objects",value:k.value.objects,tone:"success",loading:d.value},null,8,["value","loading"]),l(n(b),{label:"Total size",value:B(k.value.size),tone:"neutral",loading:d.value},null,8,["value","loading"])]),_:1}),v.value?(o(),u(n(O),{key:0,variant:"danger",dismissible:"",onDismiss:s[0]||(s[0]=e=>v.value=null)},{default:a(()=>[c(r(v.value),1)]),_:1})):T("",!0),l(n(E),{variant:"outline"},{header:a(()=>[l(n(C),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:a(()=>[...s[1]||(s[1]=[_("strong",null,"S3 Buckets",-1),_("span",{class:"muted"},"Refreshes every 10s",-1)])]),_:1})]),default:a(()=>[d.value?(o(),z("div",A,[l(n(K),{label:"Loading buckets..."})])):i.value.length?(o(),u(n(F),{key:2,columns:$,rows:M.value},{"cell-name":a(({row:e})=>[_("a",{href:"#",style:{"text-decoration":"none","font-weight":"600"},onClick:q(f=>w(String(e.name)),["prevent"])},r(e.name),9,X)]),"cell-service":a(({row:e})=>[e.service?(o(),u(n(J),{key:0,to:`/services/${encodeURIComponent(String(e.service))}`,style:{"text-decoration":"none"}},{default:a(()=>[l(n(P),{size:"sm",variant:"soft",clickable:""},{default:a(()=>[c(r(e.service),1)]),_:2},1024)]),_:2},1032,["to"])):(o(),z("span",H,"unmanaged"))]),"cell-objectCount":a(({row:e})=>[l(n(p),{tone:"info",variant:"soft"},{default:a(()=>[c(r(e.objectCount??0),1)]),_:2},1024)]),"cell-totalSize":a(({row:e})=>[c(r(B(e.totalSize)),1)]),"cell-versioning":a(({row:e})=>[l(n(p),{tone:e.versioning?"success":"neutral",variant:"soft"},{default:a(()=>[c(r(e.versioning?"Enabled":"Disabled"),1)]),_:2},1032,["tone"])]),"cell-notifications":a(({row:e})=>[l(n(p),{tone:Number(e.notifications)>0?"info":"neutral",variant:"soft"},{default:a(()=>[c(r(e.notifications??0),1)]),_:2},1032,["tone"])]),"cell-actions":a(({row:e})=>[l(n(G),{size:"sm",variant:"ghost",onClick:f=>w(String(e.name))},{default:a(()=>[...s[2]||(s[2]=[c(" Open ",-1)])]),_:1},8,["onClick"])]),_:1},8,["rows"])):(o(),u(n(U),{key:1,title:"No buckets found",description:"Register a microservice that defines S3 resources or create buckets directly in LocalStack."}))]),_:1})]),_:1}))}}),Y=x({__name:"BucketsPage",setup(V){return(y,i)=>(o(),u(Q))}});export{Y as default};
1
+ import{o as x,L as N,v as D,u as I,w as o,i as u,G as n,f as C,S as a,n as l,D as L,s as b,b as O,m as c,E as r,j as T,K as E,k as z,R as K,J as U,V as F,A as G,_ as p,a as J,B as P,h as _,X as q,y as m,g as j,d as R}from"./index-BWlB542w.js";const A={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},X=["onClick"],H={key:1,class:"muted",style:{"font-size":"0.75rem"}},Q=x({__name:"BucketsView",setup(V){const y=N(),i=m([]),h=m({}),d=m(!0),v=m(null);let g=null;const $=[{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"}],M=j(()=>i.value.map(t=>({...t,service:h.value[t.name]||""}))),k=j(()=>({buckets:i.value.length,objects:i.value.reduce((t,s)=>t+(s.objectCount||0),0),size:i.value.reduce((t,s)=>t+(s.totalSize||0),0)}));function B(t){if(t==null)return"—";if(t===0)return"0 B";const s=["B","KB","MB","GB","TB"],e=Math.floor(Math.log(t)/Math.log(1024));return`${(t/Math.pow(1024,e)).toFixed(e===0?0:1)} ${s[e]}`}async function S(){try{const[t,s]=await Promise.all([R.listBuckets(),R.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);i.value=t;const e={};for(const f of s.buckets||[])e[f.name]=f.service;h.value=e,v.value=null}catch(t){v.value=t.message||"Failed to load buckets"}finally{d.value=!1}}function w(t){y.push(`/buckets/${encodeURIComponent(t)}`)}return D(()=>{S(),g=window.setInterval(S,1e4)}),I(()=>{g&&window.clearInterval(g)}),(t,s)=>(o(),u(n(C),{direction:"vertical",gap:"1.25rem"},{default:a(()=>[l(n(L),{columns:3,gap:"1rem"},{default:a(()=>[l(n(b),{label:"Buckets",value:k.value.buckets,tone:"info",loading:d.value},null,8,["value","loading"]),l(n(b),{label:"Objects",value:k.value.objects,tone:"success",loading:d.value},null,8,["value","loading"]),l(n(b),{label:"Total size",value:B(k.value.size),tone:"neutral",loading:d.value},null,8,["value","loading"])]),_:1}),v.value?(o(),u(n(O),{key:0,variant:"danger",dismissible:"",onDismiss:s[0]||(s[0]=e=>v.value=null)},{default:a(()=>[c(r(v.value),1)]),_:1})):T("",!0),l(n(E),{variant:"outline"},{header:a(()=>[l(n(C),{direction:"horizontal",gap:"0.5rem",align:"center",justify:"space-between"},{default:a(()=>[...s[1]||(s[1]=[_("strong",null,"S3 Buckets",-1),_("span",{class:"muted"},"Refreshes every 10s",-1)])]),_:1})]),default:a(()=>[d.value?(o(),z("div",A,[l(n(K),{label:"Loading buckets..."})])):i.value.length?(o(),u(n(F),{key:2,columns:$,rows:M.value},{"cell-name":a(({row:e})=>[_("a",{href:"#",style:{"text-decoration":"none","font-weight":"600"},onClick:q(f=>w(String(e.name)),["prevent"])},r(e.name),9,X)]),"cell-service":a(({row:e})=>[e.service?(o(),u(n(J),{key:0,to:`/services/${encodeURIComponent(String(e.service))}`,style:{"text-decoration":"none"}},{default:a(()=>[l(n(P),{size:"sm",variant:"soft",clickable:""},{default:a(()=>[c(r(e.service),1)]),_:2},1024)]),_:2},1032,["to"])):(o(),z("span",H,"unmanaged"))]),"cell-objectCount":a(({row:e})=>[l(n(p),{tone:"info",variant:"soft"},{default:a(()=>[c(r(e.objectCount??0),1)]),_:2},1024)]),"cell-totalSize":a(({row:e})=>[c(r(B(e.totalSize)),1)]),"cell-versioning":a(({row:e})=>[l(n(p),{tone:e.versioning?"success":"neutral",variant:"soft"},{default:a(()=>[c(r(e.versioning?"Enabled":"Disabled"),1)]),_:2},1032,["tone"])]),"cell-notifications":a(({row:e})=>[l(n(p),{tone:Number(e.notifications)>0?"info":"neutral",variant:"soft"},{default:a(()=>[c(r(e.notifications??0),1)]),_:2},1032,["tone"])]),"cell-actions":a(({row:e})=>[l(n(G),{size:"sm",variant:"ghost",onClick:f=>w(String(e.name))},{default:a(()=>[...s[2]||(s[2]=[c(" Open ",-1)])]),_:1},8,["onClick"])]),_:1},8,["rows"])):(o(),u(n(U),{key:1,title:"No buckets found",description:"Register a microservice that defines S3 resources or create buckets directly in LocalStack."}))]),_:1})]),_:1}))}}),Y=x({__name:"BucketsPage",setup(V){return(y,i)=>(o(),u(Q))}});export{Y as default};
@@ -1 +1 @@
1
- import{o as A,v as j,u as F,w as n,i,G as s,f as C,S as a,n as o,D as q,s as N,b as H,m as r,E as u,j as f,K as J,k as y,R as W,J as P,V as Q,A as X,B as p,_ as I,a as Y,h as L,p as Z,y as g,g as B,d as T,L as ee}from"./index-D3WwZ4lY.js";const te={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},se=["onClick"],ae={key:1},ne={class:"muted mono",style:{"font-size":"0.75rem"}},le={key:1,class:"muted",style:{"font-size":"0.75rem"}},ie={key:1,class:"muted",style:{"font-size":"0.75rem"}},oe={key:1,class:"muted",style:{"font-size":"0.75rem"}},re=A({__name:"DynamoTablesList",emits:["open"],setup(M,{emit:D}){const w=D,d=g([]),b=g([]),R=g({}),c=g(!0),k=g(null),h=g("");let z=null;const U=[{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"}],S=B(()=>{const l=d.value.map(e=>{var G,K;const t=(G=e.keySchema.find(_=>_.KeyType==="HASH"))==null?void 0:G.AttributeName,m=(K=e.keySchema.find(_=>_.KeyType==="RANGE"))==null?void 0:K.AttributeName,x=m?`PK: ${t} · SK: ${m}`:`PK: ${t??"—"}`,O=b.value.find(_=>_.tableName===e.name);return{name:e.name,status:e.status,itemCount:e.itemCount||0,keyDescriptor:x,billingMode:e.billingMode,ttlOn:e.ttl.enabled,streamOn:e.streamEnabled,hasGsi:e.hasGsi,hasLsi:e.hasLsi,service:R.value[e.name]||"",seedItemCount:O?O.itemCount:null,exists:!0}});for(const e of b.value)!e.tableExists&&!l.some(t=>t.name===e.tableName)&&l.push({name:e.tableName,status:"PENDING",itemCount:0,keyDescriptor:"—",ttlOn:!1,streamOn:!1,hasGsi:!1,hasLsi:!1,service:R.value[e.tableName]||"",seedItemCount:e.itemCount,exists:!1});return l.sort((e,t)=>e.name.localeCompare(t.name))}),E=B(()=>{const l=h.value.trim().toLowerCase();return l?S.value.filter(e=>e.name.toLowerCase().includes(l)||(e.service||"").toLowerCase().includes(l)):S.value}),v=B(()=>({tables:d.value.length,items:d.value.reduce((l,e)=>l+(e.itemCount||0),0),warnings:d.value.reduce((l,e)=>{var t;return l+(((t=e.warnings)==null?void 0:t.length)||0)},0),seedsPending:b.value.filter(l=>!l.tableExists).length}));async function V(){try{const[l,e,t]=await Promise.all([T.listDynamoTables(),T.listSeeds().catch(()=>({seedsDir:"",entries:[]})),T.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);d.value=l.tables,b.value=e.entries;const m={};for(const x of t.tables)m[x.name]=x.service;R.value=m,k.value=null}catch(l){k.value=l.message||"Failed to load DynamoDB tables"}finally{c.value=!1}}function $(l){l.exists&&w("open",l.name)}return j(()=>{V(),z=window.setInterval(V,15e3)}),F(()=>{z&&window.clearInterval(z)}),(l,e)=>(n(),i(s(C),{direction:"vertical",gap:"1.25rem"},{default:a(()=>[o(s(q),{columns:4,gap:"1rem"},{default:a(()=>[o(s(N),{label:"Tables",value:v.value.tables,tone:"info",loading:c.value},null,8,["value","loading"]),o(s(N),{label:"Total items",value:v.value.items,tone:"success",loading:c.value},null,8,["value","loading"]),o(s(N),{label:"Seeds pending",value:v.value.seedsPending,tone:v.value.seedsPending>0?"warning":"neutral",loading:c.value},null,8,["value","tone","loading"]),o(s(N),{label:"Warnings",value:v.value.warnings,tone:v.value.warnings>0?"warning":"neutral",loading:c.value},null,8,["value","tone","loading"])]),_:1}),k.value?(n(),i(s(H),{key:0,variant:"danger",dismissible:"",onDismiss:e[0]||(e[0]=t=>k.value=null)},{default:a(()=>[r(u(k.value),1)]),_:1})):f("",!0),o(s(J),{variant:"outline"},{header:a(()=>[o(s(C),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:a(()=>[e[3]||(e[3]=L("strong",null,"DynamoDB tables",-1)),o(s(C),{direction:"horizontal",align:"center",gap:"1rem"},{default:a(()=>[o(s(Z),{modelValue:h.value,"onUpdate:modelValue":e[1]||(e[1]=t=>h.value=t),placeholder:"Filter tables...",style:{"min-width":"16rem"}},null,8,["modelValue"]),e[2]||(e[2]=L("span",{class:"muted",style:{"font-size":"0.75rem"}}," Rows with reduced opacity exist only as a seed file ",-1))]),_:1})]),_:1})]),default:a(()=>[c.value?(n(),y("div",te,[o(s(W),{label:"Loading tables..."})])):S.value.length?E.value.length?(n(),i(s(Q),{key:3,columns:U,rows:E.value,"row-class":t=>t.exists?"":"dim-row"},{"cell-name":a(({row:t})=>[o(s(C),{direction:"vertical",gap:"0.125rem"},{default:a(()=>[t.exists?(n(),y("strong",{key:0,style:{cursor:"pointer","text-decoration":"underline","text-decoration-style":"dotted","text-underline-offset":"3px"},onClick:m=>$(t)},u(t.name),9,se)):(n(),y("strong",ae,u(t.name),1)),L("span",ne,u(t.keyDescriptor),1)]),_:2},1024)]),"cell-service":a(({row:t})=>[t.service?(n(),i(s(Y),{key:0,to:`/services/${encodeURIComponent(String(t.service))}`,style:{"text-decoration":"none"}},{default:a(()=>[o(s(p),{size:"sm",variant:"soft",clickable:""},{default:a(()=>[r(u(t.service),1)]),_:2},1024)]),_:2},1032,["to"])):(n(),y("span",le,"—"))]),"cell-status":a(({row:t})=>[t.exists?(n(),i(s(I),{key:0,tone:t.status==="ACTIVE"?"success":"warning",variant:"soft"},{default:a(()=>[r(u(t.status||"UNKNOWN"),1)]),_:2},1032,["tone"])):(n(),i(s(I),{key:1,tone:"warning",variant:"outline"},{default:a(()=>[...e[4]||(e[4]=[r("Not created",-1)])]),_:1}))]),"cell-itemCount":a(({row:t})=>[r(u(t.exists?t.itemCount:"—"),1)]),"cell-seed":a(({row:t})=>[t.seedItemCount!==null?(n(),i(s(I),{key:0,tone:t.exists?"info":"warning",variant:"soft"},{default:a(()=>[r(u(t.seedItemCount)+" seeded item"+u(t.seedItemCount===1?"":"s"),1)]),_:2},1032,["tone"])):(n(),y("span",ie,"no seed"))]),"cell-features":a(({row:t})=>[o(s(C),{direction:"horizontal",gap:"0.25rem",wrap:""},{default:a(()=>[t.billingMode?(n(),i(s(p),{key:0,size:"sm",variant:"soft"},{default:a(()=>[r(u(t.billingMode),1)]),_:2},1024)):f("",!0),t.ttlOn?(n(),i(s(p),{key:1,size:"sm",variant:"solid"},{default:a(()=>[...e[5]||(e[5]=[r("TTL",-1)])]),_:1})):f("",!0),t.streamOn?(n(),i(s(p),{key:2,size:"sm",variant:"solid"},{default:a(()=>[...e[6]||(e[6]=[r("Streams",-1)])]),_:1})):f("",!0),t.hasGsi?(n(),i(s(p),{key:3,size:"sm",variant:"soft"},{default:a(()=>[...e[7]||(e[7]=[r("GSI",-1)])]),_:1})):f("",!0),t.hasLsi?(n(),i(s(p),{key:4,size:"sm",variant:"soft"},{default:a(()=>[...e[8]||(e[8]=[r("LSI",-1)])]),_:1})):f("",!0)]),_:2},1024)]),"cell-actions":a(({row:t})=>[t.exists?(n(),i(s(X),{key:0,size:"sm",variant:"soft",onClick:m=>$(t)},{default:a(()=>[...e[9]||(e[9]=[r(" Explore ",-1)])]),_:1},8,["onClick"])):(n(),y("span",oe," Register service to provision "))]),_:1},8,["rows","row-class"])):(n(),i(s(P),{key:2,title:"No matching tables",description:`No tables match "${h.value}".`},null,8,["description"])):(n(),i(s(P),{key:1,title:"No DynamoDB tables",description:"Register a microservice with DynamoDB resources or drop a seed file into the seeds directory."}))]),_:1})]),_:1}))}}),de=A({__name:"DynamoPage",setup(M){const D=ee();function w(d){D.push(`/dynamo/${encodeURIComponent(d)}`)}return(d,b)=>(n(),i(re,{onOpen:w}))}});export{de as default};
1
+ import{o as A,v as j,u as F,w as n,i,G as s,f as C,S as a,n as o,D as q,s as N,b as H,m as r,E as u,j as f,K as J,k as y,R as W,J as P,V as Q,A as X,B as p,_ as I,a as Y,h as L,p as Z,y as g,g as B,d as T,L as ee}from"./index-BWlB542w.js";const te={key:0,style:{display:"flex","justify-content":"center",padding:"2rem"}},se=["onClick"],ae={key:1},ne={class:"muted mono",style:{"font-size":"0.75rem"}},le={key:1,class:"muted",style:{"font-size":"0.75rem"}},ie={key:1,class:"muted",style:{"font-size":"0.75rem"}},oe={key:1,class:"muted",style:{"font-size":"0.75rem"}},re=A({__name:"DynamoTablesList",emits:["open"],setup(M,{emit:D}){const w=D,d=g([]),b=g([]),R=g({}),c=g(!0),k=g(null),h=g("");let z=null;const U=[{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"}],S=B(()=>{const l=d.value.map(e=>{var G,K;const t=(G=e.keySchema.find(_=>_.KeyType==="HASH"))==null?void 0:G.AttributeName,m=(K=e.keySchema.find(_=>_.KeyType==="RANGE"))==null?void 0:K.AttributeName,x=m?`PK: ${t} · SK: ${m}`:`PK: ${t??"—"}`,O=b.value.find(_=>_.tableName===e.name);return{name:e.name,status:e.status,itemCount:e.itemCount||0,keyDescriptor:x,billingMode:e.billingMode,ttlOn:e.ttl.enabled,streamOn:e.streamEnabled,hasGsi:e.hasGsi,hasLsi:e.hasLsi,service:R.value[e.name]||"",seedItemCount:O?O.itemCount:null,exists:!0}});for(const e of b.value)!e.tableExists&&!l.some(t=>t.name===e.tableName)&&l.push({name:e.tableName,status:"PENDING",itemCount:0,keyDescriptor:"—",ttlOn:!1,streamOn:!1,hasGsi:!1,hasLsi:!1,service:R.value[e.tableName]||"",seedItemCount:e.itemCount,exists:!1});return l.sort((e,t)=>e.name.localeCompare(t.name))}),E=B(()=>{const l=h.value.trim().toLowerCase();return l?S.value.filter(e=>e.name.toLowerCase().includes(l)||(e.service||"").toLowerCase().includes(l)):S.value}),v=B(()=>({tables:d.value.length,items:d.value.reduce((l,e)=>l+(e.itemCount||0),0),warnings:d.value.reduce((l,e)=>{var t;return l+(((t=e.warnings)==null?void 0:t.length)||0)},0),seedsPending:b.value.filter(l=>!l.tableExists).length}));async function V(){try{const[l,e,t]=await Promise.all([T.listDynamoTables(),T.listSeeds().catch(()=>({seedsDir:"",entries:[]})),T.listResourceOwners().catch(()=>({tables:[],queues:[],topics:[],buckets:[]}))]);d.value=l.tables,b.value=e.entries;const m={};for(const x of t.tables)m[x.name]=x.service;R.value=m,k.value=null}catch(l){k.value=l.message||"Failed to load DynamoDB tables"}finally{c.value=!1}}function $(l){l.exists&&w("open",l.name)}return j(()=>{V(),z=window.setInterval(V,15e3)}),F(()=>{z&&window.clearInterval(z)}),(l,e)=>(n(),i(s(C),{direction:"vertical",gap:"1.25rem"},{default:a(()=>[o(s(q),{columns:4,gap:"1rem"},{default:a(()=>[o(s(N),{label:"Tables",value:v.value.tables,tone:"info",loading:c.value},null,8,["value","loading"]),o(s(N),{label:"Total items",value:v.value.items,tone:"success",loading:c.value},null,8,["value","loading"]),o(s(N),{label:"Seeds pending",value:v.value.seedsPending,tone:v.value.seedsPending>0?"warning":"neutral",loading:c.value},null,8,["value","tone","loading"]),o(s(N),{label:"Warnings",value:v.value.warnings,tone:v.value.warnings>0?"warning":"neutral",loading:c.value},null,8,["value","tone","loading"])]),_:1}),k.value?(n(),i(s(H),{key:0,variant:"danger",dismissible:"",onDismiss:e[0]||(e[0]=t=>k.value=null)},{default:a(()=>[r(u(k.value),1)]),_:1})):f("",!0),o(s(J),{variant:"outline"},{header:a(()=>[o(s(C),{direction:"horizontal",justify:"space-between",align:"center",gap:"1rem"},{default:a(()=>[e[3]||(e[3]=L("strong",null,"DynamoDB tables",-1)),o(s(C),{direction:"horizontal",align:"center",gap:"1rem"},{default:a(()=>[o(s(Z),{modelValue:h.value,"onUpdate:modelValue":e[1]||(e[1]=t=>h.value=t),placeholder:"Filter tables...",style:{"min-width":"16rem"}},null,8,["modelValue"]),e[2]||(e[2]=L("span",{class:"muted",style:{"font-size":"0.75rem"}}," Rows with reduced opacity exist only as a seed file ",-1))]),_:1})]),_:1})]),default:a(()=>[c.value?(n(),y("div",te,[o(s(W),{label:"Loading tables..."})])):S.value.length?E.value.length?(n(),i(s(Q),{key:3,columns:U,rows:E.value,"row-class":t=>t.exists?"":"dim-row"},{"cell-name":a(({row:t})=>[o(s(C),{direction:"vertical",gap:"0.125rem"},{default:a(()=>[t.exists?(n(),y("strong",{key:0,style:{cursor:"pointer","text-decoration":"underline","text-decoration-style":"dotted","text-underline-offset":"3px"},onClick:m=>$(t)},u(t.name),9,se)):(n(),y("strong",ae,u(t.name),1)),L("span",ne,u(t.keyDescriptor),1)]),_:2},1024)]),"cell-service":a(({row:t})=>[t.service?(n(),i(s(Y),{key:0,to:`/services/${encodeURIComponent(String(t.service))}`,style:{"text-decoration":"none"}},{default:a(()=>[o(s(p),{size:"sm",variant:"soft",clickable:""},{default:a(()=>[r(u(t.service),1)]),_:2},1024)]),_:2},1032,["to"])):(n(),y("span",le,"—"))]),"cell-status":a(({row:t})=>[t.exists?(n(),i(s(I),{key:0,tone:t.status==="ACTIVE"?"success":"warning",variant:"soft"},{default:a(()=>[r(u(t.status||"UNKNOWN"),1)]),_:2},1032,["tone"])):(n(),i(s(I),{key:1,tone:"warning",variant:"outline"},{default:a(()=>[...e[4]||(e[4]=[r("Not created",-1)])]),_:1}))]),"cell-itemCount":a(({row:t})=>[r(u(t.exists?t.itemCount:"—"),1)]),"cell-seed":a(({row:t})=>[t.seedItemCount!==null?(n(),i(s(I),{key:0,tone:t.exists?"info":"warning",variant:"soft"},{default:a(()=>[r(u(t.seedItemCount)+" seeded item"+u(t.seedItemCount===1?"":"s"),1)]),_:2},1032,["tone"])):(n(),y("span",ie,"no seed"))]),"cell-features":a(({row:t})=>[o(s(C),{direction:"horizontal",gap:"0.25rem",wrap:""},{default:a(()=>[t.billingMode?(n(),i(s(p),{key:0,size:"sm",variant:"soft"},{default:a(()=>[r(u(t.billingMode),1)]),_:2},1024)):f("",!0),t.ttlOn?(n(),i(s(p),{key:1,size:"sm",variant:"solid"},{default:a(()=>[...e[5]||(e[5]=[r("TTL",-1)])]),_:1})):f("",!0),t.streamOn?(n(),i(s(p),{key:2,size:"sm",variant:"solid"},{default:a(()=>[...e[6]||(e[6]=[r("Streams",-1)])]),_:1})):f("",!0),t.hasGsi?(n(),i(s(p),{key:3,size:"sm",variant:"soft"},{default:a(()=>[...e[7]||(e[7]=[r("GSI",-1)])]),_:1})):f("",!0),t.hasLsi?(n(),i(s(p),{key:4,size:"sm",variant:"soft"},{default:a(()=>[...e[8]||(e[8]=[r("LSI",-1)])]),_:1})):f("",!0)]),_:2},1024)]),"cell-actions":a(({row:t})=>[t.exists?(n(),i(s(X),{key:0,size:"sm",variant:"soft",onClick:m=>$(t)},{default:a(()=>[...e[9]||(e[9]=[r(" Explore ",-1)])]),_:1},8,["onClick"])):(n(),y("span",oe," Register service to provision "))]),_:1},8,["rows","row-class"])):(n(),i(s(P),{key:2,title:"No matching tables",description:`No tables match "${h.value}".`},null,8,["description"])):(n(),i(s(P),{key:1,title:"No DynamoDB tables",description:"Register a microservice with DynamoDB resources or drop a seed file into the seeds directory."}))]),_:1})]),_:1}))}}),de=A({__name:"DynamoPage",setup(M){const D=ee();function w(d){D.push(`/dynamo/${encodeURIComponent(d)}`)}return(d,b)=>(n(),i(re,{onOpen:w}))}});export{de as default};