commandkit 1.0.0-dev.20250722021811 → 1.0.0-dev.20250723021937

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 (102) hide show
  1. package/dist/ActionRow-CmTHbo2t.js.map +1 -1
  2. package/dist/CommandKitEventsChannel-BSdcgY3Q.js.map +1 -1
  3. package/dist/CommandsRouter-Bs9UuowL.js.map +1 -1
  4. package/dist/EventInterceptor-CQ4PBpBJ.js.map +1 -1
  5. package/dist/EventWorkerContext-DxfS_0fJ.js.map +1 -1
  6. package/dist/EventsRouter-B7oifgM6.js.map +1 -1
  7. package/dist/MessageCommandParser-CGhN3xNN.js.map +1 -1
  8. package/dist/PluginCommon-Di1xIa8d.js.map +1 -1
  9. package/dist/analytics/analytics-engine.js +1 -1
  10. package/dist/analytics/utils.js +1 -1
  11. package/dist/app/commands/AppCommandRunner.js +1 -1
  12. package/dist/app/commands/Context.js +1 -1
  13. package/dist/app/handlers/AppCommandHandler.js +1 -1
  14. package/dist/app/handlers/AppEventsHandler.js +1 -1
  15. package/dist/app/index.js +1 -1
  16. package/dist/app/register/CommandRegistrar.js +1 -1
  17. package/dist/app-process-CKLJAmil.js.map +1 -1
  18. package/dist/{build-BylWoAy4.js → build-D8P0ENm6.js} +2 -2
  19. package/dist/{build-BylWoAy4.js.map → build-D8P0ENm6.js.map} +1 -1
  20. package/dist/cli/build.js +2 -2
  21. package/dist/cli/common.d.ts +2 -2
  22. package/dist/cli/development.js +2 -2
  23. package/dist/cli/development.js.map +1 -1
  24. package/dist/cli/generators.js.map +1 -1
  25. package/dist/cli/information.js +1 -1
  26. package/dist/cli/information.js.map +1 -1
  27. package/dist/cli/init.d.ts +1 -1
  28. package/dist/cli/init.js +2 -2
  29. package/dist/cli/production.d.ts +2 -2
  30. package/dist/cli/production.js +2 -2
  31. package/dist/cli/production.js.map +1 -1
  32. package/dist/colors-Cd4Oz-r-.js.map +1 -1
  33. package/dist/{commandkit-DYYj5_OH.js → commandkit-CUFTPuzm.js} +24 -24
  34. package/dist/{commandkit-DYYj5_OH.js.map → commandkit-CUFTPuzm.js.map} +1 -1
  35. package/dist/commandkit.js +1 -1
  36. package/dist/common-DoZjgUs0.js.map +1 -1
  37. package/dist/common-vnMIelAE.js.map +1 -1
  38. package/dist/components/index.js +1 -1
  39. package/dist/components/v1/button/Button.js +1 -1
  40. package/dist/components/v1/button/ButtonKit.js +1 -1
  41. package/dist/components/v1/modal/Modal.js +1 -1
  42. package/dist/components/v1/modal/ModalKit.js +1 -1
  43. package/dist/components/v1/select-menu/ChannelSelectMenuKit.js +1 -1
  44. package/dist/components/v1/select-menu/MentionableSelectMenuKit.js +1 -1
  45. package/dist/components/v1/select-menu/RoleSelectMenuKit.js +1 -1
  46. package/dist/components/v1/select-menu/SelectMenu.js +1 -1
  47. package/dist/components/v1/select-menu/StringSelectMenuKit.js +1 -1
  48. package/dist/components/v1/select-menu/UserSelectMenuKit.js +1 -1
  49. package/dist/config/config.js +1 -1
  50. package/dist/config/default.js +1 -1
  51. package/dist/config/loader.js +1 -1
  52. package/dist/config/utils.js.map +1 -1
  53. package/dist/constants-DYSMm0U6.js.map +1 -1
  54. package/dist/constants-R96vEAFD.js.map +1 -1
  55. package/dist/container-DCjIgp-B.js.map +1 -1
  56. package/dist/context/async-context.js +1 -1
  57. package/dist/context/environment.js +1 -1
  58. package/dist/dotprops-C22abhGZ.js.map +1 -1
  59. package/dist/element-Bak9llw_.js.map +1 -1
  60. package/dist/env-DakvrBzy.js.map +1 -1
  61. package/dist/error-codes-C-ViHyu-.js.map +1 -1
  62. package/dist/{feature-flags-aCvzjoPi.js → feature-flags-CNRFFY4k.js} +2 -2
  63. package/dist/{feature-flags-aCvzjoPi.js.map → feature-flags-CNRFFY4k.js.map} +1 -1
  64. package/dist/file-DVZC0QXI.js.map +1 -1
  65. package/dist/flags/FlagProvider.js.map +1 -1
  66. package/dist/flags/feature-flags.js +2 -2
  67. package/dist/helpers-DfV6HlgI.js.map +1 -1
  68. package/dist/index.d.ts +2 -2
  69. package/dist/index.js +4 -4
  70. package/dist/{init-DsaK1AfD.d.ts → init-DOr-Y3GQ.d.ts} +3 -3
  71. package/dist/{init-5BxpQb8k.js → init-Dc4Qbgpg.js} +2 -2
  72. package/dist/{init-5BxpQb8k.js.map → init-Dc4Qbgpg.js.map} +1 -1
  73. package/dist/kv/kv.d.ts +1 -1
  74. package/dist/kv/kv.js.map +1 -1
  75. package/dist/logger/DefaultLogger.js +1 -1
  76. package/dist/logger/Logger.js +1 -1
  77. package/dist/media-gallery-CIKypjbJ.js.map +1 -1
  78. package/dist/plugins/index.js +1 -1
  79. package/dist/plugins/plugin-runtime/CommandKitPluginRuntime.js +1 -1
  80. package/dist/plugins/plugin-runtime/CompilerPluginRuntime.js +1 -1
  81. package/dist/plugins/plugin-runtime/builtin/CommonDirectiveTransformer.js +1 -1
  82. package/dist/plugins/plugin-runtime/builtin/MacroPlugin.js +1 -1
  83. package/dist/resolve-file-url-9aPt6A_n.js.map +1 -1
  84. package/dist/section-CuYr0Inu.js.map +1 -1
  85. package/dist/serde-CXY4F7OD.js.map +1 -1
  86. package/dist/signals-Bu7gndaS.js.map +1 -1
  87. package/dist/text-display--p2-BoUa.js.map +1 -1
  88. package/dist/type-checker-DDHZIEBi.js.map +1 -1
  89. package/dist/types-package-Dwub9JsW.js.map +1 -1
  90. package/dist/utils/colors.d.ts +2 -2
  91. package/dist/utils/dev-hooks.js +1 -1
  92. package/dist/utils/useful-stuff/async-queue.js.map +1 -1
  93. package/dist/utils/useful-stuff/mutex.js.map +1 -1
  94. package/dist/utils/useful-stuff/ratelimiter.js.map +1 -1
  95. package/dist/utils/useful-stuff/semaphore.js.map +1 -1
  96. package/dist/utils/utilities.js +1 -1
  97. package/dist/utils/warn-unstable.js.map +1 -1
  98. package/dist/utils-n4MoGDDR.js.map +1 -1
  99. package/dist/{version-c0OD-7y_.js → version-DrMgT0Vo.js} +2 -2
  100. package/dist/{version-c0OD-7y_.js.map → version-DrMgT0Vo.js.map} +1 -1
  101. package/dist/version.js +1 -1
  102. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"init-5BxpQb8k.js","names":[],"sources":["../src/cli/init.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { generateTypesPackage } from '../utils/types-package';\nimport { loadConfigFile } from '../config/loader';\nimport {\n CompilerPlugin,\n CompilerPluginRuntime,\n isCompilerPlugin,\n} from '../plugins';\nimport { panic } from './common';\nimport { COMMANDKIT_CWD } from '../utils/constants';\n\n/**\n * Creates a command line interface for CommandKit.\n * @param argv The arguments passed to the CLI.\n * @param options The options passed to the CLI.\n */\nexport async function bootstrapCommandkitCLI(\n argv: string[],\n options?: import('commander').ParseOptions | undefined,\n) {\n process.title = 'CommandKit CLI';\n\n // imports are lazily loaded when the cli is used, instead of loading it with the lib itself\n const { Command } = await import('commander');\n const { bootstrapDevelopmentServer } = await import('./development');\n const { bootstrapProductionServer, createProductionBuild } = await import(\n './production'\n );\n const { generateCommand, generateEvent } = await import('./generators');\n const { version } = await import('../version');\n const { showInformation } = await import('./information');\n const { setCLIEnv } = await import('./env');\n\n const program = new Command('commandkit');\n\n program\n .command('dev')\n .version(version)\n .description('Start your bot in development mode.')\n .option(\n '-c, --config [path]',\n 'Path to your commandkit config file.',\n './commandkit.js',\n )\n .action(() => {\n const options = program.opts();\n bootstrapDevelopmentServer(options.config);\n });\n\n program\n .command('info')\n .description(\n 'Show information about the system which can be used to report bugs.',\n )\n .action(async () => {\n await showInformation();\n });\n\n program\n .command('start')\n .description(\n 'Start your bot in production mode after running the build command.',\n )\n .option('-c, --config [path]', 'Path to your commandkit config file.')\n .action(() => {\n const options = program.opts();\n bootstrapProductionServer(options.config);\n });\n\n program\n .command('build')\n .description('Build your project for production usage.')\n .option('-c, --config [path]', 'Path to your commandkit config file.')\n .action(() => {\n setCLIEnv();\n const options = program.opts();\n return createProductionBuild(options.config);\n });\n\n program\n .command('create')\n .description(\n 'Create new files using built-in templates or custom plugin templates',\n )\n .argument(\n '<template>',\n 'The template to use (e.g. command, event, or custom plugin template)',\n )\n .argument('[args...]', 'Additional arguments for the template')\n .action(async (template, args) => {\n setCLIEnv();\n\n // Handle custom plugin templates\n const { plugins } = await loadConfigFile();\n const runtime = new CompilerPluginRuntime(\n plugins.filter((p) => isCompilerPlugin(p)) as CompilerPlugin[],\n );\n\n try {\n await runtime.init();\n const templateHandler = runtime.getTemplate(template);\n\n if (!templateHandler) {\n // Handle built-in templates\n if (template === 'command') {\n const [name] = args;\n if (!name) {\n panic('Command name is required');\n }\n await generateCommand(name);\n return;\n }\n\n if (template === 'event') {\n const [name] = args;\n if (!name) {\n panic('Event name is required');\n }\n await generateEvent(name);\n return;\n }\n\n const valid = Array.from(\n new Set([\n 'command',\n 'event',\n ...Array.from(runtime.getTemplates().keys()),\n ]),\n ).map((t) => `\"${t}\"`);\n\n panic(\n `Template \"${template}\" not found. Available templates: ${valid.join(', ')}`,\n );\n }\n\n await templateHandler(args);\n } catch (e: any) {\n panic(`Failed to execute template \"${template}\": ${e?.message || e}`);\n } finally {\n await runtime.destroy();\n }\n });\n\n const types = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n\n if (!existsSync(types)) {\n await mkdir(types, { recursive: true }).catch(() => {});\n await generateTypesPackage(true).catch(() => {});\n }\n\n await program.parseAsync(argv, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,eAAsB,uBACtB,MACA,SACA;AACE,SAAQ,QAAQ;CAGhB,MAAM,EAAE,SAAS,GAAG,MAAM,OAAO;CACjC,MAAM,EAAE,4BAA4B,GAAG,2CAAM;CAC7C,MAAM,EAAE,2BAA2B,uBAAuB,GAAG,2CAAM;CAGnE,MAAM,EAAE,iBAAiB,eAAe,GAAG,2CAAM;CACjD,MAAM,EAAE,SAAS,GAAG,2CAAM;CAC1B,MAAM,EAAE,iBAAiB,GAAG,2CAAM;CAClC,MAAM,EAAE,WAAW,GAAG,2CAAM;CAE5B,MAAM,UAAU,IAAI,QAAQ;AAE5B,SACA,QAAQ,MAAM,CACd,QAAQ,QAAQ,CAChB,YAAY,sCAAsC,CAClD,OACE,uBACA,wCACA,kBACD,CACD,OAAO,MAAM;EACX,MAAM,YAAU,QAAQ,MAAM;AAC9B,6BAA2B,UAAQ,OAAO;CAC3C,EAAC;AAEF,SACA,QAAQ,OAAO,CACf,YACE,sEACD,CACD,OAAO,YAAY;AACjB,QAAM,iBAAiB;CACxB,EAAC;AAEF,SACA,QAAQ,QAAQ,CAChB,YACE,qEACD,CACD,OAAO,uBAAuB,uCAAuC,CACrE,OAAO,MAAM;EACX,MAAM,YAAU,QAAQ,MAAM;AAC9B,4BAA0B,UAAQ,OAAO;CAC1C,EAAC;AAEF,SACA,QAAQ,QAAQ,CAChB,YAAY,2CAA2C,CACvD,OAAO,uBAAuB,uCAAuC,CACrE,OAAO,MAAM;AACX,aAAW;EACX,MAAM,YAAU,QAAQ,MAAM;AAC9B,SAAO,sBAAsB,UAAQ,OAAO;CAC7C,EAAC;AAEF,SACA,QAAQ,SAAS,CACjB,YACE,uEACD,CACD,SACE,cACA,uEACD,CACD,SAAS,aAAa,wCAAwC,CAC9D,OAAO,OAAO,UAAU,SAAS;AAC/B,aAAW;EAGX,MAAM,EAAE,SAAS,GAAG,MAAM,mCAAgB;EAC1C,MAAM,UAAU,IAAI,yCAClB,QAAQ,OAAO,CAAC,MAAM,wCAAiB,EAAE,CAAC;AAG5C,MAAI;AACF,SAAM,QAAQ,MAAM;GACpB,MAAM,kBAAkB,QAAQ,YAAY,SAAS;AAErD,QAAK,iBAAiB;AAEpB,QAAI,aAAa,WAAW;KAC1B,MAAM,CAAC,KAAK,GAAG;AACf,UAAK,KACH,sBAAM,2BAA2B;AAEnC,WAAM,gBAAgB,KAAK;AAC3B;IACD;AAED,QAAI,aAAa,SAAS;KACxB,MAAM,CAAC,KAAK,GAAG;AACf,UAAK,KACH,sBAAM,yBAAyB;AAEjC,WAAM,cAAc,KAAK;AACzB;IACD;IAED,MAAM,QAAQ,MAAM,KAClB,IAAI,IAAI;KACR;KACA;KACA,GAAG,MAAM,KAAK,QAAQ,cAAc,CAAC,MAAM,CAAC;IAAC,GAE9C,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG;AAEtB,0BACG,YAAY,SAAS,oCAAoC,MAAM,KAAK,KAAK,GAC3E;GACF;AAED,SAAM,gBAAgB,KAAK;EAC5B,SAAQ,GAAQ;AACf,yBAAO,8BAA8B,SAAS,4CAAK,EAAG,YAAW,IAAI;EACtE,UAAS;AACR,SAAM,QAAQ,SAAS;EACxB;CACF,EAAC;CAEF,MAAM,QAAQ,oBAAK,kCAAgB,gBAAgB,mBAAmB;AAEtE,MAAK,wBAAW,MAAM,EAAE;AACtB,QAAM,4BAAM,OAAO,EAAE,WAAW,KAAM,EAAC,CAAC,MAAM,MAAM,CAAE,EAAC;AACvD,QAAM,2CAAqB,KAAK,CAAC,MAAM,MAAM,CAAE,EAAC;CAClD;AAEA,OAAM,QAAQ,WAAW,MAAM,QAAQ;AACzC"}
