@soederpop/luca 0.0.2

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 (358) hide show
  1. package/CLAUDE.md +71 -0
  2. package/README.md +78 -0
  3. package/bun.lock +2928 -0
  4. package/bunfig.toml +3 -0
  5. package/commands/audit-docs.ts +740 -0
  6. package/commands/build-scaffolds.ts +154 -0
  7. package/commands/generate-api-docs.ts +114 -0
  8. package/commands/update-introspection.ts +67 -0
  9. package/docs/CLI.md +335 -0
  10. package/docs/README.md +88 -0
  11. package/docs/TABLE-OF-CONTENTS.md +157 -0
  12. package/docs/apis/clients/elevenlabs.md +84 -0
  13. package/docs/apis/clients/graph.md +56 -0
  14. package/docs/apis/clients/openai.md +69 -0
  15. package/docs/apis/clients/rest.md +41 -0
  16. package/docs/apis/clients/websocket.md +107 -0
  17. package/docs/apis/features/agi/assistant.md +471 -0
  18. package/docs/apis/features/agi/assistants-manager.md +154 -0
  19. package/docs/apis/features/agi/claude-code.md +602 -0
  20. package/docs/apis/features/agi/conversation-history.md +352 -0
  21. package/docs/apis/features/agi/conversation.md +333 -0
  22. package/docs/apis/features/agi/docs-reader.md +121 -0
  23. package/docs/apis/features/agi/openai-codex.md +318 -0
  24. package/docs/apis/features/agi/openapi.md +138 -0
  25. package/docs/apis/features/agi/semantic-search.md +387 -0
  26. package/docs/apis/features/agi/skills-library.md +216 -0
  27. package/docs/apis/features/node/container-link.md +133 -0
  28. package/docs/apis/features/node/content-db.md +313 -0
  29. package/docs/apis/features/node/disk-cache.md +379 -0
  30. package/docs/apis/features/node/dns.md +651 -0
  31. package/docs/apis/features/node/docker.md +705 -0
  32. package/docs/apis/features/node/downloader.md +81 -0
  33. package/docs/apis/features/node/esbuild.md +59 -0
  34. package/docs/apis/features/node/file-manager.md +182 -0
  35. package/docs/apis/features/node/fs.md +581 -0
  36. package/docs/apis/features/node/git.md +330 -0
  37. package/docs/apis/features/node/google-auth.md +174 -0
  38. package/docs/apis/features/node/google-calendar.md +187 -0
  39. package/docs/apis/features/node/google-docs.md +151 -0
  40. package/docs/apis/features/node/google-drive.md +225 -0
  41. package/docs/apis/features/node/google-sheets.md +179 -0
  42. package/docs/apis/features/node/grep.md +290 -0
  43. package/docs/apis/features/node/helpers.md +135 -0
  44. package/docs/apis/features/node/ink.md +334 -0
  45. package/docs/apis/features/node/ipc-socket.md +260 -0
  46. package/docs/apis/features/node/json-tree.md +86 -0
  47. package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
  48. package/docs/apis/features/node/networking.md +281 -0
  49. package/docs/apis/features/node/nlp.md +133 -0
  50. package/docs/apis/features/node/opener.md +97 -0
  51. package/docs/apis/features/node/os.md +118 -0
  52. package/docs/apis/features/node/package-finder.md +402 -0
  53. package/docs/apis/features/node/postgres.md +212 -0
  54. package/docs/apis/features/node/proc.md +430 -0
  55. package/docs/apis/features/node/process-manager.md +210 -0
  56. package/docs/apis/features/node/python.md +278 -0
  57. package/docs/apis/features/node/repl.md +88 -0
  58. package/docs/apis/features/node/runpod.md +673 -0
  59. package/docs/apis/features/node/secure-shell.md +169 -0
  60. package/docs/apis/features/node/semantic-search.md +401 -0
  61. package/docs/apis/features/node/sqlite.md +211 -0
  62. package/docs/apis/features/node/telegram.md +254 -0
  63. package/docs/apis/features/node/tts.md +118 -0
  64. package/docs/apis/features/node/ui.md +703 -0
  65. package/docs/apis/features/node/vault.md +64 -0
  66. package/docs/apis/features/node/vm.md +84 -0
  67. package/docs/apis/features/node/window-manager.md +337 -0
  68. package/docs/apis/features/node/yaml-tree.md +85 -0
  69. package/docs/apis/features/node/yaml.md +176 -0
  70. package/docs/apis/features/web/asset-loader.md +47 -0
  71. package/docs/apis/features/web/container-link.md +133 -0
  72. package/docs/apis/features/web/esbuild.md +59 -0
  73. package/docs/apis/features/web/helpers.md +135 -0
  74. package/docs/apis/features/web/network.md +30 -0
  75. package/docs/apis/features/web/speech.md +55 -0
  76. package/docs/apis/features/web/vault.md +64 -0
  77. package/docs/apis/features/web/vm.md +84 -0
  78. package/docs/apis/features/web/voice.md +67 -0
  79. package/docs/apis/servers/express.md +127 -0
  80. package/docs/apis/servers/mcp.md +213 -0
  81. package/docs/apis/servers/websocket.md +99 -0
  82. package/docs/documentation-audit.md +134 -0
  83. package/docs/examples/content-db.md +77 -0
  84. package/docs/examples/disk-cache.md +83 -0
  85. package/docs/examples/docker.md +101 -0
  86. package/docs/examples/downloader.md +70 -0
  87. package/docs/examples/esbuild.md +80 -0
  88. package/docs/examples/file-manager.md +82 -0
  89. package/docs/examples/fs.md +83 -0
  90. package/docs/examples/git.md +85 -0
  91. package/docs/examples/google-auth.md +88 -0
  92. package/docs/examples/google-calendar.md +94 -0
  93. package/docs/examples/google-docs.md +82 -0
  94. package/docs/examples/google-drive.md +96 -0
  95. package/docs/examples/google-sheets.md +95 -0
  96. package/docs/examples/grep.md +85 -0
  97. package/docs/examples/ink-blocks.md +75 -0
  98. package/docs/examples/ink-renderer.md +41 -0
  99. package/docs/examples/ink.md +103 -0
  100. package/docs/examples/ipc-socket.md +103 -0
  101. package/docs/examples/json-tree.md +91 -0
  102. package/docs/examples/launcher-app-command-listener.md +120 -0
  103. package/docs/examples/networking.md +58 -0
  104. package/docs/examples/nlp.md +91 -0
  105. package/docs/examples/opener.md +78 -0
  106. package/docs/examples/os.md +72 -0
  107. package/docs/examples/package-finder.md +89 -0
  108. package/docs/examples/port-exposer.md +89 -0
  109. package/docs/examples/postgres.md +91 -0
  110. package/docs/examples/proc.md +81 -0
  111. package/docs/examples/process-manager.md +79 -0
  112. package/docs/examples/python.md +91 -0
  113. package/docs/examples/repl.md +93 -0
  114. package/docs/examples/runpod.md +119 -0
  115. package/docs/examples/secure-shell.md +92 -0
  116. package/docs/examples/sqlite.md +86 -0
  117. package/docs/examples/telegram.md +77 -0
  118. package/docs/examples/tts.md +86 -0
  119. package/docs/examples/ui.md +80 -0
  120. package/docs/examples/vault.md +70 -0
  121. package/docs/examples/vm.md +86 -0
  122. package/docs/examples/window-manager.md +125 -0
  123. package/docs/examples/yaml-tree.md +93 -0
  124. package/docs/examples/yaml.md +104 -0
  125. package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
  126. package/docs/ideas/container-use-api.md +9 -0
  127. package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
  128. package/docs/ideas/feature-stacks.md +22 -0
  129. package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
  130. package/docs/ideas/mcp-design.md +9 -0
  131. package/docs/ideas/web-container-debugging-feature.md +13 -0
  132. package/docs/introspection-audit.md +49 -0
  133. package/docs/introspection.md +154 -0
  134. package/docs/mcp/readme.md +162 -0
  135. package/docs/models.ts +38 -0
  136. package/docs/philosophy.md +85 -0
  137. package/docs/principles.md +7 -0
  138. package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
  139. package/docs/prompts/mcp-test-easy-command.md +27 -0
  140. package/docs/reports/assistant-bugs.md +38 -0
  141. package/docs/reports/attach-pattern-usage.md +18 -0
  142. package/docs/reports/code-audit-results.md +391 -0
  143. package/docs/reports/introspection-audit-tasks.md +378 -0
  144. package/docs/reports/luca-mcp-improvements.md +128 -0
  145. package/docs/scaffolds/client.md +140 -0
  146. package/docs/scaffolds/command.md +106 -0
  147. package/docs/scaffolds/endpoint.md +176 -0
  148. package/docs/scaffolds/feature.md +148 -0
  149. package/docs/scaffolds/server.md +187 -0
  150. package/docs/tasks/web-container-helper-discovery.md +71 -0
  151. package/docs/todos.md +1 -0
  152. package/docs/tutorials/01-getting-started.md +106 -0
  153. package/docs/tutorials/02-container.md +210 -0
  154. package/docs/tutorials/03-scripts.md +194 -0
  155. package/docs/tutorials/04-features-overview.md +196 -0
  156. package/docs/tutorials/05-state-and-events.md +171 -0
  157. package/docs/tutorials/06-servers.md +157 -0
  158. package/docs/tutorials/07-endpoints.md +198 -0
  159. package/docs/tutorials/08-commands.md +171 -0
  160. package/docs/tutorials/09-clients.md +162 -0
  161. package/docs/tutorials/10-creating-features.md +198 -0
  162. package/docs/tutorials/11-contentbase.md +191 -0
  163. package/docs/tutorials/12-assistants.md +215 -0
  164. package/docs/tutorials/13-introspection.md +147 -0
  165. package/docs/tutorials/14-type-system.md +174 -0
  166. package/docs/tutorials/15-project-patterns.md +222 -0
  167. package/docs/tutorials/16-google-features.md +534 -0
  168. package/docs/tutorials/17-tui-blocks.md +530 -0
  169. package/docs/tutorials/18-semantic-search.md +334 -0
  170. package/index.ts +1 -0
  171. package/luca.console.ts +9 -0
  172. package/main.py +6 -0
  173. package/package.json +154 -0
  174. package/pyproject.toml +7 -0
  175. package/scripts/animations/chrome-glitch.ts +55 -0
  176. package/scripts/animations/index.ts +16 -0
  177. package/scripts/animations/neon-pulse.ts +64 -0
  178. package/scripts/animations/types.ts +6 -0
  179. package/scripts/build-web.ts +28 -0
  180. package/scripts/examples/ask-luca-expert.ts +42 -0
  181. package/scripts/examples/assistant-questions.ts +12 -0
  182. package/scripts/examples/excalidraw-expert.ts +75 -0
  183. package/scripts/examples/expert-chat.ts +0 -0
  184. package/scripts/examples/file-manager.ts +14 -0
  185. package/scripts/examples/ideas.ts +12 -0
  186. package/scripts/examples/interactive-chat.ts +20 -0
  187. package/scripts/examples/openai-tool-calls.ts +113 -0
  188. package/scripts/examples/opening-a-web-browser.ts +5 -0
  189. package/scripts/examples/telegram-bot.ts +79 -0
  190. package/scripts/examples/telegram-ink-ui.ts +302 -0
  191. package/scripts/examples/using-assistant-with-mcp.ts +560 -0
  192. package/scripts/examples/using-claude-code.ts +10 -0
  193. package/scripts/examples/using-contentdb.ts +35 -0
  194. package/scripts/examples/using-conversations.ts +35 -0
  195. package/scripts/examples/using-disk-cache.ts +10 -0
  196. package/scripts/examples/using-docker-shell.ts +75 -0
  197. package/scripts/examples/using-elevenlabs.ts +25 -0
  198. package/scripts/examples/using-google-calendar.ts +57 -0
  199. package/scripts/examples/using-google-docs.ts +74 -0
  200. package/scripts/examples/using-google-drive.ts +74 -0
  201. package/scripts/examples/using-google-sheets.ts +89 -0
  202. package/scripts/examples/using-nlp.ts +55 -0
  203. package/scripts/examples/using-ollama.ts +10 -0
  204. package/scripts/examples/using-openai-codex.ts +23 -0
  205. package/scripts/examples/using-postgres.ts +55 -0
  206. package/scripts/examples/using-runpod.ts +32 -0
  207. package/scripts/examples/using-tts.ts +40 -0
  208. package/scripts/examples/vm-loading-esm-modules.ts +16 -0
  209. package/scripts/scaffold.ts +391 -0
  210. package/scripts/scratch.ts +15 -0
  211. package/scripts/test-command-listener.ts +123 -0
  212. package/scripts/test-window-manager-lifecycle.ts +86 -0
  213. package/scripts/test-window-manager.ts +43 -0
  214. package/scripts/update-introspection-data.ts +58 -0
  215. package/src/agi/README.md +14 -0
  216. package/src/agi/container.server.ts +114 -0
  217. package/src/agi/endpoints/ask.ts +60 -0
  218. package/src/agi/endpoints/conversations/[id].ts +45 -0
  219. package/src/agi/endpoints/conversations.ts +31 -0
  220. package/src/agi/endpoints/experts.ts +37 -0
  221. package/src/agi/features/assistant.ts +767 -0
  222. package/src/agi/features/assistants-manager.ts +260 -0
  223. package/src/agi/features/claude-code.ts +1111 -0
  224. package/src/agi/features/conversation-history.ts +497 -0
  225. package/src/agi/features/conversation.ts +799 -0
  226. package/src/agi/features/openai-codex.ts +631 -0
  227. package/src/agi/features/openapi.ts +438 -0
  228. package/src/agi/features/skills-library.ts +425 -0
  229. package/src/agi/index.ts +6 -0
  230. package/src/agi/lib/token-counter.ts +122 -0
  231. package/src/browser.ts +25 -0
  232. package/src/bus.ts +100 -0
  233. package/src/cli/cli.ts +70 -0
  234. package/src/client.ts +461 -0
  235. package/src/clients/civitai/index.ts +541 -0
  236. package/src/clients/client-template.ts +41 -0
  237. package/src/clients/comfyui/index.ts +597 -0
  238. package/src/clients/elevenlabs/index.ts +291 -0
  239. package/src/clients/openai/index.ts +451 -0
  240. package/src/clients/supabase/index.ts +366 -0
  241. package/src/command.ts +164 -0
  242. package/src/commands/chat.ts +182 -0
  243. package/src/commands/console.ts +192 -0
  244. package/src/commands/describe.ts +433 -0
  245. package/src/commands/eval.ts +116 -0
  246. package/src/commands/help.ts +214 -0
  247. package/src/commands/index.ts +14 -0
  248. package/src/commands/mcp.ts +64 -0
  249. package/src/commands/prompt.ts +807 -0
  250. package/src/commands/run.ts +257 -0
  251. package/src/commands/sandbox-mcp.ts +439 -0
  252. package/src/commands/scaffold.ts +79 -0
  253. package/src/commands/serve.ts +172 -0
  254. package/src/container.ts +781 -0
  255. package/src/endpoint.ts +340 -0
  256. package/src/feature.ts +75 -0
  257. package/src/hash-object.ts +97 -0
  258. package/src/helper.ts +543 -0
  259. package/src/introspection/generated.agi.ts +23388 -0
  260. package/src/introspection/generated.node.ts +18899 -0
  261. package/src/introspection/generated.web.ts +2021 -0
  262. package/src/introspection/index.ts +256 -0
  263. package/src/introspection/scan.ts +912 -0
  264. package/src/node/container.ts +354 -0
  265. package/src/node/feature.ts +13 -0
  266. package/src/node/features/container-link.ts +558 -0
  267. package/src/node/features/content-db.ts +475 -0
  268. package/src/node/features/disk-cache.ts +382 -0
  269. package/src/node/features/dns.ts +655 -0
  270. package/src/node/features/docker.ts +912 -0
  271. package/src/node/features/downloader.ts +92 -0
  272. package/src/node/features/esbuild.ts +68 -0
  273. package/src/node/features/file-manager.ts +357 -0
  274. package/src/node/features/fs.ts +534 -0
  275. package/src/node/features/git.ts +492 -0
  276. package/src/node/features/google-auth.ts +502 -0
  277. package/src/node/features/google-calendar.ts +300 -0
  278. package/src/node/features/google-docs.ts +404 -0
  279. package/src/node/features/google-drive.ts +339 -0
  280. package/src/node/features/google-sheets.ts +279 -0
  281. package/src/node/features/grep.ts +406 -0
  282. package/src/node/features/helpers.ts +374 -0
  283. package/src/node/features/ink.ts +490 -0
  284. package/src/node/features/ipc-socket.ts +459 -0
  285. package/src/node/features/json-tree.ts +188 -0
  286. package/src/node/features/launcher-app-command-listener.ts +388 -0
  287. package/src/node/features/networking.ts +925 -0
  288. package/src/node/features/nlp.ts +211 -0
  289. package/src/node/features/opener.ts +166 -0
  290. package/src/node/features/os.ts +157 -0
  291. package/src/node/features/package-finder.ts +539 -0
  292. package/src/node/features/port-exposer.ts +342 -0
  293. package/src/node/features/postgres.ts +273 -0
  294. package/src/node/features/proc.ts +502 -0
  295. package/src/node/features/process-manager.ts +542 -0
  296. package/src/node/features/python.ts +444 -0
  297. package/src/node/features/repl.ts +194 -0
  298. package/src/node/features/runpod.ts +802 -0
  299. package/src/node/features/secure-shell.ts +248 -0
  300. package/src/node/features/semantic-search.ts +924 -0
  301. package/src/node/features/sqlite.ts +289 -0
  302. package/src/node/features/telegram.ts +342 -0
  303. package/src/node/features/tts.ts +184 -0
  304. package/src/node/features/ui.ts +857 -0
  305. package/src/node/features/vault.ts +164 -0
  306. package/src/node/features/vm.ts +312 -0
  307. package/src/node/features/window-manager.ts +804 -0
  308. package/src/node/features/yaml-tree.ts +149 -0
  309. package/src/node/features/yaml.ts +132 -0
  310. package/src/node.ts +70 -0
  311. package/src/react/index.ts +175 -0
  312. package/src/registry.ts +199 -0
  313. package/src/scaffolds/generated.ts +1613 -0
  314. package/src/scaffolds/template.ts +37 -0
  315. package/src/schemas/base.ts +255 -0
  316. package/src/server.ts +135 -0
  317. package/src/servers/express.ts +209 -0
  318. package/src/servers/mcp.ts +805 -0
  319. package/src/servers/socket.ts +120 -0
  320. package/src/state.ts +101 -0
  321. package/src/web/clients/socket.ts +82 -0
  322. package/src/web/container.ts +74 -0
  323. package/src/web/extension.ts +30 -0
  324. package/src/web/feature.ts +12 -0
  325. package/src/web/features/asset-loader.ts +64 -0
  326. package/src/web/features/container-link.ts +385 -0
  327. package/src/web/features/esbuild.ts +79 -0
  328. package/src/web/features/helpers.ts +267 -0
  329. package/src/web/features/network.ts +61 -0
  330. package/src/web/features/speech.ts +87 -0
  331. package/src/web/features/vault.ts +189 -0
  332. package/src/web/features/vm.ts +78 -0
  333. package/src/web/features/voice-recognition.ts +129 -0
  334. package/src/web/shims/isomorphic-vm.ts +149 -0
  335. package/test/bus.test.ts +134 -0
  336. package/test/clients-servers.test.ts +216 -0
  337. package/test/container-link.test.ts +274 -0
  338. package/test/features.test.ts +160 -0
  339. package/test/integration.test.ts +787 -0
  340. package/test/node-container.test.ts +121 -0
  341. package/test/rate-limit.test.ts +272 -0
  342. package/test/semantic-search.test.ts +550 -0
  343. package/test/state.test.ts +121 -0
  344. package/test-integration/assistant.test.ts +138 -0
  345. package/test-integration/assistants-manager.test.ts +123 -0
  346. package/test-integration/claude-code.test.ts +98 -0
  347. package/test-integration/conversation-history.test.ts +205 -0
  348. package/test-integration/conversation.test.ts +137 -0
  349. package/test-integration/elevenlabs.test.ts +55 -0
  350. package/test-integration/google-services.test.ts +80 -0
  351. package/test-integration/helpers.ts +89 -0
  352. package/test-integration/openai-codex.test.ts +93 -0
  353. package/test-integration/runpod.test.ts +58 -0
  354. package/test-integration/server-endpoints.test.ts +97 -0
  355. package/test-integration/skills-library.test.ts +157 -0
  356. package/test-integration/telegram.test.ts +46 -0
  357. package/tsconfig.json +58 -0
  358. package/uv.lock +8 -0
