@dbx-tools/appkit 0.9.73 → 0.9.79

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.
package/README.md CHANGED
@@ -131,6 +131,11 @@ one-time code) is lost on every restart. `"env"` is the right mode inside a
131
131
  deployed app, since the app service principal cannot grant on the cache schema
132
132
  anyway.
133
133
 
134
+ The injected persistent storage includes a bounded process-local L1 powered by
135
+ `lru-cache`. Warm hits avoid Lakebase reads and `last_accessed` writes; misses,
136
+ expiry, deletion, and clear operations remain coherent with the persistent
137
+ store.
138
+
134
139
  `lakebaseResolver.resolveLakebaseConnection()` accepts:
135
140
 
136
141
  | Option | Type | Default | Description |
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
6
- export const PACKAGE_VERSION = "0.9.73";
6
+ export const PACKAGE_VERSION = "0.9.79";
7
7
  export * as appkit from "./src/appkit.ts";
8
8
  export * as brandContext from "./src/brand-context.ts";
9
9
  export * as bundle from "./src/bundle.ts";
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
2
- export declare const PACKAGE_VERSION = "0.9.73";
2
+ export declare const PACKAGE_VERSION = "0.9.79";
3
3
  export * as appkit from "./src/appkit.ts";
4
4
  export * as brandContext from "./src/brand-context.ts";
5
5
  export * as bundle from "./src/bundle.ts";
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
5
- export const PACKAGE_VERSION = "0.9.73";
5
+ export const PACKAGE_VERSION = "0.9.79";
6
6
  export * as appkit from "./src/appkit.js";
7
7
  export * as brandContext from "./src/brand-context.js";
8
8
  export * as bundle from "./src/bundle.js";
@@ -25,4 +25,4 @@ export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER, IDENTITY_MODES,
25
25
  export { LifecycleBridgePlugin, lifecycleBridge } from "./src/interceptor.js";
26
26
  export { SSL_MODES } from "./src/pgaddress.js";
27
27
  export { ToolRegistryPlugin } from "./src/tool-provider.js";
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxXQUFXLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssZUFBZSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sS0FBSyxjQUFjLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLGNBQWMsTUFBTSwwQkFBMEIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzVELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEksT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBSTlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUsvQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9WRVJTSU9OID0gXCIwLjkuNzNcIjtcbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBicmFuZENvbnRleHQgZnJvbSBcIi4vc3JjL2JyYW5kLWNvbnRleHQudHNcIjtcbmV4cG9ydCAqIGFzIGJ1bmRsZSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgKiBhcyBjaGlsZFByb2Nlc3MgZnJvbSBcIi4vc3JjL2NoaWxkLXByb2Nlc3MudHNcIjtcbmV4cG9ydCAqIGFzIGRhdGFicmlja3MgZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCAqIGFzIGlkZW50aXR5IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0ICogYXMgaW50ZXJjZXB0b3IgZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgKiBhcyBsYWtlYmFzZVJlc29sdmVyIGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0ICogYXMgbWlncmF0aW9uIGZyb20gXCIuL3NyYy9taWdyYXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBnYWRkcmVzcyBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW5FeGVjdXRpb24gZnJvbSBcIi4vc3JjL3BsdWdpbi1leGVjdXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpblJlZ2lzdHJ5IGZyb20gXCIuL3NyYy9wbHVnaW4tcmVnaXN0cnkudHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgKiBhcyByZXF1ZXN0VGFncyBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgKiBhcyB0b29sUHJvdmlkZXIgZnJvbSBcIi4vc3JjL3Rvb2wtcHJvdmlkZXIudHNcIjtcbmV4cG9ydCAqIGFzIHRvb2xraXRFbnRyaWVzIGZyb20gXCIuL3NyYy90b29sa2l0LWVudHJpZXMudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0b0NvbmZpZ3VyZU1vZGUsIENyZWF0ZUFwcENvbmZpZywgRXhlY3V0aW9uQ29udGV4dExpa2UsIFdvcmtzcGFjZUNsaWVudExpa2UgfSBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgeyBidW5kbGVBcHBSZXNvdXJjZVNjaGVtYSwgZmxhdHRlbkFwcFlhbWxFbnYsIGZsYXR0ZW5BcHBFbnYsIGdldEJ1bmRsZVBhdGggfSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEJ1bmRsZVZhbGlkYXRlSnNvbiwgQ29uZmlnRmlsZSwgQ29uZmlnTWFwVmFsdWUsIENvbmZpZ1NvdXJjZSwgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9idW5kbGUudHNcIjtcbmV4cG9ydCB7IEFwcEtpdENoaWxkUHJvY2VzcyB9IGZyb20gXCIuL3NyYy9jaGlsZC1wcm9jZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IEFwcEtpdFNwYXduQXJncywgQXBwS2l0Q2hpbGRQcm9jZXNzSGVhbHRoQ2hlY2tDb250ZXh0LCBBcHBLaXRDaGlsZFByb2Nlc3NIZWFsdGhDaGVjaywgQXBwS2l0Q2hpbGRQcm9jZXNzT3B0aW9ucywgQXBwS2l0Q2hpbGRQcm9jZXNzUnVuT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jaGlsZC1wcm9jZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IENvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB7IEFDQ0VTU19UT0tFTl9IRUFERVIsIFVTRVJfSURfSEVBREVSLCBVU0VSX0VNQUlMX0hFQURFUiwgSURFTlRJVFlfTU9ERVMsIERFRkFVTFRfSURFTlRJVFlfTU9ERSB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHR5cGUgeyBJZGVudGl0eU1vZGUsIEhlYWRlckJlYXJpbmcgfSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCB7IExpZmVjeWNsZUJyaWRnZVBsdWdpbiwgbGlmZWN5Y2xlQnJpZGdlIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExpZmVjeWNsZUV2ZW50LCBMaWZlY3ljbGVIYW5kbGVyLCBSZXNvbHZlZEFwcEVudiwgSW50ZXJjZXB0b3JDb250ZXh0LCBJbnRlcmNlcHRvciwgSW50ZXJjZXB0b3JSdW50aW1lIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2ViYXNlUmVzb2x2ZXJJbnB1dHMsIExha2ViYXNlQ29ubmVjdGlvbiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBPd25lcnNoaXBNaWdyYXRpb25FcnJvck9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgeyBTU0xfTU9ERVMgfSBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFNzbE1vZGUsIFBhcnNlZEFkZHJlc3MsIExha2ViYXNlQ29ubmVjdGlvbklucHV0cyB9IGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgUnVuUGx1Z2luRXhlY3V0aW9uT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9wbHVnaW4tZXhlY3V0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi1yZWdpc3RyeS50c1wiO1xuZXhwb3J0IHR5cGUgeyBSZXF1ZXN0VGFnVmFsdWUgfSBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgeyBUb29sUmVnaXN0cnlQbHVnaW4gfSBmcm9tIFwiLi9zcmMvdG9vbC1wcm92aWRlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBBZ2VudFRvb2xFeGVjdXRpb25Db250ZXh0IH0gZnJvbSBcIi4vc3JjL3Rvb2wtcHJvdmlkZXIudHNcIjtcbiJdfQ==
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxXQUFXLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssZUFBZSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sS0FBSyxjQUFjLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLGNBQWMsTUFBTSwwQkFBMEIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzVELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbEksT0FBTyxFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBSTlFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUsvQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9WRVJTSU9OID0gXCIwLjkuNzlcIjtcbmV4cG9ydCAqIGFzIGFwcGtpdCBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgKiBhcyBicmFuZENvbnRleHQgZnJvbSBcIi4vc3JjL2JyYW5kLWNvbnRleHQudHNcIjtcbmV4cG9ydCAqIGFzIGJ1bmRsZSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgKiBhcyBjaGlsZFByb2Nlc3MgZnJvbSBcIi4vc3JjL2NoaWxkLXByb2Nlc3MudHNcIjtcbmV4cG9ydCAqIGFzIGRhdGFicmlja3MgZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCAqIGFzIGlkZW50aXR5IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0ICogYXMgaW50ZXJjZXB0b3IgZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgKiBhcyBsYWtlYmFzZVJlc29sdmVyIGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0ICogYXMgbWlncmF0aW9uIGZyb20gXCIuL3NyYy9taWdyYXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBnYWRkcmVzcyBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW5FeGVjdXRpb24gZnJvbSBcIi4vc3JjL3BsdWdpbi1leGVjdXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpblJlZ2lzdHJ5IGZyb20gXCIuL3NyYy9wbHVnaW4tcmVnaXN0cnkudHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgKiBhcyByZXF1ZXN0VGFncyBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgKiBhcyB0b29sUHJvdmlkZXIgZnJvbSBcIi4vc3JjL3Rvb2wtcHJvdmlkZXIudHNcIjtcbmV4cG9ydCAqIGFzIHRvb2xraXRFbnRyaWVzIGZyb20gXCIuL3NyYy90b29sa2l0LWVudHJpZXMudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0b0NvbmZpZ3VyZU1vZGUsIENyZWF0ZUFwcENvbmZpZywgRXhlY3V0aW9uQ29udGV4dExpa2UsIFdvcmtzcGFjZUNsaWVudExpa2UgfSBmcm9tIFwiLi9zcmMvYXBwa2l0LnRzXCI7XG5leHBvcnQgeyBidW5kbGVBcHBSZXNvdXJjZVNjaGVtYSwgZmxhdHRlbkFwcFlhbWxFbnYsIGZsYXR0ZW5BcHBFbnYsIGdldEJ1bmRsZVBhdGggfSBmcm9tIFwiLi9zcmMvYnVuZGxlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEJ1bmRsZVZhbGlkYXRlSnNvbiwgQ29uZmlnRmlsZSwgQ29uZmlnTWFwVmFsdWUsIENvbmZpZ1NvdXJjZSwgUmVzb2x2ZUNvbmZpZ1ZhbHVlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9idW5kbGUudHNcIjtcbmV4cG9ydCB7IEFwcEtpdENoaWxkUHJvY2VzcyB9IGZyb20gXCIuL3NyYy9jaGlsZC1wcm9jZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IEFwcEtpdFNwYXduQXJncywgQXBwS2l0Q2hpbGRQcm9jZXNzSGVhbHRoQ2hlY2tDb250ZXh0LCBBcHBLaXRDaGlsZFByb2Nlc3NIZWFsdGhDaGVjaywgQXBwS2l0Q2hpbGRQcm9jZXNzT3B0aW9ucywgQXBwS2l0Q2hpbGRQcm9jZXNzUnVuT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jaGlsZC1wcm9jZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IENvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB7IEFDQ0VTU19UT0tFTl9IRUFERVIsIFVTRVJfSURfSEVBREVSLCBVU0VSX0VNQUlMX0hFQURFUiwgSURFTlRJVFlfTU9ERVMsIERFRkFVTFRfSURFTlRJVFlfTU9ERSB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHR5cGUgeyBJZGVudGl0eU1vZGUsIEhlYWRlckJlYXJpbmcgfSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCB7IExpZmVjeWNsZUJyaWRnZVBsdWdpbiwgbGlmZWN5Y2xlQnJpZGdlIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExpZmVjeWNsZUV2ZW50LCBMaWZlY3ljbGVIYW5kbGVyLCBSZXNvbHZlZEFwcEVudiwgSW50ZXJjZXB0b3JDb250ZXh0LCBJbnRlcmNlcHRvciwgSW50ZXJjZXB0b3JSdW50aW1lIH0gZnJvbSBcIi4vc3JjL2ludGVyY2VwdG9yLnRzXCI7XG5leHBvcnQgdHlwZSB7IExha2ViYXNlUmVzb2x2ZXJJbnB1dHMsIExha2ViYXNlQ29ubmVjdGlvbiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBPd25lcnNoaXBNaWdyYXRpb25FcnJvck9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgeyBTU0xfTU9ERVMgfSBmcm9tIFwiLi9zcmMvcGdhZGRyZXNzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFNzbE1vZGUsIFBhcnNlZEFkZHJlc3MsIExha2ViYXNlQ29ubmVjdGlvbklucHV0cyB9IGZyb20gXCIuL3NyYy9wZ2FkZHJlc3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgUnVuUGx1Z2luRXhlY3V0aW9uT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9wbHVnaW4tZXhlY3V0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi1yZWdpc3RyeS50c1wiO1xuZXhwb3J0IHR5cGUgeyBSZXF1ZXN0VGFnVmFsdWUgfSBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgeyBUb29sUmVnaXN0cnlQbHVnaW4gfSBmcm9tIFwiLi9zcmMvdG9vbC1wcm92aWRlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBBZ2VudFRvb2xFeGVjdXRpb25Db250ZXh0IH0gZnJvbSBcIi4vc3JjL3Rvb2wtcHJvdmlkZXIudHNcIjtcbiJdfQ==
@@ -16,6 +16,15 @@
16
16
  import { createLakebasePool, type CacheConfig } from "@databricks/appkit";