1
+ {"version":3,"file":"init-Dc4Qbgpg.js","names":[],"sources":["../src/cli/init.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { generateTypesPackage } from '../utils/types-package';\nimport { loadConfigFile } from '../config/loader';\nimport {\n CompilerPlugin,\n CompilerPluginRuntime,\n isCompilerPlugin,\n} from '../plugins';\nimport { panic } from './common';\nimport { COMMANDKIT_CWD } from '../utils/constants';\n\n/**\n * Creates a command line interface for CommandKit.\n * @param argv The arguments passed to the CLI.\n * @param options The options passed to the CLI.\n */\nexport async function bootstrapCommandkitCLI(\n argv: string[],\n options?: import('commander').ParseOptions | undefined,\n) {\n process.title = 'CommandKit CLI';\n\n // imports are lazily loaded when the cli is used, instead of loading it with the lib itself\n const { Command } = await import('commander');\n const { bootstrapDevelopmentServer } = await import('./development');\n const { bootstrapProductionServer, createProductionBuild } = await import(\n './production'\n );\n const { generateCommand, generateEvent } = await import('./generators');\n const { version } = await import('../version');\n const { showInformation } = await import('./information');\n const { setCLIEnv } = await import('./env');\n\n const program = new Command('commandkit');\n\n program\n .command('dev')\n .version(version)\n .description('Start your bot in development mode.')\n .option(\n '-c, --config [path]',\n 'Path to your commandkit config file.',\n './commandkit.js',\n )\n .action(() => {\n const options = program.opts();\n bootstrapDevelopmentServer(options.config);\n });\n\n program\n .command('info')\n .description(\n 'Show information about the system which can be used to report bugs.',\n )\n .action(async () => {\n await showInformation();\n });\n\n program\n .command('start')\n .description(\n 'Start your bot in production mode after running the build command.',\n )\n .option('-c, --config [path]', 'Path to your commandkit config file.')\n .action(() => {\n const options = program.opts();\n bootstrapProductionServer(options.config);\n });\n\n program\n .command('build')\n .description('Build your project for production usage.')\n .option('-c, --config [path]', 'Path to your commandkit config file.')\n .action(() => {\n setCLIEnv();\n const options = program.opts();\n return createProductionBuild(options.config);\n });\n\n program\n .command('create')\n .description(\n 'Create new files using built-in templates or custom plugin templates',\n )\n .argument(\n '<template>',\n 'The template to use (e.g. command, event, or custom plugin template)',\n )\n .argument('[args...]', 'Additional arguments for the template')\n .action(async (template, args) => {\n setCLIEnv();\n\n // Handle custom plugin templates\n const { plugins } = await loadConfigFile();\n const runtime = new CompilerPluginRuntime(\n plugins.filter((p) => isCompilerPlugin(p)) as CompilerPlugin[],\n );\n\n try {\n await runtime.init();\n const templateHandler = runtime.getTemplate(template);\n\n if (!templateHandler) {\n // Handle built-in templates\n if (template === 'command') {\n const [name] = args;\n if (!name) {\n panic('Command name is required');\n }\n await generateCommand(name);\n return;\n }\n\n if (template === 'event') {\n const [name] = args;\n if (!name) {\n panic('Event name is required');\n }\n await generateEvent(name);\n return;\n }\n\n const valid = Array.from(\n new Set([\n 'command',\n 'event',\n ...Array.from(runtime.getTemplates().keys()),\n ]),\n ).map((t) => `\"${t}\"`);\n\n panic(\n `Template \"${template}\" not found. Available templates: ${valid.join(', ')}`,\n );\n }\n\n await templateHandler(args);\n } catch (e: any) {\n panic(`Failed to execute template \"${template}\": ${e?.message || e}`);\n } finally {\n await runtime.destroy();\n }\n });\n\n const types = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n\n if (!existsSync(types)) {\n await mkdir(types, { recursive: true }).catch(() => {});\n await generateTypesPackage(true).catch(() => {});\n }\n\n await program.parseAsync(argv, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,eAAsB,uBACtB,MACA,SACA;CACE,QAAQ,QAAQ;CAGhB,MAAM,EAAE,SAAS,GAAG,MAAM,OAAO;CACjC,MAAM,EAAE,4BAA4B,GAAG,2CAAM;CAC7C,MAAM,EAAE,2BAA2B,uBAAuB,GAAG,2CAAM;CAGnE,MAAM,EAAE,iBAAiB,eAAe,GAAG,2CAAM;CACjD,MAAM,EAAE,SAAS,GAAG,2CAAM;CAC1B,MAAM,EAAE,iBAAiB,GAAG,2CAAM;CAClC,MAAM,EAAE,WAAW,GAAG,2CAAM;CAE5B,MAAM,UAAU,IAAI,QAAQ;CAE5B,QACA,QAAQ,MAAM,CACd,QAAQ,QAAQ,CAChB,YAAY,sCAAsC,CAClD,OACE,uBACA,wCACA,kBACD,CACD,OAAO,MAAM;EACX,MAAM,YAAU,QAAQ,MAAM;EAC9B,2BAA2B,UAAQ,OAAO;CAC3C,EAAC;CAEF,QACA,QAAQ,OAAO,CACf,YACE,sEACD,CACD,OAAO,YAAY;EACjB,MAAM,iBAAiB;CACxB,EAAC;CAEF,QACA,QAAQ,QAAQ,CAChB,YACE,qEACD,CACD,OAAO,uBAAuB,uCAAuC,CACrE,OAAO,MAAM;EACX,MAAM,YAAU,QAAQ,MAAM;EAC9B,0BAA0B,UAAQ,OAAO;CAC1C,EAAC;CAEF,QACA,QAAQ,QAAQ,CAChB,YAAY,2CAA2C,CACvD,OAAO,uBAAuB,uCAAuC,CACrE,OAAO,MAAM;EACX,WAAW;EACX,MAAM,YAAU,QAAQ,MAAM;AAC9B,SAAO,sBAAsB,UAAQ,OAAO;CAC7C,EAAC;CAEF,QACA,QAAQ,SAAS,CACjB,YACE,uEACD,CACD,SACE,cACA,uEACD,CACD,SAAS,aAAa,wCAAwC,CAC9D,OAAO,OAAO,UAAU,SAAS;EAC/B,WAAW;EAGX,MAAM,EAAE,SAAS,GAAG,MAAM,mCAAgB;EAC1C,MAAM,UAAU,IAAI,yCAClB,QAAQ,OAAO,CAAC,MAAM,wCAAiB,EAAE,CAAC;AAG5C,MAAI;GACF,MAAM,QAAQ,MAAM;GACpB,MAAM,kBAAkB,QAAQ,YAAY,SAAS;AAErD,OAAI,CAAC,iBAAiB;AAEpB,QAAI,aAAa,WAAW;KAC1B,MAAM,CAAC,KAAK,GAAG;AACf,SAAI,CAAC,MACH,qBAAM,2BAA2B;KAEnC,MAAM,gBAAgB,KAAK;AAC3B;IACD;AAED,QAAI,aAAa,SAAS;KACxB,MAAM,CAAC,KAAK,GAAG;AACf,SAAI,CAAC,MACH,qBAAM,yBAAyB;KAEjC,MAAM,cAAc,KAAK;AACzB;IACD;IAED,MAAM,QAAQ,MAAM,KAClB,IAAI,IAAI;KACR;KACA;KACA,GAAG,MAAM,KAAK,QAAQ,cAAc,CAAC,MAAM,CAAC;IAAC,GAE9C,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAEtB,qBACE,CAAC,UAAU,EAAE,SAAS,kCAAkC,EAAE,MAAM,KAAK,KAAK,EAAE,CAC7E;GACF;GAED,MAAM,gBAAgB,KAAK;EAC5B,SAAQ,GAAQ;GACf,qBAAM,CAAC,4BAA4B,EAAE,SAAS,GAAG,yCAAE,EAAG,YAAW,GAAG,CAAC;EACtE,UAAS;GACR,MAAM,QAAQ,SAAS;EACxB;CACF,EAAC;CAEF,MAAM,4BAAa,kCAAgB,gBAAgB,mBAAmB;AAEtE,KAAI,yBAAY,MAAM,EAAE;EACtB,kCAAY,OAAO,EAAE,WAAW,KAAM,EAAC,CAAC,MAAM,MAAM,CAAE,EAAC;EACvD,MAAM,2CAAqB,KAAK,CAAC,MAAM,MAAM,CAAE,EAAC;CAClD;CAEA,MAAM,QAAQ,WAAW,MAAM,QAAQ;AACzC"}
package/dist/kv/kv.d.ts CHANGED
@@ -359,5 +359,5 @@ declare class KV implements Disposable, AsyncDisposable {
359
359
  */
360
360
  declare function openKV(path?: string | Buffer | URL | DatabaseSync, options?: KvOptions): KV;
361
361
  //#endregion
362
- export { KV, KvOptions, SerializedValue, openKV };
362
+ export { KV, KvOptions, type SerializedValue, openKV };
363
363
  //# sourceMappingURL=kv.d.ts.map
package/dist/kv/kv.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kv.js","names":[],"sources":["../../src/kv/kv.ts"],"sourcesContent":["import { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { deserializer, serializer } from './serde';\nimport { getNestedValue, setNestedValue } from './dotprops';\n\nexport type { SerializedValue } from './serde';\n\n/**\n * Configuration options for the KV store\n */\nexport interface KvOptions {\n /** Enable Write-Ahead Logging for better performance and durability */\n enableWAL?: boolean;\n /** Namespace for the key-value store table */\n namespace?: string;\n}\n\n/**\n * A key-value store implementation using SQLite\n *\n * This class provides a simple, persistent key-value storage solution\n * with support for namespaces, automatic cleanup, iteration, expiration, and JSON serialization.\n *\n * @example\n * ```typescript\n * const kv = new KV('data.db');\n *\n * // Store any JSON-serializable data\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('dates', [new Date(), new Date()]);\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.name', 'John');\n * kv.set('user:123.settings.theme', 'dark');\n *\n * // Retrieve data\n * const user = kv.get('user:123'); // { name: 'John', age: 30, settings: { theme: 'dark' } }\n * const name = kv.get('user:123.name'); // 'John'\n * ```\n */\nexport class KV implements Disposable, AsyncDisposable {\n private db: DatabaseSync;\n private statements: Record<string, StatementSync> = {};\n\n /**\n * Creates a new KV store instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n */\n public constructor(\n path: string | Buffer | URL | DatabaseSync,\n private options: KvOptions = {\n enableWAL: true,\n namespace: 'commandkit_kv',\n },\n ) {\n this.db =\n path instanceof DatabaseSync\n ? path\n : new DatabaseSync(path, { open: true });\n\n if (options.enableWAL) {\n this.db.exec(/* sql */ `PRAGMA journal_mode = WAL;`);\n }\n\n const namespace = this.options.namespace ?? 'commandkit_kv';\n\n this.db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS ${namespace} (\n key TEXT PRIMARY KEY,\n value TEXT,\n expires_at INTEGER\n )\n `);\n\n this.statements = {\n get: this.db.prepare(\n /* sql */ `SELECT value, expires_at FROM ${namespace} WHERE key = ?`,\n ),\n set: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n setex: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n delete: this.db.prepare(\n /* sql */ `DELETE FROM ${namespace} WHERE key = ?`,\n ),\n has: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`,\n ),\n keys: this.db.prepare(\n /* sql */ `SELECT key FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n values: this.db.prepare(\n /* sql */ `SELECT value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n clear: this.db.prepare(/* sql */ `DELETE FROM ${namespace}`),\n count: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n all: this.db.prepare(\n /* sql */ `SELECT key, value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n expire: this.db.prepare(\n /* sql */ `UPDATE ${namespace} SET expires_at = ? WHERE key = ?`,\n ),\n ttl: this.db.prepare(\n /* sql */ `SELECT expires_at FROM ${namespace} WHERE key = ?`,\n ),\n namespaces: this.db.prepare(\n /* sql */ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`,\n ),\n begin: this.db.prepare(/* sql */ `BEGIN TRANSACTION`),\n commit: this.db.prepare(/* sql */ `COMMIT`),\n rollback: this.db.prepare(/* sql */ `ROLLBACK`),\n };\n }\n\n /**\n * Gets the current timestamp in milliseconds\n */\n private getCurrentTime(): number {\n return Date.now();\n }\n\n /**\n * Checks if the database connection is open\n *\n * @returns `true` if the database is open, `false` otherwise\n */\n public isOpen(): boolean {\n return this.db.isOpen;\n }\n\n /**\n * Gets the underlying SQLite database instance\n *\n * @returns The DatabaseSync instance\n */\n public getDatabase(): DatabaseSync {\n return this.db;\n }\n\n /**\n * Closes the database connection\n */\n public close(): void {\n if (this.db.isOpen) this.db.close();\n }\n\n /**\n * Disposable implementation - closes the database when disposed\n */\n public [Symbol.dispose]() {\n this.close();\n }\n\n /**\n * AsyncDisposable implementation - closes the database when disposed\n */\n public async [Symbol.asyncDispose]() {\n this.close();\n }\n\n /**\n * Retrieves a value by key\n *\n * @param key - The key to retrieve (supports dot notation for nested properties)\n * @returns The value associated with the key, or `undefined` if not found or expired\n *\n * @example\n * ```typescript\n * // Store an object\n * kv.set('user:123', { name: 'John', age: 30, settings: { theme: 'dark' } });\n *\n * // Get the entire object\n * const user = kv.get('user:123');\n * // { name: 'John', age: 30, settings: { theme: 'dark' } }\n *\n * // Get nested properties using dot notation\n * const name = kv.get('user:123.name'); // 'John'\n * const theme = kv.get('user:123.settings.theme'); // 'dark'\n * ```\n */\n public get<T = any>(key: string): T | undefined {\n const result = this.statements.get.get(key);\n\n if (!result) return undefined;\n\n // Check if the key has expired\n if (\n result.expires_at &&\n Number(result.expires_at) <= this.getCurrentTime()\n ) {\n this.delete(key);\n return undefined;\n }\n\n const serialized = JSON.parse(result.value as string);\n const deserialized = deserializer(serialized);\n\n // Handle dot notation for nested properties\n if (key.includes('.')) {\n return getNestedValue(deserialized, key.split('.').slice(1).join('.'));\n }\n\n return deserialized;\n }\n\n /**\n * Sets a key-value pair\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n *\n * @example\n * ```typescript\n * // Store primitive values\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('name', 'John');\n *\n * // Store objects\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Store arrays\n * kv.set('tags', ['javascript', 'typescript', 'sqlite']);\n *\n * // Store dates\n * kv.set('created', new Date());\n *\n * // Store maps and sets\n * kv.set('permissions', new Map([['admin', true], ['user', false]]));\n * kv.set('unique_ids', new Set([1, 2, 3, 4, 5]));\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.settings.theme', 'dark');\n * kv.set('user:123.settings.notifications', true);\n * ```\n */\n public set(key: string, value: any): void {\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(baseKey, serializedValue, null);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(key, serializedValue, null);\n }\n }\n\n /**\n * Sets a key-value pair with expiration\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n * @param ttl - Time to live in milliseconds\n *\n * @example\n * ```typescript\n * // Set with 1 hour expiration\n * kv.setex('session:123', { userId: 123, token: 'abc123' }, 60 * 60 * 1000);\n *\n * // Set with 5 minutes expiration\n * kv.setex('temp:data', { cached: true, timestamp: Date.now() }, 5 * 60 * 1000);\n *\n * // Use dot notation with expiration\n * kv.setex('user:123.temp_settings', { theme: 'light' }, 30 * 60 * 1000);\n * ```\n */\n public setex(key: string, value: any, ttl: number): void {\n const expiresAt = this.getCurrentTime() + ttl;\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(baseKey, serializedValue, expiresAt);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(key, serializedValue, expiresAt);\n }\n }\n\n /**\n * Sets expiration for an existing key\n *\n * @param key - The key to set expiration for\n * @param ttl - Time to live in milliseconds\n * @returns `true` if the key exists and expiration was set, `false` otherwise\n *\n * @example\n * ```typescript\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Set 30 minute expiration\n * if (kv.expire('user:123', 30 * 60 * 1000)) {\n * console.log('Expiration set successfully');\n * }\n * ```\n */\n public expire(key: string, ttl: number): boolean {\n if (!this.has(key)) return false;\n\n const expiresAt = this.getCurrentTime() + ttl;\n this.statements.expire.run(expiresAt, key);\n return true;\n }\n\n /**\n * Gets the time to live for a key\n *\n * @param key - The key to check\n * @returns Time to live in milliseconds, or `-1` if the key doesn't exist, or `-2` if the key has no expiration\n *\n * @example\n * ```typescript\n * const ttl = kv.ttl('user:123');\n * if (ttl > 0) {\n * console.log(`Key expires in ${ttl}ms`);\n * } else if (ttl === -2) {\n * console.log('Key has no expiration');\n * } else {\n * console.log('Key does not exist');\n * }\n * ```\n */\n public ttl(key: string): number {\n const result = this.statements.ttl.get(key);\n\n if (!result) return -1; // Key doesn't exist\n\n if (!result.expires_at) return -2; // No expiration\n\n const remaining = Number(result.expires_at) - this.getCurrentTime();\n return remaining > 0 ? remaining : -1; // Expired or doesn't exist\n }\n\n /**\n * Deletes a key-value pair\n *\n * @param key - The key to delete\n *\n * @example\n * ```typescript\n * kv.delete('user:123');\n * kv.delete('user:123.settings.theme'); // Delete nested property\n * ```\n */\n public delete(key: string): void {\n this.statements.delete.run(key);\n }\n\n /**\n * Checks if a key exists and is not expired\n *\n * @param key - The key to check\n * @returns `true` if the key exists and is not expired, `false` otherwise\n *\n * @example\n * ```typescript\n * if (kv.has('user:123')) {\n * console.log('User exists and is not expired');\n * }\n *\n * if (kv.has('user:123.settings.theme')) {\n * console.log('Theme setting exists');\n * }\n * ```\n */\n public has(key: string): boolean {\n const result = this.statements.has.get(key, this.getCurrentTime());\n\n return (\n result?.count !== undefined &&\n result.count !== null &&\n Number(result.count) > 0\n );\n }\n\n /**\n * Gets all keys in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired keys\n *\n * @example\n * ```typescript\n * const keys = kv.keys();\n * console.log('All keys:', keys);\n * ```\n */\n public keys(): string[] {\n const result = this.statements.keys.all(this.getCurrentTime());\n\n return result.map((row) => row.key as string);\n }\n\n /**\n * Gets all values in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired values\n *\n * @example\n * ```typescript\n * const values = kv.values();\n * console.log('All values:', values);\n * ```\n */\n public values(): any[] {\n const result = this.statements.values.all(this.getCurrentTime());\n\n return result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return deserializer(serialized);\n });\n }\n\n /**\n * Gets the total number of key-value pairs in the current namespace (excluding expired keys)\n *\n * @returns The count of non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const count = kv.count();\n * console.log(`Total entries: ${count}`);\n * ```\n */\n public count(): number {\n const result = this.statements.count.get(this.getCurrentTime());\n\n return Number(result?.count ?? 0);\n }\n\n /**\n * Removes all key-value pairs from the current namespace\n *\n * @example\n * ```typescript\n * kv.clear(); // Removes all entries in current namespace\n * ```\n */\n public clear(): void {\n this.statements.clear.run();\n }\n\n /**\n * Gets all key-value pairs as an object (excluding expired keys)\n *\n * @returns Object with all non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const all = kv.all();\n * console.log('All entries:', all);\n * // Output: { 'key1': value1, 'key2': value2 }\n * ```\n */\n public all(): Record<string, any> {\n const result = this.statements.all.all(this.getCurrentTime());\n\n return Object.fromEntries(\n result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return [row.key as string, deserializer(serialized)];\n }),\n );\n }\n\n /**\n * Gets all available namespaces (tables) in the database\n *\n * @returns Array of namespace names\n *\n * @example\n * ```typescript\n * const namespaces = kv.namespaces();\n * console.log('Available namespaces:', namespaces);\n * ```\n */\n public namespaces(): string[] {\n const result = this.statements.namespaces.all();\n\n return result.map((row) => row.name as string);\n }\n\n /**\n * Gets the current namespace name\n *\n * @returns The current namespace string\n */\n public getCurrentNamespace(): string {\n return this.options.namespace ?? 'commandkit_kv';\n }\n\n /**\n * Creates a new KV instance with a different namespace\n *\n * @param namespace - The namespace to use for the new instance\n * @returns A new KV instance with the specified namespace\n *\n * @example\n * ```typescript\n * const userKv = kv.namespace('users');\n * const configKv = kv.namespace('config');\n *\n * userKv.set('123', { name: 'John', age: 30 });\n * configKv.set('theme', 'dark');\n * ```\n */\n public namespace(namespace: string): KV {\n return new KV(this.db, {\n enableWAL: this.options.enableWAL,\n namespace,\n });\n }\n\n /**\n * Iterator implementation for iterating over all non-expired key-value pairs\n *\n * @returns Iterator yielding [key, value] tuples\n *\n * @example\n * ```typescript\n * for (const [key, value] of kv) {\n * console.log(`${key}:`, value);\n * }\n *\n * // Or using spread operator\n * const entries = [...kv];\n * ```\n */\n public *[Symbol.iterator](): Iterator<[string, any]> {\n const result = this.statements.all.iterate(this.getCurrentTime());\n\n for (const row of result) {\n const serialized = JSON.parse(row.value as string);\n yield [row.key as string, deserializer(serialized)];\n }\n }\n\n /**\n * Executes a function within a transaction\n *\n * @param fn - Function to execute within the transaction (can be async)\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * // Synchronous transaction\n * kv.transaction(() => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n *\n * // Async transaction\n * await kv.transaction(async () => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * await someAsyncOperation();\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n * ```\n */\n public async transaction<T>(fn: () => T | Promise<T>): Promise<T> {\n try {\n // Begin transaction\n this.statements.begin.run();\n\n // Execute the function\n const result = await fn();\n\n // Commit transaction\n this.statements.commit.run();\n\n return result;\n } catch (error) {\n // Rollback transaction on error\n this.statements.rollback.run();\n throw error;\n }\n }\n}\n\n/**\n * Opens a new KV instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n * @returns A new KV instance\n */\nexport function openKV(\n path: string | Buffer | URL | DatabaseSync = 'commandkit_kv.db',\n options: KvOptions = { enableWAL: true, namespace: 'commandkit_kv' },\n): KV {\n return new KV(path, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa,KAAb,MAAa,GAA0C;CACrD,AAAQ;CACR,AAAQ,aAA4C,CAAE;;;;;;;CAQtD,AAAO,YACP,MACQ,UAAqB;EAC3B,WAAW;EACX,WAAW;CACZ,GACD;EAJQ;AAKN,OAAK,KACL,gBAAgB,2BAChB,OACA,IAAI,yBAAa,MAAM,EAAE,MAAM,KAAM;AAErC,MAAI,QAAQ,UACV,MAAK,GAAG,MAAe,4BAA4B;EAGrD,MAAM,YAAY,KAAK,QAAQ,aAAa;AAE5C,OAAK,GAAG,MAAe;mCACQ,UAAU;;;;;MAKvC;AAEF,OAAK,aAAa;GAChB,KAAK,KAAK,GAAG,SACD,gCAAgC,UAAU,gBACrD;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,4CAC9C;GACD,OAAO,KAAK,GAAG,SACH,yBAAyB,UAAU,4CAC9C;GACD,QAAQ,KAAK,GAAG,SACJ,cAAc,UAAU,gBACnC;GACD,KAAK,KAAK,GAAG,SACD,uBAAuB,UAAU,2DAC5C;GACD,MAAM,KAAK,GAAG,SACF,kBAAkB,UAAU,6CACvC;GACD,QAAQ,KAAK,GAAG,SACJ,oBAAoB,UAAU,6CACzC;GACD,OAAO,KAAK,GAAG,SAAkB,cAAc,YAAY;GAC3D,OAAO,KAAK,GAAG,SACH,uBAAuB,UAAU,6CAC5C;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,6CAC9C;GACD,QAAQ,KAAK,GAAG,SACJ,SAAS,UAAU,mCAC9B;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,gBAC9C;GACD,YAAY,KAAK,GAAG,SACR,kFACX;GACD,OAAO,KAAK,GAAG,SAAkB,mBAAmB;GACpD,QAAQ,KAAK,GAAG,SAAkB,QAAQ;GAC1C,UAAU,KAAK,GAAG,SAAkB,UAAU;EAC/C;CACH;;;;CAKA,AAAQ,iBAAyB;AAC/B,SAAO,KAAK,KAAK;CACnB;;;;;;CAOA,AAAO,SAAkB;AACvB,SAAO,KAAK,GAAG;CACjB;;;;;;CAOA,AAAO,cAA4B;AACjC,SAAO,KAAK;CACd;;;;CAKA,AAAO,QAAc;AACnB,MAAI,KAAK,GAAG,OAAQ,MAAK,GAAG,OAAO;CACrC;;;;CAKA,CAAQ,OAAO,WAAW;AACxB,OAAK,OAAO;CACd;;;;CAKA,OAAc,OAAO,gBAAgB;AACnC,OAAK,OAAO;CACd;;;;;;;;;;;;;;;;;;;;;CAsBA,AAAO,IAAa,KAA4B;EAC9C,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,IAAI;AAE3C,OAAK,OAAQ;AAGb,MACA,OAAO,cACP,OAAO,OAAO,WAAW,IAAI,KAAK,gBAAgB,EAClD;AACE,QAAK,OAAO,IAAI;AAChB;EACF;EAEA,MAAM,aAAa,KAAK,MAAM,OAAO,MAAgB;EACrD,MAAM,eAAe,2BAAa,WAAW;AAG7C,MAAI,IAAI,SAAS,IAAI,CACnB,QAAO,gCAAe,cAAc,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;AAGxE,SAAO;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCA,AAAO,IAAI,KAAa,OAAkB;EACxC,IAAI;AAEJ,MAAI,IAAI,SAAS,IAAI,EAAE;GAErB,MAAM,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,MAAM,IAAI;GAC9C,MAAM,OAAO,UAAU,KAAK,IAAI;GAGhC,MAAM,WAAW,KAAK,IAAI,QAAQ,IAAI,CAAE;AACxC,mCAAe,UAAU,MAAM,MAAM;GAErC,MAAM,aAAa,yBAAW,SAAS;AACvC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,IAAI,IAAI,SAAS,iBAAiB,KAAK;EACxD,OAAM;GACL,MAAM,aAAa,yBAAW,MAAM;AACpC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,IAAI,IAAI,KAAK,iBAAiB,KAAK;EACrD;CACF;;;;;;;;;;;;;;;;;;;;CAqBA,AAAO,MAAM,KAAa,OAAY,KAAmB;EACvD,MAAM,YAAY,KAAK,gBAAgB,GAAG;EAC1C,IAAI;AAEJ,MAAI,IAAI,SAAS,IAAI,EAAE;GAErB,MAAM,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,MAAM,IAAI;GAC9C,MAAM,OAAO,UAAU,KAAK,IAAI;GAGhC,MAAM,WAAW,KAAK,IAAI,QAAQ,IAAI,CAAE;AACxC,mCAAe,UAAU,MAAM,MAAM;GAErC,MAAM,aAAa,yBAAW,SAAS;AACvC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,MAAM,IAAI,SAAS,iBAAiB,UAAU;EAC/D,OAAM;GACL,MAAM,aAAa,yBAAW,MAAM;AACpC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,MAAM,IAAI,KAAK,iBAAiB,UAAU;EAC5D;CACF;;;;;;;;;;;;;;;;;;CAmBA,AAAO,OAAO,KAAa,KAAsB;AAC/C,OAAK,KAAK,IAAI,IAAI,CAAE,QAAO;EAE3B,MAAM,YAAY,KAAK,gBAAgB,GAAG;AAC1C,OAAK,WAAW,OAAO,IAAI,WAAW,IAAI;AAC1C,SAAO;CACT;;;;;;;;;;;;;;;;;;;CAoBA,AAAO,IAAI,KAAqB;EAC9B,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,IAAI;AAE3C,OAAK,OAAQ,QAAO;AAEpB,OAAK,OAAO,WAAY,QAAO;EAE/B,MAAM,YAAY,OAAO,OAAO,WAAW,GAAG,KAAK,gBAAgB;AACnE,SAAO,YAAY,IAAI,YAAY;CACrC;;;;;;;;;;;;CAaA,AAAO,OAAO,KAAmB;AAC/B,OAAK,WAAW,OAAO,IAAI,IAAI;CACjC;;;;;;;;;;;;;;;;;;CAmBA,AAAO,IAAI,KAAsB;EAC/B,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,gBAAgB,CAAC;AAElE,0DACE,OAAQ,qBACR,OAAO,UAAU,QACjB,OAAO,OAAO,MAAM,GAAG;CAE3B;;;;;;;;;;;;CAaA,AAAO,OAAiB;EACtB,MAAM,SAAS,KAAK,WAAW,KAAK,IAAI,KAAK,gBAAgB,CAAC;AAE9D,SAAO,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAc;CAC/C;;;;;;;;;;;;CAaA,AAAO,SAAgB;EACrB,MAAM,SAAS,KAAK,WAAW,OAAO,IAAI,KAAK,gBAAgB,CAAC;AAEhE,SAAO,OAAO,IAAI,CAAC,QAAQ;GACzB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,UAAO,2BAAa,WAAW;EAChC,EAAC;CACJ;;;;;;;;;;;;CAaA,AAAO,QAAgB;EACrB,MAAM,SAAS,KAAK,WAAW,MAAM,IAAI,KAAK,gBAAgB,CAAC;AAE/D,SAAO,wDAAO,OAAQ,UAAS,EAAE;CACnC;;;;;;;;;CAUA,AAAO,QAAc;AACnB,OAAK,WAAW,MAAM,KAAK;CAC7B;;;;;;;;;;;;;CAcA,AAAO,MAA2B;EAChC,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,KAAK,gBAAgB,CAAC;AAE7D,SAAO,OAAO,YACZ,OAAO,IAAI,CAAC,QAAQ;GAClB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,UAAO,CAAC,IAAI,KAAe,2BAAa,WAAW,AAAC;EACrD,EAAC,CACH;CACH;;;;;;;;;;;;CAaA,AAAO,aAAuB;EAC5B,MAAM,SAAS,KAAK,WAAW,WAAW,KAAK;AAE/C,SAAO,OAAO,IAAI,CAAC,QAAQ,IAAI,KAAe;CAChD;;;;;;CAOA,AAAO,sBAA8B;AACnC,SAAO,KAAK,QAAQ,aAAa;CACnC;;;;;;;;;;;;;;;;CAiBA,AAAO,UAAU,WAAuB;AACtC,SAAO,IAAI,GAAG,KAAK,IAAI;GACrB,WAAW,KAAK,QAAQ;GACxB;EACD;CACH;;;;;;;;;;;;;;;;CAiBA,EAAS,OAAO,YAAqC;EACnD,MAAM,SAAS,KAAK,WAAW,IAAI,QAAQ,KAAK,gBAAgB,CAAC;AAEjE,OAAK,MAAM,OAAO,QAAQ;GACxB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,SAAM,CAAC,IAAI,KAAe,2BAAa,WAAW,AAAC;EACrD;CACF;;;;;;;;;;;;;;;;;;;;;;;;;CA0BA,MAAa,YAAe,IAAsC;AAChE,MAAI;AAEF,QAAK,WAAW,MAAM,KAAK;GAG3B,MAAM,SAAS,MAAM,IAAI;AAGzB,QAAK,WAAW,OAAO,KAAK;AAE5B,UAAO;EACR,SAAQ,OAAO;AAEd,QAAK,WAAW,SAAS,KAAK;AAC9B,SAAM;EACR;CACF;AACF;;;;;;;;AASA,SAAgB,OAChB,OAA6C,oBAC7C,UAAqB;CAAE,WAAW;CAAM,WAAW;AAAiB,GAC/D;AACH,QAAO,IAAI,GAAG,MAAM;AACtB"}
1
+ {"version":3,"file":"kv.js","names":[],"sources":["../../src/kv/kv.ts"],"sourcesContent":["import { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { deserializer, serializer } from './serde';\nimport { getNestedValue, setNestedValue } from './dotprops';\n\nexport type { SerializedValue } from './serde';\n\n/**\n * Configuration options for the KV store\n */\nexport interface KvOptions {\n /** Enable Write-Ahead Logging for better performance and durability */\n enableWAL?: boolean;\n /** Namespace for the key-value store table */\n namespace?: string;\n}\n\n/**\n * A key-value store implementation using SQLite\n *\n * This class provides a simple, persistent key-value storage solution\n * with support for namespaces, automatic cleanup, iteration, expiration, and JSON serialization.\n *\n * @example\n * ```typescript\n * const kv = new KV('data.db');\n *\n * // Store any JSON-serializable data\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('dates', [new Date(), new Date()]);\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.name', 'John');\n * kv.set('user:123.settings.theme', 'dark');\n *\n * // Retrieve data\n * const user = kv.get('user:123'); // { name: 'John', age: 30, settings: { theme: 'dark' } }\n * const name = kv.get('user:123.name'); // 'John'\n * ```\n */\nexport class KV implements Disposable, AsyncDisposable {\n private db: DatabaseSync;\n private statements: Record<string, StatementSync> = {};\n\n /**\n * Creates a new KV store instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n */\n public constructor(\n path: string | Buffer | URL | DatabaseSync,\n private options: KvOptions = {\n enableWAL: true,\n namespace: 'commandkit_kv',\n },\n ) {\n this.db =\n path instanceof DatabaseSync\n ? path\n : new DatabaseSync(path, { open: true });\n\n if (options.enableWAL) {\n this.db.exec(/* sql */ `PRAGMA journal_mode = WAL;`);\n }\n\n const namespace = this.options.namespace ?? 'commandkit_kv';\n\n this.db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS ${namespace} (\n key TEXT PRIMARY KEY,\n value TEXT,\n expires_at INTEGER\n )\n `);\n\n this.statements = {\n get: this.db.prepare(\n /* sql */ `SELECT value, expires_at FROM ${namespace} WHERE key = ?`,\n ),\n set: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n setex: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n delete: this.db.prepare(\n /* sql */ `DELETE FROM ${namespace} WHERE key = ?`,\n ),\n has: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`,\n ),\n keys: this.db.prepare(\n /* sql */ `SELECT key FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n values: this.db.prepare(\n /* sql */ `SELECT value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n clear: this.db.prepare(/* sql */ `DELETE FROM ${namespace}`),\n count: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n all: this.db.prepare(\n /* sql */ `SELECT key, value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n expire: this.db.prepare(\n /* sql */ `UPDATE ${namespace} SET expires_at = ? WHERE key = ?`,\n ),\n ttl: this.db.prepare(\n /* sql */ `SELECT expires_at FROM ${namespace} WHERE key = ?`,\n ),\n namespaces: this.db.prepare(\n /* sql */ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`,\n ),\n begin: this.db.prepare(/* sql */ `BEGIN TRANSACTION`),\n commit: this.db.prepare(/* sql */ `COMMIT`),\n rollback: this.db.prepare(/* sql */ `ROLLBACK`),\n };\n }\n\n /**\n * Gets the current timestamp in milliseconds\n */\n private getCurrentTime(): number {\n return Date.now();\n }\n\n /**\n * Checks if the database connection is open\n *\n * @returns `true` if the database is open, `false` otherwise\n */\n public isOpen(): boolean {\n return this.db.isOpen;\n }\n\n /**\n * Gets the underlying SQLite database instance\n *\n * @returns The DatabaseSync instance\n */\n public getDatabase(): DatabaseSync {\n return this.db;\n }\n\n /**\n * Closes the database connection\n */\n public close(): void {\n if (this.db.isOpen) this.db.close();\n }\n\n /**\n * Disposable implementation - closes the database when disposed\n */\n public [Symbol.dispose]() {\n this.close();\n }\n\n /**\n * AsyncDisposable implementation - closes the database when disposed\n */\n public async [Symbol.asyncDispose]() {\n this.close();\n }\n\n /**\n * Retrieves a value by key\n *\n * @param key - The key to retrieve (supports dot notation for nested properties)\n * @returns The value associated with the key, or `undefined` if not found or expired\n *\n * @example\n * ```typescript\n * // Store an object\n * kv.set('user:123', { name: 'John', age: 30, settings: { theme: 'dark' } });\n *\n * // Get the entire object\n * const user = kv.get('user:123');\n * // { name: 'John', age: 30, settings: { theme: 'dark' } }\n *\n * // Get nested properties using dot notation\n * const name = kv.get('user:123.name'); // 'John'\n * const theme = kv.get('user:123.settings.theme'); // 'dark'\n * ```\n */\n public get<T = any>(key: string): T | undefined {\n const result = this.statements.get.get(key);\n\n if (!result) return undefined;\n\n // Check if the key has expired\n if (\n result.expires_at &&\n Number(result.expires_at) <= this.getCurrentTime()\n ) {\n this.delete(key);\n return undefined;\n }\n\n const serialized = JSON.parse(result.value as string);\n const deserialized = deserializer(serialized);\n\n // Handle dot notation for nested properties\n if (key.includes('.')) {\n return getNestedValue(deserialized, key.split('.').slice(1).join('.'));\n }\n\n return deserialized;\n }\n\n /**\n * Sets a key-value pair\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n *\n * @example\n * ```typescript\n * // Store primitive values\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('name', 'John');\n *\n * // Store objects\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Store arrays\n * kv.set('tags', ['javascript', 'typescript', 'sqlite']);\n *\n * // Store dates\n * kv.set('created', new Date());\n *\n * // Store maps and sets\n * kv.set('permissions', new Map([['admin', true], ['user', false]]));\n * kv.set('unique_ids', new Set([1, 2, 3, 4, 5]));\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.settings.theme', 'dark');\n * kv.set('user:123.settings.notifications', true);\n * ```\n */\n public set(key: string, value: any): void {\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(baseKey, serializedValue, null);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(key, serializedValue, null);\n }\n }\n\n /**\n * Sets a key-value pair with expiration\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n * @param ttl - Time to live in milliseconds\n *\n * @example\n * ```typescript\n * // Set with 1 hour expiration\n * kv.setex('session:123', { userId: 123, token: 'abc123' }, 60 * 60 * 1000);\n *\n * // Set with 5 minutes expiration\n * kv.setex('temp:data', { cached: true, timestamp: Date.now() }, 5 * 60 * 1000);\n *\n * // Use dot notation with expiration\n * kv.setex('user:123.temp_settings', { theme: 'light' }, 30 * 60 * 1000);\n * ```\n */\n public setex(key: string, value: any, ttl: number): void {\n const expiresAt = this.getCurrentTime() + ttl;\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(baseKey, serializedValue, expiresAt);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(key, serializedValue, expiresAt);\n }\n }\n\n /**\n * Sets expiration for an existing key\n *\n * @param key - The key to set expiration for\n * @param ttl - Time to live in milliseconds\n * @returns `true` if the key exists and expiration was set, `false` otherwise\n *\n * @example\n * ```typescript\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Set 30 minute expiration\n * if (kv.expire('user:123', 30 * 60 * 1000)) {\n * console.log('Expiration set successfully');\n * }\n * ```\n */\n public expire(key: string, ttl: number): boolean {\n if (!this.has(key)) return false;\n\n const expiresAt = this.getCurrentTime() + ttl;\n this.statements.expire.run(expiresAt, key);\n return true;\n }\n\n /**\n * Gets the time to live for a key\n *\n * @param key - The key to check\n * @returns Time to live in milliseconds, or `-1` if the key doesn't exist, or `-2` if the key has no expiration\n *\n * @example\n * ```typescript\n * const ttl = kv.ttl('user:123');\n * if (ttl > 0) {\n * console.log(`Key expires in ${ttl}ms`);\n * } else if (ttl === -2) {\n * console.log('Key has no expiration');\n * } else {\n * console.log('Key does not exist');\n * }\n * ```\n */\n public ttl(key: string): number {\n const result = this.statements.ttl.get(key);\n\n if (!result) return -1; // Key doesn't exist\n\n if (!result.expires_at) return -2; // No expiration\n\n const remaining = Number(result.expires_at) - this.getCurrentTime();\n return remaining > 0 ? remaining : -1; // Expired or doesn't exist\n }\n\n /**\n * Deletes a key-value pair\n *\n * @param key - The key to delete\n *\n * @example\n * ```typescript\n * kv.delete('user:123');\n * kv.delete('user:123.settings.theme'); // Delete nested property\n * ```\n */\n public delete(key: string): void {\n this.statements.delete.run(key);\n }\n\n /**\n * Checks if a key exists and is not expired\n *\n * @param key - The key to check\n * @returns `true` if the key exists and is not expired, `false` otherwise\n *\n * @example\n * ```typescript\n * if (kv.has('user:123')) {\n * console.log('User exists and is not expired');\n * }\n *\n * if (kv.has('user:123.settings.theme')) {\n * console.log('Theme setting exists');\n * }\n * ```\n */\n public has(key: string): boolean {\n const result = this.statements.has.get(key, this.getCurrentTime());\n\n return (\n result?.count !== undefined &&\n result.count !== null &&\n Number(result.count) > 0\n );\n }\n\n /**\n * Gets all keys in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired keys\n *\n * @example\n * ```typescript\n * const keys = kv.keys();\n * console.log('All keys:', keys);\n * ```\n */\n public keys(): string[] {\n const result = this.statements.keys.all(this.getCurrentTime());\n\n return result.map((row) => row.key as string);\n }\n\n /**\n * Gets all values in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired values\n *\n * @example\n * ```typescript\n * const values = kv.values();\n * console.log('All values:', values);\n * ```\n */\n public values(): any[] {\n const result = this.statements.values.all(this.getCurrentTime());\n\n return result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return deserializer(serialized);\n });\n }\n\n /**\n * Gets the total number of key-value pairs in the current namespace (excluding expired keys)\n *\n * @returns The count of non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const count = kv.count();\n * console.log(`Total entries: ${count}`);\n * ```\n */\n public count(): number {\n const result = this.statements.count.get(this.getCurrentTime());\n\n return Number(result?.count ?? 0);\n }\n\n /**\n * Removes all key-value pairs from the current namespace\n *\n * @example\n * ```typescript\n * kv.clear(); // Removes all entries in current namespace\n * ```\n */\n public clear(): void {\n this.statements.clear.run();\n }\n\n /**\n * Gets all key-value pairs as an object (excluding expired keys)\n *\n * @returns Object with all non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const all = kv.all();\n * console.log('All entries:', all);\n * // Output: { 'key1': value1, 'key2': value2 }\n * ```\n */\n public all(): Record<string, any> {\n const result = this.statements.all.all(this.getCurrentTime());\n\n return Object.fromEntries(\n result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return [row.key as string, deserializer(serialized)];\n }),\n );\n }\n\n /**\n * Gets all available namespaces (tables) in the database\n *\n * @returns Array of namespace names\n *\n * @example\n * ```typescript\n * const namespaces = kv.namespaces();\n * console.log('Available namespaces:', namespaces);\n * ```\n */\n public namespaces(): string[] {\n const result = this.statements.namespaces.all();\n\n return result.map((row) => row.name as string);\n }\n\n /**\n * Gets the current namespace name\n *\n * @returns The current namespace string\n */\n public getCurrentNamespace(): string {\n return this.options.namespace ?? 'commandkit_kv';\n }\n\n /**\n * Creates a new KV instance with a different namespace\n *\n * @param namespace - The namespace to use for the new instance\n * @returns A new KV instance with the specified namespace\n *\n * @example\n * ```typescript\n * const userKv = kv.namespace('users');\n * const configKv = kv.namespace('config');\n *\n * userKv.set('123', { name: 'John', age: 30 });\n * configKv.set('theme', 'dark');\n * ```\n */\n public namespace(namespace: string): KV {\n return new KV(this.db, {\n enableWAL: this.options.enableWAL,\n namespace,\n });\n }\n\n /**\n * Iterator implementation for iterating over all non-expired key-value pairs\n *\n * @returns Iterator yielding [key, value] tuples\n *\n * @example\n * ```typescript\n * for (const [key, value] of kv) {\n * console.log(`${key}:`, value);\n * }\n *\n * // Or using spread operator\n * const entries = [...kv];\n * ```\n */\n public *[Symbol.iterator](): Iterator<[string, any]> {\n const result = this.statements.all.iterate(this.getCurrentTime());\n\n for (const row of result) {\n const serialized = JSON.parse(row.value as string);\n yield [row.key as string, deserializer(serialized)];\n }\n }\n\n /**\n * Executes a function within a transaction\n *\n * @param fn - Function to execute within the transaction (can be async)\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * // Synchronous transaction\n * kv.transaction(() => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n *\n * // Async transaction\n * await kv.transaction(async () => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * await someAsyncOperation();\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n * ```\n */\n public async transaction<T>(fn: () => T | Promise<T>): Promise<T> {\n try {\n // Begin transaction\n this.statements.begin.run();\n\n // Execute the function\n const result = await fn();\n\n // Commit transaction\n this.statements.commit.run();\n\n return result;\n } catch (error) {\n // Rollback transaction on error\n this.statements.rollback.run();\n throw error;\n }\n }\n}\n\n/**\n * Opens a new KV instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n * @returns A new KV instance\n */\nexport function openKV(\n path: string | Buffer | URL | DatabaseSync = 'commandkit_kv.db',\n options: KvOptions = { enableWAL: true, namespace: 'commandkit_kv' },\n): KV {\n return new KV(path, options);\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  require('../colors-Cd4Oz-r-.js');
2
2
  require('../ActionRow-CmTHbo2t.js');
3
3
  require('../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../commandkit-CUFTPuzm.js');
5
5
  require('../common-CcfjYnPG.js');
6
6
  require('../common-vnMIelAE.js');
7
7
  require('../container-DCjIgp-B.js');
@@ -1,7 +1,7 @@
1
1
  require('../colors-Cd4Oz-r-.js');
2
2
  require('../ActionRow-CmTHbo2t.js');
3
3
  require('../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../commandkit-CUFTPuzm.js');
5
5
  require('../common-CcfjYnPG.js');
6
6
  require('../common-vnMIelAE.js');
7
7
  require('../container-DCjIgp-B.js');
@@ -1 +1 @@
1
- {"version":3,"file":"media-gallery-CIKypjbJ.js","names":[],"sources":["../src/components/v2/media-gallery.ts"],"sourcesContent":["import { MediaGalleryBuilder, MediaGalleryItemBuilder } from 'discord.js';\nimport { applyId } from './common';\n\n/**\n * Represents the properties for a media gallery component.\n */\nexport interface MediaGalleryProps {\n id?: number;\n children?: MediaGalleryItemBuilder[];\n}\n\n/**\n * The media gallery component\n * @param props The properties for the media gallery component.\n * @returns The media gallery builder instance.\n * @example ```tsx\n * import { MediaGallery } from 'commandkit';\n *\n * const gallery = (\n * <MediaGallery>\n * <MediaGalleryItem url=\"https://example.com/image1.png\" description=\"Image 1\" />\n * <MediaGalleryItem url=\"https://example.com/image2.png\" description=\"Image 2\" />\n * </MediaGallery>\n * );\n * ```\n */\nexport function MediaGallery(props: MediaGalleryProps) {\n const gallery = new MediaGalleryBuilder();\n\n applyId(props, gallery);\n\n if (props.children != null) {\n if (!Array.isArray(props.children)) props.children = [props.children];\n gallery.addItems(props.children.flat());\n }\n\n return gallery;\n}\n\n/**\n * Represents the properties for a media gallery item component.\n */\nexport interface MediaGalleryItemProps {\n description?: string;\n spoiler?: boolean;\n url?: string;\n}\n\n/**\n * The media gallery item component\n * @param props The properties for the media gallery item component.\n * @returns The media gallery item builder instance.\n * @example ```tsx\n * import { MediaGalleryItem } from 'commandkit';\n *\n * const item = <MediaGalleryItem url=\"https://example.com/image.png\" description=\"An image\" />;\n * ```\n */\nexport function MediaGalleryItem(props: MediaGalleryItemProps) {\n const item = new MediaGalleryItemBuilder();\n\n if (props.description != null) {\n item.setDescription(props.description);\n }\n\n if (props.spoiler != null) {\n item.setSpoiler(props.spoiler);\n }\n\n if (props.url != null) {\n item.setURL(props.url);\n }\n\n return item;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAa,OAA0B;CACrD,MAAM,UAAU,IAAI;AAEpB,wBAAQ,OAAO,QAAQ;AAEvB,KAAI,MAAM,YAAY,MAAM;AAC1B,OAAK,MAAM,QAAQ,MAAM,SAAS,CAAE,OAAM,WAAW,CAAC,MAAM,QAAS;AACrE,UAAQ,SAAS,MAAM,SAAS,MAAM,CAAC;CACzC;AAEA,QAAO;AACT;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,OAA8B;CAC7D,MAAM,OAAO,IAAI;AAEjB,KAAI,MAAM,eAAe,KACvB,MAAK,eAAe,MAAM,YAAY;AAGxC,KAAI,MAAM,WAAW,KACnB,MAAK,WAAW,MAAM,QAAQ;AAGhC,KAAI,MAAM,OAAO,KACf,MAAK,OAAO,MAAM,IAAI;AAGxB,QAAO;AACT"}
1
+ {"version":3,"file":"media-gallery-CIKypjbJ.js","names":[],"sources":["../src/components/v2/media-gallery.ts"],"sourcesContent":["import { MediaGalleryBuilder, MediaGalleryItemBuilder } from 'discord.js';\nimport { applyId } from './common';\n\n/**\n * Represents the properties for a media gallery component.\n */\nexport interface MediaGalleryProps {\n id?: number;\n children?: MediaGalleryItemBuilder[];\n}\n\n/**\n * The media gallery component\n * @param props The properties for the media gallery component.\n * @returns The media gallery builder instance.\n * @example ```tsx\n * import { MediaGallery } from 'commandkit';\n *\n * const gallery = (\n * <MediaGallery>\n * <MediaGalleryItem url=\"https://example.com/image1.png\" description=\"Image 1\" />\n * <MediaGalleryItem url=\"https://example.com/image2.png\" description=\"Image 2\" />\n * </MediaGallery>\n * );\n * ```\n */\nexport function MediaGallery(props: MediaGalleryProps) {\n const gallery = new MediaGalleryBuilder();\n\n applyId(props, gallery);\n\n if (props.children != null) {\n if (!Array.isArray(props.children)) props.children = [props.children];\n gallery.addItems(props.children.flat());\n }\n\n return gallery;\n}\n\n/**\n * Represents the properties for a media gallery item component.\n */\nexport interface MediaGalleryItemProps {\n description?: string;\n spoiler?: boolean;\n url?: string;\n}\n\n/**\n * The media gallery item component\n * @param props The properties for the media gallery item component.\n * @returns The media gallery item builder instance.\n * @example ```tsx\n * import { MediaGalleryItem } from 'commandkit';\n *\n * const item = <MediaGalleryItem url=\"https://example.com/image.png\" description=\"An image\" />;\n * ```\n */\nexport function MediaGalleryItem(props: MediaGalleryItemProps) {\n const item = new MediaGalleryItemBuilder();\n\n if (props.description != null) {\n item.setDescription(props.description);\n }\n\n if (props.spoiler != null) {\n item.setSpoiler(props.spoiler);\n }\n\n if (props.url != null) {\n item.setURL(props.url);\n }\n\n return item;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAa,OAA0B;CACrD,MAAM,UAAU,IAAI;CAEpB,uBAAQ,OAAO,QAAQ;AAEvB,KAAI,MAAM,YAAY,MAAM;AAC1B,MAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,EAAE,MAAM,WAAW,CAAC,MAAM,QAAS;EACrE,QAAQ,SAAS,MAAM,SAAS,MAAM,CAAC;CACzC;AAEA,QAAO;AACT;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,OAA8B;CAC7D,MAAM,OAAO,IAAI;AAEjB,KAAI,MAAM,eAAe,MACvB,KAAK,eAAe,MAAM,YAAY;AAGxC,KAAI,MAAM,WAAW,MACnB,KAAK,WAAW,MAAM,QAAQ;AAGhC,KAAI,MAAM,OAAO,MACf,KAAK,OAAO,MAAM,IAAI;AAGxB,QAAO;AACT"}
@@ -1,7 +1,7 @@
1
1
  require('../colors-Cd4Oz-r-.js');
2
2
  require('../ActionRow-CmTHbo2t.js');
3
3
  require('../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../commandkit-CUFTPuzm.js');
5
5
  require('../common-CcfjYnPG.js');
6
6
  require('../common-vnMIelAE.js');
7
7
  require('../container-DCjIgp-B.js');
@@ -1,7 +1,7 @@
1
1
  require('../../colors-Cd4Oz-r-.js');
2
2
  require('../../ActionRow-CmTHbo2t.js');
3
3
  require('../../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../../commandkit-CUFTPuzm.js');
5
5
  require('../../common-CcfjYnPG.js');
6
6
  require('../../common-vnMIelAE.js');
7
7
  require('../../container-DCjIgp-B.js');
@@ -1,7 +1,7 @@
1
1
  require('../../colors-Cd4Oz-r-.js');
2
2
  require('../../ActionRow-CmTHbo2t.js');
3
3
  require('../../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../../commandkit-CUFTPuzm.js');
5
5
  require('../../common-CcfjYnPG.js');
6
6
  require('../../common-vnMIelAE.js');
7
7
  require('../../container-DCjIgp-B.js');
@@ -1,7 +1,7 @@
1
1
  require('../../../colors-Cd4Oz-r-.js');
2
2
  require('../../../ActionRow-CmTHbo2t.js');
3
3
  require('../../../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../../../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../../../commandkit-CUFTPuzm.js');
5
5
  require('../../../common-CcfjYnPG.js');
6
6
  require('../../../common-vnMIelAE.js');
7
7
  require('../../../container-DCjIgp-B.js');
@@ -1,7 +1,7 @@
1
1
  require('../../../colors-Cd4Oz-r-.js');
2
2
  require('../../../ActionRow-CmTHbo2t.js');
3
3
  require('../../../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../../../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../../../commandkit-CUFTPuzm.js');
5
5
  require('../../../common-CcfjYnPG.js');
6
6
  require('../../../common-vnMIelAE.js');
7
7
  require('../../../container-DCjIgp-B.js');
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-file-url-9aPt6A_n.js","names":[],"sources":["../src/utils/resolve-file-url.ts"],"sourcesContent":["import path from 'path';\n\n/**\n * Convert a local file path to a file URL.\n * @param filePath - The local file's path.\n * @param withTs - Whether to append a timestamp to the URL.\n * @returns - The converted file URL.\n */\nexport function toFileURL(filePath: string, withTs = false) {\n const resolvedPath = path.resolve(filePath);\n return `${'file://' + resolvedPath.replace(/\\\\\\\\|\\\\/g, '/')}${withTs ? `?ts=${Date.now()}` : ''}`;\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,UAAU,UAAkB,SAAS,OAAO;CAC1D,MAAM,eAAe,aAAK,QAAQ,SAAS;AAC3C,WAAU,YAAY,aAAa,QAAQ,YAAY,IAAI,GAAG,UAAU,MAAM,KAAK,KAAK,KAAK;AAC/F"}
1
+ {"version":3,"file":"resolve-file-url-9aPt6A_n.js","names":[],"sources":["../src/utils/resolve-file-url.ts"],"sourcesContent":["import path from 'path';\n\n/**\n * Convert a local file path to a file URL.\n * @param filePath - The local file's path.\n * @param withTs - Whether to append a timestamp to the URL.\n * @returns - The converted file URL.\n */\nexport function toFileURL(filePath: string, withTs = false) {\n const resolvedPath = path.resolve(filePath);\n return `${'file://' + resolvedPath.replace(/\\\\\\\\|\\\\/g, '/')}${withTs ? `?ts=${Date.now()}` : ''}`;\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,UAAU,UAAkB,SAAS,OAAO;CAC1D,MAAM,eAAe,aAAK,QAAQ,SAAS;AAC3C,QAAO,GAAG,YAAY,aAAa,QAAQ,YAAY,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,GAAG,IAAI;AACnG"}
@@ -1 +1 @@
1
- {"version":3,"file":"section-CuYr0Inu.js","names":[],"sources":["../src/components/v2/section.ts"],"sourcesContent":["import {\n ButtonBuilder,\n SectionBuilder,\n TextDisplayBuilder,\n ThumbnailBuilder,\n} from 'discord.js';\nimport { applyId } from './common';\n\n/**\n * Represents the properties for a section component.\n */\nexport interface SectionProps {\n children?: (ThumbnailBuilder | ButtonBuilder | TextDisplayBuilder)[];\n id?: number;\n}\n\n/**\n * The components v2 section component\n * @param props The properties for the section component.\n * @returns The section builder instance.\n * @example ```tsx\n * import { Section } from 'commandkit';\n *\n * const section = <Section>...</Section>;\n * ```\n */\nexport function Section(props: SectionProps): SectionBuilder {\n const section = new SectionBuilder();\n\n applyId(props, section);\n\n if (props.children != null) {\n if (!Array.isArray(props.children)) props.children = [props.children];\n for (const accessory of props.children.flat()) {\n if (accessory instanceof ThumbnailBuilder) {\n section.setThumbnailAccessory(accessory);\n } else if (accessory instanceof ButtonBuilder) {\n section.setButtonAccessory(accessory);\n } else if (accessory instanceof TextDisplayBuilder) {\n section.addTextDisplayComponents(accessory);\n }\n }\n }\n\n return section;\n}\n\n/**\n * Represents the properties for a thumbnail component.\n */\nexport interface ThumbnailProps {\n id?: number;\n description?: string;\n spoiler?: boolean;\n url: string;\n}\n\n/**\n * The thumbnail component\n * @param props The properties for the thumbnail component.\n * @returns The thumbnail builder instance.\n * @example ```tsx\n * import { Thumbnail } from 'commandkit';\n *\n * const thumbnail = <Thumbnail url=\"https://example.com/image.png\" description=\"An image\" />;\n * ```\n */\nexport function Thumbnail(props: ThumbnailProps) {\n const thumbnail = new ThumbnailBuilder({\n description: props.description,\n spoiler: props.spoiler,\n id: props.id,\n media: { url: props.url },\n });\n\n return thumbnail;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,QAAQ,OAAqC;CAC3D,MAAM,UAAU,IAAI;AAEpB,wBAAQ,OAAO,QAAQ;AAEvB,KAAI,MAAM,YAAY,MAAM;AAC1B,OAAK,MAAM,QAAQ,MAAM,SAAS,CAAE,OAAM,WAAW,CAAC,MAAM,QAAS;AACrE,OAAK,MAAM,aAAa,MAAM,SAAS,MAAM,CAC3C,KAAI,qBAAqB,4BACvB,SAAQ,sBAAsB,UAAU;WAC/B,qBAAqB,yBAC9B,SAAQ,mBAAmB,UAAU;WAC5B,qBAAqB,8BAC9B,SAAQ,yBAAyB,UAAU;CAGjD;AAEA,QAAO;AACT;;;;;;;;;;;AAsBA,SAAgB,UAAU,OAAuB;CAC/C,MAAM,YAAY,IAAI,4BAAiB;EACrC,aAAa,MAAM;EACnB,SAAS,MAAM;EACf,IAAI,MAAM;EACV,OAAO,EAAE,KAAK,MAAM,IAAK;CAC1B;AAED,QAAO;AACT"}
1
+ {"version":3,"file":"section-CuYr0Inu.js","names":[],"sources":["../src/components/v2/section.ts"],"sourcesContent":["import {\n ButtonBuilder,\n SectionBuilder,\n TextDisplayBuilder,\n ThumbnailBuilder,\n} from 'discord.js';\nimport { applyId } from './common';\n\n/**\n * Represents the properties for a section component.\n */\nexport interface SectionProps {\n children?: (ThumbnailBuilder | ButtonBuilder | TextDisplayBuilder)[];\n id?: number;\n}\n\n/**\n * The components v2 section component\n * @param props The properties for the section component.\n * @returns The section builder instance.\n * @example ```tsx\n * import { Section } from 'commandkit';\n *\n * const section = <Section>...</Section>;\n * ```\n */\nexport function Section(props: SectionProps): SectionBuilder {\n const section = new SectionBuilder();\n\n applyId(props, section);\n\n if (props.children != null) {\n if (!Array.isArray(props.children)) props.children = [props.children];\n for (const accessory of props.children.flat()) {\n if (accessory instanceof ThumbnailBuilder) {\n section.setThumbnailAccessory(accessory);\n } else if (accessory instanceof ButtonBuilder) {\n section.setButtonAccessory(accessory);\n } else if (accessory instanceof TextDisplayBuilder) {\n section.addTextDisplayComponents(accessory);\n }\n }\n }\n\n return section;\n}\n\n/**\n * Represents the properties for a thumbnail component.\n */\nexport interface ThumbnailProps {\n id?: number;\n description?: string;\n spoiler?: boolean;\n url: string;\n}\n\n/**\n * The thumbnail component\n * @param props The properties for the thumbnail component.\n * @returns The thumbnail builder instance.\n * @example ```tsx\n * import { Thumbnail } from 'commandkit';\n *\n * const thumbnail = <Thumbnail url=\"https://example.com/image.png\" description=\"An image\" />;\n * ```\n */\nexport function Thumbnail(props: ThumbnailProps) {\n const thumbnail = new ThumbnailBuilder({\n description: props.description,\n spoiler: props.spoiler,\n id: props.id,\n media: { url: props.url },\n });\n\n return thumbnail;\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0BA,SAAgB,QAAQ,OAAqC;CAC3D,MAAM,UAAU,IAAI;CAEpB,uBAAQ,OAAO,QAAQ;AAEvB,KAAI,MAAM,YAAY,MAAM;AAC1B,MAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,EAAE,MAAM,WAAW,CAAC,MAAM,QAAS;AACrE,OAAK,MAAM,aAAa,MAAM,SAAS,MAAM,CAC3C,KAAI,qBAAqB,6BACvB,QAAQ,sBAAsB,UAAU;WAC/B,qBAAqB,0BAC9B,QAAQ,mBAAmB,UAAU;WAC5B,qBAAqB,+BAC9B,QAAQ,yBAAyB,UAAU;CAGjD;AAEA,QAAO;AACT;;;;;;;;;;;AAsBA,SAAgB,UAAU,OAAuB;CAC/C,MAAM,YAAY,IAAI,4BAAiB;EACrC,aAAa,MAAM;EACnB,SAAS,MAAM;EACf,IAAI,MAAM;EACV,OAAO,EAAE,KAAK,MAAM,IAAK;CAC1B;AAED,QAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"serde-CXY4F7OD.js","names":[],"sources":["../src/kv/serde.ts"],"sourcesContent":["import { SerializerType } from './constants';\n\nexport interface SerializedValue {\n t: SerializerType;\n v: any;\n}\n\nexport function serializer(value: any): SerializedValue {\n if (value === null) {\n return { t: SerializerType.Null, v: null };\n }\n\n if (value === undefined) {\n return { t: SerializerType.Undefined, v: undefined };\n }\n\n if (typeof value === 'string') {\n return { t: SerializerType.String, v: value };\n }\n\n if (typeof value === 'number') {\n return { t: SerializerType.Number, v: value };\n }\n\n if (typeof value === 'boolean') {\n return { t: SerializerType.Boolean, v: value };\n }\n\n if (typeof value === 'bigint') {\n return { t: SerializerType.BigInt, v: value.toString() };\n }\n\n if (value instanceof Date) {\n return { t: SerializerType.Date, v: value.toISOString() };\n }\n\n if (Array.isArray(value)) {\n return { t: SerializerType.Array, v: value };\n }\n\n if (value instanceof Map) {\n return { t: SerializerType.Map, v: Array.from(value.entries()) };\n }\n\n if (value instanceof Set) {\n return { t: SerializerType.Set, v: Array.from(value) };\n }\n\n if (Buffer.isBuffer(value)) {\n return { t: SerializerType.Buffer, v: value.toString('base64') };\n }\n\n if (value instanceof RegExp) {\n return {\n t: SerializerType.RegExp,\n v: { source: value.source, flags: value.flags },\n };\n }\n\n if (typeof value === 'object') {\n return { t: SerializerType.Object, v: value };\n }\n\n // Fallback to string\n return { t: SerializerType.String, v: String(value) };\n}\n\nexport function deserializer(serialized: SerializedValue): any {\n switch (serialized.t) {\n case SerializerType.Null:\n return null;\n case SerializerType.Undefined:\n return undefined;\n case SerializerType.String:\n return serialized.v;\n case SerializerType.Number:\n return serialized.v;\n case SerializerType.Boolean:\n return serialized.v;\n case SerializerType.BigInt:\n return BigInt(serialized.v);\n case SerializerType.Date:\n return new Date(serialized.v);\n case SerializerType.Array:\n return serialized.v;\n case SerializerType.Map:\n return new Map(serialized.v);\n case SerializerType.Set:\n return new Set(serialized.v);\n case SerializerType.Buffer:\n return Buffer.from(serialized.v, 'base64');\n case SerializerType.RegExp:\n return new RegExp(serialized.v.source, serialized.v.flags);\n case SerializerType.Object:\n return serialized.v;\n default:\n return serialized.v;\n }\n}\n"],"mappings":";;;AAOA,SAAgB,WAAW,OAA6B;AACtD,KAAI,UAAU,KACZ,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG;CAAM;AAG5C,KAAI,iBACF,QAAO;EAAE,GAAG,iCAAe;EAAW;CAAc;AAGtD,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,YAAW,UAAU,UACnB,QAAO;EAAE,GAAG,iCAAe;EAAS,GAAG;CAAO;AAGhD,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,UAAU;CAAE;AAG1D,KAAI,iBAAiB,KACnB,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG,MAAM,aAAa;CAAE;AAG3D,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO;EAAE,GAAG,iCAAe;EAAO,GAAG;CAAO;AAG9C,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM,SAAS,CAAC;CAAE;AAGlE,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM;CAAE;AAGxD,KAAI,OAAO,SAAS,MAAM,CACxB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,SAAS,SAAS;CAAE;AAGlE,KAAI,iBAAiB,OACnB,QAAO;EACL,GAAG,iCAAe;EAClB,GAAG;GAAE,QAAQ,MAAM;GAAQ,OAAO,MAAM;EAAO;CAChD;AAGH,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAI/C,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,OAAO,MAAM;CAAE;AACvD;AAEA,SAAgB,aAAa,YAAkC;AAC7D,SAAQ,WAAW,GAAnB;EACE,KAAK,iCAAe,KAClB,QAAO;EACT,KAAK,iCAAe,UAClB;EACF,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,QAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,OAAO,WAAW,EAAE;EAC7B,KAAK,iCAAe,KAClB,QAAO,IAAI,KAAK,WAAW;EAC7B,KAAK,iCAAe,MAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,OAClB,QAAO,OAAO,KAAK,WAAW,GAAG,SAAS;EAC5C,KAAK,iCAAe,OAClB,QAAO,IAAI,OAAO,WAAW,EAAE,QAAQ,WAAW,EAAE;EACtD,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,QACE,QAAO,WAAW;CACtB;AACF"}
1
+ {"version":3,"file":"serde-CXY4F7OD.js","names":[],"sources":["../src/kv/serde.ts"],"sourcesContent":["import { SerializerType } from './constants';\n\nexport interface SerializedValue {\n t: SerializerType;\n v: any;\n}\n\nexport function serializer(value: any): SerializedValue {\n if (value === null) {\n return { t: SerializerType.Null, v: null };\n }\n\n if (value === undefined) {\n return { t: SerializerType.Undefined, v: undefined };\n }\n\n if (typeof value === 'string') {\n return { t: SerializerType.String, v: value };\n }\n\n if (typeof value === 'number') {\n return { t: SerializerType.Number, v: value };\n }\n\n if (typeof value === 'boolean') {\n return { t: SerializerType.Boolean, v: value };\n }\n\n if (typeof value === 'bigint') {\n return { t: SerializerType.BigInt, v: value.toString() };\n }\n\n if (value instanceof Date) {\n return { t: SerializerType.Date, v: value.toISOString() };\n }\n\n if (Array.isArray(value)) {\n return { t: SerializerType.Array, v: value };\n }\n\n if (value instanceof Map) {\n return { t: SerializerType.Map, v: Array.from(value.entries()) };\n }\n\n if (value instanceof Set) {\n return { t: SerializerType.Set, v: Array.from(value) };\n }\n\n if (Buffer.isBuffer(value)) {\n return { t: SerializerType.Buffer, v: value.toString('base64') };\n }\n\n if (value instanceof RegExp) {\n return {\n t: SerializerType.RegExp,\n v: { source: value.source, flags: value.flags },\n };\n }\n\n if (typeof value === 'object') {\n return { t: SerializerType.Object, v: value };\n }\n\n // Fallback to string\n return { t: SerializerType.String, v: String(value) };\n}\n\nexport function deserializer(serialized: SerializedValue): any {\n switch (serialized.t) {\n case SerializerType.Null:\n return null;\n case SerializerType.Undefined:\n return undefined;\n case SerializerType.String:\n return serialized.v;\n case SerializerType.Number:\n return serialized.v;\n case SerializerType.Boolean:\n return serialized.v;\n case SerializerType.BigInt:\n return BigInt(serialized.v);\n case SerializerType.Date:\n return new Date(serialized.v);\n case SerializerType.Array:\n return serialized.v;\n case SerializerType.Map:\n return new Map(serialized.v);\n case SerializerType.Set:\n return new Set(serialized.v);\n case SerializerType.Buffer:\n return Buffer.from(serialized.v, 'base64');\n case SerializerType.RegExp:\n return new RegExp(serialized.v.source, serialized.v.flags);\n case SerializerType.Object:\n return serialized.v;\n default:\n return serialized.v;\n }\n}\n"],"mappings":";;;AAOA,SAAgB,WAAW,OAA6B;AACtD,KAAI,UAAU,KACZ,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG;CAAM;AAG5C,KAAI,UAAU,OACZ,QAAO;EAAE,GAAG,iCAAe;EAAW,GAAG;CAAW;AAGtD,KAAI,OAAO,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,KAAI,OAAO,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,KAAI,OAAO,UAAU,UACnB,QAAO;EAAE,GAAG,iCAAe;EAAS,GAAG;CAAO;AAGhD,KAAI,OAAO,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,UAAU;CAAE;AAG1D,KAAI,iBAAiB,KACnB,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG,MAAM,aAAa;CAAE;AAG3D,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO;EAAE,GAAG,iCAAe;EAAO,GAAG;CAAO;AAG9C,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM,SAAS,CAAC;CAAE;AAGlE,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM;CAAE;AAGxD,KAAI,OAAO,SAAS,MAAM,CACxB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,SAAS,SAAS;CAAE;AAGlE,KAAI,iBAAiB,OACnB,QAAO;EACL,GAAG,iCAAe;EAClB,GAAG;GAAE,QAAQ,MAAM;GAAQ,OAAO,MAAM;EAAO;CAChD;AAGH,KAAI,OAAO,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAI/C,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,OAAO,MAAM;CAAE;AACvD;AAEA,SAAgB,aAAa,YAAkC;AAC7D,SAAQ,WAAW,GAAnB;EACE,KAAK,iCAAe,KAClB,QAAO;EACT,KAAK,iCAAe,UAClB,QAAO;EACT,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,QAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,OAAO,WAAW,EAAE;EAC7B,KAAK,iCAAe,KAClB,QAAO,IAAI,KAAK,WAAW;EAC7B,KAAK,iCAAe,MAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,OAClB,QAAO,OAAO,KAAK,WAAW,GAAG,SAAS;EAC5C,KAAK,iCAAe,OAClB,QAAO,IAAI,OAAO,WAAW,EAAE,QAAQ,WAAW,EAAE;EACtD,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,QACE,QAAO,WAAW;CACtB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"signals-Bu7gndaS.js","names":[],"sources":["../src/app/interrupt/signals.ts"],"sourcesContent":["import {\n CommandKitErrorCodes,\n createCommandKitError,\n isCommandKitError,\n} from '../../utils/error-codes';\nimport { eventWorkerContext } from '../events/EventWorkerContext';\n\n/**\n * Cancel upcoming middleware execution.\n * If this is called inside pre-stage middleware, the next run will be the actual command, skipping all other pre-stage middlewares.\n * If this is called inside a command itself, it will skip all post-stage middlewares.\n * If this is called inside post-stage middleware, it will skip all other post-stage middlewares.\n */\nexport function exitMiddleware(): never {\n throw createCommandKitError(CommandKitErrorCodes.ExitMiddleware);\n}\n\n/**\n * Rethrow the error if it is a CommandKit error.\n * @param error The error to rethrow.\n * @example try {\n * doSomething();\n * } catch(e) {\n * // do something\n *\n * // throw the error if it's a commandkit error\n * rethrow(e)\n * }\n */\nexport function rethrow(error: unknown): void {\n if (isCommandKitError(error)) throw error;\n}\n\n/**\n * Stops current command assuming it has been redirected to another command.\n */\nexport function redirect(): never {\n throw createCommandKitError(CommandKitErrorCodes.ForwardedCommand);\n}\n\n/**\n * Stops event propagation. This function should be called inside an event handler\n * to prevent further event handling.\n * @example // src/app/events/messageCreate/handler.ts\n * import { stopEvents } from 'commandkit';\n *\n * export default async function messageCreateHandler() {\n * console.log('Message created');\n * // Stop further event propagation\n * stopEvents();\n * }\n */\nexport function stopEvents(): never {\n if (!eventWorkerContext.getStore()) {\n throw new Error('stopEvents() may only be called inside an event handler');\n }\n\n throw createCommandKitError(CommandKitErrorCodes.StopEvents);\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAgB,iBAAwB;AACtC,OAAM,0CAAsB,yCAAqB,eAAe;AAClE;;;;;;;;;;;;;AAcA,SAAgB,QAAQ,OAAsB;AAC5C,KAAI,sCAAkB,MAAM,CAAE,OAAM;AACtC;;;;AAKA,SAAgB,WAAkB;AAChC,OAAM,0CAAsB,yCAAqB,iBAAiB;AACpE;;;;;;;;;;;;;AAcA,SAAgB,aAAoB;AAClC,MAAK,8CAAmB,UAAU,CAChC,OAAM,IAAI,MAAM;AAGlB,OAAM,0CAAsB,yCAAqB,WAAW;AAC9D"}
1
+ {"version":3,"file":"signals-Bu7gndaS.js","names":[],"sources":["../src/app/interrupt/signals.ts"],"sourcesContent":["import {\n CommandKitErrorCodes,\n createCommandKitError,\n isCommandKitError,\n} from '../../utils/error-codes';\nimport { eventWorkerContext } from '../events/EventWorkerContext';\n\n/**\n * Cancel upcoming middleware execution.\n * If this is called inside pre-stage middleware, the next run will be the actual command, skipping all other pre-stage middlewares.\n * If this is called inside a command itself, it will skip all post-stage middlewares.\n * If this is called inside post-stage middleware, it will skip all other post-stage middlewares.\n */\nexport function exitMiddleware(): never {\n throw createCommandKitError(CommandKitErrorCodes.ExitMiddleware);\n}\n\n/**\n * Rethrow the error if it is a CommandKit error.\n * @param error The error to rethrow.\n * @example try {\n * doSomething();\n * } catch(e) {\n * // do something\n *\n * // throw the error if it's a commandkit error\n * rethrow(e)\n * }\n */\nexport function rethrow(error: unknown): void {\n if (isCommandKitError(error)) throw error;\n}\n\n/**\n * Stops current command assuming it has been redirected to another command.\n */\nexport function redirect(): never {\n throw createCommandKitError(CommandKitErrorCodes.ForwardedCommand);\n}\n\n/**\n * Stops event propagation. This function should be called inside an event handler\n * to prevent further event handling.\n * @example // src/app/events/messageCreate/handler.ts\n * import { stopEvents } from 'commandkit';\n *\n * export default async function messageCreateHandler() {\n * console.log('Message created');\n * // Stop further event propagation\n * stopEvents();\n * }\n */\nexport function stopEvents(): never {\n if (!eventWorkerContext.getStore()) {\n throw new Error('stopEvents() may only be called inside an event handler');\n }\n\n throw createCommandKitError(CommandKitErrorCodes.StopEvents);\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAgB,iBAAwB;AACtC,OAAM,0CAAsB,yCAAqB,eAAe;AAClE;;;;;;;;;;;;;AAcA,SAAgB,QAAQ,OAAsB;AAC5C,KAAI,sCAAkB,MAAM,CAAE,OAAM;AACtC;;;;AAKA,SAAgB,WAAkB;AAChC,OAAM,0CAAsB,yCAAqB,iBAAiB;AACpE;;;;;;;;;;;;;AAcA,SAAgB,aAAoB;AAClC,KAAI,CAAC,8CAAmB,UAAU,CAChC,OAAM,IAAI,MAAM;AAGlB,OAAM,0CAAsB,yCAAqB,WAAW;AAC9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"text-display--p2-BoUa.js","names":[],"sources":["../src/components/v2/text-display.ts"],"sourcesContent":["import { TextDisplayBuilder, TextDisplayComponentData } from 'discord.js';\n\n/**\n * Represents a type that can be encoded as a string.\n */\nexport type StringEncodable = string | number | boolean;\n\n/**\n * Represents the properties for a text display component.\n * This interface extends the TextDisplayComponentData type from discord.js,\n * excluding the 'type' and 'content' properties.\n */\nexport interface TextDisplayProps\n extends Omit<TextDisplayComponentData, 'type' | 'content'> {\n children?: StringEncodable | StringEncodable[];\n content?: string;\n}\n\n/**\n * The components v2 text display component\n * @param props The properties for the text display component.\n * @returns The text display builder instance.\n * @example ```tsx\n * import { TextDisplay } from 'commandkit';\n *\n * const textDisplay = <TextDisplay content=\"Hello, world!\" />;\n * // or\n * const textDisplay = <TextDisplay>Some text content</TextDisplay>;\n * ```\n */\nexport function TextDisplay(props: TextDisplayProps) {\n const textDisplay = new TextDisplayBuilder(props);\n\n if (!props.content && props.children) {\n if (Array.isArray(props.children)) {\n textDisplay.setContent(props.children.join(' '));\n } else {\n textDisplay.setContent(\n typeof props.children === 'string'\n ? props.children\n : String(props.children),\n );\n }\n }\n\n return textDisplay;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8BA,SAAgB,YAAY,OAAyB;CACnD,MAAM,cAAc,IAAI,8BAAmB;AAE3C,MAAK,MAAM,WAAW,MAAM,SAC1B,KAAI,MAAM,QAAQ,MAAM,SAAS,CAC/B,aAAY,WAAW,MAAM,SAAS,KAAK,IAAI,CAAC;KAEhD,aAAY,kBACH,MAAM,aAAa,WAC1B,MAAM,WACN,OAAO,MAAM,SAAS,CACvB;AAIL,QAAO;AACT"}
1
+ {"version":3,"file":"text-display--p2-BoUa.js","names":[],"sources":["../src/components/v2/text-display.ts"],"sourcesContent":["import { TextDisplayBuilder, TextDisplayComponentData } from 'discord.js';\n\n/**\n * Represents a type that can be encoded as a string.\n */\nexport type StringEncodable = string | number | boolean;\n\n/**\n * Represents the properties for a text display component.\n * This interface extends the TextDisplayComponentData type from discord.js,\n * excluding the 'type' and 'content' properties.\n */\nexport interface TextDisplayProps\n extends Omit<TextDisplayComponentData, 'type' | 'content'> {\n children?: StringEncodable | StringEncodable[];\n content?: string;\n}\n\n/**\n * The components v2 text display component\n * @param props The properties for the text display component.\n * @returns The text display builder instance.\n * @example ```tsx\n * import { TextDisplay } from 'commandkit';\n *\n * const textDisplay = <TextDisplay content=\"Hello, world!\" />;\n * // or\n * const textDisplay = <TextDisplay>Some text content</TextDisplay>;\n * ```\n */\nexport function TextDisplay(props: TextDisplayProps) {\n const textDisplay = new TextDisplayBuilder(props);\n\n if (!props.content && props.children) {\n if (Array.isArray(props.children)) {\n textDisplay.setContent(props.children.join(' '));\n } else {\n textDisplay.setContent(\n typeof props.children === 'string'\n ? props.children\n : String(props.children),\n );\n }\n }\n\n return textDisplay;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8BA,SAAgB,YAAY,OAAyB;CACnD,MAAM,cAAc,IAAI,8BAAmB;AAE3C,KAAI,CAAC,MAAM,WAAW,MAAM,SAC1B,KAAI,MAAM,QAAQ,MAAM,SAAS,EAC/B,YAAY,WAAW,MAAM,SAAS,KAAK,IAAI,CAAC;MAEhD,YAAY,WACV,OAAO,MAAM,aAAa,WAC1B,MAAM,WACN,OAAO,MAAM,SAAS,CACvB;AAIL,QAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"type-checker-DDHZIEBi.js","names":[],"sources":["../src/cli/type-checker.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { loadTypeScript } from './common';\nimport { join, relative } from 'node:path';\nimport colors from '../utils/colors';\n\nconst TS_NOT_FOUND_ERR = `TypeScript must be installed in order to use the type checker. Please install it using \\`npm install typescript\\` or \\`yarn add typescript\\``;\n\n/**\n * Formats a TypeScript diagnostic message in a pretty, readable format\n * @private\n * @internal\n */\nfunction formatDiagnostic(\n ts: typeof import('typescript'),\n diagnostic: import('typescript').Diagnostic,\n cwd: string,\n): string {\n const messageText = ts.flattenDiagnosticMessageText(\n diagnostic.messageText,\n '\\n',\n );\n\n if (!diagnostic.file) {\n return `${colors.red('error')}: ${messageText}`;\n }\n\n const { line, character } = ts.getLineAndCharacterOfPosition(\n diagnostic.file,\n diagnostic.start!,\n );\n const fileName = relative(cwd, diagnostic.file.fileName);\n const position = `${line + 1}:${character + 1}`;\n const errorCode = diagnostic.code ? `TS${diagnostic.code}` : '';\n\n // Format the error message nicely\n return [\n `${colors.bold(colors.cyan(fileName))}:${colors.bold(colors.yellow(position))} - ${colors.red('error')} ${colors.gray(errorCode)}`,\n `${messageText}`,\n ].join('\\n');\n}\n\n/**\n * Performs a type check on the project using TypeScript.\n * @param path The project root or cwd\n * @private\n * @internal\n */\nexport async function performTypeCheck(path: string) {\n const tsconfigPath = join(path, 'tsconfig.json');\n\n if (!existsSync(tsconfigPath)) return;\n\n const ts = await loadTypeScript(TS_NOT_FOUND_ERR);\n\n // Format host for error reporting\n const formatHost = {\n getCanonicalFileName: (path: string) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n };\n\n // Read tsconfig.json\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configFile.error) {\n console.error(\n colors.red(\n `Error reading tsconfig.json: ${ts.formatDiagnostic(configFile.error, formatHost)}`,\n ),\n );\n process.exit(1);\n }\n\n // Parse the config file\n const parsedConfig = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path,\n );\n\n // Force noEmit to true as we only want type checking\n parsedConfig.options.noEmit = true;\n\n // Create a program\n const program = ts.createProgram({\n rootNames: parsedConfig.fileNames,\n options: parsedConfig.options,\n projectReferences: parsedConfig.projectReferences,\n });\n\n // Get the diagnostics\n const diagnostics = [\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...program.getSyntacticDiagnostics(),\n ...program.getSemanticDiagnostics(),\n ];\n\n // Report any errors\n if (diagnostics.length > 0) {\n console.log('');\n console.error(\n colors.bold(\n colors.red('Type checking failed with the following errors:'),\n ),\n );\n console.log('');\n\n // Group diagnostics by file for better readability\n const byFile = new Map<string, import('typescript').Diagnostic[]>();\n\n for (const diagnostic of diagnostics) {\n const fileName = diagnostic.file ? diagnostic.file.fileName : 'Global';\n if (!byFile.has(fileName)) {\n byFile.set(fileName, []);\n }\n byFile.get(fileName)!.push(diagnostic);\n }\n\n // Pretty-print each diagnostic\n const totalErrors = diagnostics.length;\n let counter = 0;\n\n for (const [_, fileDiags] of byFile) {\n for (const diagnostic of fileDiags) {\n counter++;\n console.log(formatDiagnostic(ts, diagnostic, path));\n // Add separator between errors for better readability, except for the last one\n if (counter < totalErrors) {\n console.log('');\n }\n }\n }\n\n console.log('');\n console.error(\n colors.bold(\n colors.red(`Found ${totalErrors} error${totalErrors > 1 ? 's' : ''}`),\n ),\n );\n console.log('');\n\n process.exit(1);\n }\n\n console.log(colors.green('✓ Type checking completed successfully.'));\n}\n"],"mappings":";;;;;;;AAKA,MAAM,oBAAoB;;;;;;AAO1B,SAAS,iBACT,IACA,YACA,KACS;CACP,MAAM,cAAc,GAAG,6BACrB,WAAW,aACX,KACD;AAED,MAAK,WAAW,KACd,WAAU,8BAAO,IAAI,QAAQ,CAAC,IAAI;CAGpC,MAAM,EAAE,MAAM,WAAW,GAAG,GAAG,8BAC7B,WAAW,MACX,WAAW,MACZ;CACD,MAAM,WAAW,wBAAS,KAAK,WAAW,KAAK,SAAS;CACxD,MAAM,cAAc,OAAO,EAAE,GAAG,YAAY;CAC5C,MAAM,YAAY,WAAW,QAAQ,IAAI,WAAW,SAAS;AAG7D,QAAO,IACJ,8BAAO,KAAK,8BAAO,KAAK,SAAS,CAAC,CAAC,GAAG,8BAAO,KAAK,8BAAO,OAAO,SAAS,CAAC,CAAC,KAAK,8BAAO,IAAI,QAAQ,CAAC,GAAG,8BAAO,KAAK,UAAU,OAC7H,aAAc,EACjB,KAAK,KAAK;AACZ;;;;;;;AAQA,eAAsB,iBAAiB,MAAc;CACnD,MAAM,eAAe,oBAAK,MAAM,gBAAgB;AAEhD,MAAK,wBAAW,aAAa,CAAE;CAE/B,MAAM,KAAK,MAAM,8BAAe,iBAAiB;CAGjD,MAAM,aAAa;EACjB,sBAAsB,CAAC,WAAiB;EACxC,qBAAqB,GAAG,IAAI;EAC5B,YAAY,MAAM,GAAG,IAAI;CAC1B;CAGD,MAAM,aAAa,GAAG,eAAe,cAAc,GAAG,IAAI,SAAS;AAEnE,KAAI,WAAW,OAAO;AACpB,UAAQ,MACN,8BAAO,KACJ,+BAA+B,GAAG,iBAAiB,WAAW,OAAO,WAAW,GAClF,CACF;AACD,UAAQ,KAAK,EAAE;CACjB;CAGA,MAAM,eAAe,GAAG,2BACtB,WAAW,QACX,GAAG,KACH,KACD;AAGD,cAAa,QAAQ,SAAS;CAG9B,MAAM,UAAU,GAAG,cAAc;EAC/B,WAAW,aAAa;EACxB,SAAS,aAAa;EACtB,mBAAmB,aAAa;CACjC,EAAC;CAGF,MAAM,cAAc;EACpB,GAAG,QAAQ,uBAAuB;EAClC,GAAG,QAAQ,sBAAsB;EACjC,GAAG,QAAQ,yBAAyB;EACpC,GAAG,QAAQ,wBAAwB;CAAC;AAIpC,KAAI,YAAY,SAAS,GAAG;AAC1B,UAAQ,IAAI,GAAG;AACf,UAAQ,MACN,8BAAO,KACL,8BAAO,IAAI,kDAAkD,CAC9D,CACF;AACD,UAAQ,IAAI,GAAG;EAGf,MAAM,yBAAS,IAAI;AAEnB,OAAK,MAAM,cAAc,aAAa;GACpC,MAAM,WAAW,WAAW,OAAO,WAAW,KAAK,WAAW;AAC9D,QAAK,OAAO,IAAI,SAAS,CACvB,QAAO,IAAI,UAAU,CAAE,EAAC;AAE1B,UAAO,IAAI,SAAS,CAAE,KAAK,WAAW;EACxC;EAGA,MAAM,cAAc,YAAY;EAChC,IAAI,UAAU;AAEd,OAAK,MAAM,CAAC,GAAG,UAAU,IAAI,OAC3B,MAAK,MAAM,cAAc,WAAW;AAClC;AACA,WAAQ,IAAI,iBAAiB,IAAI,YAAY,KAAK,CAAC;AAEnD,OAAI,UAAU,YACZ,SAAQ,IAAI,GAAG;EAEnB;AAGF,UAAQ,IAAI,GAAG;AACf,UAAQ,MACN,8BAAO,KACL,8BAAO,KAAK,QAAQ,YAAY,QAAQ,cAAc,IAAI,MAAM,KAAK,CACtE,CACF;AACD,UAAQ,IAAI,GAAG;AAEf,UAAQ,KAAK,EAAE;CACjB;AAEA,SAAQ,IAAI,8BAAO,MAAM,0CAA0C,CAAC;AACtE"}
1
+ {"version":3,"file":"type-checker-DDHZIEBi.js","names":[],"sources":["../src/cli/type-checker.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { loadTypeScript } from './common';\nimport { join, relative } from 'node:path';\nimport colors from '../utils/colors';\n\nconst TS_NOT_FOUND_ERR = `TypeScript must be installed in order to use the type checker. Please install it using \\`npm install typescript\\` or \\`yarn add typescript\\``;\n\n/**\n * Formats a TypeScript diagnostic message in a pretty, readable format\n * @private\n * @internal\n */\nfunction formatDiagnostic(\n ts: typeof import('typescript'),\n diagnostic: import('typescript').Diagnostic,\n cwd: string,\n): string {\n const messageText = ts.flattenDiagnosticMessageText(\n diagnostic.messageText,\n '\\n',\n );\n\n if (!diagnostic.file) {\n return `${colors.red('error')}: ${messageText}`;\n }\n\n const { line, character } = ts.getLineAndCharacterOfPosition(\n diagnostic.file,\n diagnostic.start!,\n );\n const fileName = relative(cwd, diagnostic.file.fileName);\n const position = `${line + 1}:${character + 1}`;\n const errorCode = diagnostic.code ? `TS${diagnostic.code}` : '';\n\n // Format the error message nicely\n return [\n `${colors.bold(colors.cyan(fileName))}:${colors.bold(colors.yellow(position))} - ${colors.red('error')} ${colors.gray(errorCode)}`,\n `${messageText}`,\n ].join('\\n');\n}\n\n/**\n * Performs a type check on the project using TypeScript.\n * @param path The project root or cwd\n * @private\n * @internal\n */\nexport async function performTypeCheck(path: string) {\n const tsconfigPath = join(path, 'tsconfig.json');\n\n if (!existsSync(tsconfigPath)) return;\n\n const ts = await loadTypeScript(TS_NOT_FOUND_ERR);\n\n // Format host for error reporting\n const formatHost = {\n getCanonicalFileName: (path: string) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n };\n\n // Read tsconfig.json\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configFile.error) {\n console.error(\n colors.red(\n `Error reading tsconfig.json: ${ts.formatDiagnostic(configFile.error, formatHost)}`,\n ),\n );\n process.exit(1);\n }\n\n // Parse the config file\n const parsedConfig = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path,\n );\n\n // Force noEmit to true as we only want type checking\n parsedConfig.options.noEmit = true;\n\n // Create a program\n const program = ts.createProgram({\n rootNames: parsedConfig.fileNames,\n options: parsedConfig.options,\n projectReferences: parsedConfig.projectReferences,\n });\n\n // Get the diagnostics\n const diagnostics = [\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...program.getSyntacticDiagnostics(),\n ...program.getSemanticDiagnostics(),\n ];\n\n // Report any errors\n if (diagnostics.length > 0) {\n console.log('');\n console.error(\n colors.bold(\n colors.red('Type checking failed with the following errors:'),\n ),\n );\n console.log('');\n\n // Group diagnostics by file for better readability\n const byFile = new Map<string, import('typescript').Diagnostic[]>();\n\n for (const diagnostic of diagnostics) {\n const fileName = diagnostic.file ? diagnostic.file.fileName : 'Global';\n if (!byFile.has(fileName)) {\n byFile.set(fileName, []);\n }\n byFile.get(fileName)!.push(diagnostic);\n }\n\n // Pretty-print each diagnostic\n const totalErrors = diagnostics.length;\n let counter = 0;\n\n for (const [_, fileDiags] of byFile) {\n for (const diagnostic of fileDiags) {\n counter++;\n console.log(formatDiagnostic(ts, diagnostic, path));\n // Add separator between errors for better readability, except for the last one\n if (counter < totalErrors) {\n console.log('');\n }\n }\n }\n\n console.log('');\n console.error(\n colors.bold(\n colors.red(`Found ${totalErrors} error${totalErrors > 1 ? 's' : ''}`),\n ),\n );\n console.log('');\n\n process.exit(1);\n }\n\n console.log(colors.green('✓ Type checking completed successfully.'));\n}\n"],"mappings":";;;;;;;AAKA,MAAM,mBAAmB,CAAC,4IAA4I,CAAC;;;;;;AAOvK,SAAS,iBACT,IACA,YACA,KACS;CACP,MAAM,cAAc,GAAG,6BACrB,WAAW,aACX,KACD;AAED,KAAI,CAAC,WAAW,KACd,QAAO,GAAG,8BAAO,IAAI,QAAQ,CAAC,EAAE,EAAE,aAAa;CAGjD,MAAM,EAAE,MAAM,WAAW,GAAG,GAAG,8BAC7B,WAAW,MACX,WAAW,MACZ;CACD,MAAM,mCAAoB,KAAK,WAAW,KAAK,SAAS;CACxD,MAAM,WAAW,GAAG,OAAO,EAAE,CAAC,EAAE,YAAY,GAAG;CAC/C,MAAM,YAAY,WAAW,OAAO,CAAC,EAAE,EAAE,WAAW,MAAM,GAAG;AAG7D,QAAO,CACP,GAAG,8BAAO,KAAK,8BAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,8BAAO,KAAK,8BAAO,OAAO,SAAS,CAAC,CAAC,GAAG,EAAE,8BAAO,IAAI,QAAQ,CAAC,CAAC,EAAE,8BAAO,KAAK,UAAU,EAAE,EAClI,GAAG,aAAa,AAAC,EACjB,KAAK,KAAK;AACZ;;;;;;;AAQA,eAAsB,iBAAiB,MAAc;CACnD,MAAM,mCAAoB,MAAM,gBAAgB;AAEhD,KAAI,yBAAY,aAAa,CAAE;CAE/B,MAAM,KAAK,MAAM,8BAAe,iBAAiB;CAGjD,MAAM,aAAa;EACjB,sBAAsB,CAAC,WAAiB;EACxC,qBAAqB,GAAG,IAAI;EAC5B,YAAY,MAAM,GAAG,IAAI;CAC1B;CAGD,MAAM,aAAa,GAAG,eAAe,cAAc,GAAG,IAAI,SAAS;AAEnE,KAAI,WAAW,OAAO;EACpB,QAAQ,MACN,8BAAO,IACL,CAAC,6BAA6B,EAAE,GAAG,iBAAiB,WAAW,OAAO,WAAW,EAAE,CACpF,CACF;EACD,QAAQ,KAAK,EAAE;CACjB;CAGA,MAAM,eAAe,GAAG,2BACtB,WAAW,QACX,GAAG,KACH,KACD;CAGD,aAAa,QAAQ,SAAS;CAG9B,MAAM,UAAU,GAAG,cAAc;EAC/B,WAAW,aAAa;EACxB,SAAS,aAAa;EACtB,mBAAmB,aAAa;CACjC,EAAC;CAGF,MAAM,cAAc;EACpB,GAAG,QAAQ,uBAAuB;EAClC,GAAG,QAAQ,sBAAsB;EACjC,GAAG,QAAQ,yBAAyB;EACpC,GAAG,QAAQ,wBAAwB;CAAC;AAIpC,KAAI,YAAY,SAAS,GAAG;EAC1B,QAAQ,IAAI,GAAG;EACf,QAAQ,MACN,8BAAO,KACL,8BAAO,IAAI,kDAAkD,CAC9D,CACF;EACD,QAAQ,IAAI,GAAG;EAGf,MAAM,yBAAS,IAAI;AAEnB,OAAK,MAAM,cAAc,aAAa;GACpC,MAAM,WAAW,WAAW,OAAO,WAAW,KAAK,WAAW;AAC9D,OAAI,CAAC,OAAO,IAAI,SAAS,EACvB,OAAO,IAAI,UAAU,CAAE,EAAC;GAE1B,OAAO,IAAI,SAAS,CAAE,KAAK,WAAW;EACxC;EAGA,MAAM,cAAc,YAAY;EAChC,IAAI,UAAU;AAEd,OAAK,MAAM,CAAC,GAAG,UAAU,IAAI,OAC3B,MAAK,MAAM,cAAc,WAAW;GAClC;GACA,QAAQ,IAAI,iBAAiB,IAAI,YAAY,KAAK,CAAC;AAEnD,OAAI,UAAU,aACZ,QAAQ,IAAI,GAAG;EAEnB;EAGF,QAAQ,IAAI,GAAG;EACf,QAAQ,MACN,8BAAO,KACL,8BAAO,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,EAAE,cAAc,IAAI,MAAM,IAAI,CAAC,CACtE,CACF;EACD,QAAQ,IAAI,GAAG;EAEf,QAAQ,KAAK,EAAE;CACjB;CAEA,QAAQ,IAAI,8BAAO,MAAM,0CAA0C,CAAC;AACtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"types-package-Dwub9JsW.js","names":[],"sources":["../src/utils/types-package.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { COMMANDKIT_CWD, COMMANDKIT_IS_DEV } from './constants';\nimport { existsSync } from 'node:fs';\n\n/**\n * @private\n */\nexport async function generateTypesPackage(force = false) {\n const location = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n if (!COMMANDKIT_IS_DEV && !force) return location;\n const packageJSON = join(location, 'package.json');\n const index = join(location, 'index.js');\n const types = join(location, 'index.d.ts');\n const command = join(location, 'command.d.ts');\n\n const packageJSONContent = {\n name: 'commandkit-types',\n version: '1.0.0',\n description: 'CommandKit types package',\n type: 'commonjs',\n main: 'index.js',\n types: 'index.d.ts',\n };\n\n const indexContent = `module.exports = {};`;\n\n // Restructuring the type declarations to properly extend rather than replace types\n const typesContent = `// Main types index file - imports all type declarations\nimport './command';\nexport {};\n`;\n\n // Properly set up command types to extend the CommandTypeData interface\n const commandTypesContent = `// Auto-generated command types\n export {};\ndeclare module 'commandkit' {\n type CommandTypeData = string\n}`;\n\n await mkdir(location, { recursive: true }).catch(() => {});\n await writeFile(packageJSON, JSON.stringify(packageJSONContent, null, 2));\n await writeFile(index, indexContent);\n await writeFile(types, typesContent);\n await writeFile(command, commandTypesContent);\n\n return location;\n}\n\n/**\n * @private\n */\nexport async function rewriteCommandDeclaration(data: string) {\n const commandTypesContent = `// Auto-generated command types\n declare module 'commandkit' {\n ${data}\n}\n export {};\n`;\n\n const location = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n\n if (!existsSync(location)) return;\n\n const type = join(location, 'command.d.ts');\n\n await writeFile(type, commandTypesContent, { encoding: 'utf-8' });\n}\n"],"mappings":";;;;;;;;;;AAQA,eAAsB,qBAAqB,QAAQ,OAAO;CACxD,MAAM,WAAW,oBAAK,kCAAgB,gBAAgB,mBAAmB;AACzE,MAAK,wCAAsB,MAAO,QAAO;CACzC,MAAM,cAAc,oBAAK,UAAU,eAAe;CAClD,MAAM,QAAQ,oBAAK,UAAU,WAAW;CACxC,MAAM,QAAQ,oBAAK,UAAU,aAAa;CAC1C,MAAM,UAAU,oBAAK,UAAU,eAAe;CAE9C,MAAM,qBAAqB;EACzB,MAAM;EACN,SAAS;EACT,aAAa;EACb,MAAM;EACN,MAAM;EACN,OAAO;CACR;CAED,MAAM,gBAAgB;CAGtB,MAAM,gBAAgB;;;;CAMtB,MAAM,uBAAuB;;;;;AAM7B,OAAM,4BAAM,UAAU,EAAE,WAAW,KAAM,EAAC,CAAC,MAAM,MAAM,CAAE,EAAC;AAC1D,OAAM,gCAAU,aAAa,KAAK,UAAU,oBAAoB,MAAM,EAAE,CAAC;AACzE,OAAM,gCAAU,OAAO,aAAa;AACpC,OAAM,gCAAU,OAAO,aAAa;AACpC,OAAM,gCAAU,SAAS,oBAAoB;AAE7C,QAAO;AACT;;;;AAKA,eAAsB,0BAA0B,MAAc;CAC5D,MAAM,uBAAuB;;MAEzB,KAAI;;;;CAKR,MAAM,WAAW,oBAAK,kCAAgB,gBAAgB,mBAAmB;AAEzE,MAAK,wBAAW,SAAS,CAAE;CAE3B,MAAM,OAAO,oBAAK,UAAU,eAAe;AAE3C,OAAM,gCAAU,MAAM,qBAAqB,EAAE,UAAU,QAAS,EAAC;AACnE"}
1
+ {"version":3,"file":"types-package-Dwub9JsW.js","names":[],"sources":["../src/utils/types-package.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { COMMANDKIT_CWD, COMMANDKIT_IS_DEV } from './constants';\nimport { existsSync } from 'node:fs';\n\n/**\n * @private\n */\nexport async function generateTypesPackage(force = false) {\n const location = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n if (!COMMANDKIT_IS_DEV && !force) return location;\n const packageJSON = join(location, 'package.json');\n const index = join(location, 'index.js');\n const types = join(location, 'index.d.ts');\n const command = join(location, 'command.d.ts');\n\n const packageJSONContent = {\n name: 'commandkit-types',\n version: '1.0.0',\n description: 'CommandKit types package',\n type: 'commonjs',\n main: 'index.js',\n types: 'index.d.ts',\n };\n\n const indexContent = `module.exports = {};`;\n\n // Restructuring the type declarations to properly extend rather than replace types\n const typesContent = `// Main types index file - imports all type declarations\nimport './command';\nexport {};\n`;\n\n // Properly set up command types to extend the CommandTypeData interface\n const commandTypesContent = `// Auto-generated command types\n export {};\ndeclare module 'commandkit' {\n type CommandTypeData = string\n}`;\n\n await mkdir(location, { recursive: true }).catch(() => {});\n await writeFile(packageJSON, JSON.stringify(packageJSONContent, null, 2));\n await writeFile(index, indexContent);\n await writeFile(types, typesContent);\n await writeFile(command, commandTypesContent);\n\n return location;\n}\n\n/**\n * @private\n */\nexport async function rewriteCommandDeclaration(data: string) {\n const commandTypesContent = `// Auto-generated command types\n declare module 'commandkit' {\n ${data}\n}\n export {};\n`;\n\n const location = join(COMMANDKIT_CWD, 'node_modules', 'commandkit-types');\n\n if (!existsSync(location)) return;\n\n const type = join(location, 'command.d.ts');\n\n await writeFile(type, commandTypesContent, { encoding: 'utf-8' });\n}\n"],"mappings":";;;;;;;;;;AAQA,eAAsB,qBAAqB,QAAQ,OAAO;CACxD,MAAM,+BAAgB,kCAAgB,gBAAgB,mBAAmB;AACzE,KAAI,CAAC,uCAAqB,CAAC,MAAO,QAAO;CACzC,MAAM,kCAAmB,UAAU,eAAe;CAClD,MAAM,4BAAa,UAAU,WAAW;CACxC,MAAM,4BAAa,UAAU,aAAa;CAC1C,MAAM,8BAAe,UAAU,eAAe;CAE9C,MAAM,qBAAqB;EACzB,MAAM;EACN,SAAS;EACT,aAAa;EACb,MAAM;EACN,MAAM;EACN,OAAO;CACR;CAED,MAAM,eAAe,CAAC,oBAAoB,CAAC;CAG3C,MAAM,eAAe,CAAC;;;AAGxB,CAAC;CAGC,MAAM,sBAAsB,CAAC;;;;CAI9B,CAAC;CAEA,kCAAY,UAAU,EAAE,WAAW,KAAM,EAAC,CAAC,MAAM,MAAM,CAAE,EAAC;CAC1D,sCAAgB,aAAa,KAAK,UAAU,oBAAoB,MAAM,EAAE,CAAC;CACzE,sCAAgB,OAAO,aAAa;CACpC,sCAAgB,OAAO,aAAa;CACpC,sCAAgB,SAAS,oBAAoB;AAE7C,QAAO;AACT;;;;AAKA,eAAsB,0BAA0B,MAAc;CAC5D,MAAM,sBAAsB,CAAC;;IAE3B,EAAE,KAAI;;;AAGV,CAAC;CAEC,MAAM,+BAAgB,kCAAgB,gBAAgB,mBAAmB;AAEzE,KAAI,yBAAY,SAAS,CAAE;CAE3B,MAAM,2BAAY,UAAU,eAAe;CAE3C,sCAAgB,MAAM,qBAAqB,EAAE,UAAU,QAAS,EAAC;AACnE"}
@@ -1,7 +1,7 @@
1
- import * as picocolors_types7 from "picocolors/types";
1
+ import * as picocolors_types0 from "picocolors/types";
2
2
 
3
3
  //#region src/utils/colors.d.ts
4
- declare const _default: picocolors_types7.Colors;
4
+ declare const _default: picocolors_types0.Colors;
5
5
  //#endregion
6
6
  export { _default as default };
7
7
  //# sourceMappingURL=colors.d.ts.map
@@ -1,7 +1,7 @@
1
1
  require('../colors-Cd4Oz-r-.js');
2
2
  require('../ActionRow-CmTHbo2t.js');
3
3
  require('../error-codes-C-ViHyu-.js');
4
- const require_commandkit = require('../commandkit-DYYj5_OH.js');
4
+ const require_commandkit = require('../commandkit-CUFTPuzm.js');
5
5
  require('../common-CcfjYnPG.js');
6
6
  require('../common-vnMIelAE.js');
7
7
  require('../container-DCjIgp-B.js');
@@ -1 +1 @@
1
- {"version":3,"file":"async-queue.js","names":[],"sources":["../../../src/utils/useful-stuff/async-queue.ts"],"sourcesContent":["/**\n * Async queue implementation for processing tasks sequentially or with limited concurrency.\n * Useful for rate-limiting, batching, or controlling resource usage.\n */\n\nexport interface AsyncQueueOptions {\n /** Maximum number of concurrent tasks. Default: 1 (sequential) */\n concurrency?: number;\n /** Optional callback invoked when all tasks are completed */\n onDrain?: () => void | Promise<void>;\n /** Optional AbortSignal for cancelling the queue */\n signal?: AbortSignal;\n}\n\nexport type AsyncQueueTask<T> = () => Promise<T>;\n\nexport class AsyncQueue {\n private readonly concurrency: number;\n private readonly onDrain?: () => void | Promise<void>;\n private readonly signal?: AbortSignal;\n private running = 0;\n private paused = false;\n private aborted = false;\n private queue: Array<() => void> = [];\n\n constructor(options: AsyncQueueOptions = {}) {\n this.concurrency = options.concurrency ?? 1;\n this.onDrain = options.onDrain;\n this.signal = options.signal;\n\n if (this.signal) {\n this.signal.addEventListener('abort', () => {\n this.abort();\n });\n }\n }\n\n /**\n * Adds a task to the queue.\n * @param task - The async function to execute.\n * @param signal - Optional AbortSignal for cancelling this specific task.\n * @returns Promise resolving to the result of the task.\n */\n public add<T>(task: AsyncQueueTask<T>, signal?: AbortSignal): Promise<T> {\n if (this.aborted) {\n return Promise.reject(new Error('Queue has been aborted'));\n }\n\n return new Promise<T>((resolve, reject) => {\n const run = async () => {\n if (this.paused || this.aborted) {\n if (this.aborted) {\n reject(new Error('Queue has been aborted'));\n } else {\n this.queue.push(run);\n }\n return;\n }\n\n // Check if task-specific signal is aborted\n if (signal?.aborted) {\n reject(new Error('Task was aborted'));\n return;\n }\n\n this.running++;\n try {\n const result = await task();\n resolve(result);\n } catch (err) {\n reject(err);\n } finally {\n this.running--;\n this.next();\n }\n };\n\n if (this.running < this.concurrency && !this.paused && !this.aborted) {\n run();\n } else {\n this.queue.push(run);\n }\n });\n }\n\n /**\n * Pauses the queue. No new tasks will be started until resumed.\n */\n public pause() {\n this.paused = true;\n }\n\n /**\n * Resumes the queue and processes pending tasks.\n */\n public resume() {\n if (!this.paused) return;\n this.paused = false;\n this.next();\n }\n\n /**\n * Aborts the queue, rejecting all pending tasks.\n */\n public abort() {\n this.aborted = true;\n this.clear();\n }\n\n /**\n * Clears all pending tasks from the queue.\n */\n public clear() {\n this.queue = [];\n }\n\n /**\n * Returns the number of running tasks.\n */\n public getRunning(): number {\n return this.running;\n }\n\n /**\n * Returns the number of pending tasks in the queue.\n */\n public getPending(): number {\n return this.queue.length;\n }\n\n /**\n * Returns true if the queue is currently paused.\n */\n public isPaused(): boolean {\n return this.paused;\n }\n\n /**\n * Returns true if the queue has been aborted.\n */\n public isAborted(): boolean {\n return this.aborted;\n }\n\n private next() {\n if (this.paused || this.aborted) return;\n while (this.running < this.concurrency && this.queue.length > 0) {\n const fn = this.queue.shift();\n if (fn) fn();\n }\n if (this.running === 0 && this.queue.length === 0 && this.onDrain) {\n this.onDrain();\n }\n }\n}\n\n/**\n * Creates a new async queue instance with the specified configuration.\n * @param options - Configuration options for the async queue.\n * @returns New AsyncQueue instance.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * const queue = createAsyncQueue({\n * concurrency: 2,\n * signal: controller.signal\n * });\n * queue.add(async () => await doSomething());\n * controller.abort(); // Aborts the queue\n * ```\n */\nexport function createAsyncQueue(options?: AsyncQueueOptions): AsyncQueue {\n return new AsyncQueue(options);\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAAwB;CACtB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAQ,UAAU;CAClB,AAAQ,SAAS;CACjB,AAAQ,UAAU;CAClB,AAAQ,QAA2B,CAAE;CAErC,YAAY,UAA6B,CAAE,GAAE;AAC3C,OAAK,cAAc,QAAQ,eAAe;AAC1C,OAAK,UAAU,QAAQ;AACvB,OAAK,SAAS,QAAQ;AAEtB,MAAI,KAAK,OACP,MAAK,OAAO,iBAAiB,SAAS,MAAM;AAC1C,QAAK,OAAO;EACb,EAAC;CAEN;;;;;;;CAQA,AAAO,IAAO,MAAyB,QAAkC;AACvE,MAAI,KAAK,QACP,QAAO,QAAQ,uBAAO,IAAI,MAAM,0BAA0B;AAG5D,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;GACzC,MAAM,MAAM,YAAY;AACtB,QAAI,KAAK,UAAU,KAAK,SAAS;AAC/B,SAAI,KAAK,QACP,wBAAO,IAAI,MAAM,0BAA0B;SAE3C,MAAK,MAAM,KAAK,IAAI;AAEtB;IACF;AAGA,wDAAI,OAAQ,SAAS;AACnB,4BAAO,IAAI,MAAM,oBAAoB;AACrC;IACF;AAEA,SAAK;AACL,QAAI;KACF,MAAM,SAAS,MAAM,MAAM;AAC3B,aAAQ,OAAO;IAChB,SAAQ,KAAK;AACZ,YAAO,IAAI;IACZ,UAAS;AACR,UAAK;AACL,UAAK,MAAM;IACb;GACD;AAED,OAAI,KAAK,UAAU,KAAK,gBAAgB,KAAK,WAAW,KAAK,QAC3D,MAAK;OAEL,MAAK,MAAM,KAAK,IAAI;EAEvB;CACH;;;;CAKA,AAAO,QAAQ;AACb,OAAK,SAAS;CAChB;;;;CAKA,AAAO,SAAS;AACd,OAAK,KAAK,OAAQ;AAClB,OAAK,SAAS;AACd,OAAK,MAAM;CACb;;;;CAKA,AAAO,QAAQ;AACb,OAAK,UAAU;AACf,OAAK,OAAO;CACd;;;;CAKA,AAAO,QAAQ;AACb,OAAK,QAAQ,CAAE;CACjB;;;;CAKA,AAAO,aAAqB;AAC1B,SAAO,KAAK;CACd;;;;CAKA,AAAO,aAAqB;AAC1B,SAAO,KAAK,MAAM;CACpB;;;;CAKA,AAAO,WAAoB;AACzB,SAAO,KAAK;CACd;;;;CAKA,AAAO,YAAqB;AAC1B,SAAO,KAAK;CACd;CAEA,AAAQ,OAAO;AACb,MAAI,KAAK,UAAU,KAAK,QAAS;AACjC,SAAO,KAAK,UAAU,KAAK,eAAe,KAAK,MAAM,SAAS,GAAG;GAC/D,MAAM,KAAK,KAAK,MAAM,OAAO;AAC7B,OAAI,GAAI,KAAI;EACd;AACA,MAAI,KAAK,YAAY,KAAK,KAAK,MAAM,WAAW,KAAK,KAAK,QACxD,MAAK,SAAS;CAElB;AACF;;;;;;;;;;;;;;;;;AAkBA,SAAgB,iBAAiB,SAAyC;AACxE,QAAO,IAAI,WAAW;AACxB"}
1
+ {"version":3,"file":"async-queue.js","names":[],"sources":["../../../src/utils/useful-stuff/async-queue.ts"],"sourcesContent":["/**\n * Async queue implementation for processing tasks sequentially or with limited concurrency.\n * Useful for rate-limiting, batching, or controlling resource usage.\n */\n\nexport interface AsyncQueueOptions {\n /** Maximum number of concurrent tasks. Default: 1 (sequential) */\n concurrency?: number;\n /** Optional callback invoked when all tasks are completed */\n onDrain?: () => void | Promise<void>;\n /** Optional AbortSignal for cancelling the queue */\n signal?: AbortSignal;\n}\n\nexport type AsyncQueueTask<T> = () => Promise<T>;\n\nexport class AsyncQueue {\n private readonly concurrency: number;\n private readonly onDrain?: () => void | Promise<void>;\n private readonly signal?: AbortSignal;\n private running = 0;\n private paused = false;\n private aborted = false;\n private queue: Array<() => void> = [];\n\n constructor(options: AsyncQueueOptions = {}) {\n this.concurrency = options.concurrency ?? 1;\n this.onDrain = options.onDrain;\n this.signal = options.signal;\n\n if (this.signal) {\n this.signal.addEventListener('abort', () => {\n this.abort();\n });\n }\n }\n\n /**\n * Adds a task to the queue.\n * @param task - The async function to execute.\n * @param signal - Optional AbortSignal for cancelling this specific task.\n * @returns Promise resolving to the result of the task.\n */\n public add<T>(task: AsyncQueueTask<T>, signal?: AbortSignal): Promise<T> {\n if (this.aborted) {\n return Promise.reject(new Error('Queue has been aborted'));\n }\n\n return new Promise<T>((resolve, reject) => {\n const run = async () => {\n if (this.paused || this.aborted) {\n if (this.aborted) {\n reject(new Error('Queue has been aborted'));\n } else {\n this.queue.push(run);\n }\n return;\n }\n\n // Check if task-specific signal is aborted\n if (signal?.aborted) {\n reject(new Error('Task was aborted'));\n return;\n }\n\n this.running++;\n try {\n const result = await task();\n resolve(result);\n } catch (err) {\n reject(err);\n } finally {\n this.running--;\n this.next();\n }\n };\n\n if (this.running < this.concurrency && !this.paused && !this.aborted) {\n run();\n } else {\n this.queue.push(run);\n }\n });\n }\n\n /**\n * Pauses the queue. No new tasks will be started until resumed.\n */\n public pause() {\n this.paused = true;\n }\n\n /**\n * Resumes the queue and processes pending tasks.\n */\n public resume() {\n if (!this.paused) return;\n this.paused = false;\n this.next();\n }\n\n /**\n * Aborts the queue, rejecting all pending tasks.\n */\n public abort() {\n this.aborted = true;\n this.clear();\n }\n\n /**\n * Clears all pending tasks from the queue.\n */\n public clear() {\n this.queue = [];\n }\n\n /**\n * Returns the number of running tasks.\n */\n public getRunning(): number {\n return this.running;\n }\n\n /**\n * Returns the number of pending tasks in the queue.\n */\n public getPending(): number {\n return this.queue.length;\n }\n\n /**\n * Returns true if the queue is currently paused.\n */\n public isPaused(): boolean {\n return this.paused;\n }\n\n /**\n * Returns true if the queue has been aborted.\n */\n public isAborted(): boolean {\n return this.aborted;\n }\n\n private next() {\n if (this.paused || this.aborted) return;\n while (this.running < this.concurrency && this.queue.length > 0) {\n const fn = this.queue.shift();\n if (fn) fn();\n }\n if (this.running === 0 && this.queue.length === 0 && this.onDrain) {\n this.onDrain();\n }\n }\n}\n\n/**\n * Creates a new async queue instance with the specified configuration.\n * @param options - Configuration options for the async queue.\n * @returns New AsyncQueue instance.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * const queue = createAsyncQueue({\n * concurrency: 2,\n * signal: controller.signal\n * });\n * queue.add(async () => await doSomething());\n * controller.abort(); // Aborts the queue\n * ```\n */\nexport function createAsyncQueue(options?: AsyncQueueOptions): AsyncQueue {\n return new AsyncQueue(options);\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAAwB;CACtB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAQ,UAAU;CAClB,AAAQ,SAAS;CACjB,AAAQ,UAAU;CAClB,AAAQ,QAA2B,CAAE;CAErC,YAAY,UAA6B,CAAE,GAAE;EAC3C,KAAK,cAAc,QAAQ,eAAe;EAC1C,KAAK,UAAU,QAAQ;EACvB,KAAK,SAAS,QAAQ;AAEtB,MAAI,KAAK,QACP,KAAK,OAAO,iBAAiB,SAAS,MAAM;GAC1C,KAAK,OAAO;EACb,EAAC;CAEN;;;;;;;CAQA,AAAO,IAAO,MAAyB,QAAkC;AACvE,MAAI,KAAK,QACP,QAAO,QAAQ,uBAAO,IAAI,MAAM,0BAA0B;AAG5D,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;GACzC,MAAM,MAAM,YAAY;AACtB,QAAI,KAAK,UAAU,KAAK,SAAS;AAC/B,SAAI,KAAK,SACP,uBAAO,IAAI,MAAM,0BAA0B;UAE3C,KAAK,MAAM,KAAK,IAAI;AAEtB;IACF;AAGA,wDAAI,OAAQ,SAAS;KACnB,uBAAO,IAAI,MAAM,oBAAoB;AACrC;IACF;IAEA,KAAK;AACL,QAAI;KACF,MAAM,SAAS,MAAM,MAAM;KAC3B,QAAQ,OAAO;IAChB,SAAQ,KAAK;KACZ,OAAO,IAAI;IACZ,UAAS;KACR,KAAK;KACL,KAAK,MAAM;IACb;GACD;AAED,OAAI,KAAK,UAAU,KAAK,eAAe,CAAC,KAAK,UAAU,CAAC,KAAK,SAC3D,KAAK;QAEL,KAAK,MAAM,KAAK,IAAI;EAEvB;CACH;;;;CAKA,AAAO,QAAQ;EACb,KAAK,SAAS;CAChB;;;;CAKA,AAAO,SAAS;AACd,MAAI,CAAC,KAAK,OAAQ;EAClB,KAAK,SAAS;EACd,KAAK,MAAM;CACb;;;;CAKA,AAAO,QAAQ;EACb,KAAK,UAAU;EACf,KAAK,OAAO;CACd;;;;CAKA,AAAO,QAAQ;EACb,KAAK,QAAQ,CAAE;CACjB;;;;CAKA,AAAO,aAAqB;AAC1B,SAAO,KAAK;CACd;;;;CAKA,AAAO,aAAqB;AAC1B,SAAO,KAAK,MAAM;CACpB;;;;CAKA,AAAO,WAAoB;AACzB,SAAO,KAAK;CACd;;;;CAKA,AAAO,YAAqB;AAC1B,SAAO,KAAK;CACd;CAEA,AAAQ,OAAO;AACb,MAAI,KAAK,UAAU,KAAK,QAAS;AACjC,SAAO,KAAK,UAAU,KAAK,eAAe,KAAK,MAAM,SAAS,GAAG;GAC/D,MAAM,KAAK,KAAK,MAAM,OAAO;AAC7B,OAAI,IAAI,IAAI;EACd;AACA,MAAI,KAAK,YAAY,KAAK,KAAK,MAAM,WAAW,KAAK,KAAK,SACxD,KAAK,SAAS;CAElB;AACF;;;;;;;;;;;;;;;;;AAkBA,SAAgB,iBAAiB,SAAyC;AACxE,QAAO,IAAI,WAAW;AACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"mutex.js","names":[],"sources":["../../../src/utils/useful-stuff/mutex.ts"],"sourcesContent":["/**\n * Async mutex implementation for coordinating access to shared resources.\n * Provides mutual exclusion to ensure only one task can access a resource at a time.\n */\n\n/**\n * Interface for mutex storage implementations.\n * Provides methods to store, retrieve, and delete mutex lock data.\n */\nexport interface MutexStorage {\n /**\n * Attempts to acquire a lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for the lock\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout or already locked\n */\n acquire(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<boolean>;\n\n /**\n * Releases the lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n release(key: string): Promise<void>;\n\n /**\n * Checks if a lock is currently held for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n isLocked(key: string): Promise<boolean>;\n}\n\n/**\n * Configuration options for mutex\n */\nexport interface MutexOptions {\n /** Default timeout in milliseconds for lock acquisition. Default: 30000 */\n timeout?: number;\n /** Storage implementation for persisting mutex data. Default: {@link MemoryMutexStorage} */\n storage?: MutexStorage;\n}\n\n/**\n * In-memory storage implementation for mutex locks.\n * Suitable for single-instance applications.\n */\nexport class MemoryMutexStorage implements MutexStorage {\n private readonly locks = new Map<\n string,\n { holder: string; acquiredAt: number }\n >();\n\n /**\n * Attempts to acquire a lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for the lock\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout or already locked\n */\n async acquire(\n key: string,\n timeout: number = 30000,\n signal?: AbortSignal,\n ): Promise<boolean> {\n const holder = this.generateHolderId();\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n // Check if aborted\n if (signal?.aborted) {\n throw new Error('Lock acquisition was aborted');\n }\n\n if (!this.locks.has(key)) {\n this.locks.set(key, { holder, acquiredAt: Date.now() });\n return true;\n }\n await this.delay(10);\n }\n\n return false;\n }\n\n /**\n * Releases the lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n async release(key: string): Promise<void> {\n this.locks.delete(key);\n }\n\n /**\n * Checks if a lock is currently held for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n async isLocked(key: string): Promise<boolean> {\n return this.locks.has(key);\n }\n\n private generateHolderId(): string {\n return `holder_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Async mutex implementation that provides mutual exclusion for shared resources.\n * Ensures only one task can access a protected resource at a time.\n */\nexport class Mutex {\n private storage: MutexStorage;\n private readonly defaultTimeout: number;\n\n /**\n * Creates a new mutex instance\n * @param options - Configuration options for the mutex\n */\n public constructor(options: MutexOptions = {}) {\n this.storage = options.storage || new MemoryMutexStorage();\n this.defaultTimeout = options.timeout || 30000;\n }\n\n /**\n * Sets the storage implementation for the mutex\n * @param storage - The storage implementation to use\n */\n public setStorage(storage: MutexStorage) {\n this.storage = storage;\n }\n\n /**\n * Gets the storage implementation for the mutex\n * @returns The storage implementation\n */\n public getStorage(): MutexStorage {\n return this.storage;\n }\n\n /**\n * Acquires a lock for the given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout\n */\n public async acquire(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<boolean> {\n return this.storage.acquire(key, timeout || this.defaultTimeout, signal);\n }\n\n /**\n * Releases the lock for the given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n public async release(key: string): Promise<void> {\n return this.storage.release(key);\n }\n\n /**\n * Checks if a lock is currently held for the given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n public async isLocked(key: string): Promise<boolean> {\n return this.storage.isLocked(key);\n }\n\n /**\n * Executes a function with exclusive access to the resource\n * @param key - The unique identifier for the mutex lock\n * @param fn - The function to execute with exclusive access\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the lock acquisition\n * @returns Promise resolving to the result of the function execution\n * @throws Error if lock acquisition fails or function execution fails\n */\n public async withLock<T>(\n key: string,\n fn: () => Promise<T> | T,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<T> {\n const acquired = await this.acquire(key, timeout, signal);\n if (!acquired) {\n throw new Error(`Failed to acquire lock for key: ${key}`);\n }\n\n try {\n return await fn();\n } finally {\n await this.release(key);\n }\n }\n\n /**\n * Gets the current configuration of the mutex\n * @returns Object containing the current timeout value\n */\n public getConfig(): Omit<MutexOptions, 'storage'> {\n return {\n timeout: this.defaultTimeout,\n };\n }\n}\n\n/**\n * Default mutex instance for global use\n */\nexport const defaultMutex = new Mutex();\n\n/**\n * Convenience function to execute a function with exclusive access using the default mutex.\n *\n * @param key - The unique identifier for the mutex lock\n * @param fn - The function to execute with exclusive access\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the lock acquisition\n * @returns Promise resolving to the result of the function execution\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * const result = await withMutex('shared-resource', async () => {\n * // This code runs with exclusive access\n * return await updateSharedResource();\n * }, 30000, controller.signal);\n * controller.abort(); // Cancels the lock acquisition\n * ```\n */\nexport async function withMutex<T>(\n key: string,\n fn: () => Promise<T> | T,\n timeout?: number,\n signal?: AbortSignal,\n): Promise<T> {\n return defaultMutex.withLock(key, fn, timeout, signal);\n}\n\n/**\n * Creates a new mutex instance with the specified configuration\n * @param options - Configuration options for the mutex\n * @returns New Mutex instance\n *\n * @example\n * ```typescript\n * const mutex = createMutex({\n * timeout: 60000,\n * storage: new RedisMutexStorage()\n * });\n * ```\n */\nexport function createMutex(options: MutexOptions): Mutex {\n return new Mutex(options);\n}\n\n/**\n * Acquires a lock using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout\n */\nexport async function acquireLock(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n): Promise<boolean> {\n return defaultMutex.acquire(key, timeout, signal);\n}\n\n/**\n * Releases a lock using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\nexport async function releaseLock(key: string): Promise<void> {\n return defaultMutex.release(key);\n}\n\n/**\n * Checks if a lock is held using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\nexport async function isLocked(key: string): Promise<boolean> {\n return defaultMutex.isLocked(key);\n}\n"],"mappings":";;;;;;AAoDA,IAAa,qBAAb,MAAwD;CACtD,AAAiB,wBAAQ,IAAI;;;;;;;;CAY7B,MAAM,QACN,KACA,UAAkB,KAClB,QACmB;EACjB,MAAM,SAAS,KAAK,kBAAkB;EACtC,MAAM,YAAY,KAAK,KAAK;AAE5B,SAAO,KAAK,KAAK,GAAG,YAAY,SAAS;AAEvC,uDAAI,OAAQ,QACV,OAAM,IAAI,MAAM;AAGlB,QAAK,KAAK,MAAM,IAAI,IAAI,EAAE;AACxB,SAAK,MAAM,IAAI,KAAK;KAAE;KAAQ,YAAY,KAAK,KAAK;IAAE,EAAC;AACvD,WAAO;GACT;AACA,SAAM,KAAK,MAAM,GAAG;EACtB;AAEA,SAAO;CACT;;;;;;CAOA,MAAM,QAAQ,KAA4B;AACxC,OAAK,MAAM,OAAO,IAAI;CACxB;;;;;;CAOA,MAAM,SAAS,KAA+B;AAC5C,SAAO,KAAK,MAAM,IAAI,IAAI;CAC5B;CAEA,AAAQ,mBAA2B;AACjC,UAAQ,SAAS,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,OAAO,GAAG,EAAE;CACxE;CAEA,AAAQ,MAAM,IAA2B;AACvC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;CACzD;AACF;;;;;AAMA,IAAa,QAAb,MAAmB;CACjB,AAAQ;CACR,AAAiB;;;;;CAMjB,AAAO,YAAY,UAAwB,CAAE,GAAE;AAC7C,OAAK,UAAU,QAAQ,WAAW,IAAI;AACtC,OAAK,iBAAiB,QAAQ,WAAW;CAC3C;;;;;CAMA,AAAO,WAAW,SAAuB;AACvC,OAAK,UAAU;CACjB;;;;;CAMA,AAAO,aAA2B;AAChC,SAAO,KAAK;CACd;;;;;;;;CASA,MAAa,QACb,KACA,SACA,QACmB;AACjB,SAAO,KAAK,QAAQ,QAAQ,KAAK,WAAW,KAAK,gBAAgB,OAAO;CAC1E;;;;;;CAOA,MAAa,QAAQ,KAA4B;AAC/C,SAAO,KAAK,QAAQ,QAAQ,IAAI;CAClC;;;;;;CAOA,MAAa,SAAS,KAA+B;AACnD,SAAO,KAAK,QAAQ,SAAS,IAAI;CACnC;;;;;;;;;;CAWA,MAAa,SACb,KACA,IACA,SACA,QACa;EACX,MAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,SAAS,OAAO;AACzD,OAAK,SACH,OAAM,IAAI,OAAO,kCAAkC;AAGrD,MAAI;AACF,UAAO,MAAM,IAAI;EAClB,UAAS;AACR,SAAM,KAAK,QAAQ,IAAI;EACzB;CACF;;;;;CAMA,AAAO,YAA2C;AAChD,SAAO,EACL,SAAS,KAAK,eACf;CACH;AACF;;;;AAKA,MAAa,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;AAqBhC,eAAsB,UACtB,KACA,IACA,SACA,QACa;AACX,QAAO,aAAa,SAAS,KAAK,IAAI,SAAS,OAAO;AACxD;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,SAA8B;AACxD,QAAO,IAAI,MAAM;AACnB;;;;;;;;AASA,eAAsB,YACtB,KACA,SACA,QACmB;AACjB,QAAO,aAAa,QAAQ,KAAK,SAAS,OAAO;AACnD;;;;;;AAOA,eAAsB,YAAY,KAA4B;AAC5D,QAAO,aAAa,QAAQ,IAAI;AAClC;;;;;;AAOA,eAAsB,SAAS,KAA+B;AAC5D,QAAO,aAAa,SAAS,IAAI;AACnC"}
1
+ {"version":3,"file":"mutex.js","names":[],"sources":["../../../src/utils/useful-stuff/mutex.ts"],"sourcesContent":["/**\n * Async mutex implementation for coordinating access to shared resources.\n * Provides mutual exclusion to ensure only one task can access a resource at a time.\n */\n\n/**\n * Interface for mutex storage implementations.\n * Provides methods to store, retrieve, and delete mutex lock data.\n */\nexport interface MutexStorage {\n /**\n * Attempts to acquire a lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for the lock\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout or already locked\n */\n acquire(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<boolean>;\n\n /**\n * Releases the lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n release(key: string): Promise<void>;\n\n /**\n * Checks if a lock is currently held for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n isLocked(key: string): Promise<boolean>;\n}\n\n/**\n * Configuration options for mutex\n */\nexport interface MutexOptions {\n /** Default timeout in milliseconds for lock acquisition. Default: 30000 */\n timeout?: number;\n /** Storage implementation for persisting mutex data. Default: {@link MemoryMutexStorage} */\n storage?: MutexStorage;\n}\n\n/**\n * In-memory storage implementation for mutex locks.\n * Suitable for single-instance applications.\n */\nexport class MemoryMutexStorage implements MutexStorage {\n private readonly locks = new Map<\n string,\n { holder: string; acquiredAt: number }\n >();\n\n /**\n * Attempts to acquire a lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for the lock\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout or already locked\n */\n async acquire(\n key: string,\n timeout: number = 30000,\n signal?: AbortSignal,\n ): Promise<boolean> {\n const holder = this.generateHolderId();\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n // Check if aborted\n if (signal?.aborted) {\n throw new Error('Lock acquisition was aborted');\n }\n\n if (!this.locks.has(key)) {\n this.locks.set(key, { holder, acquiredAt: Date.now() });\n return true;\n }\n await this.delay(10);\n }\n\n return false;\n }\n\n /**\n * Releases the lock for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n async release(key: string): Promise<void> {\n this.locks.delete(key);\n }\n\n /**\n * Checks if a lock is currently held for a given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n async isLocked(key: string): Promise<boolean> {\n return this.locks.has(key);\n }\n\n private generateHolderId(): string {\n return `holder_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Async mutex implementation that provides mutual exclusion for shared resources.\n * Ensures only one task can access a protected resource at a time.\n */\nexport class Mutex {\n private storage: MutexStorage;\n private readonly defaultTimeout: number;\n\n /**\n * Creates a new mutex instance\n * @param options - Configuration options for the mutex\n */\n public constructor(options: MutexOptions = {}) {\n this.storage = options.storage || new MemoryMutexStorage();\n this.defaultTimeout = options.timeout || 30000;\n }\n\n /**\n * Sets the storage implementation for the mutex\n * @param storage - The storage implementation to use\n */\n public setStorage(storage: MutexStorage) {\n this.storage = storage;\n }\n\n /**\n * Gets the storage implementation for the mutex\n * @returns The storage implementation\n */\n public getStorage(): MutexStorage {\n return this.storage;\n }\n\n /**\n * Acquires a lock for the given key\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout\n */\n public async acquire(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<boolean> {\n return this.storage.acquire(key, timeout || this.defaultTimeout, signal);\n }\n\n /**\n * Releases the lock for the given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\n public async release(key: string): Promise<void> {\n return this.storage.release(key);\n }\n\n /**\n * Checks if a lock is currently held for the given key\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\n public async isLocked(key: string): Promise<boolean> {\n return this.storage.isLocked(key);\n }\n\n /**\n * Executes a function with exclusive access to the resource\n * @param key - The unique identifier for the mutex lock\n * @param fn - The function to execute with exclusive access\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the lock acquisition\n * @returns Promise resolving to the result of the function execution\n * @throws Error if lock acquisition fails or function execution fails\n */\n public async withLock<T>(\n key: string,\n fn: () => Promise<T> | T,\n timeout?: number,\n signal?: AbortSignal,\n ): Promise<T> {\n const acquired = await this.acquire(key, timeout, signal);\n if (!acquired) {\n throw new Error(`Failed to acquire lock for key: ${key}`);\n }\n\n try {\n return await fn();\n } finally {\n await this.release(key);\n }\n }\n\n /**\n * Gets the current configuration of the mutex\n * @returns Object containing the current timeout value\n */\n public getConfig(): Omit<MutexOptions, 'storage'> {\n return {\n timeout: this.defaultTimeout,\n };\n }\n}\n\n/**\n * Default mutex instance for global use\n */\nexport const defaultMutex = new Mutex();\n\n/**\n * Convenience function to execute a function with exclusive access using the default mutex.\n *\n * @param key - The unique identifier for the mutex lock\n * @param fn - The function to execute with exclusive access\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the lock acquisition\n * @returns Promise resolving to the result of the function execution\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * const result = await withMutex('shared-resource', async () => {\n * // This code runs with exclusive access\n * return await updateSharedResource();\n * }, 30000, controller.signal);\n * controller.abort(); // Cancels the lock acquisition\n * ```\n */\nexport async function withMutex<T>(\n key: string,\n fn: () => Promise<T> | T,\n timeout?: number,\n signal?: AbortSignal,\n): Promise<T> {\n return defaultMutex.withLock(key, fn, timeout, signal);\n}\n\n/**\n * Creates a new mutex instance with the specified configuration\n * @param options - Configuration options for the mutex\n * @returns New Mutex instance\n *\n * @example\n * ```typescript\n * const mutex = createMutex({\n * timeout: 60000,\n * storage: new RedisMutexStorage()\n * });\n * ```\n */\nexport function createMutex(options: MutexOptions): Mutex {\n return new Mutex(options);\n}\n\n/**\n * Acquires a lock using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @param timeout - Optional timeout in milliseconds for lock acquisition\n * @param signal - Optional AbortSignal for cancelling the acquisition\n * @returns Promise resolving to true if lock was acquired, false if timeout\n */\nexport async function acquireLock(\n key: string,\n timeout?: number,\n signal?: AbortSignal,\n): Promise<boolean> {\n return defaultMutex.acquire(key, timeout, signal);\n}\n\n/**\n * Releases a lock using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @returns Promise that resolves when the lock is released\n */\nexport async function releaseLock(key: string): Promise<void> {\n return defaultMutex.release(key);\n}\n\n/**\n * Checks if a lock is held using the default mutex\n * @param key - The unique identifier for the mutex lock\n * @returns Promise resolving to true if the lock is held, false otherwise\n */\nexport async function isLocked(key: string): Promise<boolean> {\n return defaultMutex.isLocked(key);\n}\n"],"mappings":";;;;;;AAoDA,IAAa,qBAAb,MAAwD;CACtD,AAAiB,wBAAQ,IAAI;;;;;;;;CAY7B,MAAM,QACN,KACA,UAAkB,KAClB,QACmB;EACjB,MAAM,SAAS,KAAK,kBAAkB;EACtC,MAAM,YAAY,KAAK,KAAK;AAE5B,SAAO,KAAK,KAAK,GAAG,YAAY,SAAS;AAEvC,uDAAI,OAAQ,QACV,OAAM,IAAI,MAAM;AAGlB,OAAI,CAAC,KAAK,MAAM,IAAI,IAAI,EAAE;IACxB,KAAK,MAAM,IAAI,KAAK;KAAE;KAAQ,YAAY,KAAK,KAAK;IAAE,EAAC;AACvD,WAAO;GACT;GACA,MAAM,KAAK,MAAM,GAAG;EACtB;AAEA,SAAO;CACT;;;;;;CAOA,MAAM,QAAQ,KAA4B;EACxC,KAAK,MAAM,OAAO,IAAI;CACxB;;;;;;CAOA,MAAM,SAAS,KAA+B;AAC5C,SAAO,KAAK,MAAM,IAAI,IAAI;CAC5B;CAEA,AAAQ,mBAA2B;AACjC,SAAO,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,OAAO,GAAG,EAAE,EAAE;CAC1E;CAEA,AAAQ,MAAM,IAA2B;AACvC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;CACzD;AACF;;;;;AAMA,IAAa,QAAb,MAAmB;CACjB,AAAQ;CACR,AAAiB;;;;;CAMjB,AAAO,YAAY,UAAwB,CAAE,GAAE;EAC7C,KAAK,UAAU,QAAQ,WAAW,IAAI;EACtC,KAAK,iBAAiB,QAAQ,WAAW;CAC3C;;;;;CAMA,AAAO,WAAW,SAAuB;EACvC,KAAK,UAAU;CACjB;;;;;CAMA,AAAO,aAA2B;AAChC,SAAO,KAAK;CACd;;;;;;;;CASA,MAAa,QACb,KACA,SACA,QACmB;AACjB,SAAO,KAAK,QAAQ,QAAQ,KAAK,WAAW,KAAK,gBAAgB,OAAO;CAC1E;;;;;;CAOA,MAAa,QAAQ,KAA4B;AAC/C,SAAO,KAAK,QAAQ,QAAQ,IAAI;CAClC;;;;;;CAOA,MAAa,SAAS,KAA+B;AACnD,SAAO,KAAK,QAAQ,SAAS,IAAI;CACnC;;;;;;;;;;CAWA,MAAa,SACb,KACA,IACA,SACA,QACa;EACX,MAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,SAAS,OAAO;AACzD,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,CAAC,gCAAgC,EAAE,KAAK;AAG1D,MAAI;AACF,UAAO,MAAM,IAAI;EAClB,UAAS;GACR,MAAM,KAAK,QAAQ,IAAI;EACzB;CACF;;;;;CAMA,AAAO,YAA2C;AAChD,SAAO,EACL,SAAS,KAAK,eACf;CACH;AACF;;;;AAKA,MAAa,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;AAqBhC,eAAsB,UACtB,KACA,IACA,SACA,QACa;AACX,QAAO,aAAa,SAAS,KAAK,IAAI,SAAS,OAAO;AACxD;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,SAA8B;AACxD,QAAO,IAAI,MAAM;AACnB;;;;;;;;AASA,eAAsB,YACtB,KACA,SACA,QACmB;AACjB,QAAO,aAAa,QAAQ,KAAK,SAAS,OAAO;AACnD;;;;;;AAOA,eAAsB,YAAY,KAA4B;AAC5D,QAAO,aAAa,QAAQ,IAAI;AAClC;;;;;;AAOA,eAAsB,SAAS,KAA+B;AAC5D,QAAO,aAAa,SAAS,IAAI;AACnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ratelimiter.js","names":[],"sources":["../../../src/utils/useful-stuff/ratelimiter.ts"],"sourcesContent":["/**\n * Default timeout interval for rate limiting in milliseconds\n */\nexport const DEFAULT_TIMEOUT = 60000;\n\n/**\n * Default maximum number of requests allowed per interval\n */\nexport const DEFAULT_MAX_REQUESTS = 10;\n\n/**\n * Interface for rate limit storage implementations.\n * Provides methods to store, retrieve, and delete rate limit data.\n */\nexport interface RateLimitStorage {\n /**\n * Retrieves the current request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the current request count\n */\n get(key: string): Promise<number>;\n\n /**\n * Sets the request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @param value - The request count to store\n * @returns Promise that resolves when the value is stored\n */\n set(key: string, value: number): Promise<void>;\n\n /**\n * Deletes the rate limit entry for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the entry is deleted\n */\n delete(key: string): Promise<void>;\n}\n\n/**\n * Configuration options for rate limiting\n */\nexport interface RateLimitOptions {\n /** Maximum number of requests allowed per interval. Default: 10 */\n maxRequests?: number;\n /** Time interval in milliseconds for the rate limit window. Default: 60000 */\n interval?: number;\n /** Storage implementation for persisting rate limit data. Default: {@link MemoryRateLimitStorage} */\n storage?: RateLimitStorage;\n}\n\n/**\n * In-memory storage implementation for rate limiting.\n * Suitable for single-instance applications.\n */\nexport class MemoryRateLimitStorage implements RateLimitStorage {\n private readonly store = new Map<string, number>();\n\n /**\n * Retrieves the current request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the current request count or 0 if not found\n */\n async get(key: string): Promise<number> {\n return this.store.get(key) || 0;\n }\n\n /**\n * Sets the request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @param value - The request count to store\n * @returns Promise that resolves immediately\n */\n async set(key: string, value: number): Promise<void> {\n this.store.set(key, value);\n }\n\n /**\n * Deletes the rate limit entry for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves immediately\n */\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\n/**\n * Rate limiter implementation that enforces request limits per key.\n * Supports configurable request limits and time intervals.\n */\nexport class RateLimiter {\n private readonly limits: Map<string, number> = new Map();\n private readonly lastReset: Map<string, number> = new Map();\n private readonly resetInterval: number;\n\n /**\n * Creates a new rate limiter instance\n * @param maxRequests - Maximum number of requests allowed per interval (default: 10)\n * @param interval - Time interval in milliseconds for the rate limit window (default: 60000)\n * @param storage - Optional storage implementation (default: MemoryRateLimitStorage)\n */\n public constructor(\n private readonly maxRequests: number = DEFAULT_MAX_REQUESTS,\n private readonly interval: number = DEFAULT_TIMEOUT,\n private storage: RateLimitStorage = new MemoryRateLimitStorage(),\n ) {\n this.resetInterval = interval;\n }\n\n /**\n * Sets the storage implementation for the rate limiter\n * @param storage - The storage implementation to use\n */\n public setStorage(storage: RateLimitStorage) {\n this.storage = storage;\n }\n\n /**\n * Gets the storage implementation for the rate limiter\n * @returns The storage implementation\n */\n public getStorage(): RateLimitStorage {\n return this.storage;\n }\n\n /**\n * Checks if a request is allowed for the given key and increments the counter if allowed\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to true if the request is allowed, false if rate limited\n */\n public async limit(key: string): Promise<boolean> {\n const now = Date.now();\n const lastReset = this.lastReset.get(key) || 0;\n const timeSinceReset = now - lastReset;\n\n // Reset counter if interval has passed\n if (timeSinceReset > this.resetInterval) {\n await this.storage.delete(key);\n this.lastReset.set(key, now);\n this.limits.set(key, 0);\n }\n\n // Get current count from storage\n const currentCount = await this.storage.get(key);\n\n // Check if limit exceeded\n if (currentCount >= this.maxRequests) {\n return false;\n }\n\n // Increment counter\n const newCount = currentCount + 1;\n await this.storage.set(key, newCount);\n this.limits.set(key, newCount);\n\n return true;\n }\n\n /**\n * Gets the remaining requests allowed for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the number of remaining requests\n */\n public async getRemaining(key: string): Promise<number> {\n const currentCount = await this.storage.get(key);\n return Math.max(0, this.maxRequests - currentCount);\n }\n\n /**\n * Gets the time until the rate limit resets for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the time in milliseconds until reset, or 0 if no limit is active\n */\n public async getResetTime(key: string): Promise<number> {\n const lastReset = this.lastReset.get(key) || 0;\n const now = Date.now();\n const timeSinceReset = now - lastReset;\n\n if (timeSinceReset >= this.resetInterval) {\n return 0;\n }\n\n return this.resetInterval - timeSinceReset;\n }\n\n /**\n * Resets the rate limit for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the reset is complete\n */\n public async reset(key: string): Promise<void> {\n await this.storage.delete(key);\n this.limits.delete(key);\n this.lastReset.delete(key);\n }\n\n /**\n * Gets the current configuration of the rate limiter\n * @returns Object containing the current maxRequests and interval values\n */\n public getConfig(): Omit<RateLimitOptions, 'storage'> {\n return {\n maxRequests: this.maxRequests,\n interval: this.interval,\n };\n }\n}\n\n/**\n * Default rate limiter instance for global use\n */\nexport const defaultRateLimiter = new RateLimiter();\n\n/**\n * Convenience function to check if a request is allowed for a given key.\n * Uses the default rate limiter instance.\n *\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to true if the request is allowed, false if rate limited\n *\n * @example\n * ```typescript\n * const allowed = await ratelimit('user:123');\n * // update the default rate limiter config\n * import { defaultRateLimiter } from 'commandkit/ratelimit';\n *\n * // update max allowed requests\n * defaultRateLimiter.setMaxRequests(10);\n *\n * // update the timeout interval\n * defaultRateLimiter.setInterval(30000);\n *\n * // update the storage implementation\n * defaultRateLimiter.setStorage(new RedisStorage());\n * ```\n */\nexport async function ratelimit(key: string): Promise<boolean> {\n return defaultRateLimiter.limit(key);\n}\n\n/**\n * Creates a new rate limiter instance with the specified configuration\n * @param options - Configuration options for the rate limiter\n * @returns New RateLimiter instance\n *\n * @example\n * ```typescript\n * const limiter = createRateLimiter({\n * maxRequests: 5,\n * interval: 30000,\n * storage: new CustomStorage()\n * });\n * ```\n */\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(\n options.maxRequests,\n options.interval,\n options.storage,\n );\n}\n\n/**\n * Gets the remaining requests for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the number of remaining requests\n */\nexport async function getRemainingRequests(key: string): Promise<number> {\n return defaultRateLimiter.getRemaining(key);\n}\n\n/**\n * Gets the reset time for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the time in milliseconds until reset\n */\nexport async function getResetTime(key: string): Promise<number> {\n return defaultRateLimiter.getResetTime(key);\n}\n\n/**\n * Resets the rate limit for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the reset is complete\n */\nexport async function resetRateLimit(key: string): Promise<void> {\n return defaultRateLimiter.reset(key);\n}\n"],"mappings":";;;;;AAGA,MAAa,kBAAkB;;;;AAK/B,MAAa,uBAAuB;;;;;AA8CpC,IAAa,yBAAb,MAAgE;CAC9D,AAAiB,wBAAQ,IAAI;;;;;;CAO7B,MAAM,IAAI,KAA8B;AACtC,SAAO,KAAK,MAAM,IAAI,IAAI,IAAI;CAChC;;;;;;;CAQA,MAAM,IAAI,KAAa,OAA8B;AACnD,OAAK,MAAM,IAAI,KAAK,MAAM;CAC5B;;;;;;CAOA,MAAM,OAAO,KAA4B;AACvC,OAAK,MAAM,OAAO,IAAI;CACxB;AACF;;;;;AAMA,IAAa,cAAb,MAAyB;CACvB,AAAiB,yBAA8B,IAAI;CACnD,AAAiB,4BAAiC,IAAI;CACtD,AAAiB;;;;;;;CAQjB,AAAO,YACU,cAAsB,sBACtB,WAAmB,iBAC5B,UAA4B,IAAI,0BACxC;EAHiB;EACA;EACT;AAEN,OAAK,gBAAgB;CACvB;;;;;CAMA,AAAO,WAAW,SAA2B;AAC3C,OAAK,UAAU;CACjB;;;;;CAMA,AAAO,aAA+B;AACpC,SAAO,KAAK;CACd;;;;;;CAOA,MAAa,MAAM,KAA+B;EAChD,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,YAAY,KAAK,UAAU,IAAI,IAAI,IAAI;EAC7C,MAAM,iBAAiB,MAAM;AAG7B,MAAI,iBAAiB,KAAK,eAAe;AACvC,SAAM,KAAK,QAAQ,OAAO,IAAI;AAC9B,QAAK,UAAU,IAAI,KAAK,IAAI;AAC5B,QAAK,OAAO,IAAI,KAAK,EAAE;EACzB;EAGA,MAAM,eAAe,MAAM,KAAK,QAAQ,IAAI,IAAI;AAGhD,MAAI,gBAAgB,KAAK,YACvB,QAAO;EAIT,MAAM,WAAW,eAAe;AAChC,QAAM,KAAK,QAAQ,IAAI,KAAK,SAAS;AACrC,OAAK,OAAO,IAAI,KAAK,SAAS;AAE9B,SAAO;CACT;;;;;;CAOA,MAAa,aAAa,KAA8B;EACtD,MAAM,eAAe,MAAM,KAAK,QAAQ,IAAI,IAAI;AAChD,SAAO,KAAK,IAAI,GAAG,KAAK,cAAc,aAAa;CACrD;;;;;;CAOA,MAAa,aAAa,KAA8B;EACtD,MAAM,YAAY,KAAK,UAAU,IAAI,IAAI,IAAI;EAC7C,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,iBAAiB,MAAM;AAE7B,MAAI,kBAAkB,KAAK,cACzB,QAAO;AAGT,SAAO,KAAK,gBAAgB;CAC9B;;;;;;CAOA,MAAa,MAAM,KAA4B;AAC7C,QAAM,KAAK,QAAQ,OAAO,IAAI;AAC9B,OAAK,OAAO,OAAO,IAAI;AACvB,OAAK,UAAU,OAAO,IAAI;CAC5B;;;;;CAMA,AAAO,YAA+C;AACpD,SAAO;GACL,aAAa,KAAK;GAClB,UAAU,KAAK;EAChB;CACH;AACF;;;;AAKA,MAAa,qBAAqB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;AAyBtC,eAAsB,UAAU,KAA+B;AAC7D,QAAO,mBAAmB,MAAM,IAAI;AACtC;;;;;;;;;;;;;;;AAgBA,SAAgB,kBAAkB,SAAwC;AACxE,QAAO,IAAI,YACT,QAAQ,aACR,QAAQ,UACR,QAAQ;AAEZ;;;;;;AAOA,eAAsB,qBAAqB,KAA8B;AACvE,QAAO,mBAAmB,aAAa,IAAI;AAC7C;;;;;;AAOA,eAAsB,aAAa,KAA8B;AAC/D,QAAO,mBAAmB,aAAa,IAAI;AAC7C;;;;;;AAOA,eAAsB,eAAe,KAA4B;AAC/D,QAAO,mBAAmB,MAAM,IAAI;AACtC"}
1
+ {"version":3,"file":"ratelimiter.js","names":[],"sources":["../../../src/utils/useful-stuff/ratelimiter.ts"],"sourcesContent":["/**\n * Default timeout interval for rate limiting in milliseconds\n */\nexport const DEFAULT_TIMEOUT = 60000;\n\n/**\n * Default maximum number of requests allowed per interval\n */\nexport const DEFAULT_MAX_REQUESTS = 10;\n\n/**\n * Interface for rate limit storage implementations.\n * Provides methods to store, retrieve, and delete rate limit data.\n */\nexport interface RateLimitStorage {\n /**\n * Retrieves the current request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the current request count\n */\n get(key: string): Promise<number>;\n\n /**\n * Sets the request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @param value - The request count to store\n * @returns Promise that resolves when the value is stored\n */\n set(key: string, value: number): Promise<void>;\n\n /**\n * Deletes the rate limit entry for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the entry is deleted\n */\n delete(key: string): Promise<void>;\n}\n\n/**\n * Configuration options for rate limiting\n */\nexport interface RateLimitOptions {\n /** Maximum number of requests allowed per interval. Default: 10 */\n maxRequests?: number;\n /** Time interval in milliseconds for the rate limit window. Default: 60000 */\n interval?: number;\n /** Storage implementation for persisting rate limit data. Default: {@link MemoryRateLimitStorage} */\n storage?: RateLimitStorage;\n}\n\n/**\n * In-memory storage implementation for rate limiting.\n * Suitable for single-instance applications.\n */\nexport class MemoryRateLimitStorage implements RateLimitStorage {\n private readonly store = new Map<string, number>();\n\n /**\n * Retrieves the current request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the current request count or 0 if not found\n */\n async get(key: string): Promise<number> {\n return this.store.get(key) || 0;\n }\n\n /**\n * Sets the request count for a given key\n * @param key - The unique identifier for the rate limit entry\n * @param value - The request count to store\n * @returns Promise that resolves immediately\n */\n async set(key: string, value: number): Promise<void> {\n this.store.set(key, value);\n }\n\n /**\n * Deletes the rate limit entry for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves immediately\n */\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n}\n\n/**\n * Rate limiter implementation that enforces request limits per key.\n * Supports configurable request limits and time intervals.\n */\nexport class RateLimiter {\n private readonly limits: Map<string, number> = new Map();\n private readonly lastReset: Map<string, number> = new Map();\n private readonly resetInterval: number;\n\n /**\n * Creates a new rate limiter instance\n * @param maxRequests - Maximum number of requests allowed per interval (default: 10)\n * @param interval - Time interval in milliseconds for the rate limit window (default: 60000)\n * @param storage - Optional storage implementation (default: MemoryRateLimitStorage)\n */\n public constructor(\n private readonly maxRequests: number = DEFAULT_MAX_REQUESTS,\n private readonly interval: number = DEFAULT_TIMEOUT,\n private storage: RateLimitStorage = new MemoryRateLimitStorage(),\n ) {\n this.resetInterval = interval;\n }\n\n /**\n * Sets the storage implementation for the rate limiter\n * @param storage - The storage implementation to use\n */\n public setStorage(storage: RateLimitStorage) {\n this.storage = storage;\n }\n\n /**\n * Gets the storage implementation for the rate limiter\n * @returns The storage implementation\n */\n public getStorage(): RateLimitStorage {\n return this.storage;\n }\n\n /**\n * Checks if a request is allowed for the given key and increments the counter if allowed\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to true if the request is allowed, false if rate limited\n */\n public async limit(key: string): Promise<boolean> {\n const now = Date.now();\n const lastReset = this.lastReset.get(key) || 0;\n const timeSinceReset = now - lastReset;\n\n // Reset counter if interval has passed\n if (timeSinceReset > this.resetInterval) {\n await this.storage.delete(key);\n this.lastReset.set(key, now);\n this.limits.set(key, 0);\n }\n\n // Get current count from storage\n const currentCount = await this.storage.get(key);\n\n // Check if limit exceeded\n if (currentCount >= this.maxRequests) {\n return false;\n }\n\n // Increment counter\n const newCount = currentCount + 1;\n await this.storage.set(key, newCount);\n this.limits.set(key, newCount);\n\n return true;\n }\n\n /**\n * Gets the remaining requests allowed for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the number of remaining requests\n */\n public async getRemaining(key: string): Promise<number> {\n const currentCount = await this.storage.get(key);\n return Math.max(0, this.maxRequests - currentCount);\n }\n\n /**\n * Gets the time until the rate limit resets for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the time in milliseconds until reset, or 0 if no limit is active\n */\n public async getResetTime(key: string): Promise<number> {\n const lastReset = this.lastReset.get(key) || 0;\n const now = Date.now();\n const timeSinceReset = now - lastReset;\n\n if (timeSinceReset >= this.resetInterval) {\n return 0;\n }\n\n return this.resetInterval - timeSinceReset;\n }\n\n /**\n * Resets the rate limit for a given key\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the reset is complete\n */\n public async reset(key: string): Promise<void> {\n await this.storage.delete(key);\n this.limits.delete(key);\n this.lastReset.delete(key);\n }\n\n /**\n * Gets the current configuration of the rate limiter\n * @returns Object containing the current maxRequests and interval values\n */\n public getConfig(): Omit<RateLimitOptions, 'storage'> {\n return {\n maxRequests: this.maxRequests,\n interval: this.interval,\n };\n }\n}\n\n/**\n * Default rate limiter instance for global use\n */\nexport const defaultRateLimiter = new RateLimiter();\n\n/**\n * Convenience function to check if a request is allowed for a given key.\n * Uses the default rate limiter instance.\n *\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to true if the request is allowed, false if rate limited\n *\n * @example\n * ```typescript\n * const allowed = await ratelimit('user:123');\n * // update the default rate limiter config\n * import { defaultRateLimiter } from 'commandkit/ratelimit';\n *\n * // update max allowed requests\n * defaultRateLimiter.setMaxRequests(10);\n *\n * // update the timeout interval\n * defaultRateLimiter.setInterval(30000);\n *\n * // update the storage implementation\n * defaultRateLimiter.setStorage(new RedisStorage());\n * ```\n */\nexport async function ratelimit(key: string): Promise<boolean> {\n return defaultRateLimiter.limit(key);\n}\n\n/**\n * Creates a new rate limiter instance with the specified configuration\n * @param options - Configuration options for the rate limiter\n * @returns New RateLimiter instance\n *\n * @example\n * ```typescript\n * const limiter = createRateLimiter({\n * maxRequests: 5,\n * interval: 30000,\n * storage: new CustomStorage()\n * });\n * ```\n */\nexport function createRateLimiter(options: RateLimitOptions): RateLimiter {\n return new RateLimiter(\n options.maxRequests,\n options.interval,\n options.storage,\n );\n}\n\n/**\n * Gets the remaining requests for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the number of remaining requests\n */\nexport async function getRemainingRequests(key: string): Promise<number> {\n return defaultRateLimiter.getRemaining(key);\n}\n\n/**\n * Gets the reset time for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise resolving to the time in milliseconds until reset\n */\nexport async function getResetTime(key: string): Promise<number> {\n return defaultRateLimiter.getResetTime(key);\n}\n\n/**\n * Resets the rate limit for a key using the default rate limiter\n * @param key - The unique identifier for the rate limit entry\n * @returns Promise that resolves when the reset is complete\n */\nexport async function resetRateLimit(key: string): Promise<void> {\n return defaultRateLimiter.reset(key);\n}\n"],"mappings":";;;;;AAGA,MAAa,kBAAkB;;;;AAK/B,MAAa,uBAAuB;;;;;AA8CpC,IAAa,yBAAb,MAAgE;CAC9D,AAAiB,wBAAQ,IAAI;;;;;;CAO7B,MAAM,IAAI,KAA8B;AACtC,SAAO,KAAK,MAAM,IAAI,IAAI,IAAI;CAChC;;;;;;;CAQA,MAAM,IAAI,KAAa,OAA8B;EACnD,KAAK,MAAM,IAAI,KAAK,MAAM;CAC5B;;;;;;CAOA,MAAM,OAAO,KAA4B;EACvC,KAAK,MAAM,OAAO,IAAI;CACxB;AACF;;;;;AAMA,IAAa,cAAb,MAAyB;CACvB,AAAiB,yBAA8B,IAAI;CACnD,AAAiB,4BAAiC,IAAI;CACtD,AAAiB;;;;;;;CAQjB,AAAO,YACU,cAAsB,sBACtB,WAAmB,iBAC5B,UAA4B,IAAI,0BACxC;EAHiB;EACA;EACT;EAEN,KAAK,gBAAgB;CACvB;;;;;CAMA,AAAO,WAAW,SAA2B;EAC3C,KAAK,UAAU;CACjB;;;;;CAMA,AAAO,aAA+B;AACpC,SAAO,KAAK;CACd;;;;;;CAOA,MAAa,MAAM,KAA+B;EAChD,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,YAAY,KAAK,UAAU,IAAI,IAAI,IAAI;EAC7C,MAAM,iBAAiB,MAAM;AAG7B,MAAI,iBAAiB,KAAK,eAAe;GACvC,MAAM,KAAK,QAAQ,OAAO,IAAI;GAC9B,KAAK,UAAU,IAAI,KAAK,IAAI;GAC5B,KAAK,OAAO,IAAI,KAAK,EAAE;EACzB;EAGA,MAAM,eAAe,MAAM,KAAK,QAAQ,IAAI,IAAI;AAGhD,MAAI,gBAAgB,KAAK,YACvB,QAAO;EAIT,MAAM,WAAW,eAAe;EAChC,MAAM,KAAK,QAAQ,IAAI,KAAK,SAAS;EACrC,KAAK,OAAO,IAAI,KAAK,SAAS;AAE9B,SAAO;CACT;;;;;;CAOA,MAAa,aAAa,KAA8B;EACtD,MAAM,eAAe,MAAM,KAAK,QAAQ,IAAI,IAAI;AAChD,SAAO,KAAK,IAAI,GAAG,KAAK,cAAc,aAAa;CACrD;;;;;;CAOA,MAAa,aAAa,KAA8B;EACtD,MAAM,YAAY,KAAK,UAAU,IAAI,IAAI,IAAI;EAC7C,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,iBAAiB,MAAM;AAE7B,MAAI,kBAAkB,KAAK,cACzB,QAAO;AAGT,SAAO,KAAK,gBAAgB;CAC9B;;;;;;CAOA,MAAa,MAAM,KAA4B;EAC7C,MAAM,KAAK,QAAQ,OAAO,IAAI;EAC9B,KAAK,OAAO,OAAO,IAAI;EACvB,KAAK,UAAU,OAAO,IAAI;CAC5B;;;;;CAMA,AAAO,YAA+C;AACpD,SAAO;GACL,aAAa,KAAK;GAClB,UAAU,KAAK;EAChB;CACH;AACF;;;;AAKA,MAAa,qBAAqB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;AAyBtC,eAAsB,UAAU,KAA+B;AAC7D,QAAO,mBAAmB,MAAM,IAAI;AACtC;;;;;;;;;;;;;;;AAgBA,SAAgB,kBAAkB,SAAwC;AACxE,QAAO,IAAI,YACT,QAAQ,aACR,QAAQ,UACR,QAAQ;AAEZ;;;;;;AAOA,eAAsB,qBAAqB,KAA8B;AACvE,QAAO,mBAAmB,aAAa,IAAI;AAC7C;;;;;;AAOA,eAAsB,aAAa,KAA8B;AAC/D,QAAO,mBAAmB,aAAa,IAAI;AAC7C;;;;;;AAOA,eAAsB,eAAe,KAA4B;AAC/D,QAAO,mBAAmB,MAAM,IAAI;AACtC"}