@@ -0,0 +1,382 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
+ import cacache from "cacache";
4
+ import { Feature, type FeatureState, features } from "../feature.js";
5
+ import { NodeContainer } from "../container.js";
6
+ import { partial } from "lodash-es";
7
+ import type { ContainerContext } from "../../container.js";
8
+
9
+ export const DiskCacheOptionsSchema = FeatureOptionsSchema.extend({
10
+ /** Whether to enable encryption for cached data */
11
+ encrypt: z.boolean().optional().describe('Whether to enable encryption for cached data'),
12
+ /** Secret key used for encryption operations */
13
+ secret: z.custom<Buffer>().optional().describe('Secret key buffer used for encryption operations'),
14
+ /** Custom directory path for the cache storage */
15
+ path: z.string().optional().describe('Custom directory path for the cache storage'),
16
+ })
17
+
18
+ export type DiskCacheOptions = z.infer<typeof DiskCacheOptionsSchema>
19
+
20
+ /**
21
+ * File-backed key-value cache built on top of the cacache library (the same store
22
+ * that powers npm). Suitable for persisting arbitrary data including very large
23
+ * blobs when necessary, with optional encryption support.
24
+ *
25
+ * @extends Feature
26
+ * @example
27
+ * ```typescript
28
+ * const diskCache = container.feature('diskCache', { path: '/tmp/cache' })
29
+ * await diskCache.set('greeting', 'Hello World')
30
+ * const value = await diskCache.get('greeting')
31
+ * ```
32
+ */
33
+ export class DiskCache extends Feature<FeatureState,DiskCacheOptions> {
34
+ static override shortcut = "features.diskCache" as const
35
+ static override stateSchema = FeatureStateSchema
36
+ static override optionsSchema = DiskCacheOptionsSchema
37
+
38
+ static attach(c: NodeContainer) {}
39
+
40
+ constructor(options: DiskCacheOptions, context: ContainerContext) {
41
+ super(options, context)
42
+ this._cache = this.create()
43
+ this.hide('_cache')
44
+ }
45
+
46
+ /** Returns the underlying cacache instance configured with the cache directory path. */
47
+ get cache() {
48
+ return this._cache
49
+ }
50
+
51
+ /**
52
+ * Retrieve a file from the disk cache and save it to the local disk
53
+ * @param key - The cache key to retrieve
54
+ * @param outputPath - The local path where the file should be saved
55
+ * @param isBase64 - Whether the cached content is base64 encoded
56
+ * @returns Promise that resolves to the file data as Buffer
57
+ * @example
58
+ * ```typescript
59
+ * await diskCache.saveFile('myFile', './output/file.txt')
60
+ * await diskCache.saveFile('encodedImage', './images/photo.jpg', true)
61
+ * ```
62
+ */
63
+ async saveFile(key: string, outputPath: string, isBase64 = false) {
64
+ const outPath = this.container.paths.resolve(outputPath)
65
+ const content = await this.get(key)
66
+ const data = isBase64 ? Buffer.from(content, 'base64') : content
67
+ await this.container.fs.writeFileAsync(outPath, data)
68
+ return data
69
+ }
70
+
71
+ /**
72
+ * Ensure a key exists in the cache, setting it with the provided content if it doesn't exist
73
+ * @param key - The cache key to check/set
74
+ * @param content - The content to set if the key doesn't exist
75
+ * @returns Promise that resolves to the key
76
+ * @example
77
+ * ```typescript
78
+ * await diskCache.ensure('config', JSON.stringify(defaultConfig))
79
+ * ```
80
+ */
81
+ async ensure(key: string, content: string) {
82
+ const exists = await this.has(key)
83
+
84
+ if (!exists) {
85
+ await this.set(key, content)
86
+ }
87
+
88
+ return key
89
+ }
90
+
91
+ /**
92
+ * Copy a cached item from one key to another
93
+ * @param source - The source cache key
94
+ * @param destination - The destination cache key
95
+ * @param overwrite - Whether to overwrite if destination exists (default: false)
96
+ * @returns Promise that resolves to the destination key
97
+ * @throws Error if destination exists and overwrite is false
98
+ * @example
99
+ * ```typescript
100
+ * await diskCache.copy('original', 'backup')
101
+ * await diskCache.copy('file1', 'file2', true) // force overwrite
102
+ * ```
103
+ */
104
+ async copy(source: string, destination: string, overwrite: boolean = false) {
105
+ if(!overwrite && (await this.has(destination))) {
106
+ throw new Error('Destination already exists')
107
+ }
108
+
109
+ const content = await this.get(source)
110
+ await this.set(destination, content)
111
+ return destination
112
+ }
113
+
114
+ /**
115
+ * Move a cached item from one key to another (copy then delete source)
116
+ * @param source - The source cache key
117
+ * @param destination - The destination cache key
118
+ * @param overwrite - Whether to overwrite if destination exists (default: false)
119
+ * @returns Promise that resolves to the destination key
120
+ * @throws Error if destination exists and overwrite is false
121
+ * @example
122
+ * ```typescript
123
+ * await diskCache.move('temp', 'permanent')
124
+ * await diskCache.move('old_key', 'new_key', true) // force overwrite
125
+ * ```
126
+ */
127
+ async move(source: string, destination: string, overwrite: boolean = false) {
128
+ if(!overwrite && (await this.has(destination))) {
129
+ throw new Error('Destination already exists')
130
+ }
131
+
132
+ const content = await this.get(source)
133
+ await this.set(destination, content)
134
+ await this.rm(source)
135
+ return destination
136
+ }
137
+
138
+ /**
139
+ * Check if a key exists in the cache
140
+ * @param key - The cache key to check
141
+ * @returns Promise that resolves to true if key exists, false otherwise
142
+ * @example
143
+ * ```typescript
144
+ * if (await diskCache.has('myKey')) {
145
+ * console.log('Key exists!')
146
+ * }
147
+ * ```
148
+ */
149
+ async has(key: string) {
150
+ return this.cache.get.info(key).then((r:any) => r != null)
151
+ }
152
+
153
+ /**
154
+ * Retrieve a value from the cache
155
+ * @param key - The cache key to retrieve
156
+ * @param json - Whether to parse the value as JSON (default: false)
157
+ * @returns Promise that resolves to the cached value (string or parsed JSON)
158
+ * @example
159
+ * ```typescript
160
+ * const text = await diskCache.get('myText')
161
+ * const data = await diskCache.get('myData', true) // parse as JSON
162
+ * ```
163
+ */
164
+ async get(key: string, json = false) {
165
+ const val = this.options.encrypt
166
+ ? await this.securely.get(key)
167
+ : await this.cache.get(key).then((data: any) => data.data.toString())
168
+
169
+ if (json) {
170
+ try {
171
+ return JSON.parse(val)
172
+ } catch(error) {
173
+ return { error: "parse error "}
174
+ }
175
+ } else {
176
+ return val
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Store a value in the cache
182
+ * @param key - The cache key to store under
183
+ * @param value - The value to store (string, object, or any serializable data)
184
+ * @param meta - Optional metadata to associate with the cached item
185
+ * @returns Promise that resolves when the value is stored
186
+ * @example
187
+ * ```typescript
188
+ * await diskCache.set('myKey', 'Hello World')
189
+ * await diskCache.set('userData', { name: 'John', age: 30 })
190
+ * await diskCache.set('file', content, { size: 1024, type: 'image' })
191
+ * ```
192
+ */
193
+ async set(key: string, value: any, meta?: any) {
194
+ if (this.options.encrypt) {
195
+ return this.securely.set(key, value, meta)
196
+ }
197
+
198
+ if(typeof value !== 'string') {
199
+ return this.cache.put(key, Buffer.from(JSON.stringify(value)), {
200
+ ...(meta && { metadata: meta })
201
+ })
202
+ } else {
203
+ return this.cache.put(key, Buffer.from(value), {
204
+ ...(meta && { metadata: meta })
205
+ })
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Remove a cached item
211
+ * @param key - The cache key to remove
212
+ * @returns Promise that resolves when the item is removed
213
+ * @example
214
+ * ```typescript
215
+ * await diskCache.rm('obsoleteKey')
216
+ * ```
217
+ */
218
+ async rm(key: string) {
219
+ return this.cache.rm.entry(key)
220
+ }
221
+
222
+ /**
223
+ * Clear all cached items
224
+ * @param confirm - Must be set to true to confirm the operation
225
+ * @returns Promise that resolves to this instance for chaining
226
+ * @throws Error if confirm is not true
227
+ * @example
228
+ * ```typescript
229
+ * await diskCache.clearAll(true) // Must explicitly confirm
230
+ * ```
231
+ */
232
+ async clearAll(confirm = false) {
233
+ if(confirm !== true) {
234
+ throw new Error('Must confirm with clearAll(true)')
235
+ }
236
+ await this.cache.rm.all()
237
+ return this
238
+ }
239
+
240
+ /**
241
+ * Get all cache keys
242
+ * @returns Promise that resolves to an array of all cache keys
243
+ * @example
244
+ * ```typescript
245
+ * const allKeys = await diskCache.keys()
246
+ * console.log(`Cache contains ${allKeys.length} items`)
247
+ * ```
248
+ */
249
+ async keys() : Promise<string[]> {
250
+ return this.cache.ls().then((results: Record<string,any>) => Object.keys(results))
251
+ }
252
+
253
+ /**
254
+ * List all cache keys (alias for keys())
255
+ * @returns Promise that resolves to an array of all cache keys
256
+ * @example
257
+ * ```typescript
258
+ * const keyList = await diskCache.listKeys()
259
+ * ```
260
+ */
261
+ async listKeys() : Promise<string[]> {
262
+ return this.cache.ls().then((results: Record<string,any>) => Object.keys(results))
263
+ }
264
+
265
+ /**
266
+ * Get encrypted cache operations interface
267
+ * Requires encryption to be enabled and a secret to be provided
268
+ * @returns Object with encrypted get/set operations
269
+ * @throws Error if encryption is not enabled or no secret is provided
270
+ * @example
271
+ * ```typescript
272
+ * // Initialize with encryption
273
+ * const cache = container.feature('diskCache', {
274
+ * encrypt: true,
275
+ * secret: Buffer.from('my-secret-key')
276
+ * })
277
+ *
278
+ * // Use encrypted operations
279
+ * await cache.securely.set('sensitive', 'secret data')
280
+ * const decrypted = await cache.securely.get('sensitive')
281
+ * ```
282
+ */
283
+ get securely() {
284
+ const { secret, encrypt } = this.options
285
+
286
+ if (!encrypt) {
287
+ throw new Error(`Cannot use securely without encryption enabled`)
288
+ }
289
+
290
+ if (!secret) {
291
+ throw new Error(`Cannot use securely without a secret`)
292
+ }
293
+
294
+ const vault = this.container.feature('vault', {
295
+ secret
296
+ })
297
+
298
+ const { cache } = this
299
+
300
+ return {
301
+ /**
302
+ * Store an encrypted value in the cache
303
+ * @param name - The cache key
304
+ * @param payload - The data to encrypt and store
305
+ * @param meta - Optional metadata (will also be encrypted)
306
+ * @returns Promise that resolves when stored
307
+ */
308
+ async set(name: string, payload: any, meta?: any) {
309
+ const encrypted = vault.encrypt(payload)
310
+ return cache.put(name, Buffer.from(encrypted), {
311
+ ...(meta && { metadata: {
312
+ encrypted: vault.encrypt(JSON.stringify(meta))
313
+ }})
314
+ })
315
+ },
316
+ /**
317
+ * Retrieve and decrypt a value from the cache
318
+ * @param name - The cache key
319
+ * @returns Promise that resolves to the decrypted data
320
+ */
321
+ async get(name: string) {
322
+ const value = await cache.get(name).then((data: any) => data.data.toString())
323
+ return vault.decrypt(value)
324
+ }
325
+ }
326
+ }
327
+
328
+ _cache!: ReturnType<typeof this.create>
329
+
330
+ /**
331
+ * Create a cacache instance with the specified path
332
+ * @param path - Optional cache directory path (defaults to options.path or node_modules/.cache/luca-disk-cache)
333
+ * @returns Configured cacache instance with all methods bound to the path
334
+ * @example
335
+ * ```typescript
336
+ * const customCache = diskCache.create('/custom/cache/path')
337
+ * ```
338
+ */
339
+ create(path?: string) {
340
+ path = path || this.options.path || this.container.paths.resolve('node_modules', '.cache', 'luca-disk-cache')
341
+ this.container.fs.ensureFolder(path)
342
+ const arg = (fn: (...args: any) => any) => partial(fn, path);
343
+
344
+ const ls = arg(cacache.ls);
345
+ const get = arg(cacache.get);
346
+ const put = arg(cacache.put);
347
+ const rm = arg(cacache.rm);
348
+ const verify = arg(cacache.verify);
349
+
350
+ return {
351
+ ...cacache,
352
+ cachePath: path,
353
+ ls: Object.assign(ls, {
354
+ stream: arg(cacache.ls.stream),
355
+ }),
356
+ get: Object.assign(get, {
357
+ stream: arg(cacache.get.stream),
358
+ byDigest: arg(cacache.get.byDigest),
359
+ copy: arg(cacache.get.copy),
360
+ info: arg(cacache.get.info),
361
+ hasContent: arg(cacache.get.hasContent),
362
+ }),
363
+ put: Object.assign(put, {
364
+ stream: arg(cacache.put.stream),
365
+ }),
366
+ rm: Object.assign(rm, {
367
+ all: arg(cacache.rm.all),
368
+ entry: arg(cacache.rm.entry),
369
+ content: arg(cacache.rm.content),
370
+ }),
371
+ tmp: {
372
+ mkdir: arg(cacache.tmp.mkdir),
373
+ withTmp: arg(cacache.tmp.withTmp),
374
+ },
375
+ verify: Object.assign(verify, {
376
+ lastRun: arg(cacache.verify.lastRun),
377
+ }),
378
+ };
379
+ }
380
+ }
381
+
382
+ export default features.register("diskCache", DiskCache);