17
17
  type LakebasePool = ReturnType<typeof createLakebasePool>;
18
18
  type CacheStorage = NonNullable<CacheConfig["storage"]>;
19
+ interface CacheEntry<T = unknown> {
20
+ expiry: number;
21
+ value: T;
22
+ }
23
+ /** Bounds for the process-local cache layered over persistent AppKit storage. */
24
+ export interface L1CacheStorageOptions {
25
+ maxBytes?: number;
26
+ maxEntries?: number;
27
+ }
19
28
  /** AppKit's internal persistent storage surface. */
20
29
  export type PersistentStorageBase = CacheStorage & {
21
30
  initialize(): Promise<void>;
@@ -24,6 +33,22 @@ export type PersistentStorageBase = CacheStorage & {
24
33
  tableName?: string;
25
34
  };
26
35
  type PersistentStorageConstructor = new (config: CacheConfig, pool: LakebasePool) => PersistentStorageBase;
36
+ /** Process-local LRU that avoids a persistent cache query on every warm hit. */
37
+ export declare class L1CacheStorage implements CacheStorage {
38
+ private readonly storage;
39
+ private readonly entries;
40
+ constructor(storage: CacheStorage, options?: L1CacheStorageOptions);
41
+ get<T>(key: string): Promise<CacheEntry<T> | null>;
42
+ set<T>(key: string, entry: CacheEntry<T>): Promise<void>;
43
+ delete(key: string): Promise<void>;
44
+ clear(): Promise<void>;
45
+ has(key: string): Promise<boolean>;
46
+ size(): Promise<number>;
47
+ isPersistent(): boolean;
48
+ healthCheck(): Promise<boolean>;
49
+ close(): Promise<void>;
50
+ private retain;
51
+ }
27
52
  /**
28
53
  * Lazily resolve AppKit's internal `PersistentStorage` constructor. `null`
29
54
  * means not attempted yet; `undefined` means the lookup already failed.
@@ -18,9 +18,82 @@ import { dirname, join } from "node:path";
18
18
  import { createLakebasePool, getWorkspaceClient } from "@databricks/appkit";
19
19
  import { postgresConnectionOptions } from "@dbx-tools/postgres";
20
20
  import { errorUtils, hash, log } from "@dbx-tools/shared-core";
21
+ import { LRUCache } from "lru-cache";
21
22
  import { handleOwnershipMigrationError } from "./migration.js";
22
23
  const logger = log.logger("cache-storage");
23
24
  let persistentStorageCtor = null;
25
+ /** Process-local LRU that avoids a persistent cache query on every warm hit. */
26
+ export class L1CacheStorage {
27
+ storage;
28
+ entries;
29
+ constructor(storage, options = {}) {
30
+ this.storage = storage;
31
+ this.entries = new LRUCache({
32
+ max: positiveBound(options.maxEntries, 1_000, "maxEntries"),
33
+ maxSize: positiveBound(options.maxBytes, 64 * 1024 * 1024, "maxBytes"),
34
+ sizeCalculation: (entry, key) => retainedSize(key, entry),
35
+ });
36
+ }
37
+ async get(key) {
38
+ const local = this.entries.get(key);
39
+ if (local)
40
+ return local;
41
+ const persisted = await this.storage.get(key);
42
+ if (persisted && persisted.expiry > Date.now())
43
+ this.retain(key, persisted);
44
+ return persisted;
45
+ }
46
+ async set(key, entry) {
47
+ await this.storage.set(key, entry);
48
+ this.retain(key, entry);
49
+ }
50
+ async delete(key) {
51
+ await this.storage.delete(key);
52
+ this.entries.delete(key);
53
+ }
54
+ async clear() {
55
+ await this.storage.clear();
56
+ this.entries.clear();
57
+ }
58
+ async has(key) {
59
+ if (this.entries.has(key))
60
+ return true;
61
+ return this.storage.has(key);
62
+ }
63
+ size() {
64
+ return this.storage.size();
65
+ }
66
+ isPersistent() {
67
+ return this.storage.isPersistent();
68
+ }
69
+ healthCheck() {
70
+ return this.storage.healthCheck();
71
+ }
72
+ async close() {
73
+ this.entries.clear();
74
+ await this.storage.close();
75
+ }
76
+ retain(key, entry) {
77
+ const ttl = entry.expiry - Date.now();
78
+ if (ttl > 0)
79
+ this.entries.set(key, entry, { ttl });
80
+ }
81
+ }
82
+ function positiveBound(value, fallback, name) {
83
+ const resolved = value ?? fallback;
84
+ if (!Number.isFinite(resolved) || resolved <= 0) {
85
+ throw new RangeError(`${name} must be a finite positive number`);
86
+ }
87
+ return Math.floor(resolved);
88
+ }
89
+ function retainedSize(key, entry) {
90
+ try {
91
+ return Buffer.byteLength(key) + Buffer.byteLength(JSON.stringify(entry));
92
+ }
93
+ catch {
94
+ return Number.MAX_SAFE_INTEGER;
95
+ }
96
+ }
24
97
  /**
25
98
  * Lazily resolve AppKit's internal `PersistentStorage` constructor. `null`
26
99
  * means not attempted yet; `undefined` means the lookup already failed.
@@ -139,7 +212,10 @@ export async function createSoftPersistentStorage(cache) {
139
212
  }
140
213
  await storage.initialize();
141
214
  await probeStorage(storage);
142
- return storage;
215
+ return new L1CacheStorage(storage, {
216
+ maxBytes: cache?.maxBytes,
217
+ maxEntries: cache?.maxSize,
218
+ });
143
219
  }
144
220
  catch (err) {
145
221
  logger.debug("soft persistent cache unavailable", {
@@ -151,4 +227,4 @@ export async function createSoftPersistentStorage(cache) {
151
227
  return undefined;
152
228
  }
153
229
  }
154
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2NhY2hlLXN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX2NhY2hlLXN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFFSCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUvRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBa0IzQyxJQUFJLHFCQUFxQixHQUFvRCxJQUFJLENBQUM7QUFFbEY7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxJQUFJLHFCQUFxQixLQUFLLElBQUksRUFBRSxDQUFDO1FBQ25DLE9BQU8scUJBQXFCLENBQUM7SUFDL0IsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FDckIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxFQUM5Qyw2QkFBNkIsQ0FDOUIsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxpQkFDTyxDQUFDO1FBQzNDLElBQUksT0FBTyxN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O1lBQ25DLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztZQUN0QyxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBQ0QsTUFBTSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDM0IsTUFBTSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUIsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixNQUFNLENBQUMsS0FBSyxDQUFDLG1DQUFtQyxFQUFFO1lBQ2hELEtBQUssRUFBRSxVQUFVLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQztTQUNwQyxDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsTUFBTSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ25DLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU29mdC1mYWlsIExha2ViYXNlIGNhY2hlIHN0b3JhZ2UgZm9yIEFwcEtpdCdzIHBlcnNpc3RlbnQgY2FjaGUuXG4gKlxuICogQXBwS2l0J3MgYFBlcnNpc3RlbnRTdG9yYWdlLmluaXRpYWxpemUoKWAgcnVucyBEREwgbWlncmF0aW9ucyBhbmQgdGhyb3dzIG9uXG4gKiBhbnkgc3RlcCBmYWlsdXJlLiBXaXRoIGBjYWNoZS5zdHJpY3RQZXJzaXN0ZW5jZTogdHJ1ZWAgdGhhdCB0aHJvdyBtYWtlc1xuICogYENhY2hlTWFuYWdlcmAgc2lsZW50bHkgZGlzYWJsZSB0aGUgY2FjaGUuIFRoaXMgd3JhcHMgdGhlIHNhbWUgc3RvcmFnZSxcbiAqIHN0aWxsIHJ1bnMgaXRzIG1pZ3JhdGlvbnMsIGJ1dCBsb2dzIGEgZmFpbGVkIHN0ZXAgaW5zdGVhZCBvZiB0aHJvd2luZyBzbyBhXG4gKiB1c2FibGUgdGFibGUga2VlcHMgc2VydmluZy5cbiAqXG4gKiBgUGVyc2lzdGVudFN0b3JhZ2VgIGlzIG5vdCBvbiBBcHBLaXQncyBwdWJsaWMgZXhwb3J0IG1hcC4gVGhlIGRlZXAgbG9hZCBpc1xuICogbGF6eSBhbmQgYmVzdC1lZmZvcnQ6IGlmIHRoZSBpbnN0YWxsZWQgQXBwS2l0IGxheW91dCBjaGFuZ2VzLCB0aGlzIHJldHVybnNcbiAqIGB1bmRlZmluZWRgIGFuZCBgY3JlYXRlQXBwYCBsZWF2ZXMgQXBwS2l0IG9uIGl0cyBkZWZhdWx0IGNhY2hlIHBhdGguXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBjcmVhdGVMYWtlYmFzZVBvb2wsIGdldFdvcmtzcGFjZUNsaWVudCwgdHlwZSBDYWNoZUNvbmZpZyB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IHBvc3RncmVzQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tIFwiQGRieC10b29scy9wb3N0Z3Jlc1wiO1xuaW1wb3J0IHsgZXJyb3JVdGlscywgaGFzaCwgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGhhbmRsZU93bmVyc2hpcE1pZ3JhdGlvbkVycm9yIH0gZnJvbSBcIi4vbWlncmF0aW9uLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJjYWNoZS1zdG9yYWdlXCIpO1xuXG50eXBlIExha2ViYXNlUG9vbCA9IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUxha2ViYXNlUG9vbD47XG50eXBlIENhY2hlU3RvcmFnZSA9IE5vbk51bGxhYmxlPENhY2hlQ29uZmlnW1wic3RvcmFnZVwiXT47XG5cbi8qKiBBcHBLaXQncyBpbnRlcm5hbCBwZXJzaXN0ZW50IHN0b3JhZ2Ugc3VyZmFjZS4gKi9cbmV4cG9ydCB0eXBlIFBlcnNpc3RlbnRTdG9yYWdlQmFzZSA9IENhY2hlU3RvcmFnZSAmIHtcbiAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+O1xuICBpbml0aWFsaXplZDogYm9vbGVhbjtcbiAgc2NoZW1hTmFtZT86IHN0cmluZztcbiAgdGFibGVOYW1lPzogc3RyaW5nO1xufTtcblxudHlwZSBQZXJzaXN0ZW50U3RvcmFnZUNvbnN0cnVjdG9yID0gbmV3IChcbiAgY29uZmlnOiBDYWNoZUNvbmZpZyxcbiAgcG9vbDogTGFrZWJhc2VQb29sLFxuKSA9PiBQZXJzaXN0ZW50U3RvcmFnZUJhc2U7XG5cbmxldCBwZXJzaXN0ZW50U3RvcmFnZUN0b3I6IFBlcnNpc3RlbnRTdG9yYWdlQ29uc3RydWN0b3IgfCB1bmRlZmluZWQgfCBudWxsID0gbnVsbDtcblxuLyoqXG4gKiBMYXppbHkgcmVzb2x2ZSBBcHBLaXQncyBpbnRlcm5hbCBgUGVyc2lzdGVudFN0b3JhZ2VgIGNvbnN0cnVjdG9yLiBgbnVsbGBcbiAqIG1lYW5zIG5vdCBhdHRlbXB0ZWQgeWV0OyBgdW5kZWZpbmVkYCBtZWFucyB0aGUgbG9va3VwIGFscmVhZHkgZmFpbGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9hZFBlcnNpc3RlbnRTdG9yYWdlKCk6IFBlcnNpc3RlbnRTdG9yYWdlQ29uc3RydWN0b3IgfCB1bmRlZmluZWQge1xuICBpZiAocGVyc2lzdGVudFN0b3JhZ2VDdG9yICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIHBlcnNpc3RlbnRTdG9yYWdlQ3RvcjtcbiAgfVxuICB0cnkge1xuICAgIGNvbnN0IHJlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybCk7XG4gICAgY29uc3QgbW9kdWxlUGF0aCA9IGpvaW4oXG4gICAgICBkaXJuYW1lKHJlcXVpcmUucmVzb2x2ZShcIkBkYXRhYnJpY2tzL2FwcGtpdFwiKSksXG4gICAgICBcImNhY2hlL3N0b3JhZ2UvcGVyc2lzdGVudC5qc1wiLFxuICAgICk7XG4gICAgY29uc3QgbG9hZGVkID0gcmVxdWlyZShtb2R1bGVQYXRoKS5QZXJzaXN0ZW50U3RvcmFnZSBhc1xuICAgICAgUGVyc2lzdGVudFN0b3JhZ2VDb25zdHJ1Y3RvciB8IHVuZGVmaW5lZDtcbiAgICBpZiAodHlwZW9mIGxvYWRlZCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJzb2Z0IHBlcnNpc3RlbnQgY2FjaGUgc2tpcHBlZCAoUGVyc2lzdGVudFN0b3JhZ2UgbWlzc2luZylcIik7XG4gICAgICBwZXJzaXN0ZW50U3RvcmFnZUN0b3IgPSB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBwZXJzaXN0ZW50U3RvcmFnZUN0b3IgPSBsb2FkZWQ7XG4gICAgcmV0dXJuIGxvYWRlZDtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwic29mdCBwZXJzaXN0ZW50IGNhY2hlIHNraXBwZWQgKFBlcnNpc3RlbnRTdG9yYWdlIHVuYXZhaWxhYmxlKVwiLCB7XG4gICAgICBlcnJvcjogZXJyb3JVdGlscy5lcnJvck1lc3NhZ2UoZXJyKSxcbiAgICB9KTtcbiAgICBwZXJzaXN0ZW50U3RvcmFnZUN0b3IgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gZXhpc3RpbmcgY2FjaGUgdGFibGUgYmVsb25ncyB0byBhbm90aGVyIHJvbGUuXG4gKlxuICogUG9zdGdyZVNRTCBhbGxvd3MgZ3JhbnRlZCByZWFkcy93cml0ZXMgYnV0IHJlc2VydmVzIGluZGV4IERETCBmb3IgdGhlIHRhYmxlXG4gKiBvd25lci4gU2tpcCBBcHBLaXQgbWlncmF0aW9ucyBpbiB0aGF0IGNhc2U7IHtAbGluayBwcm9iZVN0b3JhZ2V9IHN0aWxsIHByb3Zlc1xuICogdGhlIGV4aXN0aW5nIHRhYmxlIGNhbiBzZXJ2ZSB0aGUgY2FjaGUgYmVmb3JlIGl0IGlzIGFjY2VwdGVkLlxuICovXG5hc3luYyBmdW5jdGlvbiB0YWJsZU93bmVkQnlBbm90aGVyUm9sZShcbiAgc3RvcmFnZTogUGVyc2lzdGVudFN0b3JhZ2VCYXNlLFxuICBwb29sOiBMYWtlYmFzZVBvb2wsXG4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgaWYgKCFzdG9yYWdlLnNjaGVtYU5hbWUgfHwgIXN0b3JhZ2UudGFibGVOYW1lKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBvb2wucXVlcnkoXG4gICAgYFNFTEVDVCBwZ19nZXRfdXNlcmJ5aWQoYy5yZWxvd25lcikgPSBjdXJyZW50X3VzZXIgQVMgb3duZWRcbiAgICAgRlJPTSBwZ19jbGFzcyBjXG4gICAgIEpPSU4gcGdfbmFtZXNwYWNlIG4gT04gbi5vaWQgPSBjLnJlbG5hbWVzcGFjZVxuICAgICBXSEVSRSBuLm5zcG5hbWUgPSAkMSBBTkQgYy5yZWxuYW1lID0gJDIgQU5EIGMucmVsa2luZCBJTiAoJ3InLCAncCcpYCxcbiAgICBbc3RvcmFnZS5zY2hlbWFOYW1lLCBzdG9yYWdlLnRhYmxlTmFtZV0sXG4gICk7XG4gIGlmIChyZXN1bHQucm93c1swXT8ub3duZWQgIT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gIGxvZ2dlci53YXJuKFwicGVyc2lzdGVudCBjYWNoZSBtaWdyYXRpb25zIHNraXBwZWQgKHRhYmxlIG93bmVkIGJ5IGFub3RoZXIgcm9sZSlcIiwge1xuICAgIHNjaGVtYTogc3RvcmFnZS5zY2hlbWFOYW1lLFxuICAgIHRhYmxlOiBzdG9yYWdlLnRhYmxlTmFtZSxcbiAgfSk7XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKiogU29mdGVuIGBpbml0aWFsaXplKClgIHNvIGFuIG93bmVyc2hpcC1vbmx5IG1pZ3JhdGlvbiBmYWlsdXJlIGlzIG5vdCBmYXRhbC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb2Z0ZW5Jbml0aWFsaXplKFxuICBzdG9yYWdlOiBQZXJzaXN0ZW50U3RvcmFnZUJhc2UsXG4gIHNraXBNaWdyYXRpb25zPzogKCkgPT4gUHJvbWlzZTxib29sZWFuPixcbik6IHZvaWQge1xuICBjb25zdCBvcmlnaW5hbEluaXRpYWxpemUgPSBzdG9yYWdlLmluaXRpYWxpemUuYmluZChzdG9yYWdlKTtcbiAgbGV0IHNvZnRJbml0UHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcblxuICBzdG9yYWdlLmluaXRpYWxpemUgPSBhc3luYyAoKSA9PiB7XG4gICAgaWYgKHN0b3JhZ2UuaW5pdGlhbGl6ZWQpIHJldHVybjtcbiAgICBzb2Z0SW5pdFByb21pc2UgPz89IChhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIShhd2FpdCBza2lwTWlncmF0aW9ucz8uKCkpKSBhd2FpdCBvcmlnaW5hbEluaXRpYWxpemUoKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgIWhhbmRsZU93bmVyc2hpcE1pZ3JhdGlvbkVycm9yKGVyciwge1xuICAgICAgICAgICAgc2NvcGU6IFwiY2FjaGUtc3RvcmFnZVwiLFxuICAgICAgICAgICAgbG9nZ2VyLFxuICAgICAgICAgICAgZXZlbnQ6IFwicGVyc2lzdGVudCBjYWNoZSBtaWdyYXRpb24gZmFpbGVkXCIsXG4gICAgICAgICAgfSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSkoKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgc29mdEluaXRQcm9taXNlO1xuICAgICAgc3RvcmFnZS5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBzb2Z0SW5pdFByb21pc2UgPSB1bmRlZmluZWQ7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9O1xufVxuXG4vKiogVmVyaWZ5IHRoZSBtaWdyYXRlZCBjYWNoZSB0YWJsZSBjYW4gc2VydmUgdGhlIHJlYWRzIGFuZCB3cml0ZXMgQXBwS2l0IG5lZWRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2JlU3RvcmFnZShzdG9yYWdlOiBQZXJzaXN0ZW50U3RvcmFnZUJhc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3Qga2V5ID0gYGRieC10b29sczpjYWNoZS1wcm9iZToke2hhc2guaWQoKX1gO1xuICB0cnkge1xuICAgIGF3YWl0IHN0b3JhZ2Uuc2V0KGtleSwgeyB2YWx1ZToga2V5LCBleHBpcnk6IERhdGUubm93KCkgKyA2MF8wMDAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5nZXQoa2V5KTtcbiAgICBpZiAocmVzdWx0Py52YWx1ZSAhPT0ga2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJwZXJzaXN0ZW50IGNhY2hlIHByb2JlIHJldHVybmVkIGFuIHVuZXhwZWN0ZWQgdmFsdWVcIik7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IHN0b3JhZ2UuZGVsZXRlKGtleSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkIGEgc29mdC1mYWlsIExha2ViYXNlIGNhY2hlIHN0b3JhZ2Ugd2hlbiBhIHBvb2wgY2FuIGJlIGNyZWF0ZWQgYW5kXG4gKiBBcHBLaXQncyBQZXJzaXN0ZW50U3RvcmFnZSBjYW4gYmUgbG9hZGVkLiBSZXR1cm5zIGB1bmRlZmluZWRgIG90aGVyd2lzZSBzb1xuICogQXBwS2l0IGNhbiBmYWxsIHRocm91Z2ggdG8gaXRzIG5vcm1hbCBjYWNoZSBwYXRoLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlU29mdFBlcnNpc3RlbnRTdG9yYWdlKFxuICBjYWNoZTogQ2FjaGVDb25maWcgfCB1bmRlZmluZWQsXG4pOiBQcm9taXNlPENhY2hlU3RvcmFnZSB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBQZXJzaXN0ZW50U3RvcmFnZSA9IGxvYWRQZXJzaXN0ZW50U3RvcmFnZSgpO1xuICBpZiAoIVBlcnNpc3RlbnRTdG9yYWdlKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGxldCBwb29sOiBMYWtlYmFzZVBvb2wgfCB1bmRlZmluZWQ7XG4gIHRyeSB7XG4gICAgY29uc3QgY3JlYXRlZFBvb2wgPSBjcmVhdGVMYWtlYmFzZVBvb2woXG4gICAgICBwb3N0Z3Jlc0Nvbm5lY3Rpb25PcHRpb25zKHsgd29ya3NwYWNlQ2xpZW50OiBnZXRXb3Jrc3BhY2VDbGllbnQoe30pIH0pLFxuICAgICk7XG4gICAgcG9vbCA9IGNyZWF0ZWRQb29sO1xuICAgIGNvbnN0IHN0b3JhZ2UgPSBuZXcgUGVyc2lzdGVudFN0b3JhZ2UoY2FjaGUgPz8ge30sIGNyZWF0ZWRQb29sKTtcbiAgICBzb2Z0ZW5Jbml0aWFsaXplKHN0b3JhZ2UsICgpID0+IHRhYmxlT3duZWRCeUFub3RoZXJSb2xlKHN0b3JhZ2UsIGNyZWF0ZWRQb29sKSk7XG4gICAgaWYgKCEoYXdhaXQgc3RvcmFnZS5oZWFsdGhDaGVjaygpKSkge1xuICAgICAgYXdhaXQgc3RvcmFnZS5jbG9zZSgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGF3YWl0IHN0b3JhZ2UuaW5pdGlhbGl6ZSgpO1xuICAgIGF3YWl0IHByb2JlU3RvcmFnZShzdG9yYWdlKTtcbiAgICByZXR1cm4gc3RvcmFnZTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwic29mdCBwZXJzaXN0ZW50IGNhY2hlIHVuYXZhaWxhYmxlXCIsIHtcbiAgICAgIGVycm9yOiBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShlcnIpLFxuICAgIH0pO1xuICAgIGlmIChwb29sKSB7XG4gICAgICBhd2FpdCBwb29sLmVuZCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
230
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2NhY2hlLXN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX2NhY2hlLXN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFFSCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRS9ELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7QUE2QjNDLElBQUkscUJBQXFCLEdBQW9ELElBQUksQ0FBQztBQUVsRixnRkFBZ0Y7QUFDaEYsTUFBTSxPQUFPLGNBQWM7SUFJTjtJQUhGLE9BQU8sQ0FBK0I7SUFFdkQsWUFDbUIsT0FBcUIsRUFDdEMsVUFBaUMsRUFBRTtRQURsQixZQUFPLEdBQVAsT0FBTyxDQUFjO1FBR3RDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxRQUFRLENBQUM7WUFDMUIsR0FBRyxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUM7WUFDM0QsT0FBTyxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsR0FBRyxJQUFJLEdBQUcsSUFBSSxFQUFFLFVBQVUsQ0FBQztZQUN0RSxlQUFlLEVB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LFFBQVE7WUFDekIsVUFBVSxFQUFFLEtBQUssRUFBRSxPQUFPO1NBQzNCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsRUFBRTtZQUNoRCxLQUFLLEVBQUUsVUFBVSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUM7U0FDcEMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNULE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNvZnQtZmFpbCBMYWtlYmFzZSBjYWNoZSBzdG9yYWdlIGZvciBBcHBLaXQncyBwZXJzaXN0ZW50IGNhY2hlLlxuICpcbiAqIEFwcEtpdCdzIGBQZXJzaXN0ZW50U3RvcmFnZS5pbml0aWFsaXplKClgIHJ1bnMgRERMIG1pZ3JhdGlvbnMgYW5kIHRocm93cyBvblxuICogYW55IHN0ZXAgZmFpbHVyZS4gV2l0aCBgY2FjaGUuc3RyaWN0UGVyc2lzdGVuY2U6IHRydWVgIHRoYXQgdGhyb3cgbWFrZXNcbiAqIGBDYWNoZU1hbmFnZXJgIHNpbGVudGx5IGRpc2FibGUgdGhlIGNhY2hlLiBUaGlzIHdyYXBzIHRoZSBzYW1lIHN0b3JhZ2UsXG4gKiBzdGlsbCBydW5zIGl0cyBtaWdyYXRpb25zLCBidXQgbG9ncyBhIGZhaWxlZCBzdGVwIGluc3RlYWQgb2YgdGhyb3dpbmcgc28gYVxuICogdXNhYmxlIHRhYmxlIGtlZXBzIHNlcnZpbmcuXG4gKlxuICogYFBlcnNpc3RlbnRTdG9yYWdlYCBpcyBub3Qgb24gQXBwS2l0J3MgcHVibGljIGV4cG9ydCBtYXAuIFRoZSBkZWVwIGxvYWQgaXNcbiAqIGxhenkgYW5kIGJlc3QtZWZmb3J0OiBpZiB0aGUgaW5zdGFsbGVkIEFwcEtpdCBsYXlvdXQgY2hhbmdlcywgdGhpcyByZXR1cm5zXG4gKiBgdW5kZWZpbmVkYCBhbmQgYGNyZWF0ZUFwcGAgbGVhdmVzIEFwcEtpdCBvbiBpdHMgZGVmYXVsdCBjYWNoZSBwYXRoLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSBcIm5vZGU6bW9kdWxlXCI7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgY3JlYXRlTGFrZWJhc2VQb29sLCBnZXRXb3Jrc3BhY2VDbGllbnQsIHR5cGUgQ2FjaGVDb25maWcgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBwb3N0Z3Jlc0Nvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSBcIkBkYngtdG9vbHMvcG9zdGdyZXNcIjtcbmltcG9ydCB7IGVycm9yVXRpbHMsIGhhc2gsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBMUlVDYWNoZSB9IGZyb20gXCJscnUtY2FjaGVcIjtcbmltcG9ydCB7IGhhbmRsZU93bmVyc2hpcE1pZ3JhdGlvbkVycm9yIH0gZnJvbSBcIi4vbWlncmF0aW9uLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJjYWNoZS1zdG9yYWdlXCIpO1xuXG50eXBlIExha2ViYXNlUG9vbCA9IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUxha2ViYXNlUG9vbD47XG50eXBlIENhY2hlU3RvcmFnZSA9IE5vbk51bGxhYmxlPENhY2hlQ29uZmlnW1wic3RvcmFnZVwiXT47XG5cbmludGVyZmFjZSBDYWNoZUVudHJ5PFQgPSB1bmtub3duPiB7XG4gIGV4cGlyeTogbnVtYmVyO1xuICB2YWx1ZTogVDtcbn1cblxuLyoqIEJvdW5kcyBmb3IgdGhlIHByb2Nlc3MtbG9jYWwgY2FjaGUgbGF5ZXJlZCBvdmVyIHBlcnNpc3RlbnQgQXBwS2l0IHN0b3JhZ2UuICovXG5leHBvcnQgaW50ZXJmYWNlIEwxQ2FjaGVTdG9yYWdlT3B0aW9ucyB7XG4gIG1heEJ5dGVzPzogbnVtYmVyO1xuICBtYXhFbnRyaWVzPzogbnVtYmVyO1xufVxuXG4vKiogQXBwS2l0J3MgaW50ZXJuYWwgcGVyc2lzdGVudCBzdG9yYWdlIHN1cmZhY2UuICovXG5leHBvcnQgdHlwZSBQZXJzaXN0ZW50U3RvcmFnZUJhc2UgPSBDYWNoZVN0b3JhZ2UgJiB7XG4gIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPjtcbiAgaW5pdGlhbGl6ZWQ6IGJvb2xlYW47XG4gIHNjaGVtYU5hbWU/OiBzdHJpbmc7XG4gIHRhYmxlTmFtZT86IHN0cmluZztcbn07XG5cbnR5cGUgUGVyc2lzdGVudFN0b3JhZ2VDb25zdHJ1Y3RvciA9IG5ldyAoXG4gIGNvbmZpZzogQ2FjaGVDb25maWcsXG4gIHBvb2w6IExha2ViYXNlUG9vbCxcbikgPT4gUGVyc2lzdGVudFN0b3JhZ2VCYXNlO1xuXG5sZXQgcGVyc2lzdGVudFN0b3JhZ2VDdG9yOiBQZXJzaXN0ZW50U3RvcmFnZUNvbnN0cnVjdG9yIHwgdW5kZWZpbmVkIHwgbnVsbCA9IG51bGw7XG5cbi8qKiBQcm9jZXNzLWxvY2FsIExSVSB0aGF0IGF2b2lkcyBhIHBlcnNpc3RlbnQgY2FjaGUgcXVlcnkgb24gZXZlcnkgd2FybSBoaXQuICovXG5leHBvcnQgY2xhc3MgTDFDYWNoZVN0b3JhZ2UgaW1wbGVtZW50cyBDYWNoZVN0b3JhZ2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IGVudHJpZXM6IExSVUNhY2hlPHN0cmluZywgQ2FjaGVFbnRyeT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdG9yYWdlOiBDYWNoZVN0b3JhZ2UsXG4gICAgb3B0aW9uczogTDFDYWNoZVN0b3JhZ2VPcHRpb25zID0ge30sXG4gICkge1xuICAgIHRoaXMuZW50cmllcyA9IG5ldyBMUlVDYWNoZSh7XG4gICAgICBtYXg6IHBvc2l0aXZlQm91bmQob3B0aW9ucy5tYXhFbnRyaWVzLCAxXzAwMCwgXCJtYXhFbnRyaWVzXCIpLFxuICAgICAgbWF4U2l6ZTogcG9zaXRpdmVCb3VuZChvcHRpb25zLm1heEJ5dGVzLCA2NCAqIDEwMjQgKiAxMDI0LCBcIm1heEJ5dGVzXCIpLFxuICAgICAgc2l6ZUNhbGN1bGF0aW9uOiAoZW50cnksIGtleSkgPT4gcmV0YWluZWRTaXplKGtleSwgZW50cnkpLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZ2V0PFQ+KGtleTogc3RyaW5nKTogUHJvbWlzZTxDYWNoZUVudHJ5PFQ+IHwgbnVsbD4ge1xuICAgIGNvbnN0IGxvY2FsID0gdGhpcy5lbnRyaWVzLmdldChrZXkpO1xuICAgIGlmIChsb2NhbCkgcmV0dXJuIGxvY2FsIGFzIENhY2hlRW50cnk8VD47XG4gICAgY29uc3QgcGVyc2lzdGVkID0gYXdhaXQgdGhpcy5zdG9yYWdlLmdldDxUPihrZXkpO1xuICAgIGlmIChwZXJzaXN0ZWQgJiYgcGVyc2lzdGVkLmV4cGlyeSA+IERhdGUubm93KCkpIHRoaXMucmV0YWluKGtleSwgcGVyc2lzdGVkKTtcbiAgICByZXR1cm4gcGVyc2lzdGVkO1xuICB9XG5cbiAgYXN5bmMgc2V0PFQ+KGtleTogc3RyaW5nLCBlbnRyeTogQ2FjaGVFbnRyeTxUPik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc3RvcmFnZS5zZXQoa2V5LCBlbnRyeSk7XG4gICAgdGhpcy5yZXRhaW4oa2V5LCBlbnRyeSk7XG4gIH1cblxuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnN0b3JhZ2UuZGVsZXRlKGtleSk7XG4gICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShrZXkpO1xuICB9XG5cbiAgYXN5bmMgY2xlYXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zdG9yYWdlLmNsZWFyKCk7XG4gICAgdGhpcy5lbnRyaWVzLmNsZWFyKCk7XG4gIH1cblxuICBhc3luYyBoYXMoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5lbnRyaWVzLmhhcyhrZXkpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmhhcyhrZXkpO1xuICB9XG5cbiAgc2l6ZSgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2Uuc2l6ZSgpO1xuICB9XG5cbiAgaXNQZXJzaXN0ZW50KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuaXNQZXJzaXN0ZW50KCk7XG4gIH1cblxuICBoZWFsdGhDaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmhlYWx0aENoZWNrKCk7XG4gIH1cblxuICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmVudHJpZXMuY2xlYXIoKTtcbiAgICBhd2FpdCB0aGlzLnN0b3JhZ2UuY2xvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmV0YWluPFQ+KGtleTogc3RyaW5nLCBlbnRyeTogQ2FjaGVFbnRyeTxUPik6IHZvaWQge1xuICAgIGNvbnN0IHR0bCA9IGVudHJ5LmV4cGlyeSAtIERhdGUubm93KCk7XG4gICAgaWYgKHR0bCA+IDApIHRoaXMuZW50cmllcy5zZXQoa2V5LCBlbnRyeSwgeyB0dGwgfSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcG9zaXRpdmVCb3VuZCh2YWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkLCBmYWxsYmFjazogbnVtYmVyLCBuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCByZXNvbHZlZCA9IHZhbHVlID8/IGZhbGxiYWNrO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShyZXNvbHZlZCkgfHwgcmVzb2x2ZWQgPD0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAke25hbWV9IG11c3QgYmUgYSBmaW5pdGUgcG9zaXRpdmUgbnVtYmVyYCk7XG4gIH1cbiAgcmV0dXJuIE1hdGguZmxvb3IocmVzb2x2ZWQpO1xufVxuXG5mdW5jdGlvbiByZXRhaW5lZFNpemUoa2V5OiBzdHJpbmcsIGVudHJ5OiBDYWNoZUVudHJ5KTogbnVtYmVyIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5KSArIEJ1ZmZlci5ieXRlTGVuZ3RoKEpTT04uc3RyaW5naWZ5KGVudHJ5KSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcbiAgfVxufVxuXG4vKipcbiAqIExhemlseSByZXNvbHZlIEFwcEtpdCdzIGludGVybmFsIGBQZXJzaXN0ZW50U3RvcmFnZWAgY29uc3RydWN0b3IuIGBudWxsYFxuICogbWVhbnMgbm90IGF0dGVtcHRlZCB5ZXQ7IGB1bmRlZmluZWRgIG1lYW5zIHRoZSBsb29rdXAgYWxyZWFkeSBmYWlsZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2FkUGVyc2lzdGVudFN0b3JhZ2UoKTogUGVyc2lzdGVudFN0b3JhZ2VDb25zdHJ1Y3RvciB8IHVuZGVmaW5lZCB7XG4gIGlmIChwZXJzaXN0ZW50U3RvcmFnZUN0b3IgIT09IG51bGwpIHtcbiAgICByZXR1cm4gcGVyc2lzdGVudFN0b3JhZ2VDdG9yO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKTtcbiAgICBjb25zdCBtb2R1bGVQYXRoID0gam9pbihcbiAgICAgIGRpcm5hbWUocmVxdWlyZS5yZXNvbHZlKFwiQGRhdGFicmlja3MvYXBwa2l0XCIpKSxcbiAgICAgIFwiY2FjaGUvc3RvcmFnZS9wZXJzaXN0ZW50LmpzXCIsXG4gICAgKTtcbiAgICBjb25zdCBsb2FkZWQgPSByZXF1aXJlKG1vZHVsZVBhdGgpLlBlcnNpc3RlbnRTdG9yYWdlIGFzXG4gICAgICBQZXJzaXN0ZW50U3RvcmFnZUNvbnN0cnVjdG9yIHwgdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlb2YgbG9hZGVkICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcInNvZnQgcGVyc2lzdGVudCBjYWNoZSBza2lwcGVkIChQZXJzaXN0ZW50U3RvcmFnZSBtaXNzaW5nKVwiKTtcbiAgICAgIHBlcnNpc3RlbnRTdG9yYWdlQ3RvciA9IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHBlcnNpc3RlbnRTdG9yYWdlQ3RvciA9IGxvYWRlZDtcbiAgICByZXR1cm4gbG9hZGVkO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJzb2Z0IHBlcnNpc3RlbnQgY2FjaGUgc2tpcHBlZCAoUGVyc2lzdGVudFN0b3JhZ2UgdW5hdmFpbGFibGUpXCIsIHtcbiAgICAgIGVycm9yOiBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShlcnIpLFxuICAgIH0pO1xuICAgIHBlcnNpc3RlbnRTdG9yYWdlQ3RvciA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogV2hldGhlciBhbiBleGlzdGluZyBjYWNoZSB0YWJsZSBiZWxvbmdzIHRvIGFub3RoZXIgcm9sZS5cbiAqXG4gKiBQb3N0Z3JlU1FMIGFsbG93cyBncmFudGVkIHJlYWRzL3dyaXRlcyBidXQgcmVzZXJ2ZXMgaW5kZXggRERMIGZvciB0aGUgdGFibGVcbiAqIG93bmVyLiBTa2lwIEFwcEtpdCBtaWdyYXRpb25zIGluIHRoYXQgY2FzZTsge0BsaW5rIHByb2JlU3RvcmFnZX0gc3RpbGwgcHJvdmVzXG4gKiB0aGUgZXhpc3RpbmcgdGFibGUgY2FuIHNlcnZlIHRoZSBjYWNoZSBiZWZvcmUgaXQgaXMgYWNjZXB0ZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRhYmxlT3duZWRCeUFub3RoZXJSb2xlKFxuICBzdG9yYWdlOiBQZXJzaXN0ZW50U3RvcmFnZUJhc2UsXG4gIHBvb2w6IExha2ViYXNlUG9vbCxcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBpZiAoIXN0b3JhZ2Uuc2NoZW1hTmFtZSB8fCAhc3RvcmFnZS50YWJsZU5hbWUpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcG9vbC5xdWVyeShcbiAgICBgU0VMRUNUIHBnX2dldF91c2VyYnlpZChjLnJlbG93bmVyKSA9IGN1cnJlbnRfdXNlciBBUyBvd25lZFxuICAgICBGUk9NIHBnX2NsYXNzIGNcbiAgICAgSk9JTiBwZ19uYW1lc3BhY2UgbiBPTiBuLm9pZCA9IGMucmVsbmFtZXNwYWNlXG4gICAgIFdIRVJFIG4ubnNwbmFtZSA9ICQxIEFORCBjLnJlbG5hbWUgPSAkMiBBTkQgYy5yZWxraW5kIElOICgncicsICdwJylgLFxuICAgIFtzdG9yYWdlLnNjaGVtYU5hbWUsIHN0b3JhZ2UudGFibGVOYW1lXSxcbiAgKTtcbiAgaWYgKHJlc3VsdC5yb3dzWzBdPy5vd25lZCAhPT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgbG9nZ2VyLndhcm4oXCJwZXJzaXN0ZW50IGNhY2hlIG1pZ3JhdGlvbnMgc2tpcHBlZCAodGFibGUgb3duZWQgYnkgYW5vdGhlciByb2xlKVwiLCB7XG4gICAgc2NoZW1hOiBzdG9yYWdlLnNjaGVtYU5hbWUsXG4gICAgdGFibGU6IHN0b3JhZ2UudGFibGVOYW1lLFxuICB9KTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKiBTb2Z0ZW4gYGluaXRpYWxpemUoKWAgc28gYW4gb3duZXJzaGlwLW9ubHkgbWlncmF0aW9uIGZhaWx1cmUgaXMgbm90IGZhdGFsLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvZnRlbkluaXRpYWxpemUoXG4gIHN0b3JhZ2U6IFBlcnNpc3RlbnRTdG9yYWdlQmFzZSxcbiAgc2tpcE1pZ3JhdGlvbnM/OiAoKSA9PiBQcm9taXNlPGJvb2xlYW4+LFxuKTogdm9pZCB7XG4gIGNvbnN0IG9yaWdpbmFsSW5pdGlhbGl6ZSA9IHN0b3JhZ2UuaW5pdGlhbGl6ZS5iaW5kKHN0b3JhZ2UpO1xuICBsZXQgc29mdEluaXRQcm9taXNlOiBQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG4gIHN0b3JhZ2UuaW5pdGlhbGl6ZSA9IGFzeW5jICgpID0+IHtcbiAgICBpZiAoc3RvcmFnZS5pbml0aWFsaXplZCkgcmV0dXJuO1xuICAgIHNvZnRJbml0UHJvbWlzZSA/Pz0gKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghKGF3YWl0IHNraXBNaWdyYXRpb25zPy4oKSkpIGF3YWl0IG9yaWdpbmFsSW5pdGlhbGl6ZSgpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhaGFuZGxlT3duZXJzaGlwTWlncmF0aW9uRXJyb3IoZXJyLCB7XG4gICAgICAgICAgICBzY29wZTogXCJjYWNoZS1zdG9yYWdlXCIsXG4gICAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgICBldmVudDogXCJwZXJzaXN0ZW50IGNhY2hlIG1pZ3JhdGlvbiBmYWlsZWRcIixcbiAgICAgICAgICB9KVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBzb2Z0SW5pdFByb21pc2U7XG4gICAgICBzdG9yYWdlLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHNvZnRJbml0UHJvbWlzZSA9IHVuZGVmaW5lZDtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH07XG59XG5cbi8qKiBWZXJpZnkgdGhlIG1pZ3JhdGVkIGNhY2hlIHRhYmxlIGNhbiBzZXJ2ZSB0aGUgcmVhZHMgYW5kIHdyaXRlcyBBcHBLaXQgbmVlZHMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvYmVTdG9yYWdlKHN0b3JhZ2U6IFBlcnNpc3RlbnRTdG9yYWdlQmFzZSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBrZXkgPSBgZGJ4LXRvb2xzOmNhY2hlLXByb2JlOiR7aGFzaC5pZCgpfWA7XG4gIHRyeSB7XG4gICAgYXdhaXQgc3RvcmFnZS5zZXQoa2V5LCB7IHZhbHVlOiBrZXksIGV4cGlyeTogRGF0ZS5ub3coKSArIDYwXzAwMCB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLmdldChrZXkpO1xuICAgIGlmIChyZXN1bHQ/LnZhbHVlICE9PSBrZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInBlcnNpc3RlbnQgY2FjaGUgcHJvYmUgcmV0dXJuZWQgYW4gdW5leHBlY3RlZCB2YWx1ZVwiKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgc3RvcmFnZS5kZWxldGUoa2V5KS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICB9XG59XG5cbi8qKlxuICogQnVpbGQgYSBzb2Z0LWZhaWwgTGFrZWJhc2UgY2FjaGUgc3RvcmFnZSB3aGVuIGEgcG9vbCBjYW4gYmUgY3JlYXRlZCBhbmRcbiAqIEFwcEtpdCdzIFBlcnNpc3RlbnRTdG9yYWdlIGNhbiBiZSBsb2FkZWQuIFJldHVybnMgYHVuZGVmaW5lZGAgb3RoZXJ3aXNlIHNvXG4gKiBBcHBLaXQgY2FuIGZhbGwgdGhyb3VnaCB0byBpdHMgbm9ybWFsIGNhY2hlIHBhdGguXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVTb2Z0UGVyc2lzdGVudFN0b3JhZ2UoXG4gIGNhY2hlOiBDYWNoZUNvbmZpZyB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8Q2FjaGVTdG9yYWdlIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IFBlcnNpc3RlbnRTdG9yYWdlID0gbG9hZFBlcnNpc3RlbnRTdG9yYWdlKCk7XG4gIGlmICghUGVyc2lzdGVudFN0b3JhZ2UpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgbGV0IHBvb2w6IExha2ViYXNlUG9vbCB8IHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCBjcmVhdGVkUG9vbCA9IGNyZWF0ZUxha2ViYXNlUG9vbChcbiAgICAgIHBvc3RncmVzQ29ubmVjdGlvbk9wdGlvbnMoeyB3b3Jrc3BhY2VDbGllbnQ6IGdldFdvcmtzcGFjZUNsaWVudCh7fSkgfSksXG4gICAgKTtcbiAgICBwb29sID0gY3JlYXRlZFBvb2w7XG4gICAgY29uc3Qgc3RvcmFnZSA9IG5ldyBQZXJzaXN0ZW50U3RvcmFnZShjYWNoZSA/PyB7fSwgY3JlYXRlZFBvb2wpO1xuICAgIHNvZnRlbkluaXRpYWxpemUoc3RvcmFnZSwgKCkgPT4gdGFibGVPd25lZEJ5QW5vdGhlclJvbGUoc3RvcmFnZSwgY3JlYXRlZFBvb2wpKTtcbiAgICBpZiAoIShhd2FpdCBzdG9yYWdlLmhlYWx0aENoZWNrKCkpKSB7XG4gICAgICBhd2FpdCBzdG9yYWdlLmNsb3NlKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgYXdhaXQgc3RvcmFnZS5pbml0aWFsaXplKCk7XG4gICAgYXdhaXQgcHJvYmVTdG9yYWdlKHN0b3JhZ2UpO1xuICAgIHJldHVybiBuZXcgTDFDYWNoZVN0b3JhZ2Uoc3RvcmFnZSwge1xuICAgICAgbWF4Qnl0ZXM6IGNhY2hlPy5tYXhCeXRlcyxcbiAgICAgIG1heEVudHJpZXM6IGNhY2hlPy5tYXhTaXplLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJzb2Z0IHBlcnNpc3RlbnQgY2FjaGUgdW5hdmFpbGFibGVcIiwge1xuICAgICAgZXJyb3I6IGVycm9yVXRpbHMuZXJyb3JNZXNzYWdlKGVyciksXG4gICAgfSk7XG4gICAgaWYgKHBvb2wpIHtcbiAgICAgIGF3YWl0IHBvb2wuZW5kKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "@databricks/appkit": "0.81.0",
23
- "@dbx-tools/projen": "^0.9.73",
23
+ "@dbx-tools/projen": "^0.9.79",
24
24
  "@types/node": "^24.6.0",
25
25
  "typescript": "^5.9.3",
26
26
  "vitest": "3.2.4"
@@ -30,11 +30,12 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@databricks/sdk-experimental": "^0.17.0",
33
- "@dbx-tools/auth": "^0.9.73",
34
- "@dbx-tools/core": "^0.9.73",
35
- "@dbx-tools/lakebase": "^0.9.73",
36
- "@dbx-tools/postgres": "^0.9.73",
37
- "@dbx-tools/shared-core": "^0.9.73",
33
+ "@dbx-tools/auth": "^0.9.79",
34
+ "@dbx-tools/core": "^0.9.79",
35
+ "@dbx-tools/lakebase": "^0.9.79",
36
+ "@dbx-tools/postgres": "^0.9.79",
37
+ "@dbx-tools/shared-core": "^0.9.79",
38
+ "lru-cache": "11.5.3",
38
39
  "zod": "4.3.6"
39
40
  },
40
41
  "main": "./lib/index.js",
@@ -115,7 +116,7 @@
115
116
  "./package.json": "./package.json"
116
117
  }
117
118
  },
118
- "version": "0.9.73",
119
+ "version": "0.9.79",
119
120
  "types": "./lib/index.d.ts",
120
121
  "dbxToolsConfig": {
121
122
  "tags": [
@@ -19,6 +19,7 @@ import { dirname, join } from "node:path";
19
19
  import { createLakebasePool, getWorkspaceClient, type CacheConfig } from "@databricks/appkit";
20
20
  import { postgresConnectionOptions } from "@dbx-tools/postgres";
21
21
  import { errorUtils, hash, log } from "@dbx-tools/shared-core";
22
+ import { LRUCache } from "lru-cache";
22
23
  import { handleOwnershipMigrationError } from "./migration.ts";
23
24
 
24
25
  const logger = log.logger("cache-storage");
@@ -26,6 +27,17 @@ const logger = log.logger("cache-storage");
26
27
  type LakebasePool = ReturnType<typeof createLakebasePool>;
27
28
  type CacheStorage = NonNullable<CacheConfig["storage"]>;
28
29
 
30
+ interface CacheEntry<T = unknown> {
31
+ expiry: number;
32
+ value: T;
33
+ }
34
+
35
+ /** Bounds for the process-local cache layered over persistent AppKit storage. */
36
+ export interface L1CacheStorageOptions {
37
+ maxBytes?: number;
38
+ maxEntries?: number;
39
+ }
40
+
29
41
  /** AppKit's internal persistent storage surface. */
30
42
  export type PersistentStorageBase = CacheStorage & {
31
43
  initialize(): Promise<void>;
@@ -41,6 +53,88 @@ type PersistentStorageConstructor = new (
41
53
 
42
54
  let persistentStorageCtor: PersistentStorageConstructor | undefined | null = null;
43
55
 
56
+ /** Process-local LRU that avoids a persistent cache query on every warm hit. */
57
+ export class L1CacheStorage implements CacheStorage {
58
+ private readonly entries: LRUCache<string, CacheEntry>;
59
+
60
+ constructor(
61
+ private readonly storage: CacheStorage,
62
+ options: L1CacheStorageOptions = {},
63
+ ) {
64
+ this.entries = new LRUCache({
65
+ max: positiveBound(options.maxEntries, 1_000, "maxEntries"),
66
+ maxSize: positiveBound(options.maxBytes, 64 * 1024 * 1024, "maxBytes"),
67
+ sizeCalculation: (entry, key) => retainedSize(key, entry),
68
+ });
69
+ }
70
+
71
+ async get<T>(key: string): Promise<CacheEntry<T> | null> {
72
+ const local = this.entries.get(key);
73
+ if (local) return local as CacheEntry<T>;
74
+ const persisted = await this.storage.get<T>(key);
75
+ if (persisted && persisted.expiry > Date.now()) this.retain(key, persisted);
76
+ return persisted;
77
+ }
78
+
79
+ async set<T>(key: string, entry: CacheEntry<T>): Promise<void> {
80
+ await this.storage.set(key, entry);
81
+ this.retain(key, entry);
82
+ }
83
+
84
+ async delete(key: string): Promise<void> {
85
+ await this.storage.delete(key);
86
+ this.entries.delete(key);
87
+ }
88
+
89
+ async clear(): Promise<void> {
90
+ await this.storage.clear();
91
+ this.entries.clear();
92
+ }
93
+
94
+ async has(key: string): Promise<boolean> {
95
+ if (this.entries.has(key)) return true;
96
+ return this.storage.has(key);
97
+ }
98
+
99
+ size(): Promise<number> {
100
+ return this.storage.size();
101
+ }
102
+
103
+ isPersistent(): boolean {
104
+ return this.storage.isPersistent();
105
+ }
106
+
107
+ healthCheck(): Promise<boolean> {
108
+ return this.storage.healthCheck();
109
+ }
110
+
111
+ async close(): Promise<void> {
112
+ this.entries.clear();
113
+ await this.storage.close();
114
+ }
115
+
116
+ private retain<T>(key: string, entry: CacheEntry<T>): void {
117
+ const ttl = entry.expiry - Date.now();
118
+ if (ttl > 0) this.entries.set(key, entry, { ttl });
119
+ }
120
+ }
121
+
122
+ function positiveBound(value: number | undefined, fallback: number, name: string): number {
123
+ const resolved = value ?? fallback;
124
+ if (!Number.isFinite(resolved) || resolved <= 0) {
125
+ throw new RangeError(`${name} must be a finite positive number`);
126
+ }
127
+ return Math.floor(resolved);
128
+ }
129
+
130
+ function retainedSize(key: string, entry: CacheEntry): number {
131
+ try {
132
+ return Buffer.byteLength(key) + Buffer.byteLength(JSON.stringify(entry));
133
+ } catch {
134
+ return Number.MAX_SAFE_INTEGER;
135
+ }
136
+ }
137
+
44
138
  /**
45
139
  * Lazily resolve AppKit's internal `PersistentStorage` constructor. `null`
46
140
  * means not attempted yet; `undefined` means the lookup already failed.
@@ -176,7 +270,10 @@ export async function createSoftPersistentStorage(
176
270
  }
177
271
  await storage.initialize();
178
272
  await probeStorage(storage);
179
- return storage;
273
+ return new L1CacheStorage(storage, {
274
+ maxBytes: cache?.maxBytes,
275
+ maxEntries: cache?.maxSize,
276
+ });
180
277
  } catch (err) {
181
278
  logger.debug("soft persistent cache unavailable", {
182
279
  error: errorUtils.errorMessage(err),