@burdenoff/be-sdk 2026.927.3 → 2026.927.5

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.
@@ -234,21 +234,31 @@ async function loadTranslationsForLocale(config, locale) {
234
234
  if (stats.isFile() && path.endsWith(".json")) {
235
235
  const translations = await loadTranslationFile(path, config.localesPath);
236
236
  const flattened = flattenDictionary(translations);
237
+ if (Object.keys(flattened).length === 0) {
238
+ logger.debug(`[I18n] Skipped ${path}: no translation keys`);
239
+ continue;
240
+ }
237
241
  Object.assign(result, flattened);
238
242
  logger.debug(`[I18n] Loaded translations from ${path}`);
239
243
  break;
240
244
  } else if (stats.isDirectory()) {
241
245
  const files = await safeReaddir(path, config.localesPath);
246
+ const directoryTranslations = {};
242
247
  for (const file of files) {
243
248
  if (extname(file) === ".json") {
244
249
  const namespace = basename(file, ".json");
245
250
  const filePath = join(path, file);
246
251
  const translations = await loadTranslationFile(filePath, config.localesPath);
247
252
  const flattened = flattenDictionary(translations, namespace);
248
- Object.assign(result, flattened);
253
+ Object.assign(directoryTranslations, flattened);
249
254
  logger.debug(`[I18n] Loaded namespace ${namespace} from ${filePath}`);
250
255
  }
251
256
  }
257
+ if (Object.keys(directoryTranslations).length === 0) {
258
+ logger.debug(`[I18n] Skipped ${path}: no translation keys`);
259
+ continue;
260
+ }
261
+ Object.assign(result, directoryTranslations);
252
262
  break;
253
263
  }
254
264
  } catch {
@@ -760,5 +770,5 @@ var DEFAULT_I18N_CONFIG = {
760
770
  };
761
771
 
762
772
  export { DEFAULT_I18N_CONFIG, I18n, Locales, RTL_LANGUAGES, clearTranslationCache, createI18n, createTranslator, discoverLocales, extractLocaleFromRequest, findBestMatch, flattenDictionary, getCachedTranslations, getI18n, getLanguage, getLanguageFromLocale, getLocale, getRegionFromLocale, getTextDirection, hasI18n, i18n_exports, initializeI18n, loadTranslationFile, loadTranslationsForLocale, normalizeLocale, parseAcceptLanguage, parseLocaleString, preloadAllTranslations, setCachedTranslations, t };
763
- //# sourceMappingURL=chunk-IUJSIXMM.js.map
764
- //# sourceMappingURL=chunk-IUJSIXMM.js.map
773
+ //# sourceMappingURL=chunk-EBDHIL7V.js.map
774
+ //# sourceMappingURL=chunk-EBDHIL7V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/i18n/index.ts","../src/i18n/types.ts","../src/i18n/parser.ts","../src/i18n/loader.ts","../src/i18n/i18n.ts","../src/i18n/helpers.ts"],"names":["RTL_LANGUAGES","getTextDirection","language","includes","parseLocaleString","localeStr","trimmed","trim","localePart","params","split","quality","param","key","value","toLowerCase","parsed","parseFloat","isNaN","locale","parts","region","toUpperCase","normalizedLocale","parseAcceptLanguage","header","locales","part","push","sort","a","b","extractLocaleFromRequest","request","defaultLocale","explicitLocale","headers","get","acceptLanguage","parsedLocales","length","normalizeLocale","getLanguageFromLocale","getRegionFromLocale","findBestMatch","requested","available","availableSet","Set","map","l","req","has","find","langMatch","translationCache","Map","validateFilePath","filePath","baseDir","resolvedBase","resolve","resolvedPath","relativePath","relative","startsWith","Error","safeReadFile","validatedPath","Bun","file","text","safeStat","stat","catch","safeReaddir","dirPath","readdir","flattenDictionary","obj","prefix","result","Object","entries","fullKey","assign","loadTranslationFile","content","data","JSON","parse","error","logger","getCacheKey","namespace","loadTranslationsForLocale","config","cacheKey","enableCache","pathsToTry","join","localesPath","path","stats","isFile","endsWith","translations","flattened","keys","debug","isDirectory","files","directoryTranslations","extname","basename","fallbackLocale","warn","fallbackTranslations","undefined","set","discoverLocales","validatedBasePath","entry","entryPath","preloadAllTranslations","supportedLocales","info","Promise","all","clearTranslationCache","delete","clear","getCachedTranslations","setCachedTranslations","getEnglishPluralCategory","absCount","getFrenchPluralCategory","getSlavicPluralCategory","mod10","mod100","getArabicPluralCategory","getPolishCzechPluralCategory","getRomanianPluralCategory","getHebrewPluralCategory","getPluralCategory","count","Math","abs","englishLanguages","interpolate","variables","replace","match","String","I18n","currentLocale","initialized","returnKeyOnMissing","logMissing","initialize","lazyLoad","getLocale","setLocale","getSupportedLocales","isSupported","normalized","some","supportedNorm","loadLocale","getTranslations","t","defaultValue","translate","tp","translatePlural","langTranslations","category","pluralKey","createContext","formatNumber","options","Intl","NumberFormat","format","formatCurrency","currency","style","formatDate","date","dateObj","Date","DateTimeFormat","formatRelativeTime","unit","RelativeTimeFormat","numeric","createContextFromRequest","bestMatch","getLanguageInfo","direction","code","globalI18n","initializeI18n","getI18n","createI18n","interpolateVariables","ctx","defaultMessage","i18n","translated","createTranslator","hasI18n","getLanguage","defaultLanguage","Locales","EN_US","EN_GB","EN_AU","EN_CA","EN_IN","ES_ES","ES_MX","FR_FR","FR_CA","DE_DE","DE_AT","DE_CH","IT_IT","PT_PT","PT_BR","RU_RU","ZH_CN","ZH_TW","ZH_HK","JA_JP","KO_KR","AR_SA","AR_AE","HI_IN","TA_IN","NL_NL","PL_PL","TR_TR","VI_VN","TH_TH","ID_ID","HE_IL","UK_UA","DEFAULT_I18N_CONFIG"],"mappings":";;;;;;AAAA,IAAA,YAAA,GAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgSO,IAAMA,aAAAA,GAAgC;AAAC,EAAA,IAAA;AAAM,EAAA;;AAK7C,SAASC,iBAAiBC,QAAAA,EAAsB;AACrD,EAAA,OAAOF,aAAAA,CAAcG,QAAAA,CAASD,QAAAA,CAAAA,GAAY,KAAA,GAAQ,KAAA;AACpD;AAFgBD,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;;;AC1RT,SAASG,kBAAkBC,SAAAA,EAAiB;AACjD,EAAA,MAAMC,OAAAA,GAAUD,UAAUE,IAAAA,EAAI;AAC9B,EAAA,IAAI,CAACD,OAAAA,IAAWA,OAAAA,KAAY,GAAA,EAAK;AAC/B,IAAA,OAAO,IAAA;AACT,EAAA;AAGA,EAAA,MAAM,CAACE,UAAAA,EAAY,GAAGC,MAAAA,CAAAA,GAAUH,OAAAA,CAAQI,MAAM,GAAA,CAAA;AAC9C,EAAA,IAAIC,OAAAA,GAAU,CAAA;AAEd,EAAA,KAAA,MAAWC,SAASH,MAAAA,EAAQ;AAC1B,IAAA,MAAM,CAACI,KAAKC,KAAAA,CAAAA,GAASF,MAAML,IAAAA,EAAI,CAAGG,MAAM,GAAA,CAAA;AACxC,IAAA,IAAIG,GAAAA,EAAKE,WAAAA,EAAAA,KAAkB,GAAA,IAAOD,KAAAA,EAAO;AACvC,MAAA,MAAME,MAAAA,GAASC,WAAWH,KAAAA,CAAAA;AAC1B,MAAA,IAAI,CAACI,KAAAA,CAAMF,MAAAA,KAAWA,MAAAA,IAAU,CAAA,IAAKA,UAAU,CAAA,EAAG;AAChDL,QAAAA,OAAAA,GAAUK,MAAAA;AACZ,MAAA;AACF,IAAA;AACF,EAAA;AAEA,EAAA,MAAMG,MAAAA,GAASX,YAAYD,IAAAA,EAAAA;AAC3B,EAAA,IAAI,CAACY,MAAAA,EAAQ;AACX,IAAA,OAAO,IAAA;AACT,EAAA;AAGA,EAAA,MAAMC,KAAAA,GAAQD,MAAAA,CAAOT,KAAAA,CAAM,GAAA,CAAA;AAC3B,EAAA,MAAMR,QAAAA,GAAWkB,KAAAA,CAAM,CAAA,CAAA,EAAIL,WAAAA,EAAAA;AAC3B,EAAA,MAAMM,MAAAA,GAASD,KAAAA,CAAM,CAAA,CAAA,EAAIE,WAAAA,EAAAA;AAGzB,EAAA,MAAMC,mBAAmBF,MAAAA,GAAS,CAAA,EAAGnB,QAAAA,CAAAA,CAAAA,EAAYmB,MAAAA,CAAAA,CAAAA,GAAWnB,QAAAA;AAE5D,EAAA,OAAO;IACLiB,MAAAA,EAAQI,gBAAAA;AACRrB,IAAAA,QAAAA;AACAmB,IAAAA,MAAAA;AACAV,IAAAA;AACF,GAAA;AACF;AAvCgBP,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAiDT,SAASoB,oBAAoBC,MAAAA,EAAiC;AACnE,EAAA,IAAI,CAACA,MAAAA,IAAUA,MAAAA,CAAOlB,IAAAA,OAAW,EAAA,EAAI;AACnC,IAAA,OAAO,EAAA;AACT,EAAA;AAEA,EAAA,MAAMmB,UAA0B,EAAA;AAGhC,EAAA,MAAMN,KAAAA,GAAQK,MAAAA,CAAOf,KAAAA,CAAM,GAAA,CAAA;AAC3B,EAAA,KAAA,MAAWiB,QAAQP,KAAAA,EAAO;AACxB,IAAA,MAAMJ,MAAAA,GAASZ,kBAAkBuB,IAAAA,CAAAA;AACjC,IAAA,IAAIX,MAAAA,EAAQ;AACVU,MAAAA,OAAAA,CAAQE,KAAKZ,MAAAA,CAAAA;AACf,IAAA;AACF,EAAA;AAGAU,EAAAA,OAAAA,CAAQG,KAAK,CAACC,CAAAA,EAAGC,MAAMA,CAAAA,CAAEpB,OAAAA,GAAUmB,EAAEnB,OAAO,CAAA;AAE5C,EAAA,OAAOe,OAAAA;AACT;AApBgBF,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAkCT,SAASQ,wBAAAA,CAAyBC,OAAAA,EAAkBC,aAAAA,GAA4B,OAAA,EAAO;AAE5F,EAAA,MAAMC,cAAAA,GAAiBF,QAAQG,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,IAAeJ,OAAAA,CAAQG,OAAAA,CAAQC,GAAAA,CAAI,YAAA,CAAA;AAC9E,EAAA,IAAIF,cAAAA,EAAgB;AAClB,IAAA,MAAMnB,MAAAA,GAASZ,kBAAkB+B,cAAAA,CAAAA;AACjC,IAAA,IAAInB,MAAAA,EAAQ;AACV,MAAA,OAAOA,MAAAA;AACT,IAAA;AACF,EAAA;AAGA,EAAA,MAAMsB,cAAAA,GAAiBL,OAAAA,CAAQG,OAAAA,CAAQC,GAAAA,CAAI,iBAAA,CAAA;AAC3C,EAAA,MAAME,aAAAA,GAAgBf,oBAAoBc,cAAAA,CAAAA;AAE1C,EAAA,IAAIC,aAAAA,CAAcC,SAAS,CAAA,EAAG;AAC5B,IAAA,OAAOD,cAAc,CAAA,CAAA;AACvB,EAAA;AAGA,EAAA,MAAM,CAACrC,QAAAA,EAAUmB,MAAAA,CAAAA,GAAUa,aAAAA,CAAcxB,MAAM,GAAA,CAAA;AAC/C,EAAA,OAAO;IACLS,MAAAA,EAAQe,aAAAA;AACRhC,IAAAA,QAAAA;AACAmB,IAAAA,MAAAA;IACAV,OAAAA,EAAS;AACX,GAAA;AACF;AA1BgBqB,MAAAA,CAAAA,wBAAAA,EAAAA,0BAAAA,CAAAA;AAkCT,SAASS,gBAAgBtB,MAAAA,EAAc;AAC5C,EAAA,MAAMC,KAAAA,GAAQD,MAAAA,CAAOZ,IAAAA,EAAI,CAAGG,MAAM,MAAA,CAAA;AAClC,EAAA,MAAMR,QAAAA,GAAWkB,KAAAA,CAAM,CAAA,CAAA,EAAIL,WAAAA,EAAAA;AAC3B,EAAA,MAAMM,MAAAA,GAASD,KAAAA,CAAM,CAAA,CAAA,EAAIE,WAAAA,EAAAA;AAEzB,EAAA,IAAID,MAAAA,EAAQ;AACV,IAAA,OAAO,CAAA,EAAGnB,QAAAA,CAAAA,CAAAA,EAAYmB,MAAAA,CAAAA,CAAAA;AACxB,EAAA;AACA,EAAA,OAAOnB,QAAAA;AACT;AATgBuC,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAcT,SAASC,sBAAsBvB,MAAAA,EAAkB;AACtD,EAAA,OAAOA,MAAAA,CAAOT,KAAAA,CAAM,GAAA,CAAA,CAAK,CAAA,CAAA;AAC3B;AAFgBgC,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AAOT,SAASC,oBAAoBxB,MAAAA,EAAkB;AACpD,EAAA,MAAMC,KAAAA,GAAQD,MAAAA,CAAOT,KAAAA,CAAM,GAAA,CAAA;AAC3B,EAAA,OAAOU,MAAM,CAAA,CAAA;AACf;AAHgBuB,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAaT,SAASC,aAAAA,CACdC,SAAAA,EACAC,SAAAA,EACAZ,aAAAA,EAAyB;AAEzB,EAAA,MAAMa,YAAAA,GAAe,IAAIC,GAAAA,CAAIF,SAAAA,CAAUG,GAAAA,CAAI,CAACC,CAAAA,KAAMA,CAAAA,CAAEnC,WAAAA,EAAW,CAAA,CAAA;AAE/D,EAAA,KAAA,MAAWoC,OAAON,SAAAA,EAAW;AAE3B,IAAA,IAAIE,aAAaK,GAAAA,CAAID,GAAAA,CAAIhC,MAAAA,CAAOJ,WAAAA,EAAW,CAAA,EAAK;AAE9C,MAAA,OAAO+B,SAAAA,CAAUO,IAAAA,CAAK,CAACH,CAAAA,KAAMA,CAAAA,CAAEnC,WAAAA,EAAW,KAAOoC,GAAAA,CAAIhC,MAAAA,CAAOJ,WAAAA,EAAW,CAAA,IAAOoC,GAAAA,CAAIhC,MAAAA;AACpF,IAAA;AAGA,IAAA,IAAI4B,aAAaK,GAAAA,CAAID,GAAAA,CAAIjD,QAAAA,CAASa,WAAAA,EAAW,CAAA,EAAK;AAChD,MAAA,OAAO+B,SAAAA,CAAUO,IAAAA,CAAK,CAACH,CAAAA,KAAMA,CAAAA,CAAEnC,WAAAA,EAAW,KAAOoC,GAAAA,CAAIjD,QAAAA,CAASa,WAAAA,EAAW,CAAA,IAAOoC,GAAAA,CAAIjD,QAAAA;AACtF,IAAA;AAGA,IAAA,MAAMoD,SAAAA,GAAYR,SAAAA,CAAUO,IAAAA,CAAK,CAACH,CAAAA,KAAMR,qBAAAA,CAAsBQ,CAAAA,CAAAA,CAAGnC,WAAAA,EAAW,KAAOoC,GAAAA,CAAIjD,QAAAA,CAASa,aAAW,CAAA;AAC3G,IAAA,IAAIuC,SAAAA,EAAW;AACb,MAAA,OAAOA,SAAAA;AACT,IAAA;AACF,EAAA;AAEA,EAAA,OAAOpB,aAAAA;AACT;AA3BgBU,MAAAA,CAAAA,aAAAA,EAAAA,eAAAA,CAAAA;;;ACnJhB,IAAMW,gBAAAA,uBAAuBC,GAAAA,EAAAA;AAW7B,SAASC,gBAAAA,CAAiBC,UAAkBC,OAAAA,EAAe;AACzD,EAAA,MAAMC,YAAAA,GAAeC,QAAQF,OAAAA,CAAAA;AAC7B,EAAA,MAAMG,YAAAA,GAAeD,QAAQH,QAAAA,CAAAA;AAC7B,EAAA,MAAMK,YAAAA,GAAeC,QAAAA,CAASJ,YAAAA,EAAcE,YAAAA,CAAAA;AAG5C,EAAA,IAAIC,aAAaE,UAAAA,CAAW,IAAA,KAASJ,OAAAA,CAAQE,YAAAA,MAAkBA,YAAAA,EAAc;AAC3E,IAAA,MAAM,IAAIG,KAAAA,CAAM,CAAA,mBAAA,EAAsBR,QAAAA,CAAAA,2BAAAA,EAAsCC,OAAAA,CAAAA,CAAS,CAAA;AACvF,EAAA;AAEA,EAAA,OAAOG,YAAAA;AACT;AAXSL,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;AAiBT,eAAeU,YAAAA,CAAaT,UAAkBC,OAAAA,EAAe;AAC3D,EAAA,MAAMS,aAAAA,GAAgBX,gBAAAA,CAAiBC,QAAAA,EAAUC,OAAAA,CAAAA;AACjD,EAAA,OAAOU,GAAAA,CAAIC,IAAAA,CAAKF,aAAAA,CAAAA,CAAeG,IAAAA,EAAI;AACrC;AAHeJ,MAAAA,CAAAA,YAAAA,EAAAA,cAAAA,CAAAA;AASf,eAAeK,QAAAA,CAASd,UAAkBC,OAAAA,EAAe;AACvD,EAAA,MAAMS,aAAAA,GAAgBX,gBAAAA,CAAiBC,QAAAA,EAAUC,OAAAA,CAAAA;AACjD,EAAA,OAAOc,IAAAA,CAAKL,aAAAA,CAAAA,CAAeM,KAAAA,CAAM,MAAM,IAAA,CAAA;AACzC;AAHeF,MAAAA,CAAAA,QAAAA,EAAAA,UAAAA,CAAAA;AASf,eAAeG,WAAAA,CAAYC,SAAiBjB,OAAAA,EAAe;AACzD,EAAA,MAAMS,aAAAA,GAAgBX,gBAAAA,CAAiBmB,OAAAA,EAASjB,OAAAA,CAAAA;AAChD,EAAA,OAAOkB,QAAQT,aAAAA,CAAAA;AACjB;AAHeO,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;AAYR,SAASG,iBAAAA,CAAkBC,GAAAA,EAA4BC,MAAAA,GAAS,EAAA,EAAE;AACvE,EAAA,MAAMC,SAA6B,EAAC;AAEpC,EAAA,KAAA,MAAW,CAACpE,GAAAA,EAAKC,KAAAA,KAAUoE,MAAAA,CAAOC,OAAAA,CAAQJ,GAAAA,CAAAA,EAAM;AAC9C,IAAA,MAAMK,UAAUJ,MAAAA,GAAS,CAAA,EAAGA,MAAAA,CAAAA,CAAAA,EAAUnE,GAAAA,CAAAA,CAAAA,GAAQA,GAAAA;AAE9C,IAAA,IAAI,OAAOC,UAAU,QAAA,EAAU;AAC7BmE,MAAAA,MAAAA,CAAOG,OAAAA,CAAAA,GAAWtE,KAAAA;AACpB,IAAA,CAAA,MAAA,IAAWA,KAAAA,KAAU,IAAA,IAAQ,OAAOA,KAAAA,KAAU,QAAA,EAAU;AAGtDoE,MAAAA,MAAAA,CAAOG,MAAAA,CAAOJ,MAAAA,EAAQH,iBAAAA,CAAkBhE,KAAAA,EAAOsE,OAAAA,CAAAA,CAAAA;AACjD,IAAA;AACF,EAAA;AAEA,EAAA,OAAOH,MAAAA;AACT;AAhBgBH,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAyBhB,eAAsBQ,mBAAAA,CAAoB5B,UAAkBC,OAAAA,EAAe;AACzE,EAAA,IAAI;AACF,IAAA,MAAM4B,OAAAA,GAAU,MAAMpB,YAAAA,CAAaT,QAAAA,EAAUC,OAAAA,CAAAA;AAC7C,IAAA,MAAM6B,IAAAA,GAAOC,IAAAA,CAAKC,KAAAA,CAAMH,OAAAA,CAAAA;AACxB,IAAA,OAAOC,IAAAA;AACT,EAAA,CAAA,CAAA,OAASG,KAAAA,EAAO;AACdC,IAAAA,MAAAA,CAAOD,KAAAA,CAAM,CAAA,wCAAA,EAA2CjC,QAAAA,CAAAA,CAAAA,EAAYiC,KAAAA,CAAAA;AACpE,IAAA,OAAO,EAAC;AACV,EAAA;AACF;AATsBL,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AActB,SAASO,WAAAA,CAAYC,WAA+B3E,MAAAA,EAAkB;AACpE,EAAA,OAAO2E,SAAAA,GAAY,CAAA,EAAGA,SAAAA,CAAAA,CAAAA,EAAa3E,MAAAA,CAAAA,CAAAA,GAAWA,MAAAA;AAChD;AAFS0E,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;AAgBT,eAAsBE,yBAAAA,CAA0BC,QAAoB7E,MAAAA,EAAkB;AACpF,EAAA,MAAM8E,QAAAA,GAAWJ,WAAAA,CAAYG,MAAAA,CAAOF,SAAAA,EAAW3E,MAAAA,CAAAA;AAG/C,EAAA,IAAI6E,OAAOE,WAAAA,KAAgB,KAAA,IAAS3C,gBAAAA,CAAiBH,GAAAA,CAAI6C,QAAAA,CAAAA,EAAW;AAClE,IAAA,OAAO1C,gBAAAA,CAAiBlB,IAAI4D,QAAAA,CAAAA;AAC9B,EAAA;AAEA,EAAA,MAAM1E,gBAAAA,GAAmBkB,gBAAgBtB,MAAAA,CAAAA;AACzC,EAAA,MAAMjB,QAAAA,GAAWwC,sBAAsBnB,gBAAAA,CAAAA;AACvC,EAAA,MAAM0D,SAA6B,EAAC;AAGpC,EAAA,MAAMkB,UAAAA,GAAa;;AAEjBC,IAAAA,IAAAA,CAAKJ,MAAAA,CAAOK,WAAAA,EAAa,CAAA,EAAG9E,gBAAAA,CAAAA,KAAAA,CAAuB,CAAA;;IAEnD6E,IAAAA,CAAKJ,MAAAA,CAAOK,aAAa9E,gBAAAA,CAAAA;;AAEzB6E,IAAAA,IAAAA,CAAKJ,MAAAA,CAAOK,WAAAA,EAAa,CAAA,EAAGnG,QAAAA,CAAAA,KAAAA,CAAe,CAAA;;IAE3CkG,IAAAA,CAAKJ,MAAAA,CAAOK,aAAanG,QAAAA;;AAG3B,EAAA,KAAA,MAAWoG,QAAQH,UAAAA,EAAY;AAC7B,IAAA,IAAI;AACF,MAAA,MAAMI,KAAAA,GAAQ,MAAM/B,QAAAA,CAAS8B,IAAAA,EAAMN,OAAOK,WAAW,CAAA;AACrD,MAAA,IAAI,CAACE,KAAAA,EAAO;AAEZ,MAAA,IAAIA,MAAMC,MAAAA,EAAM,IAAMF,IAAAA,CAAKG,QAAAA,CAAS,OAAA,CAAA,EAAU;AAE5C,QAAA,MAAMC,YAAAA,GAAe,MAAMpB,mBAAAA,CAAoBgB,IAAAA,EAAMN,OAAOK,WAAW,CAAA;AACvE,QAAA,MAAMM,SAAAA,GAAY7B,kBAAkB4B,YAAAA,CAAAA;AACpC,QAAA,IAAIxB,MAAAA,CAAO0B,IAAAA,CAAKD,SAAAA,CAAAA,CAAWnE,WAAW,CAAA,EAAG;AAIvCoD,UAAAA,MAAAA,CAAOiB,KAAAA,CAAM,CAAA,eAAA,EAAkBP,IAAAA,CAAAA,qBAAAA,CAA2B,CAAA;AAC1D,UAAA;AACF,QAAA;AACApB,QAAAA,MAAAA,CAAOG,MAAAA,CAAOJ,QAAQ0B,SAAAA,CAAAA;AACtBf,QAAAA,MAAAA,CAAOiB,KAAAA,CAAM,CAAA,gCAAA,EAAmCP,IAAAA,CAAAA,CAAM,CAAA;AACtD,QAAA;MACF,CAAA,MAAA,IAAWC,KAAAA,CAAMO,aAAW,EAAI;AAE9B,QAAA,MAAMC,KAAAA,GAAQ,MAAMpC,WAAAA,CAAY2B,IAAAA,EAAMN,OAAOK,WAAW,CAAA;AACxD,QAAA,MAAMW,wBAA4C,EAAC;AACnD,QAAA,KAAA,MAAW1C,QAAQyC,KAAAA,EAAO;AACxB,UAAA,IAAIE,OAAAA,CAAQ3C,IAAAA,CAAAA,KAAU,OAAA,EAAS;AAC7B,YAAA,MAAMwB,SAAAA,GAAYoB,QAAAA,CAAS5C,IAAAA,EAAM,OAAA,CAAA;AACjC,YAAA,MAAMZ,QAAAA,GAAW0C,IAAAA,CAAKE,IAAAA,EAAMhC,IAAAA,CAAAA;AAC5B,YAAA,MAAMoC,YAAAA,GAAe,MAAMpB,mBAAAA,CAAoB5B,QAAAA,EAAUsC,OAAOK,WAAW,CAAA;AAC3E,YAAA,MAAMM,SAAAA,GAAY7B,iBAAAA,CAAkB4B,YAAAA,EAAcZ,SAAAA,CAAAA;AAClDZ,YAAAA,MAAAA,CAAOG,MAAAA,CAAO2B,uBAAuBL,SAAAA,CAAAA;AACrCf,YAAAA,MAAAA,CAAOiB,KAAAA,CAAM,CAAA,wBAAA,EAA2Bf,SAAAA,CAAAA,MAAAA,EAAkBpC,QAAAA,CAAAA,CAAU,CAAA;AACtE,UAAA;AACF,QAAA;AACA,QAAA,IAAIwB,MAAAA,CAAO0B,IAAAA,CAAKI,qBAAAA,CAAAA,CAAuBxE,WAAW,CAAA,EAAG;AAGnDoD,UAAAA,MAAAA,CAAOiB,KAAAA,CAAM,CAAA,eAAA,EAAkBP,IAAAA,CAAAA,qBAAAA,CAA2B,CAAA;AAC1D,UAAA;AACF,QAAA;AACApB,QAAAA,MAAAA,CAAOG,MAAAA,CAAOJ,QAAQ+B,qBAAAA,CAAAA;AACtB,QAAA;AACF,MAAA;IACF,CAAA,CAAA,MAAQ;AAER,IAAA;AACF,EAAA;AAGA,EAAA,IAAI9B,MAAAA,CAAO0B,IAAAA,CAAK3B,MAAAA,CAAAA,CAAQzC,MAAAA,KAAW,KAAKwD,MAAAA,CAAOmB,cAAAA,IAAkBnB,MAAAA,CAAOmB,cAAAA,KAAmBhG,MAAAA,EAAQ;AACjGyE,IAAAA,MAAAA,CAAOwB,KAAK,CAAA,iCAAA,EAAoCjG,MAAAA,CAAAA,kBAAAA,EAA2B6E,MAAAA,CAAOmB,cAAc,CAAA,CAAE,CAAA;AAClG,IAAA,MAAME,oBAAAA,GAAuB,MAAMtB,yBAAAA,CACjC;MAAE,GAAGC,MAAAA;MAAQmB,cAAAA,EAAgBG;AAAU,KAAA,EACvCtB,OAAOmB,cAAc,CAAA;AAEvBjC,IAAAA,MAAAA,CAAOG,MAAAA,CAAOJ,QAAQoC,oBAAAA,CAAAA;AACxB,EAAA;AAGA,EAAA,IAAIrB,MAAAA,CAAOE,gBAAgB,KAAA,EAAO;AAChC3C,IAAAA,gBAAAA,CAAiBgE,GAAAA,CAAItB,UAAUhB,MAAAA,CAAAA;AACjC,EAAA;AAEA,EAAA,OAAOA,MAAAA;AACT;AAvFsBc,MAAAA,CAAAA,yBAAAA,EAAAA,2BAAAA,CAAAA;AA+FtB,eAAsByB,gBAAgBnB,WAAAA,EAAmB;AACvD,EAAA,MAAM3E,UAAwB,EAAA;AAE9B,EAAA,IAAI;AACF,IAAA,MAAM+F,iBAAAA,GAAoB5D,QAAQwC,WAAAA,CAAAA;AAClC,IAAA,MAAMlB,OAAAA,GAAU,MAAMN,OAAAA,CAAQ4C,iBAAAA,CAAAA;AAE9B,IAAA,KAAA,MAAWC,SAASvC,OAAAA,EAAS;AAC3B,MAAA,MAAMwC,SAAAA,GAAYvB,IAAAA,CAAKqB,iBAAAA,EAAmBC,KAAAA,CAAAA;AAC1C,MAAA,MAAMnB,KAAAA,GAAQ,MAAM/B,QAAAA,CAASmD,SAAAA,EAAWF,iBAAAA,CAAAA;AACxC,MAAA,IAAI,CAAClB,KAAAA,EAAO;AAEZ,MAAA,IAAIA,MAAMC,MAAAA,EAAM,IAAMkB,KAAAA,CAAMjB,QAAAA,CAAS,OAAA,CAAA,EAAU;AAE7C,QAAA,MAAMtF,MAAAA,GAAS+F,QAAAA,CAASQ,KAAAA,EAAO,OAAA,CAAA;AAC/BhG,QAAAA,OAAAA,CAAQE,IAAAA,CAAKa,eAAAA,CAAgBtB,MAAAA,CAAAA,CAAAA;MAC/B,CAAA,MAAA,IAAWoF,KAAAA,CAAMO,aAAW,EAAI;AAE9BpF,QAAAA,OAAAA,CAAQE,IAAAA,CAAKa,eAAAA,CAAgBiF,KAAAA,CAAAA,CAAAA;AAC/B,MAAA;AACF,IAAA;AACF,EAAA,CAAA,CAAA,OAAS/B,KAAAA,EAAO;AACdC,IAAAA,MAAAA,CAAOD,KAAAA,CAAM,CAAA,qCAAA,EAAwCU,WAAAA,CAAAA,CAAAA,EAAeV,KAAAA,CAAAA;AACtE,EAAA;AAEA,EAAA,OAAOjE,OAAAA;AACT;AA1BsB8F,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAiCtB,eAAsBI,uBAAuB5B,MAAAA,EAAkB;AAC7D,EAAA,MAAMtE,UAAUsE,MAAAA,CAAO6B,gBAAAA,IAAqB,MAAML,eAAAA,CAAgBxB,OAAOK,WAAW,CAAA;AAEpFT,EAAAA,MAAAA,CAAOkC,IAAAA,CAAK,CAAA,mCAAA,EAAsCpG,OAAAA,CAAQc,MAAM,CAAA,WAAA,CAAa,CAAA;AAE7E,EAAA,MAAMuF,OAAAA,CAAQC,GAAAA,CACZtG,OAAAA,CAAQuB,GAAAA,CAAI,OAAO9B,MAAAA,KAAAA;AACjB,IAAA,IAAI;AACF,MAAA,MAAM4E,yBAAAA,CAA0BC,QAAQ7E,MAAAA,CAAAA;AAC1C,IAAA,CAAA,CAAA,OAASwE,KAAAA,EAAO;AACdC,MAAAA,MAAAA,CAAOD,KAAAA,CAAM,CAAA,gCAAA,EAAmCxE,MAAAA,CAAAA,CAAAA,EAAUwE,KAAAA,CAAAA;AAC5D,IAAA;AACF,EAAA,CAAA,CAAA,CAAA;AAGFC,EAAAA,MAAAA,CAAOkC,KAAK,CAAA,mCAAA,EAAsCpG,OAAAA,CAAQ0E,IAAAA,CAAK,IAAA,CAAA,CAAA,CAAO,CAAA;AACxE;AAhBsBwB,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AAuBf,SAASK,sBAAsBnC,SAAAA,EAAkB;AACtD,EAAA,IAAIA,SAAAA,EAAW;AACb,IAAA,KAAA,MAAWjF,GAAAA,IAAO0C,gBAAAA,CAAiBqD,IAAAA,EAAI,EAAI;AACzC,MAAA,IAAI/F,GAAAA,CAAIoD,UAAAA,CAAW,CAAA,EAAG6B,SAAAA,GAAY,CAAA,EAAG;AACnCvC,QAAAA,gBAAAA,CAAiB2E,OAAOrH,GAAAA,CAAAA;AAC1B,MAAA;AACF,IAAA;EACF,CAAA,MAAO;AACL0C,IAAAA,gBAAAA,CAAiB4E,KAAAA,EAAK;AACxB,EAAA;AACF;AAVgBF,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AAeT,SAASG,qBAAAA,CACdtC,WACA3E,MAAAA,EAAkB;AAElB,EAAA,OAAOoC,gBAAAA,CAAiBlB,GAAAA,CAAIwD,WAAAA,CAAYC,SAAAA,EAAW3E,MAAAA,CAAAA,CAAAA;AACrD;AALgBiH,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AAUT,SAASC,qBAAAA,CACdvC,SAAAA,EACA3E,MAAAA,EACAuF,YAAAA,EAAgC;AAEhCnD,EAAAA,gBAAAA,CAAiBgE,GAAAA,CAAI1B,WAAAA,CAAYC,SAAAA,EAAW3E,MAAAA,GAASuF,YAAAA,CAAAA;AACvD;AANgB2B,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;;;AC5QhB,SAASC,yBAAyBC,QAAAA,EAAgB;AAChD,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,OAAO,OAAA;AACT;AAHSD,MAAAA,CAAAA,wBAAAA,EAAAA,0BAAAA,CAAAA;AAQT,SAASE,wBAAwBD,QAAAA,EAAgB;AAC/C,EAAA,IAAIA,QAAAA,KAAa,CAAA,IAAKA,QAAAA,KAAa,CAAA,EAAG,OAAO,KAAA;AAC7C,EAAA,OAAO,OAAA;AACT;AAHSC,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAQT,SAASC,wBAAwBF,QAAAA,EAAgB;AAC/C,EAAA,MAAMG,QAAQH,QAAAA,GAAW,EAAA;AACzB,EAAA,MAAMI,SAASJ,QAAAA,GAAW,GAAA;AAE1B,EAAA,IAAIG,KAAAA,KAAU,CAAA,IAAKC,MAAAA,KAAW,EAAA,EAAI,OAAO,KAAA;AACzC,EAAA,IAAID,KAAAA,IAAS,KAAKA,KAAAA,IAAS,CAAA,KAAMC,SAAS,EAAA,IAAMA,MAAAA,GAAS,KAAK,OAAO,KAAA;AACrE,EAAA,IAAID,KAAAA,KAAU,CAAA,IAAMA,KAAAA,IAAS,CAAA,IAAKA,KAAAA,IAAS,KAAOC,MAAAA,IAAU,EAAA,IAAMA,MAAAA,IAAU,EAAA,EAAK,OAAO,MAAA;AACxF,EAAA,OAAO,OAAA;AACT;AARSF,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAaT,SAASG,wBAAwBL,QAAAA,EAAgB;AAC/C,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,MAAA;AAC3B,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,MAAMI,SAASJ,QAAAA,GAAW,GAAA;AAC1B,EAAA,IAAII,MAAAA,IAAU,CAAA,IAAKA,MAAAA,IAAU,EAAA,EAAI,OAAO,KAAA;AACxC,EAAA,IAAIA,MAAAA,IAAU,EAAA,IAAMA,MAAAA,IAAU,EAAA,EAAI,OAAO,MAAA;AACzC,EAAA,OAAO,OAAA;AACT;AARSC,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAaT,SAASC,6BAA6BN,QAAAA,EAAgB;AACpD,EAAA,MAAMG,QAAQH,QAAAA,GAAW,EAAA;AACzB,EAAA,MAAMI,SAASJ,QAAAA,GAAW,GAAA;AAE1B,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,IAAIG,KAAAA,IAAS,KAAKA,KAAAA,IAAS,CAAA,KAAMC,SAAS,EAAA,IAAMA,MAAAA,GAAS,KAAK,OAAO,KAAA;AACrE,EAAA,OAAO,MAAA;AACT;AAPSE,MAAAA,CAAAA,4BAAAA,EAAAA,8BAAAA,CAAAA;AAYT,SAASC,0BAA0BP,QAAAA,EAAgB;AACjD,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,MAAMI,SAASJ,QAAAA,GAAW,GAAA;AAC1B,EAAA,IAAIA,aAAa,CAAA,IAAMI,MAAAA,IAAU,CAAA,IAAKA,MAAAA,IAAU,IAAK,OAAO,KAAA;AAC5D,EAAA,OAAO,OAAA;AACT;AALSG,MAAAA,CAAAA,yBAAAA,EAAAA,2BAAAA,CAAAA;AAUT,SAASC,wBAAwBR,QAAAA,EAAgB;AAC/C,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,IAAIA,QAAAA,KAAa,GAAG,OAAO,KAAA;AAC3B,EAAA,OAAO,OAAA;AACT;AAJSQ,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAUT,SAASC,iBAAAA,CAAkB9I,UAAwB+I,KAAAA,EAAa;AAC9D,EAAA,MAAMV,QAAAA,GAAWW,IAAAA,CAAKC,GAAAA,CAAIF,KAAAA,CAAAA;AAG1B,EAAA,MAAMG,gBAAAA,GAAmB;AACvB,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA,IAAA;AACA,IAAA;;AAEF,EAAA,IAAIA,gBAAAA,CAAiBjJ,QAAAA,CAASD,QAAAA,CAAAA,EAAW;AACvC,IAAA,OAAOoI,yBAAyBC,QAAAA,CAAAA;AAClC,EAAA;AAGA,EAAA,IAAIrI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAOsI,wBAAwBD,QAAAA,CAAAA;AACjC,EAAA;AAGA,EAAA,IAAIrI,QAAAA,KAAa,IAAA,IAAQA,QAAAA,KAAa,IAAA,EAAM;AAC1C,IAAA,OAAOuI,wBAAwBF,QAAAA,CAAAA;AACjC,EAAA;AAGA,EAAA,IAAIrI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO0I,wBAAwBL,QAAAA,CAAAA;AACjC,EAAA;AAGA,EAAA,IAAIrI,QAAAA,KAAa,IAAA,IAAQA,QAAAA,KAAa,IAAA,EAAM;AAC1C,IAAA,OAAO2I,6BAA6BN,QAAAA,CAAAA;AACtC,EAAA;AAGA,EAAA,IAAIrI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO4I,0BAA0BP,QAAAA,CAAAA;AACnC,EAAA;AAGA,EAAA,IAAIrI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO6I,wBAAwBR,QAAAA,CAAAA;AACjC,EAAA;AAGA,EAAA,OAAOD,yBAAyBC,QAAAA,CAAAA;AAClC;AA9DSS,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAwET,SAASK,WAAAA,CAAY9E,MAAc+E,SAAAA,EAAgC;AACjE,EAAA,IAAI,CAACA,SAAAA,IAAa,CAAC/E,IAAAA,EAAM;AACvB,IAAA,OAAOA,IAAAA;AACT,EAAA;AAIA,EAAA,OAAOA,IAAAA,CAAKgF,OAAAA,CAAQ,sBAAA,EAAwB,CAACC,OAAO3I,GAAAA,KAAAA;AAClD,IAAA,MAAMC,KAAAA,GAAQwI,SAAAA,CAAUzI,GAAAA,CAAIN,IAAAA,EAAI,CAAA;AAChC,IAAA,IAAIO,UAAUwG,MAAAA,EAAW;AACvB,MAAA,OAAOmC,OAAO3I,KAAAA,CAAAA;AAChB,IAAA;AACA,IAAA,OAAO0I,KAAAA;EACT,CAAA,CAAA;AACF;AAdSH,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;AAqBF,IAAMK,OAAN,MAAMA;EA3Mb;;;AA4MU1D,EAAAA,MAAAA;AACA2D,EAAAA,aAAAA;AACA9B,EAAAA,gBAAAA,GAAiC,EAAA;EACjC+B,WAAAA,GAAc,KAAA;AAEtB,EAAA,WAAA,CAAY5D,MAAAA,EAAoB;AAC9B,IAAA,IAAA,CAAKA,MAAAA,GAAS;MACZ,GAAGA,MAAAA;AACHmB,MAAAA,cAAAA,EAAgBnB,OAAOmB,cAAAA,IAAkB,OAAA;AACzCjB,MAAAA,WAAAA,EAAaF,OAAOE,WAAAA,KAAgB,KAAA;AACpC2D,MAAAA,kBAAAA,EAAoB7D,OAAO6D,kBAAAA,KAAuB,KAAA;AAClDC,MAAAA,UAAAA,EAAY9D,OAAO8D,UAAAA,KAAe;AACpC,KAAA;AACA,IAAA,IAAA,CAAKH,aAAAA,GAAgBlH,eAAAA,CAAgBuD,MAAAA,CAAO9D,aAAa,CAAA;AAC3D,EAAA;;;;;AAMA,EAAA,MAAM6H,UAAAA,GAA4B;AAChC,IAAA,IAAI,KAAKH,WAAAA,EAAa;AAGtB,IAAA,IAAI,KAAK5D,MAAAA,CAAO6B,gBAAAA,IAAoB,KAAK7B,MAAAA,CAAO6B,gBAAAA,CAAiBrF,SAAS,CAAA,EAAG;AAC3E,MAAA,IAAA,CAAKqF,gBAAAA,GAAmB,KAAK7B,MAAAA,CAAO6B,gBAAAA;IACtC,CAAA,MAAO;AACL,MAAA,IAAA,CAAKA,gBAAAA,GAAmB,MAAML,eAAAA,CAAgB,IAAA,CAAKxB,OAAOK,WAAW,CAAA;AACvE,IAAA;AAGA,IAAA,IAAI,CAAC,IAAA,CAAKL,MAAAA,CAAOgE,QAAAA,EAAU;AACzB,MAAA,MAAMpC,sBAAAA,CAAuB,KAAK5B,MAAM,CAAA;AAC1C,IAAA;AAEA,IAAA,IAAA,CAAK4D,WAAAA,GAAc,IAAA;AACnBhE,IAAAA,MAAAA,CAAOkC,IAAAA,CAAK,2BAA2B,IAAA,CAAKD,gBAAAA,CAAiBrF,MAAM,CAAA,mBAAA,EAAsB,IAAA,CAAKmH,aAAa,CAAA,CAAE,CAAA;AAC/G,EAAA;;;;EAKAM,SAAAA,GAAwB;AACtB,IAAA,OAAO,IAAA,CAAKN,aAAAA;AACd,EAAA;;;;AAKAO,EAAAA,SAAAA,CAAU/I,MAAAA,EAA0B;AAClC,IAAA,IAAA,CAAKwI,aAAAA,GAAgBlH,gBAAgBtB,MAAAA,CAAAA;AACvC,EAAA;;;;EAKAgJ,mBAAAA,GAAoC;AAClC,IAAA,OAAO;SAAI,IAAA,CAAKtC;;AAClB,EAAA;;;;AAKAuC,EAAAA,WAAAA,CAAYjJ,MAAAA,EAA6B;AACvC,IAAA,MAAMkJ,UAAAA,GAAa5H,gBAAgBtB,MAAAA,CAAAA;AACnC,IAAA,MAAMjB,QAAAA,GAAWwC,sBAAsB2H,UAAAA,CAAAA;AAEvC,IAAA,OAAO,IAAA,CAAKxC,gBAAAA,CAAiByC,IAAAA,CAAK,CAACpH,CAAAA,KAAAA;AACjC,MAAA,MAAMqH,aAAAA,GAAgB9H,gBAAgBS,CAAAA,CAAAA;AAEtC,MAAA,OAAOqH,aAAAA,KAAkBF,UAAAA,IAAc3H,qBAAAA,CAAsB6H,aAAAA,CAAAA,KAAmBrK,QAAAA;IAClF,CAAA,CAAA;AACF,EAAA;;;;AAKA,EAAA,MAAMsK,WAAWrJ,MAAAA,EAAmC;AAClD,IAAA,MAAM4E,yBAAAA,CAA0B,IAAA,CAAKC,MAAAA,EAAQ7E,MAAAA,CAAAA;AAC/C,EAAA;;;;AAKAsJ,EAAAA,eAAAA,CAAgBtJ,MAAAA,EAAoD;AAClE,IAAA,OAAOiH,qBAAAA,CAAsB,IAAA,CAAKpC,MAAAA,CAAOF,SAAAA,EAAW3E,MAAAA,CAAAA;AACtD,EAAA;;;;EAKAuJ,CAAAA,mBAAuB,MAAA,CAAA,CAAC7J,GAAAA,EAAayI,SAAAA,EAAkCqB,YAAAA,KAAAA;AACrE,IAAA,OAAO,KAAKC,SAAAA,CAAU,IAAA,CAAKjB,aAAAA,EAAe9I,GAAAA,EAAKyI,WAAWqB,YAAAA,CAAAA;EAC5D,CAAA,EAFuB,GAAA,CAAA;;;;EAOvBE,EAAAA,mBAA8B,MAAA,CAAA,CAAChK,GAAAA,EAAaoI,KAAAA,EAAeK,SAAAA,KAAAA;AACzD,IAAA,OAAO,KAAKwB,eAAAA,CAAgB,IAAA,CAAKnB,aAAAA,EAAe9I,GAAAA,EAAKoI,OAAOK,SAAAA,CAAAA;EAC9D,CAAA,EAF8B,IAAA,CAAA;;;;EAOtBsB,SAAAA,CAAUzJ,MAAAA,EAAoBN,GAAAA,EAAayI,SAAAA,EAAkCqB,YAAAA,EAA+B;AAClH,IAAA,MAAMjE,YAAAA,GAAe0B,qBAAAA,CAAsB,IAAA,CAAKpC,MAAAA,CAAOF,WAAW3E,MAAAA,CAAAA;AAClE,IAAA,IAAIoD,IAAAA,GAAOmC,eAAe7F,GAAAA,CAAAA;AAG1B,IAAA,IAAI,CAAC0D,QAAQ,IAAA,CAAKyB,MAAAA,CAAOmB,kBAAkBhG,MAAAA,KAAW,IAAA,CAAK6E,OAAOmB,cAAAA,EAAgB;AAChF,MAAA,MAAME,uBAAuBe,qBAAAA,CAAsB,IAAA,CAAKpC,OAAOF,SAAAA,EAAW,IAAA,CAAKE,OAAOmB,cAAc,CAAA;AACpG5C,MAAAA,IAAAA,GAAO8C,uBAAuBxG,GAAAA,CAAAA;AAChC,IAAA;AAGA,IAAA,IAAI,CAAC0D,IAAAA,EAAM;AACT,MAAA,MAAMrE,QAAAA,GAAWwC,sBAAsBvB,MAAAA,CAAAA;AACvC,MAAA,IAAIjB,aAAaiB,MAAAA,EAAQ;AACvB,QAAA,MAAM4J,gBAAAA,GAAmB3C,qBAAAA,CAAsB,IAAA,CAAKpC,MAAAA,CAAOF,WAAW5F,QAAAA,CAAAA;AACtEqE,QAAAA,IAAAA,GAAOwG,mBAAmBlK,GAAAA,CAAAA;AAC5B,MAAA;AACF,IAAA;AAEA,IAAA,IAAI,CAAC0D,IAAAA,EAAM;AACT,MAAA,IAAI,IAAA,CAAKyB,OAAO8D,UAAAA,EAAY;AAC1BlE,QAAAA,MAAAA,CAAOwB,IAAAA,CAAK,CAAA,oCAAA,EAAuCvG,GAAAA,CAAAA,YAAAA,EAAkBM,MAAAA,CAAAA,CAAQ,CAAA;AAC/E,MAAA;AASA,MAAA,OAAOkI,YAAYsB,YAAAA,KAAiB,IAAA,CAAK3E,OAAO6D,kBAAAA,GAAqBhJ,GAAAA,GAAM,KAAKyI,SAAAA,CAAAA;AAClF,IAAA;AAEA,IAAA,OAAOD,WAAAA,CAAY9E,MAAM+E,SAAAA,CAAAA;AAC3B,EAAA;;;;EAKQwB,eAAAA,CAAgB3J,MAAAA,EAAoBN,GAAAA,EAAaoI,KAAAA,EAAeK,SAAAA,EAA0C;AAChH,IAAA,MAAMpJ,QAAAA,GAAWwC,sBAAsBvB,MAAAA,CAAAA;AACvC,IAAA,MAAM6J,QAAAA,GAAWhC,iBAAAA,CAAkB9I,QAAAA,EAAU+I,KAAAA,CAAAA;AAG7C,IAAA,MAAMgC,SAAAA,GAAY,CAAA,EAAGpK,GAAAA,CAAAA,CAAAA,EAAOmK,QAAAA,CAAAA,CAAAA;AAC5B,IAAA,IAAIzG,OAAO,IAAA,CAAKqG,SAAAA,CAAUzJ,MAAAA,EAAQ8J,SAAAA,EAAW3D,QAAW,EAAA,CAAA;AAGxD,IAAA,IAAI,CAAC/C,IAAAA,IAAQyG,QAAAA,KAAa,OAAA,EAAS;AACjCzG,MAAAA,IAAAA,GAAO,KAAKqG,SAAAA,CAAUzJ,MAAAA,EAAQ,GAAGN,GAAAA,CAAAA,MAAAA,CAAAA,EAAayG,QAAW,EAAA,CAAA;AAC3D,IAAA;AAGA,IAAA,IAAI,CAAC/C,IAAAA,EAAM;AACTA,MAAAA,IAAAA,GAAO,IAAA,CAAKqG,SAAAA,CAAUzJ,MAAAA,EAAQN,GAAAA,EAAKyG,QAAWzG,GAAAA,CAAAA;AAChD,IAAA;AAEA,IAAA,OAAOwI,YAAY9E,IAAAA,EAAM;MAAE,GAAG+E,SAAAA;AAAWL,MAAAA;KAAM,CAAA;AACjD,EAAA;;;;AAKAiC,EAAAA,aAAAA,CAAc/J,MAAAA,EAAiC;AAC7C,IAAA,MAAMI,gBAAAA,GAAmBkB,gBAAgBtB,MAAAA,CAAAA;AACzC,IAAA,MAAMjB,QAAAA,GAAWwC,sBAAsBnB,gBAAAA,CAAAA;AACvC,IAAA,MAAMF,MAAAA,GAASsB,oBAAoBpB,gBAAAA,CAAAA;AAGnC,IAAA,MAAMmJ,EAAAA,mBAAuB,MAAA,CAAA,CAAC7J,GAAAA,EAAKyI,SAAAA,EAAWqB,YAAAA,KAAAA;AAC5C,MAAA,OAAO,IAAA,CAAKC,SAAAA,CAAUrJ,gBAAAA,EAAkBV,GAAAA,EAAKyI,WAAWqB,YAAAA,CAAAA;IAC1D,CAAA,EAF6B,GAAA,CAAA;AAI7B,IAAA,MAAME,EAAAA,mBAA8B,MAAA,CAAA,CAAChK,GAAAA,EAAKoI,KAAAA,EAAOK,SAAAA,KAAAA;AAC/C,MAAA,OAAO,IAAA,CAAKwB,eAAAA,CAAgBvJ,gBAAAA,EAAkBV,GAAAA,EAAKoI,OAAOK,SAAAA,CAAAA;IAC5D,CAAA,EAFoC,IAAA,CAAA;AAIpC,IAAA,MAAM6B,YAAAA,mBAAe,MAAA,CAAA,CAACrK,KAAAA,EAAesK,OAAAA,KAAAA;AACnC,MAAA,OAAO,IAAIC,IAAAA,CAAKC,YAAAA,CAAa/J,kBAAkB6J,OAAAA,CAAAA,CAASG,OAAOzK,KAAAA,CAAAA;IACjE,CAAA,EAFqB,cAAA,CAAA;AAIrB,IAAA,MAAM0K,cAAAA,mBAAiB,MAAA,CAAA,CAAC1K,KAAAA,EAAe2K,QAAAA,KAAAA;AACrC,MAAA,OAAO,IAAIJ,IAAAA,CAAKC,YAAAA,CAAa/J,gBAAAA,EAAkB;QAC7CmK,KAAAA,EAAO,UAAA;AACPD,QAAAA;OACF,CAAA,CAAGF,OAAOzK,KAAAA,CAAAA;IACZ,CAAA,EALuB,gBAAA,CAAA;AAOvB,IAAA,MAAM6K,UAAAA,mBAAa,MAAA,CAAA,CAACC,IAAAA,EAAqBR,OAAAA,KAAAA;AACvC,MAAA,MAAMS,UAAU,OAAOD,IAAAA,KAAS,WAAW,IAAIE,IAAAA,CAAKF,IAAAA,CAAAA,GAAQA,IAAAA;AAC5D,MAAA,OAAO,IAAIP,IAAAA,CAAKU,cAAAA,CAAexK,kBAAkB6J,OAAAA,CAAAA,CAASG,OAAOM,OAAAA,CAAAA;IACnE,CAAA,EAHmB,YAAA,CAAA;AAKnB,IAAA,MAAMG,kBAAAA,mBAAqB,MAAA,CAAA,CAAClL,KAAAA,EAAemL,IAAAA,KAAAA;AACzC,MAAA,OAAO,IAAIZ,IAAAA,CAAKa,kBAAAA,CAAmB3K,gBAAAA,EAAkB;QAAE4K,OAAAA,EAAS;OAAO,CAAA,CAAGZ,MAAAA,CAAOzK,KAAAA,EAAOmL,IAAAA,CAAAA;IAC1F,CAAA,EAF2B,oBAAA,CAAA;AAI3B,IAAA,OAAO;MACL9K,MAAAA,EAAQI,gBAAAA;AACRrB,MAAAA,QAAAA;AACAmB,MAAAA,MAAAA;MACAqJ,CAAAA,EAAAA,EAAAA;AACAG,MAAAA,EAAAA;AACAM,MAAAA,YAAAA;AACAK,MAAAA,cAAAA;AACAG,MAAAA,UAAAA;AACAK,MAAAA;AACF,KAAA;AACF,EAAA;;;;AAKAI,EAAAA,wBAAAA,CAAyBnK,OAAAA,EAA+B;AACtD,IAAA,MAAMjB,MAAAA,GAASgB,wBAAAA,CAAyBC,OAAAA,EAAS,IAAA,CAAK+D,OAAO9D,aAAa,CAAA;AAC1E,IAAA,MAAMmK,YAAYzJ,aAAAA,CAAc;AAAC5B,MAAAA;OAAS,IAAA,CAAK6G,gBAAAA,EAAkB,IAAA,CAAK7B,MAAAA,CAAO9D,aAAa,CAAA;AAC1F,IAAA,OAAO,IAAA,CAAKgJ,cAAcmB,SAAAA,CAAAA;AAC5B,EAAA;;;;AAKAC,EAAAA,eAAAA,CAAgBnL,MAAAA,EAKd;AACA,IAAA,MAAMjB,QAAAA,GAAWwC,sBAAsBvB,MAAAA,CAAAA;AACvC,IAAA,MAAME,MAAAA,GAASsB,oBAAoBxB,MAAAA,CAAAA;AACnC,IAAA,MAAMoL,SAAAA,GAAYtM,iBAAiBC,QAAAA,CAAAA;AAEnC,IAAA,OAAO;MACLsM,IAAAA,EAAMtM,QAAAA;AACNqM,MAAAA,SAAAA;AACApL,MAAAA,MAAAA;AACAE,MAAAA;AACF,KAAA;AACF,EAAA;AACF;AAKA,IAAIoL,UAAAA,GAA0B,IAAA;AAK9B,eAAsBC,eAAe1G,MAAAA,EAAkB;AACrDyG,EAAAA,UAAAA,GAAa,IAAI/C,KAAK1D,MAAAA,CAAAA;AACtB,EAAA,MAAMyG,WAAW1C,UAAAA,EAAU;AAC3B,EAAA,OAAO0C,UAAAA;AACT;AAJsBC,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AASf,SAASC,OAAAA,GAAAA;AACd,EAAA,OAAOF,UAAAA;AACT;AAFgBE,MAAAA,CAAAA,OAAAA,EAAAA,SAAAA,CAAAA;AAOT,SAASC,WAAW5G,MAAAA,EAAkB;AAC3C,EAAA,OAAO,IAAI0D,KAAK1D,MAAAA,CAAAA;AAClB;AAFgB4G,MAAAA,CAAAA,UAAAA,EAAAA,YAAAA,CAAAA;;;AClbhB,SAASC,oBAAAA,CAAqBtI,MAAc+E,SAAAA,EAAgC;AAC1E,EAAA,IAAI,CAACA,WAAW,OAAO/E,IAAAA;AAEvB,EAAA,OAAOA,IAAAA,CAAKgF,OAAAA,CAAQ,gBAAA,EAAkB,CAACC,OAAO3I,GAAAA,KAAAA;AAC5C,IAAA,MAAMC,KAAAA,GAAQwI,UAAUzI,GAAAA,CAAAA;AACxB,IAAA,OAAOC,KAAAA,KAAUwG,MAAAA,GAAYmC,MAAAA,CAAO3I,KAAAA,CAAAA,GAAS0I,KAAAA;EAC/C,CAAA,CAAA;AACF;AAPSqD,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA;AAmCF,SAASnC,CAAAA,CACdoC,GAAAA,EACAjM,GAAAA,EACAkM,cAAAA,EACAzD,SAAAA,EAAgC;AAGhC,EAAA,IAAI,CAACwD,GAAAA,CAAIE,IAAAA,EAAMtC,CAAAA,EAAG;AAChB,IAAA,OAAOmC,oBAAAA,CAAqBE,gBAAgBzD,SAAAA,CAAAA;AAC9C,EAAA;AAGA,EAAA,MAAM2D,aAAaH,GAAAA,CAAIE,IAAAA,CAAKtC,CAAAA,CAAE7J,GAAAA,EAAKyI,WAAWyD,cAAAA,CAAAA;AAG9C,EAAA,IAAIE,eAAepM,GAAAA,EAAK;AACtB,IAAA,OAAOgM,oBAAAA,CAAqBE,gBAAgBzD,SAAAA,CAAAA;AAC9C,EAAA;AAEA,EAAA,OAAO2D,UAAAA;AACT;AApBgBvC,MAAAA,CAAAA,CAAAA,EAAAA,GAAAA,CAAAA;AAiDT,SAASwC,iBAAiBJ,GAAAA,EAAuB;AACtD,EAAA,OAAO,CAACjM,GAAAA,EAAakM,cAAAA,EAAwBzD,SAAAA,KAAAA;AAC3C,IAAA,OAAOoB,CAAAA,CAAEoC,GAAAA,EAAKjM,GAAAA,EAAKkM,cAAAA,EAAgBzD,SAAAA,CAAAA;AACrC,EAAA,CAAA;AACF;AAJgB4D,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;AAYT,SAASC,QAAQL,GAAAA,EAAuB;AAC7C,EAAA,OAAOA,GAAAA,CAAIE,MAAMtC,CAAAA,KAAMpD,MAAAA;AACzB;AAFgB6F,MAAAA,CAAAA,OAAAA,EAAAA,SAAAA,CAAAA;AAWT,SAASlD,SAAAA,CAAU6C,GAAAA,EAAyB5K,aAAAA,GAAwB,OAAA,EAAO;AAChF,EAAA,OAAO4K,GAAAA,CAAIE,MAAM7L,MAAAA,IAAUe,aAAAA;AAC7B;AAFgB+H,MAAAA,CAAAA,SAAAA,EAAAA,WAAAA,CAAAA;AAWT,SAASmD,WAAAA,CAAYN,GAAAA,EAAyBO,eAAAA,GAA0B,IAAA,EAAI;AACjF,EAAA,OAAOP,GAAAA,CAAIE,MAAM9M,QAAAA,IAAYmN,eAAAA;AAC/B;AAFgBD,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;;;ALvDT,IAAME,OAAAA,GAAU;;EAErBC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;EACPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO,OAAA;;EAEPC,KAAAA,EAAO;AACT;AAKO,IAAMC,mBAAAA,GAAsB;EACjCtN,aAAAA,EAAe,OAAA;EACfiF,cAAAA,EAAgB,OAAA;EAChBjB,WAAAA,EAAa,IAAA;EACb8D,QAAAA,EAAU,KAAA;EACVF,UAAAA,EAAY,IAAA;EACZD,kBAAAA,EAAoB;AACtB","file":"chunk-EBDHIL7V.js","sourcesContent":["/**\n * I18n Module\n *\n * Comprehensive internationalization support for backend services.\n *\n * Features:\n * - Load translations from JSON files\n * - Accept-Language header parsing\n * - Translation with variable interpolation\n * - Pluralization support (CLDR rules)\n * - Locale-aware formatting (numbers, dates, currencies)\n * - Request context integration\n *\n * @example\n * ```typescript\n * import { I18n } from '@burdenoff/be-sdk/i18n';\n *\n * // Initialize\n * const i18n = new I18n({\n * defaultLocale: 'en-US',\n * localesPath: './locales',\n * });\n * await i18n.initialize();\n *\n * // Create context for a request\n * const ctx = i18n.createContextFromRequest(request);\n *\n * // Translate\n * const message = ctx.t('errors.notFound', { resource: 'Tag' });\n * // => \"Tag not found\"\n *\n * // Pluralize\n * const items = ctx.tp('items', 5, { count: 5 });\n * // => \"5 items\"\n * ```\n *\n * @packageDocumentation\n */\n\n// Core i18n class and functions\nexport { I18n, initializeI18n, getI18n, createI18n } from './i18n.js';\n\n// Context-based translation helpers (for use in resolvers/providers)\nexport {\n t,\n createTranslator,\n hasI18n,\n getLocale,\n getLanguage,\n type I18nCapableContext,\n type Translator,\n} from './helpers.js';\n\n// Types\nexport type {\n LocaleCode,\n LanguageCode,\n TranslationDictionary,\n FlatTranslationMap,\n TranslationVariables,\n PluralForms,\n TranslateFunction,\n PluralTranslateFunction,\n I18nConfig,\n ParsedLocale,\n I18nContext,\n II18n,\n TextDirection,\n LanguageInfo,\n} from './types.js';\n\n// Type helpers\nexport { RTL_LANGUAGES, getTextDirection } from './types.js';\n\n// Parser functions\nexport {\n parseLocaleString,\n parseAcceptLanguage,\n extractLocaleFromRequest,\n normalizeLocale,\n getLanguageFromLocale,\n getRegionFromLocale,\n findBestMatch,\n} from './parser.js';\n\n// Loader functions\nexport {\n flattenDictionary,\n loadTranslationFile,\n loadTranslationsForLocale,\n discoverLocales,\n preloadAllTranslations,\n clearTranslationCache,\n getCachedTranslations,\n setCachedTranslations,\n} from './loader.js';\n\n// ============================================================================\n// Re-exports for convenience\n// ============================================================================\n\n/**\n * Common locale codes as constants\n */\nexport const Locales = {\n // English\n EN_US: 'en-US' as const,\n EN_GB: 'en-GB' as const,\n EN_AU: 'en-AU' as const,\n EN_CA: 'en-CA' as const,\n EN_IN: 'en-IN' as const,\n // Spanish\n ES_ES: 'es-ES' as const,\n ES_MX: 'es-MX' as const,\n // French\n FR_FR: 'fr-FR' as const,\n FR_CA: 'fr-CA' as const,\n // German\n DE_DE: 'de-DE' as const,\n DE_AT: 'de-AT' as const,\n DE_CH: 'de-CH' as const,\n // Italian\n IT_IT: 'it-IT' as const,\n // Portuguese\n PT_PT: 'pt-PT' as const,\n PT_BR: 'pt-BR' as const,\n // Russian\n RU_RU: 'ru-RU' as const,\n // Chinese\n ZH_CN: 'zh-CN' as const,\n ZH_TW: 'zh-TW' as const,\n ZH_HK: 'zh-HK' as const,\n // Japanese\n JA_JP: 'ja-JP' as const,\n // Korean\n KO_KR: 'ko-KR' as const,\n // Arabic\n AR_SA: 'ar-SA' as const,\n AR_AE: 'ar-AE' as const,\n // Hindi\n HI_IN: 'hi-IN' as const,\n // Tamil\n TA_IN: 'ta-IN' as const,\n // Dutch\n NL_NL: 'nl-NL' as const,\n // Polish\n PL_PL: 'pl-PL' as const,\n // Turkish\n TR_TR: 'tr-TR' as const,\n // Vietnamese\n VI_VN: 'vi-VN' as const,\n // Thai\n TH_TH: 'th-TH' as const,\n // Indonesian\n ID_ID: 'id-ID' as const,\n // Hebrew\n HE_IL: 'he-IL' as const,\n // Ukrainian\n UK_UA: 'uk-UA' as const,\n} as const;\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_I18N_CONFIG = {\n defaultLocale: 'en-US',\n fallbackLocale: 'en-US',\n enableCache: true,\n lazyLoad: false,\n logMissing: true,\n returnKeyOnMissing: true,\n} as const;\n","/**\n * I18n Module Types\n *\n * Type definitions for internationalization support\n */\n\n/**\n * Supported locale codes (BCP 47 format)\n * Language-Region pattern: xx-XX\n */\nexport type LocaleCode =\n // English variants\n | 'en-US'\n | 'en-GB'\n | 'en-AU'\n | 'en-CA'\n | 'en-IN'\n // Spanish variants\n | 'es-ES'\n | 'es-MX'\n | 'es-AR'\n // French variants\n | 'fr-FR'\n | 'fr-CA'\n | 'fr-BE'\n // German variants\n | 'de-DE'\n | 'de-AT'\n | 'de-CH'\n // Italian\n | 'it-IT'\n // Portuguese variants\n | 'pt-PT'\n | 'pt-BR'\n // Russian\n | 'ru-RU'\n // Chinese variants\n | 'zh-CN'\n | 'zh-TW'\n | 'zh-HK'\n // Japanese\n | 'ja-JP'\n // Korean\n | 'ko-KR'\n // Arabic variants\n | 'ar-SA'\n | 'ar-AE'\n | 'ar-EG'\n // Hindi\n | 'hi-IN'\n // Bengali\n | 'bn-IN'\n | 'bn-BD'\n // Tamil\n | 'ta-IN'\n // Telugu\n | 'te-IN'\n // Malayalam\n | 'ml-IN'\n // Dutch\n | 'nl-NL'\n | 'nl-BE'\n // Polish\n | 'pl-PL'\n // Turkish\n | 'tr-TR'\n // Vietnamese\n | 'vi-VN'\n // Thai\n | 'th-TH'\n // Indonesian\n | 'id-ID'\n // Malay\n | 'ms-MY'\n // Swedish\n | 'sv-SE'\n // Norwegian\n | 'nb-NO'\n // Danish\n | 'da-DK'\n // Finnish\n | 'fi-FI'\n // Greek\n | 'el-GR'\n // Czech\n | 'cs-CZ'\n // Romanian\n | 'ro-RO'\n // Hungarian\n | 'hu-HU'\n // Hebrew\n | 'he-IL'\n // Ukrainian\n | 'uk-UA'\n // Generic fallback (allow any valid BCP 47)\n | string;\n\n/**\n * Language code (ISO 639-1)\n */\nexport type LanguageCode =\n | 'en'\n | 'es'\n | 'fr'\n | 'de'\n | 'it'\n | 'pt'\n | 'ru'\n | 'zh'\n | 'ja'\n | 'ko'\n | 'ar'\n | 'hi'\n | 'bn'\n | 'ta'\n | 'te'\n | 'ml'\n | 'nl'\n | 'pl'\n | 'tr'\n | 'vi'\n | 'th'\n | 'id'\n | 'ms'\n | 'sv'\n | 'nb'\n | 'da'\n | 'fi'\n | 'el'\n | 'cs'\n | 'ro'\n | 'hu'\n | 'he'\n | 'uk'\n | string;\n\n/**\n * Translation dictionary type\n * Supports nested keys like { errors: { notFound: \"...\" } }\n * Includes null to match JSON data which may contain null values\n */\nexport type TranslationDictionary = {\n [key: string]: string | TranslationDictionary | null;\n};\n\n/**\n * Flattened translation map\n */\nexport type FlatTranslationMap = Record<string, string>;\n\n/**\n * Translation variables for interpolation\n */\nexport type TranslationVariables = Record<string, string | number | boolean>;\n\n/**\n * Pluralization rules\n */\nexport interface PluralForms {\n zero?: string;\n one: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/**\n * Translation function type\n */\nexport type TranslateFunction = (key: string, variables?: TranslationVariables, defaultValue?: string) => string;\n\n/**\n * Plural translation function type\n */\nexport type PluralTranslateFunction = (key: string, count: number, variables?: TranslationVariables) => string;\n\n/**\n * I18n configuration options\n */\nexport interface I18nConfig {\n /** Default locale if none specified */\n defaultLocale: LocaleCode;\n /** Fallback locale when translation is missing */\n fallbackLocale?: LocaleCode;\n /** Path to locales directory */\n localesPath: string;\n /** Supported locales (if empty, all locales in directory are supported) */\n supportedLocales?: LocaleCode[];\n /** Whether to load translations lazily */\n lazyLoad?: boolean;\n /** Cache translations in memory */\n enableCache?: boolean;\n /** Namespace for this service (e.g., 'tags', 'auth') */\n namespace?: string;\n /** Log missing translations */\n logMissing?: boolean;\n /** Return key on missing translation instead of empty string */\n returnKeyOnMissing?: boolean;\n}\n\n/**\n * Parsed locale information\n */\nexport interface ParsedLocale {\n /** Full locale code (e.g., 'en-US') */\n locale: LocaleCode;\n /** Language code (e.g., 'en') */\n language: LanguageCode;\n /** Region code (e.g., 'US') */\n region?: string;\n /** Quality factor from Accept-Language header (0-1) */\n quality: number;\n}\n\n/**\n * I18n context for requests\n */\nexport interface I18nContext {\n /** Current locale */\n locale: LocaleCode;\n /** Language code */\n language: LanguageCode;\n /** Region code */\n region?: string;\n /** Geography: ISO 3166-1 alpha-2 country code (e.g., 'IN', 'US', 'DE') — from x-geo-country header */\n country?: string;\n /** Geography: ISO 4217 currency code (e.g., 'INR', 'USD', 'EUR') — from x-geo-currency header */\n currency?: string;\n /** Geography: IANA timezone (e.g., 'Asia/Kolkata', 'America/New_York') — from x-geo-timezone header */\n timezone?: string;\n /** Translation function */\n t: TranslateFunction;\n /** Plural translation function */\n tp: PluralTranslateFunction;\n /** Format number for locale */\n formatNumber: (value: number, options?: Intl.NumberFormatOptions) => string;\n /** Format currency for locale */\n formatCurrency: (value: number, currency: string) => string;\n /** Format date for locale */\n formatDate: (date: Date | string, options?: Intl.DateTimeFormatOptions) => string;\n /** Format relative time for locale */\n formatRelativeTime: (value: number, unit: Intl.RelativeTimeFormatUnit) => string;\n}\n\n/**\n * I18n instance interface\n */\nexport interface II18n {\n /** Get current locale */\n getLocale(): LocaleCode;\n /** Set current locale */\n setLocale(locale: LocaleCode): void;\n /** Get supported locales */\n getSupportedLocales(): LocaleCode[];\n /** Check if locale is supported */\n isSupported(locale: LocaleCode): boolean;\n /** Translate a key */\n t: TranslateFunction;\n /** Translate with pluralization */\n tp: PluralTranslateFunction;\n /** Create context for request */\n createContext(locale: LocaleCode): I18nContext;\n /** Load translations for a locale */\n loadLocale(locale: LocaleCode): Promise<void>;\n /** Get all translations for a locale */\n getTranslations(locale: LocaleCode): FlatTranslationMap | undefined;\n}\n\n/**\n * Language direction\n */\nexport type TextDirection = 'ltr' | 'rtl';\n\n/**\n * Language metadata\n */\nexport interface LanguageInfo {\n code: LanguageCode;\n name: string;\n nativeName: string;\n direction: TextDirection;\n locales: LocaleCode[];\n}\n\n/**\n * RTL languages\n */\nexport const RTL_LANGUAGES: LanguageCode[] = ['ar', 'he'];\n\n/**\n * Get text direction for a language\n */\nexport function getTextDirection(language: LanguageCode): TextDirection {\n return RTL_LANGUAGES.includes(language) ? 'rtl' : 'ltr';\n}\n","/**\n * I18n Parser Module\n *\n * Parses Accept-Language headers and locale strings\n */\n\nimport type { LocaleCode, LanguageCode, ParsedLocale } from './types.js';\n\n/**\n * Parse a single locale string (e.g., 'en-US', 'fr;q=0.9')\n */\nexport function parseLocaleString(localeStr: string): ParsedLocale | null {\n const trimmed = localeStr.trim();\n if (!trimmed || trimmed === '*') {\n return null;\n }\n\n // Parse quality factor if present (e.g., 'en-US;q=0.9')\n const [localePart, ...params] = trimmed.split(';');\n let quality = 1.0;\n\n for (const param of params) {\n const [key, value] = param.trim().split('=');\n if (key?.toLowerCase() === 'q' && value) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed) && parsed >= 0 && parsed <= 1) {\n quality = parsed;\n }\n }\n }\n\n const locale = localePart?.trim();\n if (!locale) {\n return null;\n }\n\n // Parse language and region\n const parts = locale.split('-');\n const language = parts[0]?.toLowerCase() as LanguageCode;\n const region = parts[1]?.toUpperCase();\n\n // Reconstruct proper locale code\n const normalizedLocale = region ? `${language}-${region}` : language;\n\n return {\n locale: normalizedLocale,\n language,\n region,\n quality,\n };\n}\n\n/**\n * Parse Accept-Language header\n *\n * Example: 'en-US,en;q=0.9,fr;q=0.8,de;q=0.7'\n *\n * @param header The Accept-Language header value\n * @returns Array of parsed locales sorted by quality (highest first)\n */\nexport function parseAcceptLanguage(header: string | null | undefined): ParsedLocale[] {\n if (!header || header.trim() === '') {\n return [];\n }\n\n const locales: ParsedLocale[] = [];\n\n // Split by comma and parse each part\n const parts = header.split(',');\n for (const part of parts) {\n const parsed = parseLocaleString(part);\n if (parsed) {\n locales.push(parsed);\n }\n }\n\n // Sort by quality factor (highest first)\n locales.sort((a, b) => b.quality - a.quality);\n\n return locales;\n}\n\n/**\n * Extract locale from request headers\n *\n * Checks in order:\n * 1. X-Locale header (explicit override)\n * 2. X-Language header (explicit override)\n * 3. Accept-Language header\n *\n * @param request Web API Request object\n * @param defaultLocale Default locale to return if none found\n * @returns The best matching locale\n */\nexport function extractLocaleFromRequest(request: Request, defaultLocale: LocaleCode = 'en-US'): ParsedLocale {\n // Check explicit locale header first\n const explicitLocale = request.headers.get('x-locale') || request.headers.get('x-language');\n if (explicitLocale) {\n const parsed = parseLocaleString(explicitLocale);\n if (parsed) {\n return parsed;\n }\n }\n\n // Parse Accept-Language header\n const acceptLanguage = request.headers.get('accept-language');\n const parsedLocales = parseAcceptLanguage(acceptLanguage);\n\n if (parsedLocales.length > 0) {\n return parsedLocales[0]!;\n }\n\n // Return default locale\n const [language, region] = defaultLocale.split('-');\n return {\n locale: defaultLocale,\n language: language as LanguageCode,\n region: region,\n quality: 1.0,\n };\n}\n\n/**\n * Normalize a locale code to standard format\n *\n * @param locale The locale to normalize\n * @returns Normalized locale (e.g., 'en-us' -> 'en-US')\n */\nexport function normalizeLocale(locale: string): LocaleCode {\n const parts = locale.trim().split(/[-_]/);\n const language = parts[0]?.toLowerCase();\n const region = parts[1]?.toUpperCase();\n\n if (region) {\n return `${language}-${region}`;\n }\n return language as LocaleCode;\n}\n\n/**\n * Get the language code from a locale\n */\nexport function getLanguageFromLocale(locale: LocaleCode): LanguageCode {\n return locale.split('-')[0] as LanguageCode;\n}\n\n/**\n * Get the region code from a locale\n */\nexport function getRegionFromLocale(locale: LocaleCode): string | undefined {\n const parts = locale.split('-');\n return parts[1];\n}\n\n/**\n * Find the best matching locale from available locales\n *\n * @param requested Requested locales (sorted by preference)\n * @param available Available locales\n * @param defaultLocale Default locale to use if no match\n * @returns The best matching locale\n */\nexport function findBestMatch(\n requested: ParsedLocale[],\n available: LocaleCode[],\n defaultLocale: LocaleCode\n): LocaleCode {\n const availableSet = new Set(available.map((l) => l.toLowerCase()));\n\n for (const req of requested) {\n // Try exact match first (e.g., 'en-US')\n if (availableSet.has(req.locale.toLowerCase())) {\n // Return with proper casing from available\n return available.find((l) => l.toLowerCase() === req.locale.toLowerCase()) || req.locale;\n }\n\n // Try language-only match (e.g., 'en')\n if (availableSet.has(req.language.toLowerCase())) {\n return available.find((l) => l.toLowerCase() === req.language.toLowerCase()) || req.language;\n }\n\n // Try to find any locale with the same language\n const langMatch = available.find((l) => getLanguageFromLocale(l).toLowerCase() === req.language.toLowerCase());\n if (langMatch) {\n return langMatch;\n }\n }\n\n return defaultLocale;\n}\n","/**\n * I18n Loader Module\n *\n * Loads and manages translation files from the filesystem\n */\n\nimport { readdir, stat } from 'fs/promises';\nimport { join, extname, basename, resolve, relative } from 'path';\nimport type { LocaleCode, TranslationDictionary, FlatTranslationMap, I18nConfig } from './types.js';\nimport { normalizeLocale, getLanguageFromLocale } from './parser.js';\nimport { logger } from '../logger/index.js';\n\n/**\n * Translation cache\n */\nconst translationCache = new Map<string, FlatTranslationMap>();\n\n/**\n * Validate that a file path is within the allowed base directory\n * Prevents directory traversal attacks\n *\n * @param filePath The file path to validate\n * @param baseDir The base directory that must contain the file\n * @returns The resolved absolute path if valid\n * @throws Error if path escapes the base directory\n */\nfunction validateFilePath(filePath: string, baseDir: string): string {\n const resolvedBase = resolve(baseDir);\n const resolvedPath = resolve(filePath);\n const relativePath = relative(resolvedBase, resolvedPath);\n\n // If relative path starts with '..' or is absolute, it's outside base directory\n if (relativePath.startsWith('..') || resolve(relativePath) === relativePath) {\n throw new Error(`Invalid file path: ${filePath} is outside base directory ${baseDir}`);\n }\n\n return resolvedPath;\n}\n\n/**\n * Safely read a file with path validation\n * Path is validated before reading to prevent directory traversal attacks\n */\nasync function safeReadFile(filePath: string, baseDir: string): Promise<string> {\n const validatedPath = validateFilePath(filePath, baseDir);\n return Bun.file(validatedPath).text();\n}\n\n/**\n * Safely stat a file with path validation\n * Path is validated before stat to prevent directory traversal attacks\n */\nasync function safeStat(filePath: string, baseDir: string): Promise<Awaited<ReturnType<typeof stat>> | null> {\n const validatedPath = validateFilePath(filePath, baseDir);\n return stat(validatedPath).catch(() => null);\n}\n\n/**\n * Safely read directory with path validation\n * Path is validated before readdir to prevent directory traversal attacks\n */\nasync function safeReaddir(dirPath: string, baseDir: string): Promise<string[]> {\n const validatedPath = validateFilePath(dirPath, baseDir);\n return readdir(validatedPath);\n}\n\n/**\n * Flatten a nested translation dictionary\n *\n * @param obj The nested dictionary\n * @param prefix Current key prefix\n * @returns Flattened key-value map\n */\nexport function flattenDictionary(obj: TranslationDictionary, prefix = ''): FlatTranslationMap {\n const result: FlatTranslationMap = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n result[fullKey] = value;\n } else if (value !== null && typeof value === 'object') {\n // Check null first to avoid different-types-comparison warning\n // (typeof null === 'object' is a JavaScript quirk)\n Object.assign(result, flattenDictionary(value, fullKey));\n }\n }\n\n return result;\n}\n\n/**\n * Load a single translation file\n *\n * @param filePath Path to the translation file\n * @param baseDir Base directory for validation\n * @returns The loaded translations\n */\nexport async function loadTranslationFile(filePath: string, baseDir: string): Promise<TranslationDictionary> {\n try {\n const content = await safeReadFile(filePath, baseDir);\n const data = JSON.parse(content) as TranslationDictionary;\n return data;\n } catch (error) {\n logger.error(`[I18n] Failed to load translation file: ${filePath}`, error);\n return {};\n }\n}\n\n/**\n * Get cache key for translations\n */\nfunction getCacheKey(namespace: string | undefined, locale: LocaleCode): string {\n return namespace ? `${namespace}:${locale}` : locale;\n}\n\n/**\n * Load translations for a locale from a directory\n *\n * Supports multiple file formats:\n * - locales/en-US.json (single file per locale)\n * - locales/en-US/common.json (directory per locale with namespace files)\n * - locales/en.json (language-only fallback)\n *\n * @param config I18n configuration\n * @param locale The locale to load\n * @returns Flattened translations map\n */\nexport async function loadTranslationsForLocale(config: I18nConfig, locale: LocaleCode): Promise<FlatTranslationMap> {\n const cacheKey = getCacheKey(config.namespace, locale);\n\n // Check cache first\n if (config.enableCache !== false && translationCache.has(cacheKey)) {\n return translationCache.get(cacheKey)!;\n }\n\n const normalizedLocale = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalizedLocale);\n const result: FlatTranslationMap = {};\n\n // Try loading in order of specificity\n const pathsToTry = [\n // Most specific: full locale\n join(config.localesPath, `${normalizedLocale}.json`),\n // Directory format\n join(config.localesPath, normalizedLocale),\n // Language only fallback\n join(config.localesPath, `${language}.json`),\n // Language directory\n join(config.localesPath, language),\n ];\n\n for (const path of pathsToTry) {\n try {\n const stats = await safeStat(path, config.localesPath);\n if (!stats) continue;\n\n if (stats.isFile() && path.endsWith('.json')) {\n // Single file\n const translations = await loadTranslationFile(path, config.localesPath);\n const flattened = flattenDictionary(translations);\n if (Object.keys(flattened).length === 0) {\n // An empty (or unparseable) file must not shadow a less specific\n // candidate: `es-ES.json` containing `{}` used to end the search and\n // leave every key missing even though `es.json` was fully populated.\n logger.debug(`[I18n] Skipped ${path}: no translation keys`);\n continue;\n }\n Object.assign(result, flattened);\n logger.debug(`[I18n] Loaded translations from ${path}`);\n break;\n } else if (stats.isDirectory()) {\n // Directory with multiple namespace files\n const files = await safeReaddir(path, config.localesPath);\n const directoryTranslations: FlatTranslationMap = {};\n for (const file of files) {\n if (extname(file) === '.json') {\n const namespace = basename(file, '.json');\n const filePath = join(path, file);\n const translations = await loadTranslationFile(filePath, config.localesPath);\n const flattened = flattenDictionary(translations, namespace);\n Object.assign(directoryTranslations, flattened);\n logger.debug(`[I18n] Loaded namespace ${namespace} from ${filePath}`);\n }\n }\n if (Object.keys(directoryTranslations).length === 0) {\n // Same rule as the file branch: an empty locale directory (no JSON\n // files, or only empty ones) falls through to the next candidate.\n logger.debug(`[I18n] Skipped ${path}: no translation keys`);\n continue;\n }\n Object.assign(result, directoryTranslations);\n break;\n }\n } catch {\n // Continue trying next path\n }\n }\n\n // If nothing loaded and we have a fallback, try that\n if (Object.keys(result).length === 0 && config.fallbackLocale && config.fallbackLocale !== locale) {\n logger.warn(`[I18n] No translations found for ${locale}, trying fallback ${config.fallbackLocale}`);\n const fallbackTranslations = await loadTranslationsForLocale(\n { ...config, fallbackLocale: undefined },\n config.fallbackLocale\n );\n Object.assign(result, fallbackTranslations);\n }\n\n // Cache the result\n if (config.enableCache !== false) {\n translationCache.set(cacheKey, result);\n }\n\n return result;\n}\n\n/**\n * Discover available locales in a directory\n *\n * @param localesPath Path to locales directory\n * @returns Array of available locale codes\n */\nexport async function discoverLocales(localesPath: string): Promise<LocaleCode[]> {\n const locales: LocaleCode[] = [];\n\n try {\n const validatedBasePath = resolve(localesPath);\n const entries = await readdir(validatedBasePath);\n\n for (const entry of entries) {\n const entryPath = join(validatedBasePath, entry);\n const stats = await safeStat(entryPath, validatedBasePath);\n if (!stats) continue;\n\n if (stats.isFile() && entry.endsWith('.json')) {\n // Single file: en-US.json or en.json\n const locale = basename(entry, '.json');\n locales.push(normalizeLocale(locale));\n } else if (stats.isDirectory()) {\n // Directory: en-US/ or en/\n locales.push(normalizeLocale(entry));\n }\n }\n } catch (error) {\n logger.error(`[I18n] Failed to discover locales in ${localesPath}`, error);\n }\n\n return locales;\n}\n\n/**\n * Preload all translations for supported locales\n *\n * @param config I18n configuration\n */\nexport async function preloadAllTranslations(config: I18nConfig): Promise<void> {\n const locales = config.supportedLocales || (await discoverLocales(config.localesPath));\n\n logger.info(`[I18n] Preloading translations for ${locales.length} locales...`);\n\n await Promise.all(\n locales.map(async (locale) => {\n try {\n await loadTranslationsForLocale(config, locale);\n } catch (error) {\n logger.error(`[I18n] Failed to preload locale ${locale}`, error);\n }\n })\n );\n\n logger.info(`[I18n] Preloaded translations for: ${locales.join(', ')}`);\n}\n\n/**\n * Clear the translation cache\n *\n * @param namespace Optional namespace to clear (clears all if not provided)\n */\nexport function clearTranslationCache(namespace?: string): void {\n if (namespace) {\n for (const key of translationCache.keys()) {\n if (key.startsWith(`${namespace}:`)) {\n translationCache.delete(key);\n }\n }\n } else {\n translationCache.clear();\n }\n}\n\n/**\n * Get cached translations for a locale\n */\nexport function getCachedTranslations(\n namespace: string | undefined,\n locale: LocaleCode\n): FlatTranslationMap | undefined {\n return translationCache.get(getCacheKey(namespace, locale));\n}\n\n/**\n * Set translations in cache (useful for testing or dynamic loading)\n */\nexport function setCachedTranslations(\n namespace: string | undefined,\n locale: LocaleCode,\n translations: FlatTranslationMap\n): void {\n translationCache.set(getCacheKey(namespace, locale), translations);\n}\n","/**\n * I18n Class\n *\n * Main internationalization class providing translation and formatting functions\n */\n\nimport type {\n LocaleCode,\n LanguageCode,\n I18nConfig,\n I18nContext,\n II18n,\n FlatTranslationMap,\n TranslationVariables,\n TranslateFunction,\n PluralTranslateFunction,\n} from './types.js';\nimport { getTextDirection } from './types.js';\nimport { loadTranslationsForLocale, preloadAllTranslations, discoverLocales, getCachedTranslations } from './loader.js';\nimport {\n normalizeLocale,\n getLanguageFromLocale,\n getRegionFromLocale,\n findBestMatch,\n extractLocaleFromRequest,\n} from './parser.js';\nimport { logger } from '../logger/index.js';\n\n/**\n * Pluralization category based on CLDR rules\n */\ntype PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';\n\n/**\n * English and most Germanic/Romance languages (simple one/other)\n */\nfunction getEnglishPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n return 'other';\n}\n\n/**\n * French pluralization (0 or 1 = one, else other)\n */\nfunction getFrenchPluralCategory(absCount: number): PluralCategory {\n if (absCount === 0 || absCount === 1) return 'one';\n return 'other';\n}\n\n/**\n * Slavic languages (Russian, Ukrainian) - complex: one, few, many, other\n */\nfunction getSlavicPluralCategory(absCount: number): PluralCategory {\n const mod10 = absCount % 10;\n const mod100 = absCount % 100;\n\n if (mod10 === 1 && mod100 !== 11) return 'one';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'few';\n if (mod10 === 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) return 'many';\n return 'other';\n}\n\n/**\n * Arabic pluralization (zero, one, two, few, many, other)\n */\nfunction getArabicPluralCategory(absCount: number): PluralCategory {\n if (absCount === 0) return 'zero';\n if (absCount === 1) return 'one';\n if (absCount === 2) return 'two';\n const mod100 = absCount % 100;\n if (mod100 >= 3 && mod100 <= 10) return 'few';\n if (mod100 >= 11 && mod100 <= 99) return 'many';\n return 'other';\n}\n\n/**\n * Polish/Czech pluralization (one, few, many)\n */\nfunction getPolishCzechPluralCategory(absCount: number): PluralCategory {\n const mod10 = absCount % 10;\n const mod100 = absCount % 100;\n\n if (absCount === 1) return 'one';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'few';\n return 'many';\n}\n\n/**\n * Romanian pluralization (one, few, other)\n */\nfunction getRomanianPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n const mod100 = absCount % 100;\n if (absCount === 0 || (mod100 >= 1 && mod100 <= 19)) return 'few';\n return 'other';\n}\n\n/**\n * Hebrew pluralization (one, two, other)\n */\nfunction getHebrewPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n if (absCount === 2) return 'two';\n return 'other';\n}\n\n/**\n * Get plural category for a count in a given language\n * Based on CLDR plural rules: https://cldr.unicode.org/index/cldr-spec/plural-rules\n */\nfunction getPluralCategory(language: LanguageCode, count: number): PluralCategory {\n const absCount = Math.abs(count);\n\n // English and most Germanic/Romance languages\n const englishLanguages = [\n 'en',\n 'de',\n 'es',\n 'it',\n 'nl',\n 'sv',\n 'da',\n 'nb',\n 'fi',\n 'pt',\n 'el',\n 'hu',\n 'tr',\n 'id',\n 'ms',\n 'th',\n 'vi',\n 'ko',\n 'zh',\n 'ja',\n ];\n if (englishLanguages.includes(language)) {\n return getEnglishPluralCategory(absCount);\n }\n\n // French\n if (language === 'fr') {\n return getFrenchPluralCategory(absCount);\n }\n\n // Russian, Ukrainian\n if (language === 'ru' || language === 'uk') {\n return getSlavicPluralCategory(absCount);\n }\n\n // Arabic\n if (language === 'ar') {\n return getArabicPluralCategory(absCount);\n }\n\n // Polish, Czech\n if (language === 'pl' || language === 'cs') {\n return getPolishCzechPluralCategory(absCount);\n }\n\n // Romanian\n if (language === 'ro') {\n return getRomanianPluralCategory(absCount);\n }\n\n // Hebrew\n if (language === 'he') {\n return getHebrewPluralCategory(absCount);\n }\n\n // Default: simple singular/plural\n return getEnglishPluralCategory(absCount);\n}\n\n/**\n * Interpolate variables in a translation string\n *\n * Supports:\n * - {{variable}} - simple interpolation\n * - {{variable, number}} - number formatting (future)\n * - {{variable, date}} - date formatting (future)\n */\nfunction interpolate(text: string, variables?: TranslationVariables): string {\n if (!variables || !text) {\n return text;\n }\n\n // Use more specific pattern to avoid catastrophic backtracking\n // Matches {{ variableName }} with word characters (alphanumeric and underscore)\n return text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, key: string) => {\n const value = variables[key.trim()];\n if (value !== undefined) {\n return String(value);\n }\n return match; // Keep original if variable not found\n });\n}\n\n/**\n * I18n Class\n *\n * Main class for internationalization functionality\n */\nexport class I18n implements II18n {\n private config: I18nConfig;\n private currentLocale: LocaleCode;\n private supportedLocales: LocaleCode[] = [];\n private initialized = false;\n\n constructor(config: I18nConfig) {\n this.config = {\n ...config,\n fallbackLocale: config.fallbackLocale || 'en-US',\n enableCache: config.enableCache !== false,\n returnKeyOnMissing: config.returnKeyOnMissing !== false,\n logMissing: config.logMissing !== false,\n };\n this.currentLocale = normalizeLocale(config.defaultLocale);\n }\n\n /**\n * Initialize the i18n instance\n * Discovers available locales and optionally preloads translations\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n // Discover available locales\n if (this.config.supportedLocales && this.config.supportedLocales.length > 0) {\n this.supportedLocales = this.config.supportedLocales;\n } else {\n this.supportedLocales = await discoverLocales(this.config.localesPath);\n }\n\n // Preload translations if not lazy loading\n if (!this.config.lazyLoad) {\n await preloadAllTranslations(this.config);\n }\n\n this.initialized = true;\n logger.info(`[I18n] Initialized with ${this.supportedLocales.length} locales, default: ${this.currentLocale}`);\n }\n\n /**\n * Get current locale\n */\n getLocale(): LocaleCode {\n return this.currentLocale;\n }\n\n /**\n * Set current locale\n */\n setLocale(locale: LocaleCode): void {\n this.currentLocale = normalizeLocale(locale);\n }\n\n /**\n * Get supported locales\n */\n getSupportedLocales(): LocaleCode[] {\n return [...this.supportedLocales];\n }\n\n /**\n * Check if a locale is supported\n */\n isSupported(locale: LocaleCode): boolean {\n const normalized = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalized);\n\n return this.supportedLocales.some((l) => {\n const supportedNorm = normalizeLocale(l);\n // Exact match or language match\n return supportedNorm === normalized || getLanguageFromLocale(supportedNorm) === language;\n });\n }\n\n /**\n * Load translations for a specific locale\n */\n async loadLocale(locale: LocaleCode): Promise<void> {\n await loadTranslationsForLocale(this.config, locale);\n }\n\n /**\n * Get all translations for a locale\n */\n getTranslations(locale: LocaleCode): FlatTranslationMap | undefined {\n return getCachedTranslations(this.config.namespace, locale);\n }\n\n /**\n * Translate a key\n */\n t: TranslateFunction = (key: string, variables?: TranslationVariables, defaultValue?: string): string => {\n return this.translate(this.currentLocale, key, variables, defaultValue);\n };\n\n /**\n * Translate with pluralization\n */\n tp: PluralTranslateFunction = (key: string, count: number, variables?: TranslationVariables): string => {\n return this.translatePlural(this.currentLocale, key, count, variables);\n };\n\n /**\n * Internal translate method\n */\n private translate(locale: LocaleCode, key: string, variables?: TranslationVariables, defaultValue?: string): string {\n const translations = getCachedTranslations(this.config.namespace, locale);\n let text = translations?.[key];\n\n // Try fallback locale if not found\n if (!text && this.config.fallbackLocale && locale !== this.config.fallbackLocale) {\n const fallbackTranslations = getCachedTranslations(this.config.namespace, this.config.fallbackLocale);\n text = fallbackTranslations?.[key];\n }\n\n // Try language-only fallback\n if (!text) {\n const language = getLanguageFromLocale(locale);\n if (language !== locale) {\n const langTranslations = getCachedTranslations(this.config.namespace, language);\n text = langTranslations?.[key];\n }\n }\n\n if (!text) {\n if (this.config.logMissing) {\n logger.warn(`[I18n] Missing translation for key: ${key} in locale: ${locale}`);\n }\n // Return default value, key, or empty string — interpolated.\n //\n // The caller's fallback is a real message, not a placeholder for one, so\n // it gets the same `{{var}}` substitution a found translation does.\n // Without this a missing key degrades to raw markup in user-facing output\n // (e.g. a careers confirmation email reading \"Hi {{name}}, thanks for\n // applying for the {{position}} role\"), which is worse than the untranslated\n // English it was meant to fall back to.\n return interpolate(defaultValue ?? (this.config.returnKeyOnMissing ? key : ''), variables);\n }\n\n return interpolate(text, variables);\n }\n\n /**\n * Internal translate with pluralization\n */\n private translatePlural(locale: LocaleCode, key: string, count: number, variables?: TranslationVariables): string {\n const language = getLanguageFromLocale(locale);\n const category = getPluralCategory(language, count);\n\n // Try plural-specific key first (e.g., 'items.one', 'items.other')\n const pluralKey = `${key}.${category}`;\n let text = this.translate(locale, pluralKey, undefined, '');\n\n // Fallback to 'other' if specific form not found\n if (!text && category !== 'other') {\n text = this.translate(locale, `${key}.other`, undefined, '');\n }\n\n // Final fallback to base key\n if (!text) {\n text = this.translate(locale, key, undefined, key);\n }\n\n return interpolate(text, { ...variables, count });\n }\n\n /**\n * Create an i18n context for a specific locale\n */\n createContext(locale: LocaleCode): I18nContext {\n const normalizedLocale = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalizedLocale);\n const region = getRegionFromLocale(normalizedLocale);\n\n // Create bound translate functions for this locale\n const t: TranslateFunction = (key, variables, defaultValue) => {\n return this.translate(normalizedLocale, key, variables, defaultValue);\n };\n\n const tp: PluralTranslateFunction = (key, count, variables) => {\n return this.translatePlural(normalizedLocale, key, count, variables);\n };\n\n const formatNumber = (value: number, options?: Intl.NumberFormatOptions): string => {\n return new Intl.NumberFormat(normalizedLocale, options).format(value);\n };\n\n const formatCurrency = (value: number, currency: string): string => {\n return new Intl.NumberFormat(normalizedLocale, {\n style: 'currency',\n currency,\n }).format(value);\n };\n\n const formatDate = (date: Date | string, options?: Intl.DateTimeFormatOptions): string => {\n const dateObj = typeof date === 'string' ? new Date(date) : date;\n return new Intl.DateTimeFormat(normalizedLocale, options).format(dateObj);\n };\n\n const formatRelativeTime = (value: number, unit: Intl.RelativeTimeFormatUnit): string => {\n return new Intl.RelativeTimeFormat(normalizedLocale, { numeric: 'auto' }).format(value, unit);\n };\n\n return {\n locale: normalizedLocale,\n language,\n region,\n t,\n tp,\n formatNumber,\n formatCurrency,\n formatDate,\n formatRelativeTime,\n };\n }\n\n /**\n * Create context from a request\n */\n createContextFromRequest(request: Request): I18nContext {\n const parsed = extractLocaleFromRequest(request, this.config.defaultLocale);\n const bestMatch = findBestMatch([parsed], this.supportedLocales, this.config.defaultLocale);\n return this.createContext(bestMatch);\n }\n\n /**\n * Get language metadata\n */\n getLanguageInfo(locale: LocaleCode): {\n code: LanguageCode;\n direction: 'ltr' | 'rtl';\n locale: LocaleCode;\n region?: string;\n } {\n const language = getLanguageFromLocale(locale);\n const region = getRegionFromLocale(locale);\n const direction = getTextDirection(language);\n\n return {\n code: language,\n direction,\n locale,\n region,\n };\n }\n}\n\n/**\n * Singleton instance (optional, for simpler usage)\n */\nlet globalI18n: I18n | null = null;\n\n/**\n * Initialize global i18n instance\n */\nexport async function initializeI18n(config: I18nConfig): Promise<I18n> {\n globalI18n = new I18n(config);\n await globalI18n.initialize();\n return globalI18n;\n}\n\n/**\n * Get global i18n instance\n */\nexport function getI18n(): I18n | null {\n return globalI18n;\n}\n\n/**\n * Create a new i18n instance (for isolated use)\n */\nexport function createI18n(config: I18nConfig): I18n {\n return new I18n(config);\n}\n","/**\n * I18n Translation Helpers\n *\n * Provides utilities for getting translated messages from GraphQL/request context.\n * These helpers work with any context that has an optional `i18n` property.\n *\n * Falls back to the provided default message if i18n is not available or translation is missing.\n *\n * @example\n * ```typescript\n * import { t, createTranslator } from '@burdenoff/be-sdk';\n *\n * // Direct usage with context\n * const message = t(ctx, 'tags.errors.notFound', 'Tag not found');\n * const message = t(ctx, 'tags.errors.keyExists', 'Tag {{key}} already exists', { key: 'my-tag' });\n *\n * // Create a bound translator for a specific context\n * const translate = createTranslator(ctx);\n * const message = translate('tags.errors.notFound', 'Tag not found');\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { I18nContext, TranslationVariables } from './types.js';\n\n/**\n * Context with optional i18n\n * Works with any object that has an optional i18n property\n */\nexport interface I18nCapableContext {\n i18n?: I18nContext;\n}\n\n/**\n * Interpolate variables in a string\n *\n * @param text - Text with {{variable}} placeholders\n * @param variables - Variables to interpolate\n * @returns Interpolated string\n */\nfunction interpolateVariables(text: string, variables?: TranslationVariables): string {\n if (!variables) return text;\n\n return text.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key: string) => {\n const value = variables[key];\n return value !== undefined ? String(value) : match;\n });\n}\n\n/**\n * Get a translated message from context\n *\n * This is the primary function for getting translations in providers and resolvers.\n * It gracefully handles cases where i18n is not available by returning the default message.\n *\n * @param ctx - Context with optional i18n (GraphQL context, request context, etc.)\n * @param key - Translation key (e.g., 'tags.errors.notFound')\n * @param defaultMessage - Fallback message if translation not found\n * @param variables - Optional variables for interpolation\n * @returns Translated message or default message\n *\n * @example\n * ```typescript\n * // Simple usage\n * const message = t(ctx, 'tags.errors.notFound', 'Tag not found');\n *\n * // With variables\n * const message = t(ctx, 'tags.errors.keyAlreadyExists', 'Tag with key {{key}} already exists', { key: 'my-tag' });\n *\n * // In a GraphQL resolver\n * if (!userId) {\n * throw new Error(t(context, 'common.errors.notAuthenticated', 'User not authenticated'));\n * }\n * ```\n */\nexport function t(\n ctx: I18nCapableContext,\n key: string,\n defaultMessage: string,\n variables?: TranslationVariables\n): string {\n // If i18n is not available, interpolate and return default message\n if (!ctx.i18n?.t) {\n return interpolateVariables(defaultMessage, variables);\n }\n\n // Get translation with fallback to default\n const translated = ctx.i18n.t(key, variables, defaultMessage);\n\n // If translation returns the key (not found), use default message\n if (translated === key) {\n return interpolateVariables(defaultMessage, variables);\n }\n\n return translated;\n}\n\n/**\n * Translator function type\n */\nexport type Translator = (key: string, defaultMessage: string, variables?: TranslationVariables) => string;\n\n/**\n * Create a bound translator function for a specific context\n *\n * This is useful when you need to pass a translator to services or\n * when you want to avoid repeating the context parameter.\n *\n * @param ctx - Context with optional i18n\n * @returns Translate function bound to the context\n *\n * @example\n * ```typescript\n * // Create translator\n * const translate = createTranslator(ctx);\n *\n * // Use it multiple times\n * const msg1 = translate('tags.errors.notFound', 'Tag not found');\n * const msg2 = translate('tags.errors.keyExists', 'Key {{key}} exists', { key: 'foo' });\n *\n * // Pass to a service\n * await someService.process(data, { translate });\n * ```\n */\nexport function createTranslator(ctx: I18nCapableContext): Translator {\n return (key: string, defaultMessage: string, variables?: TranslationVariables) => {\n return t(ctx, key, defaultMessage, variables);\n };\n}\n\n/**\n * Check if context has i18n support\n *\n * @param ctx - Context to check\n * @returns True if i18n is available and initialized\n */\nexport function hasI18n(ctx: I18nCapableContext): ctx is I18nCapableContext & { i18n: I18nContext } {\n return ctx.i18n?.t !== undefined;\n}\n\n/**\n * Get the current locale from context\n *\n * @param ctx - Context with optional i18n\n * @param defaultLocale - Default locale if i18n not available\n * @returns Current locale code\n */\nexport function getLocale(ctx: I18nCapableContext, defaultLocale: string = 'en-US'): string {\n return ctx.i18n?.locale ?? defaultLocale;\n}\n\n/**\n * Get the current language from context\n *\n * @param ctx - Context with optional i18n\n * @param defaultLanguage - Default language if i18n not available\n * @returns Current language code\n */\nexport function getLanguage(ctx: I18nCapableContext, defaultLanguage: string = 'en'): string {\n return ctx.i18n?.language ?? defaultLanguage;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { productSlugVariants, isSameProductSlug } from './chunk-5NWOQQC4.js';
1
+ import { productSlugVariants, isSameProductSlug } from './chunk-OBBCR6WY.js';
2
2
  import { withWorkspaceContextSync, withWorkspaceContext, setWorkspaceContext, runOperationWithRlsGuc, maybeTagConnection, maybeSetRlsGuc, injectWhereWorkspaceId, injectCreateFields, getWorkspaceContext, defaultWorkspaceExtensionConfig, addWorkspaceExtension } from './chunk-FA5ROGTS.js';
3
3
  import { isTransientAcquireError, installAcquireRetry, ensureServiceApplicationName, createPrismaClient, createPrismaAdapter, createConnectionPool, configurePrismaLogging, PrismaClientWrapper, addGraphExtension } from './chunk-L5TDUAFN.js';
4
4
  import { getGraphEventEmitter } from './chunk-QJN4K7LD.js';
@@ -681,5 +681,5 @@ function createContextFromSDK(sdkContext) {
681
681
  __name(createContextFromSDK, "createContextFromSDK");
682
682
 
683
683
  export { buildContextWhereClause, buildContextWhereConditions, checkDatabaseHealth, contextMatches, createContextFromSDK, createDatabaseClient, createDatabaseClientFromEnv, extractFieldsFromModel, getAllModelNames, getDatabaseManager, getDatabaseProductName, getDatabaseStats, getDatabaseVersion, getDb, getModelFields, hasModel, initializeDatabase, initializeDatabaseWithConfig, isDatabaseInitialized, loadGeneratedFields, mergeContext, parseContext, prisma_exports, resetDatabaseManager, resolvePoolTuningFromEnv, testConnection, toContextJson };
684
- //# sourceMappingURL=chunk-YTXZ6HZI.js.map
685
- //# sourceMappingURL=chunk-YTXZ6HZI.js.map
684
+ //# sourceMappingURL=chunk-LNFGZMDB.js.map
685
+ //# sourceMappingURL=chunk-LNFGZMDB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/prisma/index.ts","../src/prisma/factory.ts","../src/prisma/manager.ts","../src/prisma/health.ts","../src/prisma/fields.ts","../src/prisma/context.ts"],"names":["resolveWorkspaceExtensionDefault","productName","explicit","process","env","layer","toLowerCase","name","startsWith","createDatabaseClient","PrismaClientConstructor","config","enableGraphExtension","graphEventEmitter","enableWorkspaceExtension","workspaceExtensionConfig","registerShutdownHandlers","prismaConfig","prismaConfigWithDefaults","applicationName","ensureServiceApplicationName","wrapper","createPrismaClient","baseClient","getClient","extendedClient","eventEmitter","getGraphEventEmitter","graphConfig","enabled","addGraphExtension","logger","info","addWorkspaceExtension","db","debug","connect","retries","delay","disconnect","parsePositiveIntEnv","raw","trim","undefined","parsed","Number","parseInt","isFinite","resolvePoolTuningFromEnv","tuning","queryTimeout","queryTimeoutMillis","statementTimeout","statementTimeoutMillis","idleInTransactionTimeout","idleInTransactionTimeoutMillis","lockTimeout","lockTimeoutMillis","createDatabaseClientFromEnv","overrides","databaseUrl","Error","isDevelopment","maxConnections","idleTimeoutMillis","connectionTimeoutMillis","enableQueryLogging","slowQueryThreshold","acquireRetriesRaw","acquireRetries","acquireRetryDelay","acquireRetryDelayMillis","state","initialized","client","initializeDatabase","initializeDatabaseWithConfig","getDb","getDatabaseManager","isDatabaseInitialized","getDatabaseProductName","resetDatabaseManager","error","warn","checkDatabaseHealth","start","Date","now","$queryRaw","latency","healthy","errorMessage","message","String","testConnection","getDatabaseVersion","result","version","getDatabaseStats","health","Promise","all","timestamp","requireFn","createRequire","url","loadGeneratedFields","generatedFieldsPath","generated","default","path","extractFieldsFromModel","modelName","modelFieldsMap","options","modelFields","Object","keys","join","excludeFields","includeRelations","customFilter","fields","relations","excluded","length","filter","field","includes","push","fieldName","isRelation","shouldInclude","type","metadata","totalFields","excludedCount","excludedFields","relationFields","getModelFields","hasModel","getAllModelNames","buildContextWhereClause","contextFilter","conditions","workspaceId","equals","userId","projectId","appId","productId","organizationId","buildContextWhereConditions","context","slugs","productSlugVariants","OR","map","slug","toContextJson","contextInput","custom","filterNullValues","obj","filtered","key","value","entries","mergeContextField","merged","fieldValue","mergeContext","existingContext","newContext","Array","isArray","parseContext","contextJson","ctx","contextMatches","isSameProductSlug","createContextFromSDK","sdkContext"],"mappings":"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","file":"chunk-YTXZ6HZI.js","sourcesContent":["/**\n * Prisma Module for Burdenoff Backend SDK\n *\n * Provides Prisma 7 utilities including:\n * - Singleton database manager for microservices\n * - Unified database client factory with graph extension\n * - Prisma client configuration with PostgreSQL adapter\n * - Connection pooling and management\n * - Health checks and monitoring\n * - Graceful shutdown handling\n * - Field extraction utilities for graph sync\n * - Context filtering utilities for multi-tenant queries\n * - Workspace extension for automatic workspaceId injection\n *\n * @module prisma\n * @category Database\n */\n\nexport * from './manager.js';\nexport * from './factory.js';\nexport * from './client.js';\nexport type * from './types.js';\nexport * from './health.js';\nexport * from './fields.js';\nexport * from './context.js';\nexport * from './workspace-extension.js';\n","/**\n * Database Client Factory\n *\n * Provides a unified factory for creating fully-configured database clients\n * with Prisma 7, PostgreSQL adapter, graph extension, and graceful shutdown.\n *\n * This module consolidates all database setup into a single call, reducing\n * boilerplate across all backend services.\n *\n * @module prisma/factory\n * @category Database\n */\n\nimport { logger } from '../logger/index.js';\nimport {\n createPrismaClient,\n ensureServiceApplicationName,\n type PrismaClientBase,\n type PrismaClientWrapper,\n type PrismaClientConstructorOptions,\n} from './client.js';\nimport type { PrismaClientConfig } from './types.js';\nimport { addGraphExtension, type GraphMiddlewareConfig, type GraphEventEmitter } from '../graph/middleware/index.js';\nimport { getGraphEventEmitter } from '../event-queue/graph-emitter.js';\nimport { addWorkspaceExtension, type WorkspaceExtensionConfig } from './workspace-extension.js';\n\n/**\n * Configuration for creating a database client\n */\nexport interface DatabaseClientConfig extends PrismaClientConfig {\n /**\n * Product name for graph events (e.g., 'module-tags', 'workspaces')\n */\n productName: string;\n\n /**\n * Enable graph extension for entity sync\n * @default true (reads from GRAPH_MIDDLEWARE_ENABLED env var)\n */\n enableGraphExtension?: boolean;\n\n /**\n * Custom graph event emitter (defaults to NATS-based emitter)\n */\n graphEventEmitter?: GraphEventEmitter;\n\n /**\n * Enable workspace extension for automatic workspaceId injection.\n *\n * Default is layer-aware:\n * - Global-layer services (`productName` starting with `global-` or `global_`,\n * or `WORKSPACE_LAYER=global`) default to `false`. Global-layer tables\n * (Tenant, Organization, Workspace, PlatformProduct, etc.) are intentionally\n * not workspace-scoped — enforcing workspaceId on them would block legitimate\n * queries like `myOrganizations`, `myWorkspaces`, `myAccessibleProducts`.\n * - All other services (wspace layer, product backends) default to `true`.\n *\n * `WORKSPACE_EXTENSION_ENABLED` env var always wins when explicitly set\n * (`true` or `false`). Pass the field on `config` for code-level override.\n */\n enableWorkspaceExtension?: boolean;\n\n /**\n * Configuration for the workspace extension\n */\n workspaceExtensionConfig?: WorkspaceExtensionConfig;\n\n /**\n * Register process shutdown handlers for graceful shutdown\n * @default true\n */\n registerShutdownHandlers?: boolean;\n}\n\n/**\n * Result of creating a database client\n */\nexport interface DatabaseClient<T extends PrismaClientBase> {\n /**\n * The extended Prisma client for database operations\n * Use this for all queries: db.model.operation()\n */\n db: T & { client: T };\n\n /**\n * The Prisma client wrapper with connection management utilities\n */\n wrapper: PrismaClientWrapper<T>;\n\n /**\n * Connect to the database with retry logic\n */\n connect: (retries?: number, delay?: number) => Promise<void>;\n\n /**\n * Disconnect from the database\n */\n disconnect: () => Promise<void>;\n}\n\n/**\n * Layer-aware default for the workspace extension.\n *\n * Global-layer services (productName starting with `global-`/`global_`, or\n * `WORKSPACE_LAYER=global`) opt out by default because their tables don't carry\n * a workspaceId column — enforcement would break queries like `myOrganizations`,\n * `myAccessibleProducts`, `contentPages`.\n *\n * `WORKSPACE_EXTENSION_ENABLED` is respected as an explicit override.\n */\nfunction resolveWorkspaceExtensionDefault(productName: string): boolean {\n const explicit = process.env['WORKSPACE_EXTENSION_ENABLED'];\n if (explicit === 'true') return true;\n if (explicit === 'false') return false;\n\n const layer = process.env['WORKSPACE_LAYER']?.toLowerCase();\n if (layer === 'global') return false;\n if (layer === 'wspace') return true;\n\n const name = productName.toLowerCase();\n if (name.startsWith('global-') || name.startsWith('global_')) return false;\n return true;\n}\n\n/**\n * Create a fully-configured database client with graph extension\n *\n * This is the recommended way to create a database connection in all backend services.\n * It handles:\n * - Prisma client creation with PostgreSQL adapter\n * - Connection pooling configuration\n * - Query logging (in development)\n * - Graph extension for entity sync (via NATS or in-memory)\n * - Graceful shutdown handlers\n *\n * @example\n * ```typescript\n * // In your service's db.ts\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createDatabaseClient } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, wrapper, connect, disconnect } = createDatabaseClient(PrismaClient, {\n * productName: 'my-service',\n * databaseUrl: process.env.DATABASE_URL!,\n * });\n *\n * export { db, wrapper, connect, disconnect };\n * export type ExtendedPrismaClient = typeof db;\n * ```\n *\n * @example\n * ```typescript\n * // With custom configuration\n * const { db } = createDatabaseClient(PrismaClient, {\n * productName: 'workspaces',\n * databaseUrl: process.env.DATABASE_URL!,\n * maxConnections: 50,\n * enableQueryLogging: true,\n * slowQueryThreshold: 200,\n * enableGraphExtension: true,\n * registerShutdownHandlers: true,\n * });\n * ```\n */\nexport function createDatabaseClient<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: DatabaseClientConfig\n): DatabaseClient<T> {\n const {\n productName,\n enableGraphExtension = process.env['GRAPH_MIDDLEWARE_ENABLED'] !== 'false',\n graphEventEmitter,\n enableWorkspaceExtension = resolveWorkspaceExtensionDefault(productName),\n workspaceExtensionConfig,\n registerShutdownHandlers = true,\n ...prismaConfig\n } = config;\n\n // Tag every service's pool with `svc=<productName>` by default so its\n // connections are attributable in pg_stat_activity / pg_stat_statements\n // (the on-ramp to per-workspace observability and shard routing). This is\n // pure diagnostic metadata with no effect on behavior; explicit\n // `applicationName` on the config always wins.\n const prismaConfigWithDefaults: PrismaClientConfig = {\n ...prismaConfig,\n applicationName: prismaConfig.applicationName ?? `svc=${productName}`,\n };\n\n // Belt-and-suspenders: also set the PGAPPNAME env fallback so any additional\n // pools this service opens outside be-sdk still carry the per-service tag.\n ensureServiceApplicationName(productName);\n\n // Create Prisma client wrapper\n const wrapper = createPrismaClient(PrismaClientConstructor, prismaConfigWithDefaults);\n\n // Get the base client\n const baseClient = wrapper.getClient();\n\n // Extension chaining order:\n // 1. Graph extension (event emission on CRUD) - runs first\n // 2. Workspace extension (auto-inject workspaceId) - runs second\n //\n // The workspace extension should run BEFORE graph extension in the\n // interception chain so that graph events include the injected workspaceId.\n // In Prisma $extends, the LAST extension added runs FIRST (outermost wrapper).\n // So we add graph first, then workspace on top.\n\n let extendedClient: T;\n\n // Step 1: Add graph extension\n if (enableGraphExtension) {\n const eventEmitter = graphEventEmitter ?? getGraphEventEmitter();\n\n const graphConfig: GraphMiddlewareConfig = {\n enabled: true,\n productName,\n eventEmitter,\n };\n\n extendedClient = addGraphExtension(baseClient, graphConfig);\n\n logger.info('[Database] Graph extension enabled', { productName });\n } else {\n extendedClient = baseClient;\n logger.info('[Database] Graph extension disabled');\n }\n\n // Step 2: Add workspace extension (wraps on top of graph)\n if (enableWorkspaceExtension) {\n extendedClient = addWorkspaceExtension(extendedClient, workspaceExtensionConfig);\n\n logger.info('[Database] Workspace extension enabled', { productName });\n } else {\n logger.info('[Database] Workspace extension disabled');\n }\n\n // Add backwards compatibility alias\n const db = extendedClient as T & { client: T };\n (db as unknown as Record<string, unknown>)['client'] = db;\n\n // Register shutdown handlers if requested\n if (registerShutdownHandlers) {\n wrapper.registerShutdownHandlers();\n logger.debug('[Database] Shutdown handlers registered');\n }\n\n return {\n db,\n wrapper,\n connect: (retries?: number, delay?: number) => wrapper.connect(retries, delay),\n disconnect: () => wrapper.disconnect(),\n };\n}\n\n/**\n * Pool-tuning options resolved from environment variables.\n */\nexport interface PoolTuningEnv {\n /** Postgres application_name (defaults to `svc=<productName>`). */\n applicationName: string;\n /** Client-side node-postgres query_timeout in ms, if opted in (pooler-safe). */\n queryTimeoutMillis?: number;\n /** Server-side statement_timeout in ms, if opted in. */\n statementTimeoutMillis?: number;\n /** Server-side idle_in_transaction_session_timeout in ms, if opted in. */\n idleInTransactionTimeoutMillis?: number;\n /** Server-side lock_timeout in ms, if opted in. */\n lockTimeoutMillis?: number;\n}\n\n/**\n * Parse a strictly-positive integer environment variable.\n *\n * Returns `undefined` for unset, empty, non-numeric, zero, or negative values —\n * so a misconfigured or absent env var can never silently enable an aggressive\n * (or nonsensical) timeout. This is what keeps the DB-enforced timeouts OFF by\n * default and therefore behavior-preserving.\n */\nfunction parsePositiveIntEnv(name: string): number | undefined {\n const raw = process.env[name];\n if (raw == null || raw.trim() === '') {\n return undefined;\n }\n const parsed = Number.parseInt(raw.trim(), 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\n\n/**\n * Resolve pool tuning (application_name + opt-in DB timeouts) from env vars:\n * - DATABASE_APPLICATION_NAME: overrides the default `svc=<productName>` tag\n * - DATABASE_QUERY_TIMEOUT: client-side node-postgres query_timeout in ms (opt-in, pooler-safe)\n * - DATABASE_STATEMENT_TIMEOUT: server-side statement_timeout in ms (opt-in; DIRECT :5432 only — see note)\n * - DATABASE_IDLE_IN_TRANSACTION_TIMEOUT: idle_in_transaction_session_timeout in ms (opt-in)\n * - DATABASE_LOCK_TIMEOUT: lock_timeout in ms (opt-in)\n *\n * Timeouts are omitted entirely unless explicitly set to a positive integer, so\n * the default is exactly today's behavior (no timeouts).\n *\n * NOTE: prefer `DATABASE_QUERY_TIMEOUT` for services whose `DATABASE_URL` points\n * at the built-in PgBouncer (`:6432`). `DATABASE_STATEMENT_TIMEOUT` and friends\n * are Postgres startup parameters that Azure PgBouncer does not pass through, so\n * they silently have no effect (or fail the connection) on the pooled path.\n */\nexport function resolvePoolTuningFromEnv(productName: string): PoolTuningEnv {\n const tuning: PoolTuningEnv = {\n applicationName: process.env['DATABASE_APPLICATION_NAME']?.trim() || `svc=${productName}`,\n };\n\n const queryTimeout = parsePositiveIntEnv('DATABASE_QUERY_TIMEOUT');\n if (queryTimeout !== undefined) {\n tuning.queryTimeoutMillis = queryTimeout;\n }\n\n const statementTimeout = parsePositiveIntEnv('DATABASE_STATEMENT_TIMEOUT');\n if (statementTimeout !== undefined) {\n tuning.statementTimeoutMillis = statementTimeout;\n }\n\n const idleInTransactionTimeout = parsePositiveIntEnv('DATABASE_IDLE_IN_TRANSACTION_TIMEOUT');\n if (idleInTransactionTimeout !== undefined) {\n tuning.idleInTransactionTimeoutMillis = idleInTransactionTimeout;\n }\n\n const lockTimeout = parsePositiveIntEnv('DATABASE_LOCK_TIMEOUT');\n if (lockTimeout !== undefined) {\n tuning.lockTimeoutMillis = lockTimeout;\n }\n\n return tuning;\n}\n\n/**\n * Create a database client from environment variables\n *\n * Convenience function that reads configuration from standard environment variables:\n * - DATABASE_URL: Connection string (required)\n * - DATABASE_MAX_CONNECTIONS: Max pool connections (default: 20)\n * - DATABASE_APPLICATION_NAME: Postgres application_name (default: `svc=<productName>`)\n * - DATABASE_QUERY_TIMEOUT: opt-in client-side query timeout in ms — the\n * PgBouncer-safe query bound (default: OFF, preserving current behavior)\n * - DATABASE_STATEMENT_TIMEOUT / DATABASE_IDLE_IN_TRANSACTION_TIMEOUT / DATABASE_LOCK_TIMEOUT:\n * opt-in server-side timeouts in ms (default: OFF; DIRECT :5432 only — not\n * honored through the built-in PgBouncer :6432 runtime path)\n * - NODE_ENV: Environment for logging settings\n * - GRAPH_MIDDLEWARE_ENABLED: Enable graph sync (default: true)\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createDatabaseClientFromEnv } from '@burdenoff/be-sdk/prisma';\n *\n * const { db } = createDatabaseClientFromEnv(PrismaClient, 'module-tags');\n * export { db };\n * ```\n */\nexport function createDatabaseClientFromEnv<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n productName: string,\n overrides?: Partial<DatabaseClientConfig>\n): DatabaseClient<T> {\n const databaseUrl = process.env['DATABASE_URL'];\n if (!databaseUrl) {\n throw new Error('DATABASE_URL environment variable is required');\n }\n\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n\n const config: DatabaseClientConfig = {\n productName,\n databaseUrl,\n maxConnections: parseInt(process.env['DATABASE_MAX_CONNECTIONS'] || '20', 10),\n idleTimeoutMillis: parseInt(process.env['DATABASE_IDLE_TIMEOUT'] || '30000', 10),\n connectionTimeoutMillis: parseInt(process.env['DATABASE_CONNECTION_TIMEOUT'] || '10000', 10),\n ...resolvePoolTuningFromEnv(productName),\n enableQueryLogging: isDevelopment,\n slowQueryThreshold: isDevelopment ? 100 : 500,\n ...overrides,\n };\n\n // Transient acquire retry — env-tunable, and unlike the fields above zero is\n // meaningful (DATABASE_ACQUIRE_RETRIES=0 disables the retry entirely).\n const acquireRetriesRaw = process.env['DATABASE_ACQUIRE_RETRIES']?.trim();\n if (acquireRetriesRaw !== undefined && acquireRetriesRaw !== '' && config.acquireRetries === undefined) {\n const parsed = Number.parseInt(acquireRetriesRaw, 10);\n if (Number.isFinite(parsed) && parsed >= 0) {\n config.acquireRetries = parsed;\n }\n }\n const acquireRetryDelay = parsePositiveIntEnv('DATABASE_ACQUIRE_RETRY_DELAY');\n if (acquireRetryDelay !== undefined && config.acquireRetryDelayMillis === undefined) {\n config.acquireRetryDelayMillis = acquireRetryDelay;\n }\n\n return createDatabaseClient(PrismaClientConstructor, config);\n}\n","/**\n * Database Singleton Manager\n *\n * Provides a singleton pattern for database connections across microservices.\n * Services initialize once at startup and access the db instance globally.\n *\n * This eliminates the need for individual db.ts files in each microservice.\n *\n * @module prisma/manager\n * @category Database\n *\n * @example\n * ```typescript\n * // In your service's index.ts (startup)\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { initializeDatabase } from '@burdenoff/be-sdk/prisma';\n *\n * // Initialize once at startup\n * const { db, connect } = initializeDatabase(PrismaClient, 'module-tags');\n * await connect();\n *\n * // In any other file\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n * const db = getDb();\n * await db.client.user.findMany();\n * ```\n */\n\nimport { logger } from '../logger/index.js';\nimport {\n createDatabaseClient,\n createDatabaseClientFromEnv,\n type DatabaseClient,\n type DatabaseClientConfig,\n} from './factory.js';\nimport type { PrismaClientBase, PrismaClientConstructorOptions, DatabaseReturnType } from './client.js';\n\n/**\n * Global database manager state\n */\ninterface DatabaseManagerState {\n initialized: boolean;\n productName: string | null;\n client: DatabaseClient<PrismaClientBase> | null;\n}\n\n/**\n * Singleton state for the database manager\n */\nconst state: DatabaseManagerState = {\n initialized: false,\n productName: null,\n client: null,\n};\n\n/**\n * Initialize the database singleton\n *\n * Call this once at application startup with your service's PrismaClient.\n * After initialization, use `getDb()` to access the database anywhere.\n *\n * @param PrismaClientConstructor - The generated PrismaClient class from your service\n * @param productName - Product name for graph events (e.g., 'module-tags', 'workspaces')\n * @param config - Optional configuration overrides\n * @returns The database client with db, wrapper, connect, disconnect\n *\n * @throws Error if already initialized with a different product\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { initializeDatabase } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, connect, disconnect } = initializeDatabase(PrismaClient, 'module-tags');\n * await connect();\n * ```\n */\nexport function initializeDatabase<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n productName: string,\n config?: Partial<DatabaseClientConfig>\n): DatabaseClient<T> {\n // Check if already initialized\n if (state.initialized) {\n if (state.productName !== productName) {\n throw new Error(\n `Database already initialized for product \"${state.productName}\". ` +\n `Cannot reinitialize for \"${productName}\".`\n );\n }\n logger.debug('[DatabaseManager] Already initialized, returning existing client', { productName });\n return state.client as DatabaseClient<T>;\n }\n\n // Create the database client using env-based factory\n const client = createDatabaseClientFromEnv(PrismaClientConstructor, productName, config);\n\n // Store in singleton state\n state.initialized = true;\n state.productName = productName;\n state.client = client;\n\n logger.info('[DatabaseManager] Database initialized', { productName });\n\n return client;\n}\n\n/**\n * Initialize the database with explicit configuration\n *\n * Use this when you need full control over database configuration\n * rather than reading from environment variables.\n *\n * @param PrismaClientConstructor - The generated PrismaClient class\n * @param config - Full database configuration\n * @returns The database client\n *\n * @example\n * ```typescript\n * const { db } = initializeDatabaseWithConfig(PrismaClient, {\n * productName: 'module-tags',\n * databaseUrl: 'postgresql://...',\n * maxConnections: 50,\n * enableGraphExtension: false,\n * });\n * ```\n */\nexport function initializeDatabaseWithConfig<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: DatabaseClientConfig\n): DatabaseClient<T> {\n const { productName } = config;\n\n // Check if already initialized\n if (state.initialized) {\n if (state.productName !== productName) {\n throw new Error(\n `Database already initialized for product \"${state.productName}\". ` +\n `Cannot reinitialize for \"${productName}\".`\n );\n }\n logger.debug('[DatabaseManager] Already initialized, returning existing client', { productName });\n return state.client as DatabaseClient<T>;\n }\n\n // Create the database client\n const client = createDatabaseClient(PrismaClientConstructor, config);\n\n // Store in singleton state\n state.initialized = true;\n state.productName = productName;\n state.client = client;\n\n logger.info('[DatabaseManager] Database initialized with custom config', { productName });\n\n return client;\n}\n\n/**\n * Get the initialized database client\n *\n * Use this anywhere in your application to access the database.\n * Must call `initializeDatabase()` first at application startup.\n *\n * The returned client provides dynamic model access - you can access any\n * model property (e.g., `db.client.user`, `db.client.universalTag`) and\n * TypeScript will allow common Prisma operations (findMany, create, etc.).\n *\n * @returns The extended Prisma client (db) with dynamic model access\n * @throws Error if database not initialized\n *\n * @example\n * ```typescript\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n *\n * const db = getDb();\n * // Dynamic model access works without importing service-specific types\n * const tags = await db.client.universalTag.findMany();\n * const users = await db.client.user.findMany({ where: { active: true } });\n * ```\n */\nexport function getDb<T extends PrismaClientBase = PrismaClientBase>(): DatabaseReturnType<T> {\n if (!state.initialized || !state.client) {\n throw new Error('Database not initialized. Call initializeDatabase() at application startup before using getDb().');\n }\n return state.client.db as unknown as DatabaseReturnType<T>;\n}\n\n/**\n * Get the full database manager\n *\n * Returns the complete database client including wrapper, connect, and disconnect functions.\n * Useful when you need access to connection management utilities.\n *\n * @returns The full database client\n * @throws Error if database not initialized\n *\n * @example\n * ```typescript\n * import { getDatabaseManager } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, wrapper, connect, disconnect } = getDatabaseManager();\n * await connect();\n * ```\n */\nexport function getDatabaseManager<T extends PrismaClientBase = PrismaClientBase>(): DatabaseClient<T> {\n if (!state.initialized || !state.client) {\n throw new Error(\n 'Database not initialized. Call initializeDatabase() at application startup before using getDatabaseManager().'\n );\n }\n return state.client as DatabaseClient<T>;\n}\n\n/**\n * Check if database is initialized\n *\n * @returns True if database has been initialized\n *\n * @example\n * ```typescript\n * if (!isDatabaseInitialized()) {\n * await initializeDatabase(PrismaClient, 'my-service');\n * }\n * ```\n */\nexport function isDatabaseInitialized(): boolean {\n return state.initialized;\n}\n\n/**\n * Get the product name of the initialized database\n *\n * @returns The product name or null if not initialized\n */\nexport function getDatabaseProductName(): string | null {\n return state.productName;\n}\n\n/**\n * Reset the database manager (for testing purposes only)\n *\n * WARNING: This disconnects and resets the database manager.\n * Only use this in test environments for cleanup between tests.\n *\n * @internal\n */\nexport async function resetDatabaseManager(): Promise<void> {\n if (state.client) {\n try {\n await state.client.disconnect();\n } catch (error) {\n logger.warn('[DatabaseManager] Error during disconnect on reset', { error });\n }\n }\n\n state.initialized = false;\n state.productName = null;\n state.client = null;\n\n logger.debug('[DatabaseManager] Database manager reset');\n}\n","/**\n * Prisma Health Check Utilities\n */\n\nimport { logger } from '../logger/index.js';\nimport type { DatabaseHealth } from './types.js';\nimport type { PrismaClientBase } from './client.js';\n\n/**\n * Check database health\n */\nexport async function checkDatabaseHealth<T extends PrismaClientBase>(client: T): Promise<DatabaseHealth> {\n try {\n const start = Date.now();\n await client.$queryRaw`SELECT 1`;\n const latency = Date.now() - start;\n\n return { healthy: true, latency };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error('[Prisma] Health check failed', { error: errorMessage });\n\n return {\n healthy: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * Test database connection\n */\nexport async function testConnection<T extends PrismaClientBase>(client: T): Promise<boolean> {\n try {\n await client.$queryRaw`SELECT 1`;\n return true;\n } catch (error) {\n logger.error('[Prisma] Connection test failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n return false;\n }\n}\n\n/**\n * Get database version\n */\nexport async function getDatabaseVersion<T extends PrismaClientBase>(client: T): Promise<string | null> {\n try {\n const result = await client.$queryRaw<Array<{ version?: string }>>`SELECT version()`;\n return result[0]?.version ?? null;\n } catch (error) {\n logger.error('[Prisma] Failed to get database version', {\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n}\n\n/**\n * Get database stats\n */\nexport async function getDatabaseStats<T extends PrismaClientBase>(\n client: T\n): Promise<{\n health: DatabaseHealth;\n version: string | null;\n timestamp: Date;\n}> {\n const [health, version] = await Promise.all([checkDatabaseHealth(client), getDatabaseVersion(client)]);\n\n return {\n health,\n version,\n timestamp: new Date(),\n };\n}\n","/**\n * Prisma Field Extraction Utilities\n *\n * Provides utilities for extracting model fields from Prisma schema.\n * In Prisma 7, DMMF is not available at runtime, so this module provides\n * build-time field extraction through a generator.\n *\n * @module prisma/fields\n */\n\nimport { createRequire } from 'node:module';\nimport { logger } from '../logger/index.js';\n\nconst requireFn = createRequire(import.meta.url);\n\n/**\n * Field extraction options\n */\nexport interface FieldExtractionOptions {\n /** Fields to exclude from extraction */\n excludeFields?: string[];\n /** Whether to include relation fields */\n includeRelations?: boolean;\n /** Custom filter function */\n customFilter?: (field: { name: string; type: string; isRelation: boolean }) => boolean;\n}\n\n/**\n * Field extraction result\n */\nexport interface FieldExtractionResult {\n /** Extracted field names */\n fields: string[];\n /** Metadata about the extraction */\n metadata: {\n /** Total number of fields found */\n totalFields: number;\n /** Number of fields excluded */\n excludedCount: number;\n /** Names of excluded fields */\n excludedFields: string[];\n /** Number of relation fields */\n relationFields: number;\n };\n}\n\n/**\n * Model fields mapping\n * This will be generated at build time by the Prisma generator\n */\nexport type ModelFieldsMap = Record<\n string,\n {\n fields: string[];\n relations: string[];\n }\n>;\n\n/**\n * Import generated fields from the consuming package\n * This function should be used by backends to load their generated fields\n */\nexport function loadGeneratedFields(generatedFieldsPath: string): ModelFieldsMap {\n try {\n // Dynamic import of generated fields using createRequire\n const generated = requireFn(generatedFieldsPath) as { default: ModelFieldsMap };\n return generated.default || generated;\n } catch (error) {\n logger.error('[Prisma] Failed to load generated fields', {\n error: error instanceof Error ? error.message : String(error),\n path: generatedFieldsPath,\n });\n throw new Error(`Failed to load generated fields from ${generatedFieldsPath}`);\n }\n}\n\n/**\n * Extract fields from generated model fields with options\n */\nexport function extractFieldsFromModel(\n modelName: string,\n modelFieldsMap: ModelFieldsMap,\n options: FieldExtractionOptions = {}\n): FieldExtractionResult {\n const modelFields = modelFieldsMap[modelName];\n\n if (!modelFields) {\n throw new Error(\n `Model \"${modelName}\" not found in generated fields. ` +\n `Available models: ${Object.keys(modelFieldsMap).join(', ')}`\n );\n }\n\n const { excludeFields = [], includeRelations = false, customFilter } = options;\n\n // Start with scalar fields\n let fields = [...modelFields.fields];\n\n // Add relations if requested\n if (includeRelations) {\n fields = [...fields, ...modelFields.relations];\n }\n\n // Track excluded fields\n const excluded: string[] = [];\n\n // Apply exclusions\n if (excludeFields.length > 0) {\n fields = fields.filter((field) => {\n if (excludeFields.includes(field)) {\n excluded.push(field);\n return false;\n }\n return true;\n });\n }\n\n // Apply custom filter\n if (customFilter) {\n fields = fields.filter((fieldName) => {\n const isRelation = modelFields.relations.includes(fieldName);\n const shouldInclude = customFilter({\n name: fieldName,\n type: 'unknown', // Type information not available without full DMMF\n isRelation,\n });\n\n if (!shouldInclude) {\n excluded.push(fieldName);\n }\n\n return shouldInclude;\n });\n }\n\n return {\n fields,\n metadata: {\n totalFields: modelFields.fields.length + modelFields.relations.length,\n excludedCount: excluded.length,\n excludedFields: excluded,\n relationFields: modelFields.relations.length,\n },\n };\n}\n\n/**\n * Get all field names for a model (without options)\n */\nexport function getModelFields(modelName: string, modelFieldsMap: ModelFieldsMap, includeRelations = false): string[] {\n const result = extractFieldsFromModel(modelName, modelFieldsMap, { includeRelations });\n return result.fields;\n}\n\n/**\n * Check if a model exists in the generated fields\n */\nexport function hasModel(modelName: string, modelFieldsMap: ModelFieldsMap): boolean {\n return modelName in modelFieldsMap;\n}\n\n/**\n * Get all available model names\n */\nexport function getAllModelNames(modelFieldsMap: ModelFieldsMap): string[] {\n return Object.keys(modelFieldsMap);\n}\n","/**\n * Prisma Context Filtering Utilities\n *\n * Utilities for handling operation context in queries, mutations, and filtering.\n * Context JSON enables multi-dimensional data isolation across workspaces, users, projects, etc.\n *\n * @module prisma/context\n * @category Database\n */\n\nimport { isSameProductSlug, productSlugVariants } from '../product-alias/index.js';\n\n/**\n * Context filter input for querying entities by context\n */\nexport interface ContextFilterInput {\n workspaceId?: string | null;\n userId?: string | null;\n projectId?: string | null;\n appId?: string | null;\n /** Product identifier (e.g. \"vibecontrols\", \"workspaces\"). Stamped on cross-product\n * records so admin filters can scope by originating product. */\n productId?: string | null;\n /** Organization identifier within the tenant. */\n organizationId?: string | null;\n}\n\n/**\n * Operation context for create/update operations\n */\nexport interface OperationContext extends ContextFilterInput {\n custom?: Record<string, unknown> | null;\n}\n\n/**\n * Prisma JSON filter type (simplified for context filtering)\n * This type is designed to be compatible with Prisma's JsonNullableFilter\n * Uses Record<string, unknown> for maximum compatibility with various Prisma versions\n */\nexport type PrismaJsonFilter = Record<string, unknown>;\n\n/**\n * One entry of {@link buildContextWhereConditions}: a JSON-path predicate on `context`,\n * or an `OR` of them (used for a renamed product's slug twins).\n */\nexport type ContextWhereCondition = { context: PrismaJsonFilter } | { OR: Array<{ context: PrismaJsonFilter }> };\n\n/**\n * JSON value type for Prisma (includes null for reading from DB)\n */\nexport type JsonValue = string | number | boolean | null | { [key: string]: JsonValue } | JsonValue[];\n\n/**\n * Input JSON value type for Prisma (excludes null for writing to DB)\n * Compatible with Prisma's InputJsonValue type\n */\nexport type InputJsonValue = string | number | boolean | { [key: string]: InputJsonValue } | InputJsonValue[];\n\n/**\n * Build Prisma where condition for context filtering.\n * Uses PostgreSQL JSONB containment operators for efficient queries.\n *\n * @param contextFilter - The context filter input\n * @returns Prisma where clause for context field, or undefined if no filter provided\n *\n * @example\n * ```typescript\n * const contextWhere = buildContextWhereClause({\n * workspaceId: '123',\n * projectId: '456'\n * });\n * // Returns: { path: ['workspaceId'], equals: '123' }\n * ```\n */\nexport function buildContextWhereClause(\n contextFilter: ContextFilterInput | null | undefined\n): PrismaJsonFilter | undefined {\n if (!contextFilter) {\n return undefined;\n }\n\n // Build array of path conditions for each non-null field\n const conditions: PrismaJsonFilter[] = [];\n\n if (contextFilter.workspaceId != null) {\n conditions.push({\n path: ['workspaceId'],\n equals: contextFilter.workspaceId,\n });\n }\n\n if (contextFilter.userId != null) {\n conditions.push({\n path: ['userId'],\n equals: contextFilter.userId,\n });\n }\n\n if (contextFilter.projectId != null) {\n conditions.push({\n path: ['projectId'],\n equals: contextFilter.projectId,\n });\n }\n\n if (contextFilter.appId != null) {\n conditions.push({\n path: ['appId'],\n equals: contextFilter.appId,\n });\n }\n\n if (contextFilter.productId != null) {\n conditions.push({\n path: ['productId'],\n equals: contextFilter.productId,\n });\n }\n\n if (contextFilter.organizationId != null) {\n conditions.push({\n path: ['organizationId'],\n equals: contextFilter.organizationId,\n });\n }\n\n // If no conditions, return undefined\n if (conditions.length === 0) {\n return undefined;\n }\n\n // If single condition, return it directly\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n // For multiple conditions, return the first one\n // Caller should use buildContextWhereConditions for multiple AND conditions\n return conditions[0];\n}\n\n/**\n * Build context where conditions as an array for use in AND clause.\n * This is useful when you need to filter by multiple context fields.\n *\n * @param contextFilter - The context filter input\n * @returns Array of Prisma where conditions, each targeting the context field\n *\n * @example\n * ```typescript\n * const conditions = buildContextWhereConditions({\n * workspaceId: '123',\n * projectId: '456'\n * });\n * // Use in Prisma query:\n * prisma.entity.findMany({\n * where: { AND: conditions }\n * });\n * ```\n */\nexport function buildContextWhereConditions(\n contextFilter: ContextFilterInput | null | undefined\n): ContextWhereCondition[] {\n if (!contextFilter) {\n return [];\n }\n\n const conditions: ContextWhereCondition[] = [];\n\n if (contextFilter.workspaceId != null) {\n conditions.push({\n context: {\n path: ['workspaceId'],\n equals: contextFilter.workspaceId,\n },\n });\n }\n\n if (contextFilter.userId != null) {\n conditions.push({\n context: {\n path: ['userId'],\n equals: contextFilter.userId,\n },\n });\n }\n\n if (contextFilter.projectId != null) {\n conditions.push({\n context: {\n path: ['projectId'],\n equals: contextFilter.projectId,\n },\n });\n }\n\n if (contextFilter.appId != null) {\n conditions.push({\n context: {\n path: ['appId'],\n equals: contextFilter.appId,\n },\n });\n }\n\n if (contextFilter.productId != null) {\n // A renamed product (botlit → botmanor) matches rows stored under either slug while\n // they are migrated; every other product keeps the exact single-slug predicate.\n const slugs = productSlugVariants(contextFilter.productId);\n if (slugs.length > 1) {\n conditions.push({\n OR: slugs.map((slug) => ({ context: { path: ['productId'], equals: slug } })),\n });\n } else {\n conditions.push({\n context: {\n path: ['productId'],\n equals: contextFilter.productId,\n },\n });\n }\n }\n\n if (contextFilter.organizationId != null) {\n conditions.push({\n context: {\n path: ['organizationId'],\n equals: contextFilter.organizationId,\n },\n });\n }\n\n return conditions;\n}\n\n/**\n * Convert context input to Prisma JSON format for create/update operations.\n *\n * @param contextInput - The context input\n * @returns JSON value for the context field, or undefined if empty\n *\n * @example\n * ```typescript\n * const contextJson = toContextJson({\n * workspaceId: '123',\n * userId: '456'\n * });\n * // Use in Prisma create:\n * prisma.entity.create({\n * data: { context: contextJson }\n * });\n * ```\n */\nexport function toContextJson(contextInput: OperationContext | null | undefined): InputJsonValue | undefined {\n if (!contextInput) {\n return undefined;\n }\n\n // Remove null values and build clean context object\n const context: Record<string, InputJsonValue> = {};\n\n if (contextInput.workspaceId != null) {\n context['workspaceId'] = contextInput.workspaceId;\n }\n if (contextInput.userId != null) {\n context['userId'] = contextInput.userId;\n }\n if (contextInput.projectId != null) {\n context['projectId'] = contextInput.projectId;\n }\n if (contextInput.appId != null) {\n context['appId'] = contextInput.appId;\n }\n if (contextInput.productId != null) {\n context['productId'] = contextInput.productId;\n }\n if (contextInput.organizationId != null) {\n context['organizationId'] = contextInput.organizationId;\n }\n if (contextInput.custom != null) {\n context['custom'] = contextInput.custom as InputJsonValue;\n }\n\n // Return undefined if no fields set\n if (Object.keys(context).length === 0) {\n return undefined;\n }\n\n return context;\n}\n\n/**\n * Filter out null values from an object for Prisma compatibility\n */\nfunction filterNullValues(obj: Record<string, unknown>): Record<string, InputJsonValue> {\n const filtered: Record<string, InputJsonValue> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== null) {\n filtered[key] = value as InputJsonValue;\n }\n }\n return filtered;\n}\n\n/**\n * Merge a single field into the merged context object\n */\nfunction mergeContextField(\n merged: Record<string, InputJsonValue>,\n fieldName: string,\n fieldValue: string | Record<string, unknown> | null | undefined\n): void {\n if (fieldValue === undefined) {\n return; // Don't touch this field\n }\n\n if (fieldValue === null) {\n delete merged[fieldName]; // Explicitly remove\n } else {\n merged[fieldName] = fieldValue as InputJsonValue; // Set new value\n }\n}\n\n/**\n * Merge existing context with new context input.\n * New values override existing ones, but undefined values are preserved from existing.\n *\n * @param existingContext - The existing context JSON from database\n * @param newContext - The new context input\n * @returns Merged context as InputJsonValue (suitable for Prisma writes)\n *\n * @example\n * ```typescript\n * const merged = mergeContext(\n * { workspaceId: '123', userId: 'old' },\n * { userId: 'new', projectId: '456' }\n * );\n * // Result: { workspaceId: '123', userId: 'new', projectId: '456' }\n * ```\n */\nexport function mergeContext(\n existingContext: JsonValue | null | undefined,\n newContext: OperationContext | null | undefined\n): InputJsonValue | undefined {\n // If no new context, return existing (excluding null values)\n if (!newContext) {\n if (!existingContext) {\n return undefined;\n }\n // Filter out null values from existing context for Prisma compatibility\n if (typeof existingContext === 'object' && !Array.isArray(existingContext)) {\n const filtered = filterNullValues(existingContext);\n return Object.keys(filtered).length > 0 ? filtered : undefined;\n }\n return existingContext as InputJsonValue;\n }\n\n // If no existing context, convert new to JSON\n if (!existingContext || typeof existingContext !== 'object' || Array.isArray(existingContext)) {\n return toContextJson(newContext);\n }\n\n // Merge existing with new\n const merged = filterNullValues(existingContext);\n\n // Merge each field from new context\n mergeContextField(merged, 'workspaceId', newContext.workspaceId);\n mergeContextField(merged, 'userId', newContext.userId);\n mergeContextField(merged, 'projectId', newContext.projectId);\n mergeContextField(merged, 'appId', newContext.appId);\n mergeContextField(merged, 'productId', newContext.productId);\n mergeContextField(merged, 'organizationId', newContext.organizationId);\n mergeContextField(merged, 'custom', newContext.custom);\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * Parse context JSON from database to OperationContext interface.\n *\n * @param contextJson - The context JSON from database\n * @returns Parsed OperationContext or null\n *\n * @example\n * ```typescript\n * const context = parseContext(entity.context);\n * if (context?.workspaceId) {\n * // Use workspace-specific logic\n * }\n * ```\n */\nexport function parseContext(contextJson: JsonValue | null | undefined): OperationContext | null {\n if (!contextJson || typeof contextJson !== 'object' || Array.isArray(contextJson)) {\n return null;\n }\n\n const ctx = contextJson as Record<string, unknown>;\n\n return {\n workspaceId: typeof ctx['workspaceId'] === 'string' ? ctx['workspaceId'] : null,\n userId: typeof ctx['userId'] === 'string' ? ctx['userId'] : null,\n projectId: typeof ctx['projectId'] === 'string' ? ctx['projectId'] : null,\n appId: typeof ctx['appId'] === 'string' ? ctx['appId'] : null,\n productId: typeof ctx['productId'] === 'string' ? ctx['productId'] : null,\n organizationId: typeof ctx['organizationId'] === 'string' ? ctx['organizationId'] : null,\n custom: typeof ctx['custom'] === 'object' ? (ctx['custom'] as Record<string, unknown>) : null,\n };\n}\n\n/**\n * Check if context matches filter criteria\n *\n * @param context - The context to check\n * @param filter - The filter criteria\n * @returns True if context matches all filter criteria\n */\nexport function contextMatches(context: OperationContext | null | undefined, filter: ContextFilterInput): boolean {\n if (!context) {\n return false;\n }\n\n if (filter.workspaceId != null && context.workspaceId !== filter.workspaceId) {\n return false;\n }\n if (filter.userId != null && context.userId !== filter.userId) {\n return false;\n }\n if (filter.projectId != null && context.projectId !== filter.projectId) {\n return false;\n }\n if (filter.appId != null && context.appId !== filter.appId) {\n return false;\n }\n // Renamed products (botlit → botmanor) match under either slug while rows are migrated.\n if (filter.productId != null && !isSameProductSlug(context.productId, filter.productId)) {\n return false;\n }\n if (filter.organizationId != null && context.organizationId !== filter.organizationId) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Create a default context from SDK context\n *\n * @param sdkContext - The SDK context (from AsyncLocalStorage)\n * @returns Operation context with workspace and user info\n */\nexport function createContextFromSDK(sdkContext: {\n workspaceId?: string;\n userId?: string;\n projectId?: string;\n appId?: string;\n productId?: string;\n organizationId?: string;\n}): OperationContext {\n return {\n workspaceId: sdkContext.workspaceId ?? null,\n userId: sdkContext.userId ?? null,\n projectId: sdkContext.projectId ?? null,\n appId: sdkContext.appId ?? null,\n productId: sdkContext.productId ?? null,\n organizationId: sdkContext.organizationId ?? null,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/prisma/index.ts","../src/prisma/factory.ts","../src/prisma/manager.ts","../src/prisma/health.ts","../src/prisma/fields.ts","../src/prisma/context.ts"],"names":["resolveWorkspaceExtensionDefault","productName","explicit","process","env","layer","toLowerCase","name","startsWith","createDatabaseClient","PrismaClientConstructor","config","enableGraphExtension","graphEventEmitter","enableWorkspaceExtension","workspaceExtensionConfig","registerShutdownHandlers","prismaConfig","prismaConfigWithDefaults","applicationName","ensureServiceApplicationName","wrapper","createPrismaClient","baseClient","getClient","extendedClient","eventEmitter","getGraphEventEmitter","graphConfig","enabled","addGraphExtension","logger","info","addWorkspaceExtension","db","debug","connect","retries","delay","disconnect","parsePositiveIntEnv","raw","trim","undefined","parsed","Number","parseInt","isFinite","resolvePoolTuningFromEnv","tuning","queryTimeout","queryTimeoutMillis","statementTimeout","statementTimeoutMillis","idleInTransactionTimeout","idleInTransactionTimeoutMillis","lockTimeout","lockTimeoutMillis","createDatabaseClientFromEnv","overrides","databaseUrl","Error","isDevelopment","maxConnections","idleTimeoutMillis","connectionTimeoutMillis","enableQueryLogging","slowQueryThreshold","acquireRetriesRaw","acquireRetries","acquireRetryDelay","acquireRetryDelayMillis","state","initialized","client","initializeDatabase","initializeDatabaseWithConfig","getDb","getDatabaseManager","isDatabaseInitialized","getDatabaseProductName","resetDatabaseManager","error","warn","checkDatabaseHealth","start","Date","now","$queryRaw","latency","healthy","errorMessage","message","String","testConnection","getDatabaseVersion","result","version","getDatabaseStats","health","Promise","all","timestamp","requireFn","createRequire","url","loadGeneratedFields","generatedFieldsPath","generated","default","path","extractFieldsFromModel","modelName","modelFieldsMap","options","modelFields","Object","keys","join","excludeFields","includeRelations","customFilter","fields","relations","excluded","length","filter","field","includes","push","fieldName","isRelation","shouldInclude","type","metadata","totalFields","excludedCount","excludedFields","relationFields","getModelFields","hasModel","getAllModelNames","buildContextWhereClause","contextFilter","conditions","workspaceId","equals","userId","projectId","appId","productId","organizationId","buildContextWhereConditions","context","slugs","productSlugVariants","OR","map","slug","toContextJson","contextInput","custom","filterNullValues","obj","filtered","key","value","entries","mergeContextField","merged","fieldValue","mergeContext","existingContext","newContext","Array","isArray","parseContext","contextJson","ctx","contextMatches","isSameProductSlug","createContextFromSDK","sdkContext"],"mappings":";;;;;;;;;AAAA,IAAA,cAAA,GAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC8GA,SAASA,iCAAiCC,WAAAA,EAAmB;AAC3D,EAAA,MAAMC,QAAAA,GAAWC,OAAAA,CAAQC,GAAAA,CAAI,6BAAA,CAAA;AAC7B,EAAA,IAAIF,QAAAA,KAAa,QAAQ,OAAO,IAAA;AAChC,EAAA,IAAIA,QAAAA,KAAa,SAAS,OAAO,KAAA;AAEjC,EAAA,MAAMG,KAAAA,GAAQF,OAAAA,CAAQC,GAAAA,CAAI,iBAAA,GAAoBE,WAAAA,EAAAA;AAC9C,EAAA,IAAID,KAAAA,KAAU,UAAU,OAAO,KAAA;AAC/B,EAAA,IAAIA,KAAAA,KAAU,UAAU,OAAO,IAAA;AAE/B,EAAA,MAAME,IAAAA,GAAON,YAAYK,WAAAA,EAAW;AACpC,EAAA,IAAIC,IAAAA,CAAKC,WAAW,SAAA,CAAA,IAAcD,KAAKC,UAAAA,CAAW,SAAA,GAAY,OAAO,KAAA;AACrE,EAAA,OAAO,IAAA;AACT;AAZSR,MAAAA,CAAAA,gCAAAA,EAAAA,kCAAAA,CAAAA;AAsDF,SAASS,oBAAAA,CACdC,yBACAC,MAAAA,EAA4B;AAE5B,EAAA,MAAM,EACJV,WAAAA,EACAW,oBAAAA,GAAuBT,QAAQC,GAAAA,CAAI,0BAAA,MAAgC,OAAA,EACnES,iBAAAA,EACAC,wBAAAA,GAA2Bd,gCAAAA,CAAiCC,WAAAA,CAAAA,EAC5Dc,wBAAAA,EACAC,2BAA2B,IAAA,EAC3B,GAAGC,cAAAA,GACDN,MAAAA;AAOJ,EAAA,MAAMO,wBAAAA,GAA+C;IACnD,GAAGD,YAAAA;IACHE,eAAAA,EAAiBF,YAAAA,CAAaE,eAAAA,IAAmB,CAAA,IAAA,EAAOlB,WAAAA,CAAAA;AAC1D,GAAA;AAIAmB,EAAAA,4BAAAA,CAA6BnB,WAAAA,CAAAA;AAG7B,EAAA,MAAMoB,OAAAA,GAAUC,kBAAAA,CAAmBZ,uBAAAA,EAAyBQ,wBAAAA,CAAAA;AAG5D,EAAA,MAAMK,UAAAA,GAAaF,QAAQG,SAAAA,EAAS;AAWpC,EAAA,IAAIC,cAAAA;AAGJ,EAAA,IAAIb,oBAAAA,EAAsB;AACxB,IAAA,MAAMc,YAAAA,GAAeb,qBAAqBc,oBAAAA,EAAAA;AAE1C,IAAA,MAAMC,WAAAA,GAAqC;MACzCC,OAAAA,EAAS,IAAA;AACT5B,MAAAA,WAAAA;AACAyB,MAAAA;AACF,KAAA;AAEAD,IAAAA,cAAAA,GAAiBK,iBAAAA,CAAkBP,YAAYK,WAAAA,CAAAA;AAE/CG,IAAAA,MAAAA,CAAOC,KAAK,oCAAA,EAAsC;AAAE/B,MAAAA;KAAY,CAAA;EAClE,CAAA,MAAO;AACLwB,IAAAA,cAAAA,GAAiBF,UAAAA;AACjBQ,IAAAA,MAAAA,CAAOC,KAAK,qCAAA,CAAA;AACd,EAAA;AAGA,EAAA,IAAIlB,wBAAAA,EAA0B;AAC5BW,IAAAA,cAAAA,GAAiBQ,qBAAAA,CAAsBR,gBAAgBV,wBAAAA,CAAAA;AAEvDgB,IAAAA,MAAAA,CAAOC,KAAK,wCAAA,EAA0C;AAAE/B,MAAAA;KAAY,CAAA;EACtE,CAAA,MAAO;AACL8B,IAAAA,MAAAA,CAAOC,KAAK,yCAAA,CAAA;AACd,EAAA;AAGA,EAAA,MAAME,EAAAA,GAAKT,cAAAA;AACVS,EAAAA,EAAAA,CAA0C,QAAA,CAAA,GAAYA,EAAAA;AAGvD,EAAA,IAAIlB,wBAAAA,EAA0B;AAC5BK,IAAAA,OAAAA,CAAQL,wBAAAA,EAAwB;AAChCe,IAAAA,MAAAA,CAAOI,MAAM,yCAAA,CAAA;AACf,EAAA;AAEA,EAAA,OAAO;AACLD,IAAAA,EAAAA;AACAb,IAAAA,OAAAA;AACAe,IAAAA,OAAAA,0BAAUC,OAAAA,EAAkBC,KAAAA,KAAmBjB,QAAQe,OAAAA,CAAQC,OAAAA,EAASC,KAAAA,CAAAA,EAA/D,SAAA,CAAA;IACTC,UAAAA,kBAAY,MAAA,CAAA,MAAMlB,OAAAA,CAAQkB,UAAAA,EAAU,EAAxB,YAAA;AACd,GAAA;AACF;AAxFgB9B,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA;AAkHhB,SAAS+B,oBAAoBjC,IAAAA,EAAY;AACvC,EAAA,MAAMkC,GAAAA,GAAMtC,OAAAA,CAAQC,GAAAA,CAAIG,IAAAA,CAAAA;AACxB,EAAA,IAAIkC,GAAAA,IAAO,IAAA,IAAQA,GAAAA,CAAIC,IAAAA,OAAW,EAAA,EAAI;AACpC,IAAA,OAAOC,MAAAA;AACT,EAAA;AACA,EAAA,MAAMC,SAASC,MAAAA,CAAOC,QAAAA,CAASL,GAAAA,CAAIC,IAAAA,IAAQ,EAAA,CAAA;AAC3C,EAAA,OAAOG,OAAOE,QAAAA,CAASH,MAAAA,CAAAA,IAAWA,MAAAA,GAAS,IAAIA,MAAAA,GAASD,MAAAA;AAC1D;AAPSH,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAyBF,SAASQ,yBAAyB/C,WAAAA,EAAmB;AAC1D,EAAA,MAAMgD,MAAAA,GAAwB;AAC5B9B,IAAAA,eAAAA,EAAiBhB,QAAQC,GAAAA,CAAI,2BAAA,GAA8BsC,IAAAA,EAAAA,IAAU,OAAOzC,WAAAA,CAAAA;AAC9E,GAAA;AAEA,EAAA,MAAMiD,YAAAA,GAAeV,oBAAoB,wBAAA,CAAA;AACzC,EAAA,IAAIU,iBAAiBP,MAAAA,EAAW;AAC9BM,IAAAA,MAAAA,CAAOE,kBAAAA,GAAqBD,YAAAA;AAC9B,EAAA;AAEA,EAAA,MAAME,gBAAAA,GAAmBZ,oBAAoB,4BAAA,CAAA;AAC7C,EAAA,IAAIY,qBAAqBT,MAAAA,EAAW;AAClCM,IAAAA,MAAAA,CAAOI,sBAAAA,GAAyBD,gBAAAA;AAClC,EAAA;AAEA,EAAA,MAAME,wBAAAA,GAA2Bd,oBAAoB,sCAAA,CAAA;AACrD,EAAA,IAAIc,6BAA6BX,MAAAA,EAAW;AAC1CM,IAAAA,MAAAA,CAAOM,8BAAAA,GAAiCD,wBAAAA;AAC1C,EAAA;AAEA,EAAA,MAAME,WAAAA,GAAchB,oBAAoB,uBAAA,CAAA;AACxC,EAAA,IAAIgB,gBAAgBb,MAAAA,EAAW;AAC7BM,IAAAA,MAAAA,CAAOQ,iBAAAA,GAAoBD,WAAAA;AAC7B,EAAA;AAEA,EAAA,OAAOP,MAAAA;AACT;AA1BgBD,MAAAA,CAAAA,wBAAAA,EAAAA,0BAAAA,CAAAA;AAoDT,SAASU,2BAAAA,CACdhD,uBAAAA,EACAT,WAAAA,EACA0D,SAAAA,EAAyC;AAEzC,EAAA,MAAMC,WAAAA,GAAczD,OAAAA,CAAQC,GAAAA,CAAI,cAAA,CAAA;AAChC,EAAA,IAAI,CAACwD,WAAAA,EAAa;AAChB,IAAA,MAAM,IAAIC,MAAM,+CAAA,CAAA;AAClB,EAAA;AAEA,EAAA,MAAMC,aAAAA,GAAgB3D,OAAAA,CAAQC,GAAAA,CAAI,UAAA,CAAA,KAAgB,aAAA;AAElD,EAAA,MAAMO,MAAAA,GAA+B;AACnCV,IAAAA,WAAAA;AACA2D,IAAAA,WAAAA;AACAG,IAAAA,cAAAA,EAAgBjB,SAAS3C,OAAAA,CAAQC,GAAAA,CAAI,0BAAA,CAAA,IAA+B,MAAM,EAAA,CAAA;AAC1E4D,IAAAA,iBAAAA,EAAmBlB,SAAS3C,OAAAA,CAAQC,GAAAA,CAAI,uBAAA,CAAA,IAA4B,SAAS,EAAA,CAAA;AAC7E6D,IAAAA,uBAAAA,EAAyBnB,SAAS3C,OAAAA,CAAQC,GAAAA,CAAI,6BAAA,CAAA,IAAkC,SAAS,EAAA,CAAA;AACzF,IAAA,GAAG4C,yBAAyB/C,WAAAA,CAAAA;IAC5BiE,kBAAAA,EAAoBJ,aAAAA;AACpBK,IAAAA,kBAAAA,EAAoBL,gBAAgB,GAAA,GAAM,GAAA;IAC1C,GAAGH;AACL,GAAA;AAIA,EAAA,MAAMS,iBAAAA,GAAoBjE,OAAAA,CAAQC,GAAAA,CAAI,0BAAA,GAA6BsC,IAAAA,EAAAA;AACnE,EAAA,IAAI0B,sBAAsBzB,MAAAA,IAAayB,iBAAAA,KAAsB,EAAA,IAAMzD,MAAAA,CAAO0D,mBAAmB1B,MAAAA,EAAW;AACtG,IAAA,MAAMC,MAAAA,GAASC,MAAAA,CAAOC,QAAAA,CAASsB,iBAAAA,EAAmB,EAAA,CAAA;AAClD,IAAA,IAAIvB,MAAAA,CAAOE,QAAAA,CAASH,MAAAA,CAAAA,IAAWA,UAAU,CAAA,EAAG;AAC1CjC,MAAAA,MAAAA,CAAO0D,cAAAA,GAAiBzB,MAAAA;AAC1B,IAAA;AACF,EAAA;AACA,EAAA,MAAM0B,iBAAAA,GAAoB9B,oBAAoB,8BAAA,CAAA;AAC9C,EAAA,IAAI8B,iBAAAA,KAAsB3B,MAAAA,IAAahC,MAAAA,CAAO4D,uBAAAA,KAA4B5B,MAAAA,EAAW;AACnFhC,IAAAA,MAAAA,CAAO4D,uBAAAA,GAA0BD,iBAAAA;AACnC,EAAA;AAEA,EAAA,OAAO7D,oBAAAA,CAAqBC,yBAAyBC,MAAAA,CAAAA;AACvD;AAvCgB+C,MAAAA,CAAAA,2BAAAA,EAAAA,6BAAAA,CAAAA;;;AClThB,IAAMc,KAAAA,GAA8B;EAClCC,WAAAA,EAAa,KAAA;EACbxE,WAAAA,EAAa,IAAA;EACbyE,MAAAA,EAAQ;AACV,CAAA;AAwBO,SAASC,kBAAAA,CACdjE,uBAAAA,EACAT,WAAAA,EACAU,MAAAA,EAAsC;AAGtC,EAAA,IAAI6D,MAAMC,WAAAA,EAAa;AACrB,IAAA,IAAID,KAAAA,CAAMvE,gBAAgBA,WAAAA,EAAa;AACrC,MAAA,MAAM,IAAI4D,KAAAA,CACR,CAAA,0CAAA,EAA6CW,MAAMvE,WAAW,CAAA,4BAAA,EAChCA,WAAAA,CAAAA,EAAAA,CAAe,CAAA;AAEjD,IAAA;AACA8B,IAAAA,MAAAA,CAAOI,MAAM,kEAAA,EAAoE;AAAElC,MAAAA;KAAY,CAAA;AAC/F,IAAA,OAAOuE,KAAAA,CAAME,MAAAA;AACf,EAAA;AAGA,EAAA,MAAMA,MAAAA,GAAShB,2BAAAA,CAA4BhD,uBAAAA,EAAyBT,WAAAA,EAAaU,MAAAA,CAAAA;AAGjF6D,EAAAA,KAAAA,CAAMC,WAAAA,GAAc,IAAA;AACpBD,EAAAA,KAAAA,CAAMvE,WAAAA,GAAcA,WAAAA;AACpBuE,EAAAA,KAAAA,CAAME,MAAAA,GAASA,MAAAA;AAEf3C,EAAAA,MAAAA,CAAOC,KAAK,wCAAA,EAA0C;AAAE/B,IAAAA;GAAY,CAAA;AAEpE,EAAA,OAAOyE,MAAAA;AACT;AA5BgBC,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;AAkDT,SAASC,4BAAAA,CACdlE,yBACAC,MAAAA,EAA4B;AAE5B,EAAA,MAAM,EAAEV,aAAW,GAAKU,MAAAA;AAGxB,EAAA,IAAI6D,MAAMC,WAAAA,EAAa;AACrB,IAAA,IAAID,KAAAA,CAAMvE,gBAAgBA,WAAAA,EAAa;AACrC,MAAA,MAAM,IAAI4D,KAAAA,CACR,CAAA,0CAAA,EAA6CW,MAAMvE,WAAW,CAAA,4BAAA,EAChCA,WAAAA,CAAAA,EAAAA,CAAe,CAAA;AAEjD,IAAA;AACA8B,IAAAA,MAAAA,CAAOI,MAAM,kEAAA,EAAoE;AAAElC,MAAAA;KAAY,CAAA;AAC/F,IAAA,OAAOuE,KAAAA,CAAME,MAAAA;AACf,EAAA;AAGA,EAAA,MAAMA,MAAAA,GAASjE,oBAAAA,CAAqBC,uBAAAA,EAAyBC,MAAAA,CAAAA;AAG7D6D,EAAAA,KAAAA,CAAMC,WAAAA,GAAc,IAAA;AACpBD,EAAAA,KAAAA,CAAMvE,WAAAA,GAAcA,WAAAA;AACpBuE,EAAAA,KAAAA,CAAME,MAAAA,GAASA,MAAAA;AAEf3C,EAAAA,MAAAA,CAAOC,KAAK,2DAAA,EAA6D;AAAE/B,IAAAA;GAAY,CAAA;AAEvF,EAAA,OAAOyE,MAAAA;AACT;AA7BgBE,MAAAA,CAAAA,4BAAAA,EAAAA,8BAAAA,CAAAA;AAsDT,SAASC,KAAAA,GAAAA;AACd,EAAA,IAAI,CAACL,KAAAA,CAAMC,WAAAA,IAAe,CAACD,MAAME,MAAAA,EAAQ;AACvC,IAAA,MAAM,IAAIb,MAAM,kGAAA,CAAA;AAClB,EAAA;AACA,EAAA,OAAOW,MAAME,MAAAA,CAAOxC,EAAAA;AACtB;AALgB2C,MAAAA,CAAAA,KAAAA,EAAAA,OAAAA,CAAAA;AAwBT,SAASC,kBAAAA,GAAAA;AACd,EAAA,IAAI,CAACN,KAAAA,CAAMC,WAAAA,IAAe,CAACD,MAAME,MAAAA,EAAQ;AACvC,IAAA,MAAM,IAAIb,MACR,+GAAA,CAAA;AAEJ,EAAA;AACA,EAAA,OAAOW,KAAAA,CAAME,MAAAA;AACf;AAPgBI,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;AAqBT,SAASC,qBAAAA,GAAAA;AACd,EAAA,OAAOP,KAAAA,CAAMC,WAAAA;AACf;AAFgBM,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AAST,SAASC,sBAAAA,GAAAA;AACd,EAAA,OAAOR,KAAAA,CAAMvE,WAAAA;AACf;AAFgB+E,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AAYhB,eAAsBC,oBAAAA,GAAAA;AACpB,EAAA,IAAIT,MAAME,MAAAA,EAAQ;AAChB,IAAA,IAAI;AACF,MAAA,MAAMF,KAAAA,CAAME,OAAOnC,UAAAA,EAAU;AAC/B,IAAA,CAAA,CAAA,OAAS2C,KAAAA,EAAO;AACdnD,MAAAA,MAAAA,CAAOoD,KAAK,oDAAA,EAAsD;AAAED,QAAAA;OAAM,CAAA;AAC5E,IAAA;AACF,EAAA;AAEAV,EAAAA,KAAAA,CAAMC,WAAAA,GAAc,KAAA;AACpBD,EAAAA,KAAAA,CAAMvE,WAAAA,GAAc,IAAA;AACpBuE,EAAAA,KAAAA,CAAME,MAAAA,GAAS,IAAA;AAEf3C,EAAAA,MAAAA,CAAOI,MAAM,0CAAA,CAAA;AACf;AAdsB8C,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA;;;AC5OtB,eAAsBG,oBAAgDV,MAAAA,EAAS;AAC7E,EAAA,IAAI;AACF,IAAA,MAAMW,KAAAA,GAAQC,KAAKC,GAAAA,EAAG;AACtB,IAAA,MAAMb,MAAAA,CAAOc,SAAAA,CAAAA,QAAAA,CAAAA;AACb,IAAA,MAAMC,OAAAA,GAAUH,IAAAA,CAAKC,GAAAA,EAAG,GAAKF,KAAAA;AAE7B,IAAA,OAAO;MAAEK,OAAAA,EAAS,IAAA;AAAMD,MAAAA;AAAQ,KAAA;AAClC,EAAA,CAAA,CAAA,OAASP,KAAAA,EAAO;AACd,IAAA,MAAMS,eAAeT,KAAAA,YAAiBrB,KAAAA,GAAQqB,KAAAA,CAAMU,OAAAA,GAAUC,OAAOX,KAAAA,CAAAA;AACrEnD,IAAAA,MAAAA,CAAOmD,MAAM,8BAAA,EAAgC;MAAEA,KAAAA,EAAOS;KAAa,CAAA;AAEnE,IAAA,OAAO;MACLD,OAAAA,EAAS,KAAA;MACTR,KAAAA,EAAOS;AACT,KAAA;AACF,EAAA;AACF;AAhBsBP,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAqBtB,eAAsBU,eAA2CpB,MAAAA,EAAS;AACxE,EAAA,IAAI;AACF,IAAA,MAAMA,MAAAA,CAAOc,SAAAA,CAAAA,QAAAA,CAAAA;AACb,IAAA,OAAO,IAAA;AACT,EAAA,CAAA,CAAA,OAASN,KAAAA,EAAO;AACdnD,IAAAA,MAAAA,CAAOmD,MAAM,iCAAA,EAAmC;AAC9CA,MAAAA,KAAAA,EAAOA,KAAAA,YAAiBrB,KAAAA,GAAQqB,KAAAA,CAAMU,OAAAA,GAAUC,OAAOX,KAAAA;KACzD,CAAA;AACA,IAAA,OAAO,KAAA;AACT,EAAA;AACF;AAVsBY,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AAetB,eAAsBC,mBAA+CrB,MAAAA,EAAS;AAC5E,EAAA,IAAI;AACF,IAAA,MAAMsB,MAAAA,GAAS,MAAMtB,MAAAA,CAAOc,SAAAA,CAAAA,gBAAAA,CAAAA;AAC5B,IAAA,OAAOQ,MAAAA,CAAO,CAAA,CAAA,EAAIC,OAAAA,IAAW,IAAA;AAC/B,EAAA,CAAA,CAAA,OAASf,KAAAA,EAAO;AACdnD,IAAAA,MAAAA,CAAOmD,MAAM,yCAAA,EAA2C;AACtDA,MAAAA,KAAAA,EAAOA,KAAAA,YAAiBrB,KAAAA,GAAQqB,KAAAA,CAAMU,OAAAA,GAAUC,OAAOX,KAAAA;KACzD,CAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA;AACF;AAVsBa,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;AAetB,eAAsBG,iBACpBxB,MAAAA,EAAS;AAMT,EAAA,MAAM,CAACyB,MAAAA,EAAQF,OAAAA,CAAAA,GAAW,MAAMG,QAAQC,GAAAA,CAAI;AAACjB,IAAAA,mBAAAA,CAAoBV,MAAAA,CAAAA;AAASqB,IAAAA,kBAAAA,CAAmBrB,MAAAA;AAAQ,GAAA,CAAA;AAErG,EAAA,OAAO;AACLyB,IAAAA,MAAAA;AACAF,IAAAA,OAAAA;AACAK,IAAAA,SAAAA,sBAAehB,IAAAA;AACjB,GAAA;AACF;AAdsBY,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;ACjDtB,IAAMK,SAAAA,GAAYC,aAAAA,CAAc,MAAA,CAAA,IAAA,CAAYC,GAAG,CAAA;AAiDxC,SAASC,oBAAoBC,mBAAAA,EAA2B;AAC7D,EAAA,IAAI;AAEF,IAAA,MAAMC,SAAAA,GAAYL,UAAUI,mBAAAA,CAAAA;AAC5B,IAAA,OAAOC,UAAUC,OAAAA,IAAWD,SAAAA;AAC9B,EAAA,CAAA,CAAA,OAAS1B,KAAAA,EAAO;AACdnD,IAAAA,MAAAA,CAAOmD,MAAM,0CAAA,EAA4C;AACvDA,MAAAA,KAAAA,EAAOA,KAAAA,YAAiBrB,KAAAA,GAAQqB,KAAAA,CAAMU,OAAAA,GAAUC,OAAOX,KAAAA,CAAAA;MACvD4B,IAAAA,EAAMH;KACR,CAAA;AACA,IAAA,MAAM,IAAI9C,KAAAA,CAAM,CAAA,qCAAA,EAAwC8C,mBAAAA,CAAAA,CAAqB,CAAA;AAC/E,EAAA;AACF;AAZgBD,MAAAA,CAAAA,mBAAAA,EAAAA,qBAAAA,CAAAA;AAiBT,SAASK,sBAAAA,CACdC,SAAAA,EACAC,cAAAA,EACAC,OAAAA,GAAkC,EAAC,EAAC;AAEpC,EAAA,MAAMC,WAAAA,GAAcF,eAAeD,SAAAA,CAAAA;AAEnC,EAAA,IAAI,CAACG,WAAAA,EAAa;AAChB,IAAA,MAAM,IAAItD,KAAAA,CACR,CAAA,OAAA,EAAUmD,SAAAA,CAAAA,mDAAAA,EACaI,MAAAA,CAAOC,IAAAA,CAAKJ,cAAAA,CAAAA,CAAgBK,IAAAA,CAAK,IAAA,CAAA,CAAA,CAAO,CAAA;AAEnE,EAAA;AAEA,EAAA,MAAM,EAAEC,aAAAA,GAAgB,IAAIC,gBAAAA,GAAmB,KAAA,EAAOC,cAAY,GAAKP,OAAAA;AAGvE,EAAA,IAAIQ,MAAAA,GAAS;OAAIP,WAAAA,CAAYO;;AAG7B,EAAA,IAAIF,gBAAAA,EAAkB;AACpBE,IAAAA,MAAAA,GAAS;AAAIA,MAAAA,GAAAA,MAAAA;SAAWP,WAAAA,CAAYQ;;AACtC,EAAA;AAGA,EAAA,MAAMC,WAAqB,EAAA;AAG3B,EAAA,IAAIL,aAAAA,CAAcM,SAAS,CAAA,EAAG;AAC5BH,IAAAA,MAAAA,GAASA,MAAAA,CAAOI,MAAAA,CAAO,CAACC,KAAAA,KAAAA;AACtB,MAAA,IAAIR,aAAAA,CAAcS,QAAAA,CAASD,KAAAA,CAAAA,EAAQ;AACjCH,QAAAA,QAAAA,CAASK,KAAKF,KAAAA,CAAAA;AACd,QAAA,OAAO,KAAA;AACT,MAAA;AACA,MAAA,OAAO,IAAA;IACT,CAAA,CAAA;AACF,EAAA;AAGA,EAAA,IAAIN,YAAAA,EAAc;AAChBC,IAAAA,MAAAA,GAASA,MAAAA,CAAOI,MAAAA,CAAO,CAACI,SAAAA,KAAAA;AACtB,MAAA,MAAMC,UAAAA,GAAahB,WAAAA,CAAYQ,SAAAA,CAAUK,QAAAA,CAASE,SAAAA,CAAAA;AAClD,MAAA,MAAME,gBAAgBX,YAAAA,CAAa;QACjClH,IAAAA,EAAM2H,SAAAA;QACNG,IAAAA,EAAM,SAAA;AACNF,QAAAA;OACF,CAAA;AAEA,MAAA,IAAI,CAACC,aAAAA,EAAe;AAClBR,QAAAA,QAAAA,CAASK,KAAKC,SAAAA,CAAAA;AAChB,MAAA;AAEA,MAAA,OAAOE,aAAAA;IACT,CAAA,CAAA;AACF,EAAA;AAEA,EAAA,OAAO;AACLV,IAAAA,MAAAA;IACAY,QAAAA,EAAU;AACRC,MAAAA,WAAAA,EAAapB,WAAAA,CAAYO,MAAAA,CAAOG,MAAAA,GAASV,WAAAA,CAAYQ,SAAAA,CAAUE,MAAAA;AAC/DW,MAAAA,aAAAA,EAAeZ,QAAAA,CAASC,MAAAA;MACxBY,cAAAA,EAAgBb,QAAAA;AAChBc,MAAAA,cAAAA,EAAgBvB,YAAYQ,SAAAA,CAAUE;AACxC;AACF,GAAA;AACF;AAjEgBd,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;AAsET,SAAS4B,cAAAA,CAAe3B,SAAAA,EAAmBC,cAAAA,EAAgCO,gBAAAA,GAAmB,KAAA,EAAK;AACxG,EAAA,MAAMxB,MAAAA,GAASe,sBAAAA,CAAuBC,SAAAA,EAAWC,cAAAA,EAAgB;AAAEO,IAAAA;GAAiB,CAAA;AACpF,EAAA,OAAOxB,MAAAA,CAAO0B,MAAAA;AAChB;AAHgBiB,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AAQT,SAASC,QAAAA,CAAS5B,WAAmBC,cAAAA,EAA8B;AACxE,EAAA,OAAOD,SAAAA,IAAaC,cAAAA;AACtB;AAFgB2B,MAAAA,CAAAA,QAAAA,EAAAA,UAAAA,CAAAA;AAOT,SAASC,iBAAiB5B,cAAAA,EAA8B;AAC7D,EAAA,OAAOG,MAAAA,CAAOC,KAAKJ,cAAAA,CAAAA;AACrB;AAFgB4B,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;;;AC1FT,SAASC,wBACdC,aAAAA,EAAoD;AAEpD,EAAA,IAAI,CAACA,aAAAA,EAAe;AAClB,IAAA,OAAOpG,MAAAA;AACT,EAAA;AAGA,EAAA,MAAMqG,aAAiC,EAAA;AAEvC,EAAA,IAAID,aAAAA,CAAcE,eAAe,IAAA,EAAM;AACrCD,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcE;KACxB,CAAA;AACF,EAAA;AAEA,EAAA,IAAIF,aAAAA,CAAcI,UAAU,IAAA,EAAM;AAChCH,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcI;KACxB,CAAA;AACF,EAAA;AAEA,EAAA,IAAIJ,aAAAA,CAAcK,aAAa,IAAA,EAAM;AACnCJ,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcK;KACxB,CAAA;AACF,EAAA;AAEA,EAAA,IAAIL,aAAAA,CAAcM,SAAS,IAAA,EAAM;AAC/BL,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcM;KACxB,CAAA;AACF,EAAA;AAEA,EAAA,IAAIN,aAAAA,CAAcO,aAAa,IAAA,EAAM;AACnCN,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcO;KACxB,CAAA;AACF,EAAA;AAEA,EAAA,IAAIP,aAAAA,CAAcQ,kBAAkB,IAAA,EAAM;AACxCP,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdnB,IAAAA,EAAM;AAAC,QAAA;;AACPoC,MAAAA,MAAAA,EAAQH,aAAAA,CAAcQ;KACxB,CAAA;AACF,EAAA;AAGA,EAAA,IAAIP,UAAAA,CAAWnB,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAOlF,MAAAA;AACT,EAAA;AAGA,EAAA,IAAIqG,UAAAA,CAAWnB,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAOmB,WAAW,CAAA,CAAA;AACpB,EAAA;AAIA,EAAA,OAAOA,WAAW,CAAA,CAAA;AACpB;AAjEgBF,MAAAA,CAAAA,uBAAAA,EAAAA,yBAAAA,CAAAA;AAsFT,SAASU,4BACdT,aAAAA,EAAoD;AAEpD,EAAA,IAAI,CAACA,aAAAA,EAAe;AAClB,IAAA,OAAO,EAAA;AACT,EAAA;AAEA,EAAA,MAAMC,aAAsC,EAAA;AAE5C,EAAA,IAAID,aAAAA,CAAcE,eAAe,IAAA,EAAM;AACrCD,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdwB,OAAAA,EAAS;QACP3C,IAAAA,EAAM;AAAC,UAAA;;AACPoC,QAAAA,MAAAA,EAAQH,aAAAA,CAAcE;AACxB;KACF,CAAA;AACF,EAAA;AAEA,EAAA,IAAIF,aAAAA,CAAcI,UAAU,IAAA,EAAM;AAChCH,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdwB,OAAAA,EAAS;QACP3C,IAAAA,EAAM;AAAC,UAAA;;AACPoC,QAAAA,MAAAA,EAAQH,aAAAA,CAAcI;AACxB;KACF,CAAA;AACF,EAAA;AAEA,EAAA,IAAIJ,aAAAA,CAAcK,aAAa,IAAA,EAAM;AACnCJ,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdwB,OAAAA,EAAS;QACP3C,IAAAA,EAAM;AAAC,UAAA;;AACPoC,QAAAA,MAAAA,EAAQH,aAAAA,CAAcK;AACxB;KACF,CAAA;AACF,EAAA;AAEA,EAAA,IAAIL,aAAAA,CAAcM,SAAS,IAAA,EAAM;AAC/BL,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdwB,OAAAA,EAAS;QACP3C,IAAAA,EAAM;AAAC,UAAA;;AACPoC,QAAAA,MAAAA,EAAQH,aAAAA,CAAcM;AACxB;KACF,CAAA;AACF,EAAA;AAEA,EAAA,IAAIN,aAAAA,CAAcO,aAAa,IAAA,EAAM;AAGnC,IAAA,MAAMI,KAAAA,GAAQC,mBAAAA,CAAoBZ,aAAAA,CAAcO,SAAS,CAAA;AACzD,IAAA,IAAII,KAAAA,CAAM7B,SAAS,CAAA,EAAG;AACpBmB,MAAAA,UAAAA,CAAWf,IAAAA,CAAK;QACd2B,EAAAA,EAAIF,KAAAA,CAAMG,GAAAA,CAAI,CAACC,IAAAA,MAAU;UAAEL,OAAAA,EAAS;YAAE3C,IAAAA,EAAM;AAAC,cAAA;;YAAcoC,MAAAA,EAAQY;AAAK;SAAE,CAAA;OAC5E,CAAA;IACF,CAAA,MAAO;AACLd,MAAAA,UAAAA,CAAWf,IAAAA,CAAK;QACdwB,OAAAA,EAAS;UACP3C,IAAAA,EAAM;AAAC,YAAA;;AACPoC,UAAAA,MAAAA,EAAQH,aAAAA,CAAcO;AACxB;OACF,CAAA;AACF,IAAA;AACF,EAAA;AAEA,EAAA,IAAIP,aAAAA,CAAcQ,kBAAkB,IAAA,EAAM;AACxCP,IAAAA,UAAAA,CAAWf,IAAAA,CAAK;MACdwB,OAAAA,EAAS;QACP3C,IAAAA,EAAM;AAAC,UAAA;;AACPoC,QAAAA,MAAAA,EAAQH,aAAAA,CAAcQ;AACxB;KACF,CAAA;AACF,EAAA;AAEA,EAAA,OAAOP,UAAAA;AACT;AAzEgBQ,MAAAA,CAAAA,2BAAAA,EAAAA,6BAAAA,CAAAA;AA6FT,SAASO,cAAcC,YAAAA,EAAiD;AAC7E,EAAA,IAAI,CAACA,YAAAA,EAAc;AACjB,IAAA,OAAOrH,MAAAA;AACT,EAAA;AAGA,EAAA,MAAM8G,UAA0C,EAAC;AAEjD,EAAA,IAAIO,YAAAA,CAAaf,eAAe,IAAA,EAAM;AACpCQ,IAAAA,OAAAA,CAAQ,aAAA,IAAiBO,YAAAA,CAAaf,WAAAA;AACxC,EAAA;AACA,EAAA,IAAIe,YAAAA,CAAab,UAAU,IAAA,EAAM;AAC/BM,IAAAA,OAAAA,CAAQ,QAAA,IAAYO,YAAAA,CAAab,MAAAA;AACnC,EAAA;AACA,EAAA,IAAIa,YAAAA,CAAaZ,aAAa,IAAA,EAAM;AAClCK,IAAAA,OAAAA,CAAQ,WAAA,IAAeO,YAAAA,CAAaZ,SAAAA;AACtC,EAAA;AACA,EAAA,IAAIY,YAAAA,CAAaX,SAAS,IAAA,EAAM;AAC9BI,IAAAA,OAAAA,CAAQ,OAAA,IAAWO,YAAAA,CAAaX,KAAAA;AAClC,EAAA;AACA,EAAA,IAAIW,YAAAA,CAAaV,aAAa,IAAA,EAAM;AAClCG,IAAAA,OAAAA,CAAQ,WAAA,IAAeO,YAAAA,CAAaV,SAAAA;AACtC,EAAA;AACA,EAAA,IAAIU,YAAAA,CAAaT,kBAAkB,IAAA,EAAM;AACvCE,IAAAA,OAAAA,CAAQ,gBAAA,IAAoBO,YAAAA,CAAaT,cAAAA;AAC3C,EAAA;AACA,EAAA,IAAIS,YAAAA,CAAaC,UAAU,IAAA,EAAM;AAC/BR,IAAAA,OAAAA,CAAQ,QAAA,IAAYO,YAAAA,CAAaC,MAAAA;AACnC,EAAA;AAGA,EAAA,IAAI7C,MAAAA,CAAOC,IAAAA,CAAKoC,OAAAA,CAAAA,CAAS5B,WAAW,CAAA,EAAG;AACrC,IAAA,OAAOlF,MAAAA;AACT,EAAA;AAEA,EAAA,OAAO8G,OAAAA;AACT;AApCgBM,MAAAA,CAAAA,aAAAA,EAAAA,eAAAA,CAAAA;AAyChB,SAASG,iBAAiBC,GAAAA,EAA4B;AACpD,EAAA,MAAMC,WAA2C,EAAC;AAClD,EAAA,KAAA,MAAW,CAACC,GAAAA,EAAKC,KAAAA,KAAUlD,MAAAA,CAAOmD,OAAAA,CAAQJ,GAAAA,CAAAA,EAAM;AAC9C,IAAA,IAAIG,UAAU,IAAA,EAAM;AAClBF,MAAAA,QAAAA,CAASC,GAAAA,CAAAA,GAAOC,KAAAA;AAClB,IAAA;AACF,EAAA;AACA,EAAA,OAAOF,QAAAA;AACT;AARSF,MAAAA,CAAAA,gBAAAA,EAAAA,kBAAAA,CAAAA;AAaT,SAASM,iBAAAA,CACPC,MAAAA,EACAvC,SAAAA,EACAwC,UAAAA,EAA+D;AAE/D,EAAA,IAAIA,eAAe/H,MAAAA,EAAW;AAC5B,IAAA;AACF,EAAA;AAEA,EAAA,IAAI+H,eAAe,IAAA,EAAM;AACvB,IAAA,OAAOD,OAAOvC,SAAAA,CAAAA;EAChB,CAAA,MAAO;AACLuC,IAAAA,MAAAA,CAAOvC,SAAAA,CAAAA,GAAawC,UAAAA;AACtB,EAAA;AACF;AAdSF,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAiCF,SAASG,YAAAA,CACdC,iBACAC,UAAAA,EAA+C;AAG/C,EAAA,IAAI,CAACA,UAAAA,EAAY;AACf,IAAA,IAAI,CAACD,eAAAA,EAAiB;AACpB,MAAA,OAAOjI,MAAAA;AACT,IAAA;AAEA,IAAA,IAAI,OAAOiI,eAAAA,KAAoB,QAAA,IAAY,CAACE,KAAAA,CAAMC,OAAAA,CAAQH,eAAAA,CAAAA,EAAkB;AAC1E,MAAA,MAAMR,QAAAA,GAAWF,iBAAiBU,eAAAA,CAAAA;AAClC,MAAA,OAAOxD,OAAOC,IAAAA,CAAK+C,QAAAA,CAAAA,CAAUvC,MAAAA,GAAS,IAAIuC,QAAAA,GAAWzH,MAAAA;AACvD,IAAA;AACA,IAAA,OAAOiI,eAAAA;AACT,EAAA;AAGA,EAAA,IAAI,CAACA,mBAAmB,OAAOA,eAAAA,KAAoB,YAAYE,KAAAA,CAAMC,OAAAA,CAAQH,eAAAA,CAAAA,EAAkB;AAC7F,IAAA,OAAOb,cAAcc,UAAAA,CAAAA;AACvB,EAAA;AAGA,EAAA,MAAMJ,MAAAA,GAASP,iBAAiBU,eAAAA,CAAAA;AAGhCJ,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,aAAA,EAAeI,UAAAA,CAAW5B,WAAW,CAAA;AAC/DuB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,QAAA,EAAUI,UAAAA,CAAW1B,MAAM,CAAA;AACrDqB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,WAAA,EAAaI,UAAAA,CAAWzB,SAAS,CAAA;AAC3DoB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,OAAA,EAASI,UAAAA,CAAWxB,KAAK,CAAA;AACnDmB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,WAAA,EAAaI,UAAAA,CAAWvB,SAAS,CAAA;AAC3DkB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,gBAAA,EAAkBI,UAAAA,CAAWtB,cAAc,CAAA;AACrEiB,EAAAA,iBAAAA,CAAkBC,MAAAA,EAAQ,QAAA,EAAUI,UAAAA,CAAWZ,MAAM,CAAA;AAErD,EAAA,OAAO7C,OAAOC,IAAAA,CAAKoD,MAAAA,CAAAA,CAAQ5C,MAAAA,GAAS,IAAI4C,MAAAA,GAAS9H,MAAAA;AACnD;AAnCgBgI,MAAAA,CAAAA,YAAAA,EAAAA,cAAAA,CAAAA;AAmDT,SAASK,aAAaC,WAAAA,EAAyC;AACpE,EAAA,IAAI,CAACA,eAAe,OAAOA,WAAAA,KAAgB,YAAYH,KAAAA,CAAMC,OAAAA,CAAQE,WAAAA,CAAAA,EAAc;AACjF,IAAA,OAAO,IAAA;AACT,EAAA;AAEA,EAAA,MAAMC,GAAAA,GAAMD,WAAAA;AAEZ,EAAA,OAAO;AACLhC,IAAAA,WAAAA,EAAa,OAAOiC,GAAAA,CAAI,aAAA,MAAmB,QAAA,GAAWA,GAAAA,CAAI,aAAA,CAAA,GAAiB,IAAA;AAC3E/B,IAAAA,MAAAA,EAAQ,OAAO+B,GAAAA,CAAI,QAAA,MAAc,QAAA,GAAWA,GAAAA,CAAI,QAAA,CAAA,GAAY,IAAA;AAC5D9B,IAAAA,SAAAA,EAAW,OAAO8B,GAAAA,CAAI,WAAA,MAAiB,QAAA,GAAWA,GAAAA,CAAI,WAAA,CAAA,GAAe,IAAA;AACrE7B,IAAAA,KAAAA,EAAO,OAAO6B,GAAAA,CAAI,OAAA,MAAa,QAAA,GAAWA,GAAAA,CAAI,OAAA,CAAA,GAAW,IAAA;AACzD5B,IAAAA,SAAAA,EAAW,OAAO4B,GAAAA,CAAI,WAAA,MAAiB,QAAA,GAAWA,GAAAA,CAAI,WAAA,CAAA,GAAe,IAAA;AACrE3B,IAAAA,cAAAA,EAAgB,OAAO2B,GAAAA,CAAI,gBAAA,MAAsB,QAAA,GAAWA,GAAAA,CAAI,gBAAA,CAAA,GAAoB,IAAA;AACpFjB,IAAAA,MAAAA,EAAQ,OAAOiB,GAAAA,CAAI,QAAA,MAAc,QAAA,GAAYA,GAAAA,CAAI,QAAA,CAAA,GAAwC;AAC3F,GAAA;AACF;AAhBgBF,MAAAA,CAAAA,YAAAA,EAAAA,cAAAA,CAAAA;AAyBT,SAASG,cAAAA,CAAe1B,SAA8C3B,MAAAA,EAA0B;AACrG,EAAA,IAAI,CAAC2B,OAAAA,EAAS;AACZ,IAAA,OAAO,KAAA;AACT,EAAA;AAEA,EAAA,IAAI3B,OAAOmB,WAAAA,IAAe,IAAA,IAAQQ,OAAAA,CAAQR,WAAAA,KAAgBnB,OAAOmB,WAAAA,EAAa;AAC5E,IAAA,OAAO,KAAA;AACT,EAAA;AACA,EAAA,IAAInB,OAAOqB,MAAAA,IAAU,IAAA,IAAQM,OAAAA,CAAQN,MAAAA,KAAWrB,OAAOqB,MAAAA,EAAQ;AAC7D,IAAA,OAAO,KAAA;AACT,EAAA;AACA,EAAA,IAAIrB,OAAOsB,SAAAA,IAAa,IAAA,IAAQK,OAAAA,CAAQL,SAAAA,KAActB,OAAOsB,SAAAA,EAAW;AACtE,IAAA,OAAO,KAAA;AACT,EAAA;AACA,EAAA,IAAItB,OAAOuB,KAAAA,IAAS,IAAA,IAAQI,OAAAA,CAAQJ,KAAAA,KAAUvB,OAAOuB,KAAAA,EAAO;AAC1D,IAAA,OAAO,KAAA;AACT,EAAA;AAEA,EAAA,IAAIvB,MAAAA,CAAOwB,aAAa,IAAA,IAAQ,CAAC8B,kBAAkB3B,OAAAA,CAAQH,SAAAA,EAAWxB,MAAAA,CAAOwB,SAAS,CAAA,EAAG;AACvF,IAAA,OAAO,KAAA;AACT,EAAA;AACA,EAAA,IAAIxB,OAAOyB,cAAAA,IAAkB,IAAA,IAAQE,OAAAA,CAAQF,cAAAA,KAAmBzB,OAAOyB,cAAAA,EAAgB;AACrF,IAAA,OAAO,KAAA;AACT,EAAA;AAEA,EAAA,OAAO,IAAA;AACT;AA1BgB4B,MAAAA,CAAAA,cAAAA,EAAAA,gBAAAA,CAAAA;AAkCT,SAASE,qBAAqBC,UAAAA,EAOpC;AACC,EAAA,OAAO;AACLrC,IAAAA,WAAAA,EAAaqC,WAAWrC,WAAAA,IAAe,IAAA;AACvCE,IAAAA,MAAAA,EAAQmC,WAAWnC,MAAAA,IAAU,IAAA;AAC7BC,IAAAA,SAAAA,EAAWkC,WAAWlC,SAAAA,IAAa,IAAA;AACnCC,IAAAA,KAAAA,EAAOiC,WAAWjC,KAAAA,IAAS,IAAA;AAC3BC,IAAAA,SAAAA,EAAWgC,WAAWhC,SAAAA,IAAa,IAAA;AACnCC,IAAAA,cAAAA,EAAgB+B,WAAW/B,cAAAA,IAAkB;AAC/C,GAAA;AACF;AAhBgB8B,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA","file":"chunk-LNFGZMDB.js","sourcesContent":["/**\n * Prisma Module for Burdenoff Backend SDK\n *\n * Provides Prisma 7 utilities including:\n * - Singleton database manager for microservices\n * - Unified database client factory with graph extension\n * - Prisma client configuration with PostgreSQL adapter\n * - Connection pooling and management\n * - Health checks and monitoring\n * - Graceful shutdown handling\n * - Field extraction utilities for graph sync\n * - Context filtering utilities for multi-tenant queries\n * - Workspace extension for automatic workspaceId injection\n *\n * @module prisma\n * @category Database\n */\n\nexport * from './manager.js';\nexport * from './factory.js';\nexport * from './client.js';\nexport type * from './types.js';\nexport * from './health.js';\nexport * from './fields.js';\nexport * from './context.js';\nexport * from './workspace-extension.js';\n","/**\n * Database Client Factory\n *\n * Provides a unified factory for creating fully-configured database clients\n * with Prisma 7, PostgreSQL adapter, graph extension, and graceful shutdown.\n *\n * This module consolidates all database setup into a single call, reducing\n * boilerplate across all backend services.\n *\n * @module prisma/factory\n * @category Database\n */\n\nimport { logger } from '../logger/index.js';\nimport {\n createPrismaClient,\n ensureServiceApplicationName,\n type PrismaClientBase,\n type PrismaClientWrapper,\n type PrismaClientConstructorOptions,\n} from './client.js';\nimport type { PrismaClientConfig } from './types.js';\nimport { addGraphExtension, type GraphMiddlewareConfig, type GraphEventEmitter } from '../graph/middleware/index.js';\nimport { getGraphEventEmitter } from '../event-queue/graph-emitter.js';\nimport { addWorkspaceExtension, type WorkspaceExtensionConfig } from './workspace-extension.js';\n\n/**\n * Configuration for creating a database client\n */\nexport interface DatabaseClientConfig extends PrismaClientConfig {\n /**\n * Product name for graph events (e.g., 'module-tags', 'workspaces')\n */\n productName: string;\n\n /**\n * Enable graph extension for entity sync\n * @default true (reads from GRAPH_MIDDLEWARE_ENABLED env var)\n */\n enableGraphExtension?: boolean;\n\n /**\n * Custom graph event emitter (defaults to NATS-based emitter)\n */\n graphEventEmitter?: GraphEventEmitter;\n\n /**\n * Enable workspace extension for automatic workspaceId injection.\n *\n * Default is layer-aware:\n * - Global-layer services (`productName` starting with `global-` or `global_`,\n * or `WORKSPACE_LAYER=global`) default to `false`. Global-layer tables\n * (Tenant, Organization, Workspace, PlatformProduct, etc.) are intentionally\n * not workspace-scoped — enforcing workspaceId on them would block legitimate\n * queries like `myOrganizations`, `myWorkspaces`, `myAccessibleProducts`.\n * - All other services (wspace layer, product backends) default to `true`.\n *\n * `WORKSPACE_EXTENSION_ENABLED` env var always wins when explicitly set\n * (`true` or `false`). Pass the field on `config` for code-level override.\n */\n enableWorkspaceExtension?: boolean;\n\n /**\n * Configuration for the workspace extension\n */\n workspaceExtensionConfig?: WorkspaceExtensionConfig;\n\n /**\n * Register process shutdown handlers for graceful shutdown\n * @default true\n */\n registerShutdownHandlers?: boolean;\n}\n\n/**\n * Result of creating a database client\n */\nexport interface DatabaseClient<T extends PrismaClientBase> {\n /**\n * The extended Prisma client for database operations\n * Use this for all queries: db.model.operation()\n */\n db: T & { client: T };\n\n /**\n * The Prisma client wrapper with connection management utilities\n */\n wrapper: PrismaClientWrapper<T>;\n\n /**\n * Connect to the database with retry logic\n */\n connect: (retries?: number, delay?: number) => Promise<void>;\n\n /**\n * Disconnect from the database\n */\n disconnect: () => Promise<void>;\n}\n\n/**\n * Layer-aware default for the workspace extension.\n *\n * Global-layer services (productName starting with `global-`/`global_`, or\n * `WORKSPACE_LAYER=global`) opt out by default because their tables don't carry\n * a workspaceId column — enforcement would break queries like `myOrganizations`,\n * `myAccessibleProducts`, `contentPages`.\n *\n * `WORKSPACE_EXTENSION_ENABLED` is respected as an explicit override.\n */\nfunction resolveWorkspaceExtensionDefault(productName: string): boolean {\n const explicit = process.env['WORKSPACE_EXTENSION_ENABLED'];\n if (explicit === 'true') return true;\n if (explicit === 'false') return false;\n\n const layer = process.env['WORKSPACE_LAYER']?.toLowerCase();\n if (layer === 'global') return false;\n if (layer === 'wspace') return true;\n\n const name = productName.toLowerCase();\n if (name.startsWith('global-') || name.startsWith('global_')) return false;\n return true;\n}\n\n/**\n * Create a fully-configured database client with graph extension\n *\n * This is the recommended way to create a database connection in all backend services.\n * It handles:\n * - Prisma client creation with PostgreSQL adapter\n * - Connection pooling configuration\n * - Query logging (in development)\n * - Graph extension for entity sync (via NATS or in-memory)\n * - Graceful shutdown handlers\n *\n * @example\n * ```typescript\n * // In your service's db.ts\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createDatabaseClient } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, wrapper, connect, disconnect } = createDatabaseClient(PrismaClient, {\n * productName: 'my-service',\n * databaseUrl: process.env.DATABASE_URL!,\n * });\n *\n * export { db, wrapper, connect, disconnect };\n * export type ExtendedPrismaClient = typeof db;\n * ```\n *\n * @example\n * ```typescript\n * // With custom configuration\n * const { db } = createDatabaseClient(PrismaClient, {\n * productName: 'workspaces',\n * databaseUrl: process.env.DATABASE_URL!,\n * maxConnections: 50,\n * enableQueryLogging: true,\n * slowQueryThreshold: 200,\n * enableGraphExtension: true,\n * registerShutdownHandlers: true,\n * });\n * ```\n */\nexport function createDatabaseClient<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: DatabaseClientConfig\n): DatabaseClient<T> {\n const {\n productName,\n enableGraphExtension = process.env['GRAPH_MIDDLEWARE_ENABLED'] !== 'false',\n graphEventEmitter,\n enableWorkspaceExtension = resolveWorkspaceExtensionDefault(productName),\n workspaceExtensionConfig,\n registerShutdownHandlers = true,\n ...prismaConfig\n } = config;\n\n // Tag every service's pool with `svc=<productName>` by default so its\n // connections are attributable in pg_stat_activity / pg_stat_statements\n // (the on-ramp to per-workspace observability and shard routing). This is\n // pure diagnostic metadata with no effect on behavior; explicit\n // `applicationName` on the config always wins.\n const prismaConfigWithDefaults: PrismaClientConfig = {\n ...prismaConfig,\n applicationName: prismaConfig.applicationName ?? `svc=${productName}`,\n };\n\n // Belt-and-suspenders: also set the PGAPPNAME env fallback so any additional\n // pools this service opens outside be-sdk still carry the per-service tag.\n ensureServiceApplicationName(productName);\n\n // Create Prisma client wrapper\n const wrapper = createPrismaClient(PrismaClientConstructor, prismaConfigWithDefaults);\n\n // Get the base client\n const baseClient = wrapper.getClient();\n\n // Extension chaining order:\n // 1. Graph extension (event emission on CRUD) - runs first\n // 2. Workspace extension (auto-inject workspaceId) - runs second\n //\n // The workspace extension should run BEFORE graph extension in the\n // interception chain so that graph events include the injected workspaceId.\n // In Prisma $extends, the LAST extension added runs FIRST (outermost wrapper).\n // So we add graph first, then workspace on top.\n\n let extendedClient: T;\n\n // Step 1: Add graph extension\n if (enableGraphExtension) {\n const eventEmitter = graphEventEmitter ?? getGraphEventEmitter();\n\n const graphConfig: GraphMiddlewareConfig = {\n enabled: true,\n productName,\n eventEmitter,\n };\n\n extendedClient = addGraphExtension(baseClient, graphConfig);\n\n logger.info('[Database] Graph extension enabled', { productName });\n } else {\n extendedClient = baseClient;\n logger.info('[Database] Graph extension disabled');\n }\n\n // Step 2: Add workspace extension (wraps on top of graph)\n if (enableWorkspaceExtension) {\n extendedClient = addWorkspaceExtension(extendedClient, workspaceExtensionConfig);\n\n logger.info('[Database] Workspace extension enabled', { productName });\n } else {\n logger.info('[Database] Workspace extension disabled');\n }\n\n // Add backwards compatibility alias\n const db = extendedClient as T & { client: T };\n (db as unknown as Record<string, unknown>)['client'] = db;\n\n // Register shutdown handlers if requested\n if (registerShutdownHandlers) {\n wrapper.registerShutdownHandlers();\n logger.debug('[Database] Shutdown handlers registered');\n }\n\n return {\n db,\n wrapper,\n connect: (retries?: number, delay?: number) => wrapper.connect(retries, delay),\n disconnect: () => wrapper.disconnect(),\n };\n}\n\n/**\n * Pool-tuning options resolved from environment variables.\n */\nexport interface PoolTuningEnv {\n /** Postgres application_name (defaults to `svc=<productName>`). */\n applicationName: string;\n /** Client-side node-postgres query_timeout in ms, if opted in (pooler-safe). */\n queryTimeoutMillis?: number;\n /** Server-side statement_timeout in ms, if opted in. */\n statementTimeoutMillis?: number;\n /** Server-side idle_in_transaction_session_timeout in ms, if opted in. */\n idleInTransactionTimeoutMillis?: number;\n /** Server-side lock_timeout in ms, if opted in. */\n lockTimeoutMillis?: number;\n}\n\n/**\n * Parse a strictly-positive integer environment variable.\n *\n * Returns `undefined` for unset, empty, non-numeric, zero, or negative values —\n * so a misconfigured or absent env var can never silently enable an aggressive\n * (or nonsensical) timeout. This is what keeps the DB-enforced timeouts OFF by\n * default and therefore behavior-preserving.\n */\nfunction parsePositiveIntEnv(name: string): number | undefined {\n const raw = process.env[name];\n if (raw == null || raw.trim() === '') {\n return undefined;\n }\n const parsed = Number.parseInt(raw.trim(), 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\n\n/**\n * Resolve pool tuning (application_name + opt-in DB timeouts) from env vars:\n * - DATABASE_APPLICATION_NAME: overrides the default `svc=<productName>` tag\n * - DATABASE_QUERY_TIMEOUT: client-side node-postgres query_timeout in ms (opt-in, pooler-safe)\n * - DATABASE_STATEMENT_TIMEOUT: server-side statement_timeout in ms (opt-in; DIRECT :5432 only — see note)\n * - DATABASE_IDLE_IN_TRANSACTION_TIMEOUT: idle_in_transaction_session_timeout in ms (opt-in)\n * - DATABASE_LOCK_TIMEOUT: lock_timeout in ms (opt-in)\n *\n * Timeouts are omitted entirely unless explicitly set to a positive integer, so\n * the default is exactly today's behavior (no timeouts).\n *\n * NOTE: prefer `DATABASE_QUERY_TIMEOUT` for services whose `DATABASE_URL` points\n * at the built-in PgBouncer (`:6432`). `DATABASE_STATEMENT_TIMEOUT` and friends\n * are Postgres startup parameters that Azure PgBouncer does not pass through, so\n * they silently have no effect (or fail the connection) on the pooled path.\n */\nexport function resolvePoolTuningFromEnv(productName: string): PoolTuningEnv {\n const tuning: PoolTuningEnv = {\n applicationName: process.env['DATABASE_APPLICATION_NAME']?.trim() || `svc=${productName}`,\n };\n\n const queryTimeout = parsePositiveIntEnv('DATABASE_QUERY_TIMEOUT');\n if (queryTimeout !== undefined) {\n tuning.queryTimeoutMillis = queryTimeout;\n }\n\n const statementTimeout = parsePositiveIntEnv('DATABASE_STATEMENT_TIMEOUT');\n if (statementTimeout !== undefined) {\n tuning.statementTimeoutMillis = statementTimeout;\n }\n\n const idleInTransactionTimeout = parsePositiveIntEnv('DATABASE_IDLE_IN_TRANSACTION_TIMEOUT');\n if (idleInTransactionTimeout !== undefined) {\n tuning.idleInTransactionTimeoutMillis = idleInTransactionTimeout;\n }\n\n const lockTimeout = parsePositiveIntEnv('DATABASE_LOCK_TIMEOUT');\n if (lockTimeout !== undefined) {\n tuning.lockTimeoutMillis = lockTimeout;\n }\n\n return tuning;\n}\n\n/**\n * Create a database client from environment variables\n *\n * Convenience function that reads configuration from standard environment variables:\n * - DATABASE_URL: Connection string (required)\n * - DATABASE_MAX_CONNECTIONS: Max pool connections (default: 20)\n * - DATABASE_APPLICATION_NAME: Postgres application_name (default: `svc=<productName>`)\n * - DATABASE_QUERY_TIMEOUT: opt-in client-side query timeout in ms — the\n * PgBouncer-safe query bound (default: OFF, preserving current behavior)\n * - DATABASE_STATEMENT_TIMEOUT / DATABASE_IDLE_IN_TRANSACTION_TIMEOUT / DATABASE_LOCK_TIMEOUT:\n * opt-in server-side timeouts in ms (default: OFF; DIRECT :5432 only — not\n * honored through the built-in PgBouncer :6432 runtime path)\n * - NODE_ENV: Environment for logging settings\n * - GRAPH_MIDDLEWARE_ENABLED: Enable graph sync (default: true)\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { createDatabaseClientFromEnv } from '@burdenoff/be-sdk/prisma';\n *\n * const { db } = createDatabaseClientFromEnv(PrismaClient, 'module-tags');\n * export { db };\n * ```\n */\nexport function createDatabaseClientFromEnv<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n productName: string,\n overrides?: Partial<DatabaseClientConfig>\n): DatabaseClient<T> {\n const databaseUrl = process.env['DATABASE_URL'];\n if (!databaseUrl) {\n throw new Error('DATABASE_URL environment variable is required');\n }\n\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n\n const config: DatabaseClientConfig = {\n productName,\n databaseUrl,\n maxConnections: parseInt(process.env['DATABASE_MAX_CONNECTIONS'] || '20', 10),\n idleTimeoutMillis: parseInt(process.env['DATABASE_IDLE_TIMEOUT'] || '30000', 10),\n connectionTimeoutMillis: parseInt(process.env['DATABASE_CONNECTION_TIMEOUT'] || '10000', 10),\n ...resolvePoolTuningFromEnv(productName),\n enableQueryLogging: isDevelopment,\n slowQueryThreshold: isDevelopment ? 100 : 500,\n ...overrides,\n };\n\n // Transient acquire retry — env-tunable, and unlike the fields above zero is\n // meaningful (DATABASE_ACQUIRE_RETRIES=0 disables the retry entirely).\n const acquireRetriesRaw = process.env['DATABASE_ACQUIRE_RETRIES']?.trim();\n if (acquireRetriesRaw !== undefined && acquireRetriesRaw !== '' && config.acquireRetries === undefined) {\n const parsed = Number.parseInt(acquireRetriesRaw, 10);\n if (Number.isFinite(parsed) && parsed >= 0) {\n config.acquireRetries = parsed;\n }\n }\n const acquireRetryDelay = parsePositiveIntEnv('DATABASE_ACQUIRE_RETRY_DELAY');\n if (acquireRetryDelay !== undefined && config.acquireRetryDelayMillis === undefined) {\n config.acquireRetryDelayMillis = acquireRetryDelay;\n }\n\n return createDatabaseClient(PrismaClientConstructor, config);\n}\n","/**\n * Database Singleton Manager\n *\n * Provides a singleton pattern for database connections across microservices.\n * Services initialize once at startup and access the db instance globally.\n *\n * This eliminates the need for individual db.ts files in each microservice.\n *\n * @module prisma/manager\n * @category Database\n *\n * @example\n * ```typescript\n * // In your service's index.ts (startup)\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { initializeDatabase } from '@burdenoff/be-sdk/prisma';\n *\n * // Initialize once at startup\n * const { db, connect } = initializeDatabase(PrismaClient, 'module-tags');\n * await connect();\n *\n * // In any other file\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n * const db = getDb();\n * await db.client.user.findMany();\n * ```\n */\n\nimport { logger } from '../logger/index.js';\nimport {\n createDatabaseClient,\n createDatabaseClientFromEnv,\n type DatabaseClient,\n type DatabaseClientConfig,\n} from './factory.js';\nimport type { PrismaClientBase, PrismaClientConstructorOptions, DatabaseReturnType } from './client.js';\n\n/**\n * Global database manager state\n */\ninterface DatabaseManagerState {\n initialized: boolean;\n productName: string | null;\n client: DatabaseClient<PrismaClientBase> | null;\n}\n\n/**\n * Singleton state for the database manager\n */\nconst state: DatabaseManagerState = {\n initialized: false,\n productName: null,\n client: null,\n};\n\n/**\n * Initialize the database singleton\n *\n * Call this once at application startup with your service's PrismaClient.\n * After initialization, use `getDb()` to access the database anywhere.\n *\n * @param PrismaClientConstructor - The generated PrismaClient class from your service\n * @param productName - Product name for graph events (e.g., 'module-tags', 'workspaces')\n * @param config - Optional configuration overrides\n * @returns The database client with db, wrapper, connect, disconnect\n *\n * @throws Error if already initialized with a different product\n *\n * @example\n * ```typescript\n * import { PrismaClient } from './generated/prisma/client.js';\n * import { initializeDatabase } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, connect, disconnect } = initializeDatabase(PrismaClient, 'module-tags');\n * await connect();\n * ```\n */\nexport function initializeDatabase<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n productName: string,\n config?: Partial<DatabaseClientConfig>\n): DatabaseClient<T> {\n // Check if already initialized\n if (state.initialized) {\n if (state.productName !== productName) {\n throw new Error(\n `Database already initialized for product \"${state.productName}\". ` +\n `Cannot reinitialize for \"${productName}\".`\n );\n }\n logger.debug('[DatabaseManager] Already initialized, returning existing client', { productName });\n return state.client as DatabaseClient<T>;\n }\n\n // Create the database client using env-based factory\n const client = createDatabaseClientFromEnv(PrismaClientConstructor, productName, config);\n\n // Store in singleton state\n state.initialized = true;\n state.productName = productName;\n state.client = client;\n\n logger.info('[DatabaseManager] Database initialized', { productName });\n\n return client;\n}\n\n/**\n * Initialize the database with explicit configuration\n *\n * Use this when you need full control over database configuration\n * rather than reading from environment variables.\n *\n * @param PrismaClientConstructor - The generated PrismaClient class\n * @param config - Full database configuration\n * @returns The database client\n *\n * @example\n * ```typescript\n * const { db } = initializeDatabaseWithConfig(PrismaClient, {\n * productName: 'module-tags',\n * databaseUrl: 'postgresql://...',\n * maxConnections: 50,\n * enableGraphExtension: false,\n * });\n * ```\n */\nexport function initializeDatabaseWithConfig<T extends PrismaClientBase>(\n PrismaClientConstructor: new (options: PrismaClientConstructorOptions) => T,\n config: DatabaseClientConfig\n): DatabaseClient<T> {\n const { productName } = config;\n\n // Check if already initialized\n if (state.initialized) {\n if (state.productName !== productName) {\n throw new Error(\n `Database already initialized for product \"${state.productName}\". ` +\n `Cannot reinitialize for \"${productName}\".`\n );\n }\n logger.debug('[DatabaseManager] Already initialized, returning existing client', { productName });\n return state.client as DatabaseClient<T>;\n }\n\n // Create the database client\n const client = createDatabaseClient(PrismaClientConstructor, config);\n\n // Store in singleton state\n state.initialized = true;\n state.productName = productName;\n state.client = client;\n\n logger.info('[DatabaseManager] Database initialized with custom config', { productName });\n\n return client;\n}\n\n/**\n * Get the initialized database client\n *\n * Use this anywhere in your application to access the database.\n * Must call `initializeDatabase()` first at application startup.\n *\n * The returned client provides dynamic model access - you can access any\n * model property (e.g., `db.client.user`, `db.client.universalTag`) and\n * TypeScript will allow common Prisma operations (findMany, create, etc.).\n *\n * @returns The extended Prisma client (db) with dynamic model access\n * @throws Error if database not initialized\n *\n * @example\n * ```typescript\n * import { getDb } from '@burdenoff/be-sdk/prisma';\n *\n * const db = getDb();\n * // Dynamic model access works without importing service-specific types\n * const tags = await db.client.universalTag.findMany();\n * const users = await db.client.user.findMany({ where: { active: true } });\n * ```\n */\nexport function getDb<T extends PrismaClientBase = PrismaClientBase>(): DatabaseReturnType<T> {\n if (!state.initialized || !state.client) {\n throw new Error('Database not initialized. Call initializeDatabase() at application startup before using getDb().');\n }\n return state.client.db as unknown as DatabaseReturnType<T>;\n}\n\n/**\n * Get the full database manager\n *\n * Returns the complete database client including wrapper, connect, and disconnect functions.\n * Useful when you need access to connection management utilities.\n *\n * @returns The full database client\n * @throws Error if database not initialized\n *\n * @example\n * ```typescript\n * import { getDatabaseManager } from '@burdenoff/be-sdk/prisma';\n *\n * const { db, wrapper, connect, disconnect } = getDatabaseManager();\n * await connect();\n * ```\n */\nexport function getDatabaseManager<T extends PrismaClientBase = PrismaClientBase>(): DatabaseClient<T> {\n if (!state.initialized || !state.client) {\n throw new Error(\n 'Database not initialized. Call initializeDatabase() at application startup before using getDatabaseManager().'\n );\n }\n return state.client as DatabaseClient<T>;\n}\n\n/**\n * Check if database is initialized\n *\n * @returns True if database has been initialized\n *\n * @example\n * ```typescript\n * if (!isDatabaseInitialized()) {\n * await initializeDatabase(PrismaClient, 'my-service');\n * }\n * ```\n */\nexport function isDatabaseInitialized(): boolean {\n return state.initialized;\n}\n\n/**\n * Get the product name of the initialized database\n *\n * @returns The product name or null if not initialized\n */\nexport function getDatabaseProductName(): string | null {\n return state.productName;\n}\n\n/**\n * Reset the database manager (for testing purposes only)\n *\n * WARNING: This disconnects and resets the database manager.\n * Only use this in test environments for cleanup between tests.\n *\n * @internal\n */\nexport async function resetDatabaseManager(): Promise<void> {\n if (state.client) {\n try {\n await state.client.disconnect();\n } catch (error) {\n logger.warn('[DatabaseManager] Error during disconnect on reset', { error });\n }\n }\n\n state.initialized = false;\n state.productName = null;\n state.client = null;\n\n logger.debug('[DatabaseManager] Database manager reset');\n}\n","/**\n * Prisma Health Check Utilities\n */\n\nimport { logger } from '../logger/index.js';\nimport type { DatabaseHealth } from './types.js';\nimport type { PrismaClientBase } from './client.js';\n\n/**\n * Check database health\n */\nexport async function checkDatabaseHealth<T extends PrismaClientBase>(client: T): Promise<DatabaseHealth> {\n try {\n const start = Date.now();\n await client.$queryRaw`SELECT 1`;\n const latency = Date.now() - start;\n\n return { healthy: true, latency };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error('[Prisma] Health check failed', { error: errorMessage });\n\n return {\n healthy: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * Test database connection\n */\nexport async function testConnection<T extends PrismaClientBase>(client: T): Promise<boolean> {\n try {\n await client.$queryRaw`SELECT 1`;\n return true;\n } catch (error) {\n logger.error('[Prisma] Connection test failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n return false;\n }\n}\n\n/**\n * Get database version\n */\nexport async function getDatabaseVersion<T extends PrismaClientBase>(client: T): Promise<string | null> {\n try {\n const result = await client.$queryRaw<Array<{ version?: string }>>`SELECT version()`;\n return result[0]?.version ?? null;\n } catch (error) {\n logger.error('[Prisma] Failed to get database version', {\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n}\n\n/**\n * Get database stats\n */\nexport async function getDatabaseStats<T extends PrismaClientBase>(\n client: T\n): Promise<{\n health: DatabaseHealth;\n version: string | null;\n timestamp: Date;\n}> {\n const [health, version] = await Promise.all([checkDatabaseHealth(client), getDatabaseVersion(client)]);\n\n return {\n health,\n version,\n timestamp: new Date(),\n };\n}\n","/**\n * Prisma Field Extraction Utilities\n *\n * Provides utilities for extracting model fields from Prisma schema.\n * In Prisma 7, DMMF is not available at runtime, so this module provides\n * build-time field extraction through a generator.\n *\n * @module prisma/fields\n */\n\nimport { createRequire } from 'node:module';\nimport { logger } from '../logger/index.js';\n\nconst requireFn = createRequire(import.meta.url);\n\n/**\n * Field extraction options\n */\nexport interface FieldExtractionOptions {\n /** Fields to exclude from extraction */\n excludeFields?: string[];\n /** Whether to include relation fields */\n includeRelations?: boolean;\n /** Custom filter function */\n customFilter?: (field: { name: string; type: string; isRelation: boolean }) => boolean;\n}\n\n/**\n * Field extraction result\n */\nexport interface FieldExtractionResult {\n /** Extracted field names */\n fields: string[];\n /** Metadata about the extraction */\n metadata: {\n /** Total number of fields found */\n totalFields: number;\n /** Number of fields excluded */\n excludedCount: number;\n /** Names of excluded fields */\n excludedFields: string[];\n /** Number of relation fields */\n relationFields: number;\n };\n}\n\n/**\n * Model fields mapping\n * This will be generated at build time by the Prisma generator\n */\nexport type ModelFieldsMap = Record<\n string,\n {\n fields: string[];\n relations: string[];\n }\n>;\n\n/**\n * Import generated fields from the consuming package\n * This function should be used by backends to load their generated fields\n */\nexport function loadGeneratedFields(generatedFieldsPath: string): ModelFieldsMap {\n try {\n // Dynamic import of generated fields using createRequire\n const generated = requireFn(generatedFieldsPath) as { default: ModelFieldsMap };\n return generated.default || generated;\n } catch (error) {\n logger.error('[Prisma] Failed to load generated fields', {\n error: error instanceof Error ? error.message : String(error),\n path: generatedFieldsPath,\n });\n throw new Error(`Failed to load generated fields from ${generatedFieldsPath}`);\n }\n}\n\n/**\n * Extract fields from generated model fields with options\n */\nexport function extractFieldsFromModel(\n modelName: string,\n modelFieldsMap: ModelFieldsMap,\n options: FieldExtractionOptions = {}\n): FieldExtractionResult {\n const modelFields = modelFieldsMap[modelName];\n\n if (!modelFields) {\n throw new Error(\n `Model \"${modelName}\" not found in generated fields. ` +\n `Available models: ${Object.keys(modelFieldsMap).join(', ')}`\n );\n }\n\n const { excludeFields = [], includeRelations = false, customFilter } = options;\n\n // Start with scalar fields\n let fields = [...modelFields.fields];\n\n // Add relations if requested\n if (includeRelations) {\n fields = [...fields, ...modelFields.relations];\n }\n\n // Track excluded fields\n const excluded: string[] = [];\n\n // Apply exclusions\n if (excludeFields.length > 0) {\n fields = fields.filter((field) => {\n if (excludeFields.includes(field)) {\n excluded.push(field);\n return false;\n }\n return true;\n });\n }\n\n // Apply custom filter\n if (customFilter) {\n fields = fields.filter((fieldName) => {\n const isRelation = modelFields.relations.includes(fieldName);\n const shouldInclude = customFilter({\n name: fieldName,\n type: 'unknown', // Type information not available without full DMMF\n isRelation,\n });\n\n if (!shouldInclude) {\n excluded.push(fieldName);\n }\n\n return shouldInclude;\n });\n }\n\n return {\n fields,\n metadata: {\n totalFields: modelFields.fields.length + modelFields.relations.length,\n excludedCount: excluded.length,\n excludedFields: excluded,\n relationFields: modelFields.relations.length,\n },\n };\n}\n\n/**\n * Get all field names for a model (without options)\n */\nexport function getModelFields(modelName: string, modelFieldsMap: ModelFieldsMap, includeRelations = false): string[] {\n const result = extractFieldsFromModel(modelName, modelFieldsMap, { includeRelations });\n return result.fields;\n}\n\n/**\n * Check if a model exists in the generated fields\n */\nexport function hasModel(modelName: string, modelFieldsMap: ModelFieldsMap): boolean {\n return modelName in modelFieldsMap;\n}\n\n/**\n * Get all available model names\n */\nexport function getAllModelNames(modelFieldsMap: ModelFieldsMap): string[] {\n return Object.keys(modelFieldsMap);\n}\n","/**\n * Prisma Context Filtering Utilities\n *\n * Utilities for handling operation context in queries, mutations, and filtering.\n * Context JSON enables multi-dimensional data isolation across workspaces, users, projects, etc.\n *\n * @module prisma/context\n * @category Database\n */\n\nimport { isSameProductSlug, productSlugVariants } from '../product-alias/index.js';\n\n/**\n * Context filter input for querying entities by context\n */\nexport interface ContextFilterInput {\n workspaceId?: string | null;\n userId?: string | null;\n projectId?: string | null;\n appId?: string | null;\n /** Product identifier (e.g. \"vibecontrols\", \"workspaces\"). Stamped on cross-product\n * records so admin filters can scope by originating product. */\n productId?: string | null;\n /** Organization identifier within the tenant. */\n organizationId?: string | null;\n}\n\n/**\n * Operation context for create/update operations\n */\nexport interface OperationContext extends ContextFilterInput {\n custom?: Record<string, unknown> | null;\n}\n\n/**\n * Prisma JSON filter type (simplified for context filtering)\n * This type is designed to be compatible with Prisma's JsonNullableFilter\n * Uses Record<string, unknown> for maximum compatibility with various Prisma versions\n */\nexport type PrismaJsonFilter = Record<string, unknown>;\n\n/**\n * One entry of {@link buildContextWhereConditions}: a JSON-path predicate on `context`,\n * or an `OR` of them (used for a renamed product's slug twins).\n */\nexport type ContextWhereCondition = { context: PrismaJsonFilter } | { OR: Array<{ context: PrismaJsonFilter }> };\n\n/**\n * JSON value type for Prisma (includes null for reading from DB)\n */\nexport type JsonValue = string | number | boolean | null | { [key: string]: JsonValue } | JsonValue[];\n\n/**\n * Input JSON value type for Prisma (excludes null for writing to DB)\n * Compatible with Prisma's InputJsonValue type\n */\nexport type InputJsonValue = string | number | boolean | { [key: string]: InputJsonValue } | InputJsonValue[];\n\n/**\n * Build Prisma where condition for context filtering.\n * Uses PostgreSQL JSONB containment operators for efficient queries.\n *\n * @param contextFilter - The context filter input\n * @returns Prisma where clause for context field, or undefined if no filter provided\n *\n * @example\n * ```typescript\n * const contextWhere = buildContextWhereClause({\n * workspaceId: '123',\n * projectId: '456'\n * });\n * // Returns: { path: ['workspaceId'], equals: '123' }\n * ```\n */\nexport function buildContextWhereClause(\n contextFilter: ContextFilterInput | null | undefined\n): PrismaJsonFilter | undefined {\n if (!contextFilter) {\n return undefined;\n }\n\n // Build array of path conditions for each non-null field\n const conditions: PrismaJsonFilter[] = [];\n\n if (contextFilter.workspaceId != null) {\n conditions.push({\n path: ['workspaceId'],\n equals: contextFilter.workspaceId,\n });\n }\n\n if (contextFilter.userId != null) {\n conditions.push({\n path: ['userId'],\n equals: contextFilter.userId,\n });\n }\n\n if (contextFilter.projectId != null) {\n conditions.push({\n path: ['projectId'],\n equals: contextFilter.projectId,\n });\n }\n\n if (contextFilter.appId != null) {\n conditions.push({\n path: ['appId'],\n equals: contextFilter.appId,\n });\n }\n\n if (contextFilter.productId != null) {\n conditions.push({\n path: ['productId'],\n equals: contextFilter.productId,\n });\n }\n\n if (contextFilter.organizationId != null) {\n conditions.push({\n path: ['organizationId'],\n equals: contextFilter.organizationId,\n });\n }\n\n // If no conditions, return undefined\n if (conditions.length === 0) {\n return undefined;\n }\n\n // If single condition, return it directly\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n // For multiple conditions, return the first one\n // Caller should use buildContextWhereConditions for multiple AND conditions\n return conditions[0];\n}\n\n/**\n * Build context where conditions as an array for use in AND clause.\n * This is useful when you need to filter by multiple context fields.\n *\n * @param contextFilter - The context filter input\n * @returns Array of Prisma where conditions, each targeting the context field\n *\n * @example\n * ```typescript\n * const conditions = buildContextWhereConditions({\n * workspaceId: '123',\n * projectId: '456'\n * });\n * // Use in Prisma query:\n * prisma.entity.findMany({\n * where: { AND: conditions }\n * });\n * ```\n */\nexport function buildContextWhereConditions(\n contextFilter: ContextFilterInput | null | undefined\n): ContextWhereCondition[] {\n if (!contextFilter) {\n return [];\n }\n\n const conditions: ContextWhereCondition[] = [];\n\n if (contextFilter.workspaceId != null) {\n conditions.push({\n context: {\n path: ['workspaceId'],\n equals: contextFilter.workspaceId,\n },\n });\n }\n\n if (contextFilter.userId != null) {\n conditions.push({\n context: {\n path: ['userId'],\n equals: contextFilter.userId,\n },\n });\n }\n\n if (contextFilter.projectId != null) {\n conditions.push({\n context: {\n path: ['projectId'],\n equals: contextFilter.projectId,\n },\n });\n }\n\n if (contextFilter.appId != null) {\n conditions.push({\n context: {\n path: ['appId'],\n equals: contextFilter.appId,\n },\n });\n }\n\n if (contextFilter.productId != null) {\n // A renamed product (botlit → botmanor) matches rows stored under either slug while\n // they are migrated; every other product keeps the exact single-slug predicate.\n const slugs = productSlugVariants(contextFilter.productId);\n if (slugs.length > 1) {\n conditions.push({\n OR: slugs.map((slug) => ({ context: { path: ['productId'], equals: slug } })),\n });\n } else {\n conditions.push({\n context: {\n path: ['productId'],\n equals: contextFilter.productId,\n },\n });\n }\n }\n\n if (contextFilter.organizationId != null) {\n conditions.push({\n context: {\n path: ['organizationId'],\n equals: contextFilter.organizationId,\n },\n });\n }\n\n return conditions;\n}\n\n/**\n * Convert context input to Prisma JSON format for create/update operations.\n *\n * @param contextInput - The context input\n * @returns JSON value for the context field, or undefined if empty\n *\n * @example\n * ```typescript\n * const contextJson = toContextJson({\n * workspaceId: '123',\n * userId: '456'\n * });\n * // Use in Prisma create:\n * prisma.entity.create({\n * data: { context: contextJson }\n * });\n * ```\n */\nexport function toContextJson(contextInput: OperationContext | null | undefined): InputJsonValue | undefined {\n if (!contextInput) {\n return undefined;\n }\n\n // Remove null values and build clean context object\n const context: Record<string, InputJsonValue> = {};\n\n if (contextInput.workspaceId != null) {\n context['workspaceId'] = contextInput.workspaceId;\n }\n if (contextInput.userId != null) {\n context['userId'] = contextInput.userId;\n }\n if (contextInput.projectId != null) {\n context['projectId'] = contextInput.projectId;\n }\n if (contextInput.appId != null) {\n context['appId'] = contextInput.appId;\n }\n if (contextInput.productId != null) {\n context['productId'] = contextInput.productId;\n }\n if (contextInput.organizationId != null) {\n context['organizationId'] = contextInput.organizationId;\n }\n if (contextInput.custom != null) {\n context['custom'] = contextInput.custom as InputJsonValue;\n }\n\n // Return undefined if no fields set\n if (Object.keys(context).length === 0) {\n return undefined;\n }\n\n return context;\n}\n\n/**\n * Filter out null values from an object for Prisma compatibility\n */\nfunction filterNullValues(obj: Record<string, unknown>): Record<string, InputJsonValue> {\n const filtered: Record<string, InputJsonValue> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== null) {\n filtered[key] = value as InputJsonValue;\n }\n }\n return filtered;\n}\n\n/**\n * Merge a single field into the merged context object\n */\nfunction mergeContextField(\n merged: Record<string, InputJsonValue>,\n fieldName: string,\n fieldValue: string | Record<string, unknown> | null | undefined\n): void {\n if (fieldValue === undefined) {\n return; // Don't touch this field\n }\n\n if (fieldValue === null) {\n delete merged[fieldName]; // Explicitly remove\n } else {\n merged[fieldName] = fieldValue as InputJsonValue; // Set new value\n }\n}\n\n/**\n * Merge existing context with new context input.\n * New values override existing ones, but undefined values are preserved from existing.\n *\n * @param existingContext - The existing context JSON from database\n * @param newContext - The new context input\n * @returns Merged context as InputJsonValue (suitable for Prisma writes)\n *\n * @example\n * ```typescript\n * const merged = mergeContext(\n * { workspaceId: '123', userId: 'old' },\n * { userId: 'new', projectId: '456' }\n * );\n * // Result: { workspaceId: '123', userId: 'new', projectId: '456' }\n * ```\n */\nexport function mergeContext(\n existingContext: JsonValue | null | undefined,\n newContext: OperationContext | null | undefined\n): InputJsonValue | undefined {\n // If no new context, return existing (excluding null values)\n if (!newContext) {\n if (!existingContext) {\n return undefined;\n }\n // Filter out null values from existing context for Prisma compatibility\n if (typeof existingContext === 'object' && !Array.isArray(existingContext)) {\n const filtered = filterNullValues(existingContext);\n return Object.keys(filtered).length > 0 ? filtered : undefined;\n }\n return existingContext as InputJsonValue;\n }\n\n // If no existing context, convert new to JSON\n if (!existingContext || typeof existingContext !== 'object' || Array.isArray(existingContext)) {\n return toContextJson(newContext);\n }\n\n // Merge existing with new\n const merged = filterNullValues(existingContext);\n\n // Merge each field from new context\n mergeContextField(merged, 'workspaceId', newContext.workspaceId);\n mergeContextField(merged, 'userId', newContext.userId);\n mergeContextField(merged, 'projectId', newContext.projectId);\n mergeContextField(merged, 'appId', newContext.appId);\n mergeContextField(merged, 'productId', newContext.productId);\n mergeContextField(merged, 'organizationId', newContext.organizationId);\n mergeContextField(merged, 'custom', newContext.custom);\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * Parse context JSON from database to OperationContext interface.\n *\n * @param contextJson - The context JSON from database\n * @returns Parsed OperationContext or null\n *\n * @example\n * ```typescript\n * const context = parseContext(entity.context);\n * if (context?.workspaceId) {\n * // Use workspace-specific logic\n * }\n * ```\n */\nexport function parseContext(contextJson: JsonValue | null | undefined): OperationContext | null {\n if (!contextJson || typeof contextJson !== 'object' || Array.isArray(contextJson)) {\n return null;\n }\n\n const ctx = contextJson as Record<string, unknown>;\n\n return {\n workspaceId: typeof ctx['workspaceId'] === 'string' ? ctx['workspaceId'] : null,\n userId: typeof ctx['userId'] === 'string' ? ctx['userId'] : null,\n projectId: typeof ctx['projectId'] === 'string' ? ctx['projectId'] : null,\n appId: typeof ctx['appId'] === 'string' ? ctx['appId'] : null,\n productId: typeof ctx['productId'] === 'string' ? ctx['productId'] : null,\n organizationId: typeof ctx['organizationId'] === 'string' ? ctx['organizationId'] : null,\n custom: typeof ctx['custom'] === 'object' ? (ctx['custom'] as Record<string, unknown>) : null,\n };\n}\n\n/**\n * Check if context matches filter criteria\n *\n * @param context - The context to check\n * @param filter - The filter criteria\n * @returns True if context matches all filter criteria\n */\nexport function contextMatches(context: OperationContext | null | undefined, filter: ContextFilterInput): boolean {\n if (!context) {\n return false;\n }\n\n if (filter.workspaceId != null && context.workspaceId !== filter.workspaceId) {\n return false;\n }\n if (filter.userId != null && context.userId !== filter.userId) {\n return false;\n }\n if (filter.projectId != null && context.projectId !== filter.projectId) {\n return false;\n }\n if (filter.appId != null && context.appId !== filter.appId) {\n return false;\n }\n // Renamed products (botlit → botmanor) match under either slug while rows are migrated.\n if (filter.productId != null && !isSameProductSlug(context.productId, filter.productId)) {\n return false;\n }\n if (filter.organizationId != null && context.organizationId !== filter.organizationId) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Create a default context from SDK context\n *\n * @param sdkContext - The SDK context (from AsyncLocalStorage)\n * @returns Operation context with workspace and user info\n */\nexport function createContextFromSDK(sdkContext: {\n workspaceId?: string;\n userId?: string;\n projectId?: string;\n appId?: string;\n productId?: string;\n organizationId?: string;\n}): OperationContext {\n return {\n workspaceId: sdkContext.workspaceId ?? null,\n userId: sdkContext.userId ?? null,\n projectId: sdkContext.projectId ?? null,\n appId: sdkContext.appId ?? null,\n productId: sdkContext.productId ?? null,\n organizationId: sdkContext.organizationId ?? null,\n };\n}\n"]}
@@ -54,8 +54,8 @@ var PRODUCT_RENAME_EMIT = Object.freeze({
54
54
  rbacResource: "current",
55
55
  templateKey: "current",
56
56
  graphqlName: "legacy",
57
- activityType: "legacy",
58
- snakeName: "legacy",
57
+ activityType: "current",
58
+ snakeName: "current",
59
59
  serviceName: "legacy",
60
60
  oauthClientId: "legacy",
61
61
  envVar: "legacy"
@@ -273,5 +273,5 @@ function readRenamedEnv(name, env = process.env) {
273
273
  __name(readRenamedEnv, "readRenamedEnv");
274
274
 
275
275
  export { PRODUCT_RENAMES, PRODUCT_RENAME_EMIT, PRODUCT_SLUG_ALIASES, RENAME_CONCERNS, billingIdVariants, emitBillingId, emitName, emitProductSlug, emitQuotaKey, emitRbacResource, emitTemplateKey, isLegacyName, isSameBillingId, isSameGraphQLName, isSameName, isSameProductSlug, isSameQuotaKey, isSameRbacResource, isSameTemplateKey, nameVariants, normalizeBillingId, normalizeGraphQLName, normalizeProductSlug, normalizeQuotaKey, normalizeRbacResource, normalizeTemplateKey, productSlugVariants, product_alias_exports, quotaKeyVariants, rbacResourceVariants, readRenamedEnv, templateKeyVariants, toCurrentName, toLegacyName };
276
- //# sourceMappingURL=chunk-5NWOQQC4.js.map
277
- //# sourceMappingURL=chunk-5NWOQQC4.js.map
276
+ //# sourceMappingURL=chunk-OBBCR6WY.js.map
277
+ //# sourceMappingURL=chunk-OBBCR6WY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/product-alias/index.ts"],"names":["PRODUCT_RENAMES","Object","freeze","legacy","current","PRODUCT_SLUG_ALIASES","fromEntries","map","r","PRODUCT_RENAME_EMIT","productSlug","quotaKey","billingId","rbacResource","templateKey","graphqlName","activityType","snakeName","serviceName","oauthClientId","envVar","RENAME_CONCERNS","keys","lower","slug","toLowerCase","upper","toUpperCase","pascal","charAt","slice","atStart","prefix","atEnd","rest","endOr","separators","includes","followedBy","separator","startsWith","oneOf","prefixes","nameShapes","spell","before","after","caseInsensitive","p","test","findTokens","value","shape","token","haystack","needle","hits","at","indexOf","length","push","replaceTokens","width","replacement","out","k","rewrite","concern","direction","rename","from","to","matched","toCurrentName","toLegacyName","nameVariants","variants","Set","isSameName","a","b","isLegacyName","some","emitName","normalizeProductSlug","productSlugVariants","isSameProductSlug","emitProductSlug","normalizeQuotaKey","key","quotaKeyVariants","isSameQuotaKey","emitQuotaKey","normalizeBillingId","id","billingIdVariants","isSameBillingId","emitBillingId","normalizeRbacResource","resource","rbacResourceVariants","isSameRbacResource","emitRbacResource","normalizeTemplateKey","templateKeyVariants","isSameTemplateKey","emitTemplateKey","normalizeGraphQLName","name","isSameGraphQLName","readRenamedEnv","env","process","candidate","undefined"],"mappings":"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","file":"chunk-5NWOQQC4.js","sourcesContent":["/**\n * Product rename aliases: dual-name support for renaming a product's machine\n * identifiers (today: Botlit → BotManor, see botmanor-migration PLAN.md\n * Stage 0 / WP-E).\n *\n * The rename follows expand → migrate → contract:\n *\n * - **Readers** accept both names. Use `toCurrentName` / `nameVariants` /\n * `isSameName` (or the per-concern wrappers such as `normalizeProductSlug`,\n * `quotaKeyVariants`, `isSameRbacResource`) wherever a stored or incoming\n * identifier is compared, looked up or counted.\n * - **Writers** emit through `emitName` (or `emitProductSlug`, `emitQuotaKey`,\n * …). What they emit is decided by {@link PRODUCT_RENAME_EMIT}: one entry per\n * concern, `'legacy'` until the stage that flips it. Flipping a concern is a\n * one-line change plus a release.\n *\n * Nothing here is feature-flagged: accepting both names is always safe, and\n * the emitted value only changes when `PRODUCT_RENAME_EMIT` is edited.\n *\n * The module has no runtime dependencies so gateways and frontends can mirror\n * or import it cheaply (`@burdenoff/be-sdk/product-alias`).\n */\n\n/** One product whose machine identifiers are being renamed. Both values are lowercase slugs. */\nexport interface ProductRename {\n /** The old slug, still present in data, directives and distributed clients (`botlit`). */\n readonly legacy: string;\n /** The new slug (`botmanor`). */\n readonly current: string;\n}\n\n/** Every product rename in flight. Readers treat each pair as the same product. */\nexport const PRODUCT_RENAMES: readonly ProductRename[] = Object.freeze([\n Object.freeze({ legacy: 'botlit', current: 'botmanor' }),\n]);\n\n/** Legacy slug → current slug, e.g. `{ botlit: 'botmanor' }`. */\nexport const PRODUCT_SLUG_ALIASES: Readonly<Record<string, string>> = Object.freeze(\n Object.fromEntries(PRODUCT_RENAMES.map((r) => [r.legacy, r.current]))\n);\n\n/**\n * The kinds of identifier that embed the product slug. Each has its own shape\n * (see {@link nameShapes}) and its own emit switch in {@link PRODUCT_RENAME_EMIT}.\n *\n * | concern | legacy example | current example |\n * |------------------|-----------------------------|-------------------------------|\n * | productSlug | `botlit` | `botmanor` |\n * | quotaKey | `botlit.bots.count` | `botmanor.bots.count` |\n * | billingId | `plan-botlit-pro-monthly`, `quota-botlit-free-bots` | `plan-botmanor-…`, `quota-botmanor-…` |\n * | rbacResource | `botlit-agent` | `botmanor-agent` |\n * | templateKey | `product.botlit.admin` | `product.botmanor.admin` |\n * | graphqlName | `BotlitAgent`, `getBotlitAgent`, `_emptyBotlit`, `botlitAgents` | `BotmanorAgent`, … |\n * | activityType | `BOTLIT_EXECUTION` | `BOTMANOR_EXECUTION` |\n * | snakeName | `botlit_agent` (export entity types, metric names) | `botmanor_agent` |\n * | serviceName | `wspace-botlit`, `wspace-botlit-svc` (graph `eventSource`) | `wspace-botmanor-svc` |\n * | oauthClientId | `burdenoff_cli_botlit` | `burdenoff_cli_botmanor` |\n * | envVar | `BOTLIT_API_URL` | `BOTMANOR_API_URL` |\n */\nexport type RenameConcern =\n | 'productSlug'\n | 'quotaKey'\n | 'billingId'\n | 'rbacResource'\n | 'templateKey'\n | 'graphqlName'\n | 'activityType'\n | 'snakeName'\n | 'serviceName'\n | 'oauthClientId'\n | 'envVar';\n\n/** Which name a writer emits: the old one (`'legacy'`) or the new one (`'current'`). */\nexport type EmitGeneration = 'legacy' | 'current';\n\n/**\n * What writers emit, per concern. Every concern starts at `'legacy'`; the\n * stage that migrates a concern flips its entry to `'current'` (and releases).\n * Readers are unaffected by this table: they always accept both.\n */\nexport const PRODUCT_RENAME_EMIT: Readonly<Record<RenameConcern, EmitGeneration>> = Object.freeze({\n productSlug: 'current',\n quotaKey: 'current',\n billingId: 'current',\n rbacResource: 'current',\n templateKey: 'current',\n graphqlName: 'legacy',\n activityType: 'legacy',\n snakeName: 'legacy',\n serviceName: 'legacy',\n oauthClientId: 'legacy',\n envVar: 'legacy',\n});\n\n/** Every concern, in a stable order. */\nexport const RENAME_CONCERNS: readonly RenameConcern[] = Object.freeze(\n Object.keys(PRODUCT_RENAME_EMIT) as RenameConcern[]\n);\n\ninterface NameShape {\n /** How the slug is spelled inside this kind of identifier. */\n readonly spell: (slug: string) => string;\n /** Accepts the text before the slug token. */\n readonly before: (prefix: string) => boolean;\n /** Accepts the text after the slug token. */\n readonly after: (rest: string) => boolean;\n /** Match the token regardless of case (slugs only). */\n readonly caseInsensitive?: boolean;\n}\n\nconst lower = (slug: string): string => slug.toLowerCase();\nconst upper = (slug: string): string => slug.toUpperCase();\nconst pascal = (slug: string): string => slug.charAt(0).toUpperCase() + slug.slice(1).toLowerCase();\n\nconst atStart = (prefix: string): boolean => prefix === '';\nconst atEnd = (rest: string): boolean => rest === '';\nconst endOr =\n (...separators: string[]) =>\n (rest: string): boolean =>\n rest === '' || separators.includes(rest.charAt(0));\nconst followedBy =\n (separator: string) =>\n (rest: string): boolean =>\n rest.startsWith(separator);\nconst oneOf =\n (...prefixes: string[]) =>\n (prefix: string): boolean =>\n prefixes.includes(prefix);\n\n/**\n * Identifier shapes per concern: where the slug token may sit, and how it is\n * spelled there. Only the slug token itself is ever rewritten.\n */\nconst nameShapes: Readonly<Record<RenameConcern, readonly NameShape[]>> = {\n productSlug: [{ spell: lower, before: atStart, after: atEnd, caseInsensitive: true }],\n quotaKey: [{ spell: lower, before: atStart, after: followedBy('.') }],\n billingId: [{ spell: lower, before: oneOf('plan-', 'quota-'), after: endOr('-') }],\n rbacResource: [{ spell: lower, before: atStart, after: endOr('-', ':') }],\n templateKey: [{ spell: lower, before: oneOf('product.'), after: endOr('.') }],\n graphqlName: [\n // PascalCase token anywhere: BotlitAgent, getBotlitAgent, _emptyBotlit, CreateBotlitAgentInput.\n { spell: pascal, before: (p) => !/[A-Z]$/.test(p), after: (r) => !/^[a-z]/.test(r) },\n // camelCase prefix: botlitAgents.\n { spell: lower, before: atStart, after: (r) => /^[A-Z]/.test(r) },\n ],\n activityType: [{ spell: upper, before: atStart, after: endOr('_') }],\n snakeName: [{ spell: lower, before: atStart, after: followedBy('_') }],\n serviceName: [\n { spell: lower, before: oneOf('wspace-', 'global-'), after: endOr('-') },\n { spell: lower, before: atStart, after: (r) => r === '-svc' },\n ],\n oauthClientId: [{ spell: lower, before: (p) => /^burdenoff_[a-z0-9]+_$/.test(p), after: atEnd }],\n envVar: [{ spell: upper, before: atStart, after: followedBy('_') }],\n};\n\ntype Direction = 'toCurrent' | 'toLegacy';\n\n/** Start offsets of every occurrence of the slug token that fits `shape`. */\nfunction findTokens(value: string, shape: NameShape, slug: string): number[] {\n const token = shape.spell(slug);\n const haystack = shape.caseInsensitive ? value.toLowerCase() : value;\n const needle = shape.caseInsensitive ? token.toLowerCase() : token;\n const hits: number[] = [];\n for (let at = haystack.indexOf(needle); at !== -1; at = haystack.indexOf(needle, at + needle.length)) {\n if (shape.before(value.slice(0, at)) && shape.after(value.slice(at + needle.length))) hits.push(at);\n }\n return hits;\n}\n\nfunction replaceTokens(value: string, hits: readonly number[], width: number, replacement: string): string {\n let out = value;\n // Right to left, so earlier offsets stay valid.\n for (let k = hits.length - 1; k >= 0; k--) {\n const at = hits[k] as number;\n out = out.slice(0, at) + replacement + out.slice(at + width);\n }\n return out;\n}\n\nfunction rewrite(concern: RenameConcern, value: string, direction: Direction): string {\n for (const rename of PRODUCT_RENAMES) {\n const from = direction === 'toCurrent' ? rename.legacy : rename.current;\n const to = direction === 'toCurrent' ? rename.current : rename.legacy;\n let out = value;\n let matched = false;\n // Apply every shape, so compound names (botlitAgentsByBotlitOwner) are fully rewritten.\n for (const shape of nameShapes[concern]) {\n // Case-insensitive shapes (product slugs) also canonicalise the target spelling: BotManor → botmanor.\n for (const slug of shape.caseInsensitive ? [from, to] : [from]) {\n const hits = findTokens(out, shape, slug);\n if (hits.length === 0) continue;\n out = replaceTokens(out, hits, slug.length, shape.spell(to));\n matched = true;\n }\n }\n if (matched) return out;\n }\n return value;\n}\n\n/** Rewrite an identifier to its new-name form. Values that embed no renamed slug are returned unchanged. */\nexport function toCurrentName(concern: RenameConcern, value: string): string {\n return rewrite(concern, value, 'toCurrent');\n}\n\n/** Rewrite an identifier to its old-name form. Values that embed no renamed slug are returned unchanged. */\nexport function toLegacyName(concern: RenameConcern, value: string): string {\n return rewrite(concern, value, 'toLegacy');\n}\n\n/**\n * Every spelling a reader must accept for `value`: the value itself first,\n * then its twin (if it has one). Use it for `IN (...)` / `{ in: [...] }`\n * lookups and for summing counters across both keys.\n */\nexport function nameVariants(concern: RenameConcern, value: string): string[] {\n const variants = [value, toCurrentName(concern, value), toLegacyName(concern, value)];\n return [...new Set(variants)];\n}\n\n/** True when `a` and `b` name the same thing under the rename (identical, or legacy/current twins). */\nexport function isSameName(\n concern: RenameConcern,\n a: string | null | undefined,\n b: string | null | undefined\n): boolean {\n if (a == null || b == null) return a === b;\n if (a === b) return true;\n return toCurrentName(concern, a) === toCurrentName(concern, b);\n}\n\n/** True when `value` embeds a legacy slug for this concern (i.e. a migration still has work to do). */\nexport function isLegacyName(concern: RenameConcern, value: string): boolean {\n return PRODUCT_RENAMES.some((rename) =>\n nameShapes[concern].some((shape) => findTokens(value, shape, rename.legacy).length > 0)\n );\n}\n\n/**\n * The spelling a writer should persist or send, per {@link PRODUCT_RENAME_EMIT}.\n * Accepts either spelling as input.\n */\nexport function emitName(concern: RenameConcern, value: string): string {\n return PRODUCT_RENAME_EMIT[concern] === 'current' ? toCurrentName(concern, value) : toLegacyName(concern, value);\n}\n\n// ---------------------------------------------------------------------------\n// Per-concern conveniences (thin wrappers over the generic functions above).\n// ---------------------------------------------------------------------------\n\n/** `botlit` → `botmanor`; any other slug unchanged. Case-insensitive for renamed slugs. */\nexport function normalizeProductSlug(slug: string): string;\nexport function normalizeProductSlug(slug: string | null | undefined): string | null | undefined;\nexport function normalizeProductSlug(slug: string | null | undefined): string | null | undefined {\n return slug == null ? slug : toCurrentName('productSlug', slug);\n}\n/** `['botlit', 'botmanor']` for either; `[slug]` for any other product. */\nexport const productSlugVariants = (slug: string): string[] => nameVariants('productSlug', slug);\n/** Same product under the rename. */\nexport const isSameProductSlug = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('productSlug', a, b);\n/** The product slug writers persist today (`botlit` until Stage 5a flips it). */\nexport const emitProductSlug = (slug: string): string => emitName('productSlug', slug);\n\n/** `botlit.bots.count` → `botmanor.bots.count`. */\nexport const normalizeQuotaKey = (key: string): string => toCurrentName('quotaKey', key);\n/** Both spellings of a quota / usage key, so period-to-date counters include the old key. */\nexport const quotaKeyVariants = (key: string): string[] => nameVariants('quotaKey', key);\n/** Same quota bucket under the rename. */\nexport const isSameQuotaKey = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('quotaKey', a, b);\n/** The quota key writers use today. */\nexport const emitQuotaKey = (key: string): string => emitName('quotaKey', key);\n\n/** `plan-botlit-pro-monthly` → `plan-botmanor-pro-monthly`; `quota-botlit-*` likewise (D6). */\nexport const normalizeBillingId = (id: string): string => toCurrentName('billingId', id);\n/** Both spellings of a billing plan / quota ID, for lookups during the dual-ID window. */\nexport const billingIdVariants = (id: string): string[] => nameVariants('billingId', id);\n/** Same plan / quota under the rename. */\nexport const isSameBillingId = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('billingId', a, b);\n/** The billing ID writers use today. */\nexport const emitBillingId = (id: string): string => emitName('billingId', id);\n\n/** `botlit-agent` → `botmanor-agent` (also `botlit-agent:read`). */\nexport const normalizeRbacResource = (resource: string): string => toCurrentName('rbacResource', resource);\n/** Both spellings of an RBAC resource type; a check on one is satisfied by a grant on either. */\nexport const rbacResourceVariants = (resource: string): string[] => nameVariants('rbacResource', resource);\n/** Same RBAC resource type under the rename. */\nexport const isSameRbacResource = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('rbacResource', a, b);\n/** The RBAC resource string writers use today. */\nexport const emitRbacResource = (resource: string): string => emitName('rbacResource', resource);\n\n/** `product.botlit.admin` → `product.botmanor.admin`. */\nexport const normalizeTemplateKey = (key: string): string => toCurrentName('templateKey', key);\n/** Both spellings of a role templateKey. */\nexport const templateKeyVariants = (key: string): string[] => nameVariants('templateKey', key);\n/** Same role template under the rename. */\nexport const isSameTemplateKey = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('templateKey', a, b);\n/** The templateKey writers use today. */\nexport const emitTemplateKey = (key: string): string => emitName('templateKey', key);\n\n/** `BotlitAgent` → `BotmanorAgent`, `getBotlitAgent` → `getBotmanorAgent` (entity `__typename`, operation names). */\nexport const normalizeGraphQLName = (name: string): string => toCurrentName('graphqlName', name);\n/** Same GraphQL type / field under the rename. */\nexport const isSameGraphQLName = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('graphqlName', a, b);\n\ntype EnvSource = Readonly<Record<string, string | undefined>>;\n\n/**\n * Read an env var that is being renamed, accepting either spelling. Pass the\n * new name (`BOTMANOR_API_URL`) or the old one (`BOTLIT_API_URL`); the name you\n * pass wins, the twin is the fallback. Empty strings count as unset.\n */\nexport function readRenamedEnv(name: string, env: EnvSource = process.env): string | undefined {\n for (const candidate of nameVariants('envVar', name)) {\n const value = env[candidate];\n if (value !== undefined && value !== '') return value;\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"sources":["../src/product-alias/index.ts"],"names":["PRODUCT_RENAMES","Object","freeze","legacy","current","PRODUCT_SLUG_ALIASES","fromEntries","map","r","PRODUCT_RENAME_EMIT","productSlug","quotaKey","billingId","rbacResource","templateKey","graphqlName","activityType","snakeName","serviceName","oauthClientId","envVar","RENAME_CONCERNS","keys","lower","slug","toLowerCase","upper","toUpperCase","pascal","charAt","slice","atStart","prefix","atEnd","rest","endOr","separators","includes","followedBy","separator","startsWith","oneOf","prefixes","nameShapes","spell","before","after","caseInsensitive","p","test","findTokens","value","shape","token","haystack","needle","hits","at","indexOf","length","push","replaceTokens","width","replacement","out","k","rewrite","concern","direction","rename","from","to","matched","toCurrentName","toLegacyName","nameVariants","variants","Set","isSameName","a","b","isLegacyName","some","emitName","normalizeProductSlug","productSlugVariants","isSameProductSlug","emitProductSlug","normalizeQuotaKey","key","quotaKeyVariants","isSameQuotaKey","emitQuotaKey","normalizeBillingId","id","billingIdVariants","isSameBillingId","emitBillingId","normalizeRbacResource","resource","rbacResourceVariants","isSameRbacResource","emitRbacResource","normalizeTemplateKey","templateKeyVariants","isSameTemplateKey","emitTemplateKey","normalizeGraphQLName","name","isSameGraphQLName","readRenamedEnv","env","process","candidate","undefined"],"mappings":"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","file":"chunk-OBBCR6WY.js","sourcesContent":["/**\n * Product rename aliases: dual-name support for renaming a product's machine\n * identifiers (today: Botlit → BotManor, see botmanor-migration PLAN.md\n * Stage 0 / WP-E).\n *\n * The rename follows expand → migrate → contract:\n *\n * - **Readers** accept both names. Use `toCurrentName` / `nameVariants` /\n * `isSameName` (or the per-concern wrappers such as `normalizeProductSlug`,\n * `quotaKeyVariants`, `isSameRbacResource`) wherever a stored or incoming\n * identifier is compared, looked up or counted.\n * - **Writers** emit through `emitName` (or `emitProductSlug`, `emitQuotaKey`,\n * …). What they emit is decided by {@link PRODUCT_RENAME_EMIT}: one entry per\n * concern, `'legacy'` until the stage that flips it. Flipping a concern is a\n * one-line change plus a release.\n *\n * Nothing here is feature-flagged: accepting both names is always safe, and\n * the emitted value only changes when `PRODUCT_RENAME_EMIT` is edited.\n *\n * The module has no runtime dependencies so gateways and frontends can mirror\n * or import it cheaply (`@burdenoff/be-sdk/product-alias`).\n */\n\n/** One product whose machine identifiers are being renamed. Both values are lowercase slugs. */\nexport interface ProductRename {\n /** The old slug, still present in data, directives and distributed clients (`botlit`). */\n readonly legacy: string;\n /** The new slug (`botmanor`). */\n readonly current: string;\n}\n\n/** Every product rename in flight. Readers treat each pair as the same product. */\nexport const PRODUCT_RENAMES: readonly ProductRename[] = Object.freeze([\n Object.freeze({ legacy: 'botlit', current: 'botmanor' }),\n]);\n\n/** Legacy slug → current slug, e.g. `{ botlit: 'botmanor' }`. */\nexport const PRODUCT_SLUG_ALIASES: Readonly<Record<string, string>> = Object.freeze(\n Object.fromEntries(PRODUCT_RENAMES.map((r) => [r.legacy, r.current]))\n);\n\n/**\n * The kinds of identifier that embed the product slug. Each has its own shape\n * (see {@link nameShapes}) and its own emit switch in {@link PRODUCT_RENAME_EMIT}.\n *\n * | concern | legacy example | current example |\n * |------------------|-----------------------------|-------------------------------|\n * | productSlug | `botlit` | `botmanor` |\n * | quotaKey | `botlit.bots.count` | `botmanor.bots.count` |\n * | billingId | `plan-botlit-pro-monthly`, `quota-botlit-free-bots` | `plan-botmanor-…`, `quota-botmanor-…` |\n * | rbacResource | `botlit-agent` | `botmanor-agent` |\n * | templateKey | `product.botlit.admin` | `product.botmanor.admin` |\n * | graphqlName | `BotlitAgent`, `getBotlitAgent`, `_emptyBotlit`, `botlitAgents` | `BotmanorAgent`, … |\n * | activityType | `BOTLIT_EXECUTION` | `BOTMANOR_EXECUTION` |\n * | snakeName | `botlit_agent` (export entity types, metric names) | `botmanor_agent` |\n * | serviceName | `wspace-botlit`, `wspace-botlit-svc` (graph `eventSource`) | `wspace-botmanor-svc` |\n * | oauthClientId | `burdenoff_cli_botlit` | `burdenoff_cli_botmanor` |\n * | envVar | `BOTLIT_API_URL` | `BOTMANOR_API_URL` |\n */\nexport type RenameConcern =\n | 'productSlug'\n | 'quotaKey'\n | 'billingId'\n | 'rbacResource'\n | 'templateKey'\n | 'graphqlName'\n | 'activityType'\n | 'snakeName'\n | 'serviceName'\n | 'oauthClientId'\n | 'envVar';\n\n/** Which name a writer emits: the old one (`'legacy'`) or the new one (`'current'`). */\nexport type EmitGeneration = 'legacy' | 'current';\n\n/**\n * What writers emit, per concern. Every concern starts at `'legacy'`; the\n * stage that migrates a concern flips its entry to `'current'` (and releases).\n * Readers are unaffected by this table: they always accept both.\n */\nexport const PRODUCT_RENAME_EMIT: Readonly<Record<RenameConcern, EmitGeneration>> = Object.freeze({\n productSlug: 'current',\n quotaKey: 'current',\n billingId: 'current',\n rbacResource: 'current',\n templateKey: 'current',\n graphqlName: 'legacy',\n activityType: 'current',\n snakeName: 'current',\n serviceName: 'legacy',\n oauthClientId: 'legacy',\n envVar: 'legacy',\n});\n\n/** Every concern, in a stable order. */\nexport const RENAME_CONCERNS: readonly RenameConcern[] = Object.freeze(\n Object.keys(PRODUCT_RENAME_EMIT) as RenameConcern[]\n);\n\ninterface NameShape {\n /** How the slug is spelled inside this kind of identifier. */\n readonly spell: (slug: string) => string;\n /** Accepts the text before the slug token. */\n readonly before: (prefix: string) => boolean;\n /** Accepts the text after the slug token. */\n readonly after: (rest: string) => boolean;\n /** Match the token regardless of case (slugs only). */\n readonly caseInsensitive?: boolean;\n}\n\nconst lower = (slug: string): string => slug.toLowerCase();\nconst upper = (slug: string): string => slug.toUpperCase();\nconst pascal = (slug: string): string => slug.charAt(0).toUpperCase() + slug.slice(1).toLowerCase();\n\nconst atStart = (prefix: string): boolean => prefix === '';\nconst atEnd = (rest: string): boolean => rest === '';\nconst endOr =\n (...separators: string[]) =>\n (rest: string): boolean =>\n rest === '' || separators.includes(rest.charAt(0));\nconst followedBy =\n (separator: string) =>\n (rest: string): boolean =>\n rest.startsWith(separator);\nconst oneOf =\n (...prefixes: string[]) =>\n (prefix: string): boolean =>\n prefixes.includes(prefix);\n\n/**\n * Identifier shapes per concern: where the slug token may sit, and how it is\n * spelled there. Only the slug token itself is ever rewritten.\n */\nconst nameShapes: Readonly<Record<RenameConcern, readonly NameShape[]>> = {\n productSlug: [{ spell: lower, before: atStart, after: atEnd, caseInsensitive: true }],\n quotaKey: [{ spell: lower, before: atStart, after: followedBy('.') }],\n billingId: [{ spell: lower, before: oneOf('plan-', 'quota-'), after: endOr('-') }],\n rbacResource: [{ spell: lower, before: atStart, after: endOr('-', ':') }],\n templateKey: [{ spell: lower, before: oneOf('product.'), after: endOr('.') }],\n graphqlName: [\n // PascalCase token anywhere: BotlitAgent, getBotlitAgent, _emptyBotlit, CreateBotlitAgentInput.\n { spell: pascal, before: (p) => !/[A-Z]$/.test(p), after: (r) => !/^[a-z]/.test(r) },\n // camelCase prefix: botlitAgents.\n { spell: lower, before: atStart, after: (r) => /^[A-Z]/.test(r) },\n ],\n activityType: [{ spell: upper, before: atStart, after: endOr('_') }],\n snakeName: [{ spell: lower, before: atStart, after: followedBy('_') }],\n serviceName: [\n { spell: lower, before: oneOf('wspace-', 'global-'), after: endOr('-') },\n { spell: lower, before: atStart, after: (r) => r === '-svc' },\n ],\n oauthClientId: [{ spell: lower, before: (p) => /^burdenoff_[a-z0-9]+_$/.test(p), after: atEnd }],\n envVar: [{ spell: upper, before: atStart, after: followedBy('_') }],\n};\n\ntype Direction = 'toCurrent' | 'toLegacy';\n\n/** Start offsets of every occurrence of the slug token that fits `shape`. */\nfunction findTokens(value: string, shape: NameShape, slug: string): number[] {\n const token = shape.spell(slug);\n const haystack = shape.caseInsensitive ? value.toLowerCase() : value;\n const needle = shape.caseInsensitive ? token.toLowerCase() : token;\n const hits: number[] = [];\n for (let at = haystack.indexOf(needle); at !== -1; at = haystack.indexOf(needle, at + needle.length)) {\n if (shape.before(value.slice(0, at)) && shape.after(value.slice(at + needle.length))) hits.push(at);\n }\n return hits;\n}\n\nfunction replaceTokens(value: string, hits: readonly number[], width: number, replacement: string): string {\n let out = value;\n // Right to left, so earlier offsets stay valid.\n for (let k = hits.length - 1; k >= 0; k--) {\n const at = hits[k] as number;\n out = out.slice(0, at) + replacement + out.slice(at + width);\n }\n return out;\n}\n\nfunction rewrite(concern: RenameConcern, value: string, direction: Direction): string {\n for (const rename of PRODUCT_RENAMES) {\n const from = direction === 'toCurrent' ? rename.legacy : rename.current;\n const to = direction === 'toCurrent' ? rename.current : rename.legacy;\n let out = value;\n let matched = false;\n // Apply every shape, so compound names (botlitAgentsByBotlitOwner) are fully rewritten.\n for (const shape of nameShapes[concern]) {\n // Case-insensitive shapes (product slugs) also canonicalise the target spelling: BotManor → botmanor.\n for (const slug of shape.caseInsensitive ? [from, to] : [from]) {\n const hits = findTokens(out, shape, slug);\n if (hits.length === 0) continue;\n out = replaceTokens(out, hits, slug.length, shape.spell(to));\n matched = true;\n }\n }\n if (matched) return out;\n }\n return value;\n}\n\n/** Rewrite an identifier to its new-name form. Values that embed no renamed slug are returned unchanged. */\nexport function toCurrentName(concern: RenameConcern, value: string): string {\n return rewrite(concern, value, 'toCurrent');\n}\n\n/** Rewrite an identifier to its old-name form. Values that embed no renamed slug are returned unchanged. */\nexport function toLegacyName(concern: RenameConcern, value: string): string {\n return rewrite(concern, value, 'toLegacy');\n}\n\n/**\n * Every spelling a reader must accept for `value`: the value itself first,\n * then its twin (if it has one). Use it for `IN (...)` / `{ in: [...] }`\n * lookups and for summing counters across both keys.\n */\nexport function nameVariants(concern: RenameConcern, value: string): string[] {\n const variants = [value, toCurrentName(concern, value), toLegacyName(concern, value)];\n return [...new Set(variants)];\n}\n\n/** True when `a` and `b` name the same thing under the rename (identical, or legacy/current twins). */\nexport function isSameName(\n concern: RenameConcern,\n a: string | null | undefined,\n b: string | null | undefined\n): boolean {\n if (a == null || b == null) return a === b;\n if (a === b) return true;\n return toCurrentName(concern, a) === toCurrentName(concern, b);\n}\n\n/** True when `value` embeds a legacy slug for this concern (i.e. a migration still has work to do). */\nexport function isLegacyName(concern: RenameConcern, value: string): boolean {\n return PRODUCT_RENAMES.some((rename) =>\n nameShapes[concern].some((shape) => findTokens(value, shape, rename.legacy).length > 0)\n );\n}\n\n/**\n * The spelling a writer should persist or send, per {@link PRODUCT_RENAME_EMIT}.\n * Accepts either spelling as input.\n */\nexport function emitName(concern: RenameConcern, value: string): string {\n return PRODUCT_RENAME_EMIT[concern] === 'current' ? toCurrentName(concern, value) : toLegacyName(concern, value);\n}\n\n// ---------------------------------------------------------------------------\n// Per-concern conveniences (thin wrappers over the generic functions above).\n// ---------------------------------------------------------------------------\n\n/** `botlit` → `botmanor`; any other slug unchanged. Case-insensitive for renamed slugs. */\nexport function normalizeProductSlug(slug: string): string;\nexport function normalizeProductSlug(slug: string | null | undefined): string | null | undefined;\nexport function normalizeProductSlug(slug: string | null | undefined): string | null | undefined {\n return slug == null ? slug : toCurrentName('productSlug', slug);\n}\n/** `['botlit', 'botmanor']` for either; `[slug]` for any other product. */\nexport const productSlugVariants = (slug: string): string[] => nameVariants('productSlug', slug);\n/** Same product under the rename. */\nexport const isSameProductSlug = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('productSlug', a, b);\n/** The product slug writers persist today (`botlit` until Stage 5a flips it). */\nexport const emitProductSlug = (slug: string): string => emitName('productSlug', slug);\n\n/** `botlit.bots.count` → `botmanor.bots.count`. */\nexport const normalizeQuotaKey = (key: string): string => toCurrentName('quotaKey', key);\n/** Both spellings of a quota / usage key, so period-to-date counters include the old key. */\nexport const quotaKeyVariants = (key: string): string[] => nameVariants('quotaKey', key);\n/** Same quota bucket under the rename. */\nexport const isSameQuotaKey = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('quotaKey', a, b);\n/** The quota key writers use today. */\nexport const emitQuotaKey = (key: string): string => emitName('quotaKey', key);\n\n/** `plan-botlit-pro-monthly` → `plan-botmanor-pro-monthly`; `quota-botlit-*` likewise (D6). */\nexport const normalizeBillingId = (id: string): string => toCurrentName('billingId', id);\n/** Both spellings of a billing plan / quota ID, for lookups during the dual-ID window. */\nexport const billingIdVariants = (id: string): string[] => nameVariants('billingId', id);\n/** Same plan / quota under the rename. */\nexport const isSameBillingId = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('billingId', a, b);\n/** The billing ID writers use today. */\nexport const emitBillingId = (id: string): string => emitName('billingId', id);\n\n/** `botlit-agent` → `botmanor-agent` (also `botlit-agent:read`). */\nexport const normalizeRbacResource = (resource: string): string => toCurrentName('rbacResource', resource);\n/** Both spellings of an RBAC resource type; a check on one is satisfied by a grant on either. */\nexport const rbacResourceVariants = (resource: string): string[] => nameVariants('rbacResource', resource);\n/** Same RBAC resource type under the rename. */\nexport const isSameRbacResource = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('rbacResource', a, b);\n/** The RBAC resource string writers use today. */\nexport const emitRbacResource = (resource: string): string => emitName('rbacResource', resource);\n\n/** `product.botlit.admin` → `product.botmanor.admin`. */\nexport const normalizeTemplateKey = (key: string): string => toCurrentName('templateKey', key);\n/** Both spellings of a role templateKey. */\nexport const templateKeyVariants = (key: string): string[] => nameVariants('templateKey', key);\n/** Same role template under the rename. */\nexport const isSameTemplateKey = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('templateKey', a, b);\n/** The templateKey writers use today. */\nexport const emitTemplateKey = (key: string): string => emitName('templateKey', key);\n\n/** `BotlitAgent` → `BotmanorAgent`, `getBotlitAgent` → `getBotmanorAgent` (entity `__typename`, operation names). */\nexport const normalizeGraphQLName = (name: string): string => toCurrentName('graphqlName', name);\n/** Same GraphQL type / field under the rename. */\nexport const isSameGraphQLName = (a: string | null | undefined, b: string | null | undefined): boolean =>\n isSameName('graphqlName', a, b);\n\ntype EnvSource = Readonly<Record<string, string | undefined>>;\n\n/**\n * Read an env var that is being renamed, accepting either spelling. Pass the\n * new name (`BOTMANOR_API_URL`) or the old one (`BOTLIT_API_URL`); the name you\n * pass wins, the twin is the fallback. Empty strings count as unset.\n */\nexport function readRenamedEnv(name: string, env: EnvSource = process.env): string | undefined {\n for (const candidate of nameVariants('envVar', name)) {\n const value = env[candidate];\n if (value !== undefined && value !== '') return value;\n }\n return undefined;\n}\n"]}
@@ -1,4 +1,4 @@
1
- export { DEFAULT_I18N_CONFIG, I18n, Locales, RTL_LANGUAGES, clearTranslationCache, createI18n, createTranslator, discoverLocales, extractLocaleFromRequest, findBestMatch, flattenDictionary, getCachedTranslations, getI18n, getLanguage, getLanguageFromLocale, getLocale, getRegionFromLocale, getTextDirection, hasI18n, initializeI18n, loadTranslationFile, loadTranslationsForLocale, normalizeLocale, parseAcceptLanguage, parseLocaleString, preloadAllTranslations, setCachedTranslations, t } from '../chunk-IUJSIXMM.js';
1
+ export { DEFAULT_I18N_CONFIG, I18n, Locales, RTL_LANGUAGES, clearTranslationCache, createI18n, createTranslator, discoverLocales, extractLocaleFromRequest, findBestMatch, flattenDictionary, getCachedTranslations, getI18n, getLanguage, getLanguageFromLocale, getLocale, getRegionFromLocale, getTextDirection, hasI18n, initializeI18n, loadTranslationFile, loadTranslationsForLocale, normalizeLocale, parseAcceptLanguage, parseLocaleString, preloadAllTranslations, setCachedTranslations, t } from '../chunk-EBDHIL7V.js';
2
2
  import '../chunk-RU266375.js';
3
3
  import '../chunk-XE4OXN2W.js';
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ import { ActivityModule, UsageModule, TrackerModule } from './chunk-KW55Q6TA.js'
3
3
  export { ActivityModule, TrackerModule, UsageModule } from './chunk-KW55Q6TA.js';
4
4
  export { NAME_MAX_LENGTH, NAME_MIN_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, validation_exports as Validation, lengthInCodePoints, validateName, validateUserFields, validateUsername } from './chunk-Z32KFAPT.js';
5
5
  export { platform_exports as Platform } from './chunk-Z5BURBFZ.js';
6
- export { prisma_exports as Prisma } from './chunk-YTXZ6HZI.js';
7
- export { PRODUCT_RENAMES, PRODUCT_RENAME_EMIT, PRODUCT_SLUG_ALIASES, product_alias_exports as ProductAlias, RENAME_CONCERNS, billingIdVariants, emitBillingId, emitName, emitProductSlug, emitQuotaKey, emitRbacResource, emitTemplateKey, isLegacyName, isSameBillingId, isSameGraphQLName, isSameName, isSameProductSlug, isSameQuotaKey, isSameRbacResource, isSameTemplateKey, nameVariants, normalizeBillingId, normalizeGraphQLName, normalizeProductSlug, normalizeQuotaKey, normalizeRbacResource, normalizeTemplateKey, productSlugVariants, quotaKeyVariants, rbacResourceVariants, readRenamedEnv, templateKeyVariants, toCurrentName, toLegacyName } from './chunk-5NWOQQC4.js';
6
+ export { prisma_exports as Prisma } from './chunk-LNFGZMDB.js';
7
+ export { PRODUCT_RENAMES, PRODUCT_RENAME_EMIT, PRODUCT_SLUG_ALIASES, product_alias_exports as ProductAlias, RENAME_CONCERNS, billingIdVariants, emitBillingId, emitName, emitProductSlug, emitQuotaKey, emitRbacResource, emitTemplateKey, isLegacyName, isSameBillingId, isSameGraphQLName, isSameName, isSameProductSlug, isSameQuotaKey, isSameRbacResource, isSameTemplateKey, nameVariants, normalizeBillingId, normalizeGraphQLName, normalizeProductSlug, normalizeQuotaKey, normalizeRbacResource, normalizeTemplateKey, productSlugVariants, quotaKeyVariants, rbacResourceVariants, readRenamedEnv, templateKeyVariants, toCurrentName, toLegacyName } from './chunk-OBBCR6WY.js';
8
8
  import { RBACModule } from './chunk-5JNHVKHG.js';
9
9
  export { RBACModule, createRBACDirective, createRBACDirectiveForLayer, createRBACDirectiveFromEnv } from './chunk-5JNHVKHG.js';
10
10
  import './chunk-FA5ROGTS.js';
@@ -26,7 +26,7 @@ import { QueueType, EventQueueFactory } from './chunk-UFXHLQ2T.js';
26
26
  export { graphql_exports as GraphQL } from './chunk-KMNSVLDS.js';
27
27
  import './chunk-MWPYA2HD.js';
28
28
  import './chunk-LKCBI6B2.js';
29
- export { i18n_exports as I18n, createTranslator, getLanguage, getLocale, hasI18n, t } from './chunk-IUJSIXMM.js';
29
+ export { i18n_exports as I18n, createTranslator, getLanguage, getLocale, hasI18n, t } from './chunk-EBDHIL7V.js';
30
30
  export { init_exports as Init } from './chunk-G6XPO5D7.js';
31
31
  export { RESOURCE_CAP_DEFAULTS, ResourceCapExceededError, ResourceCapsModule, configureResourceCaps, getResourceCaps } from './chunk-MZCBEJ67.js';
32
32
  import './chunk-AWPNRV3L.js';
@@ -1,5 +1,5 @@
1
- export { buildContextWhereClause, buildContextWhereConditions, checkDatabaseHealth, contextMatches, createContextFromSDK, createDatabaseClient, createDatabaseClientFromEnv, extractFieldsFromModel, getAllModelNames, getDatabaseManager, getDatabaseProductName, getDatabaseStats, getDatabaseVersion, getDb, getModelFields, hasModel, initializeDatabase, initializeDatabaseWithConfig, isDatabaseInitialized, loadGeneratedFields, mergeContext, parseContext, resetDatabaseManager, resolvePoolTuningFromEnv, testConnection, toContextJson } from '../chunk-YTXZ6HZI.js';
2
- import '../chunk-5NWOQQC4.js';
1
+ export { buildContextWhereClause, buildContextWhereConditions, checkDatabaseHealth, contextMatches, createContextFromSDK, createDatabaseClient, createDatabaseClientFromEnv, extractFieldsFromModel, getAllModelNames, getDatabaseManager, getDatabaseProductName, getDatabaseStats, getDatabaseVersion, getDb, getModelFields, hasModel, initializeDatabase, initializeDatabaseWithConfig, isDatabaseInitialized, loadGeneratedFields, mergeContext, parseContext, resetDatabaseManager, resolvePoolTuningFromEnv, testConnection, toContextJson } from '../chunk-LNFGZMDB.js';
2
+ import '../chunk-OBBCR6WY.js';
3
3
  export { addWorkspaceExtension, defaultWorkspaceExtensionConfig, getWorkspaceContext, injectCreateFields, injectWhereWorkspaceId, maybeSetRlsGuc, maybeTagConnection, runOperationWithRlsGuc, setWorkspaceContext, withWorkspaceContext, withWorkspaceContextSync } from '../chunk-FA5ROGTS.js';
4
4
  export { PrismaClientWrapper, configurePrismaLogging, createConnectionPool, createPrismaAdapter, createPrismaClient, ensureServiceApplicationName, installAcquireRetry, isTransientAcquireError } from '../chunk-L5TDUAFN.js';
5
5
  import '../chunk-QJN4K7LD.js';
@@ -1,4 +1,4 @@
1
- export { PRODUCT_RENAMES, PRODUCT_RENAME_EMIT, PRODUCT_SLUG_ALIASES, RENAME_CONCERNS, billingIdVariants, emitBillingId, emitName, emitProductSlug, emitQuotaKey, emitRbacResource, emitTemplateKey, isLegacyName, isSameBillingId, isSameGraphQLName, isSameName, isSameProductSlug, isSameQuotaKey, isSameRbacResource, isSameTemplateKey, nameVariants, normalizeBillingId, normalizeGraphQLName, normalizeProductSlug, normalizeQuotaKey, normalizeRbacResource, normalizeTemplateKey, productSlugVariants, quotaKeyVariants, rbacResourceVariants, readRenamedEnv, templateKeyVariants, toCurrentName, toLegacyName } from '../chunk-5NWOQQC4.js';
1
+ export { PRODUCT_RENAMES, PRODUCT_RENAME_EMIT, PRODUCT_SLUG_ALIASES, RENAME_CONCERNS, billingIdVariants, emitBillingId, emitName, emitProductSlug, emitQuotaKey, emitRbacResource, emitTemplateKey, isLegacyName, isSameBillingId, isSameGraphQLName, isSameName, isSameProductSlug, isSameQuotaKey, isSameRbacResource, isSameTemplateKey, nameVariants, normalizeBillingId, normalizeGraphQLName, normalizeProductSlug, normalizeQuotaKey, normalizeRbacResource, normalizeTemplateKey, productSlugVariants, quotaKeyVariants, rbacResourceVariants, readRenamedEnv, templateKeyVariants, toCurrentName, toLegacyName } from '../chunk-OBBCR6WY.js';
2
2
  import '../chunk-XE4OXN2W.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
@@ -2,7 +2,7 @@ import { createHumanReadableErrorPlugin, formatHttpError, normalizeGraphQLRespon
2
2
  export { UserFacingGraphQLError, createHttpErrorResponse, createHumanReadableErrorPlugin, createWorkspaceGuardPlugin, formatHttpError, normalizeError, normalizeExecutionResultErrors, normalizeGraphQLResponse, normalizeGraphQLResponsePayload, toUserFacingGraphQLError } from '../chunk-6GL4SLU7.js';
3
3
  import { getWorkspaceQuotaRegistry } from '../chunk-WTEHAVBX.js';
4
4
  import { setWorkspaceContext } from '../chunk-FA5ROGTS.js';
5
- import { I18n } from '../chunk-IUJSIXMM.js';
5
+ import { I18n } from '../chunk-EBDHIL7V.js';
6
6
  import { getMetricsRegistry } from '../chunk-AWPNRV3L.js';
7
7
  import { ContextManager } from '../chunk-RZOFS2BQ.js';
8
8
  import { logger } from '../chunk-RU266375.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/be-sdk",
3
- "version": "2026.927.3",
3
+ "version": "2026.927.5",
4
4
  "description": "Backend SDK for Burdenoff products providing unified access to notifications, RBAC, activity tracking, usage monitoring, and more",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/i18n/index.ts","../src/i18n/types.ts","../src/i18n/parser.ts","../src/i18n/loader.ts","../src/i18n/i18n.ts","../src/i18n/helpers.ts"],"names":["RTL_LANGUAGES","getTextDirection","language","includes","parseLocaleString","localeStr","trimmed","trim","localePart","params","split","quality","param","key","value","toLowerCase","parsed","parseFloat","isNaN","locale","parts","region","toUpperCase","normalizedLocale","parseAcceptLanguage","header","locales","part","push","sort","a","b","extractLocaleFromRequest","request","defaultLocale","explicitLocale","headers","get","acceptLanguage","parsedLocales","length","normalizeLocale","getLanguageFromLocale","getRegionFromLocale","findBestMatch","requested","available","availableSet","Set","map","l","req","has","find","langMatch","translationCache","Map","validateFilePath","filePath","baseDir","resolvedBase","resolve","resolvedPath","relativePath","relative","startsWith","Error","safeReadFile","validatedPath","Bun","file","text","safeStat","stat","catch","safeReaddir","dirPath","readdir","flattenDictionary","obj","prefix","result","Object","entries","fullKey","assign","loadTranslationFile","content","data","JSON","parse","error","logger","getCacheKey","namespace","loadTranslationsForLocale","config","cacheKey","enableCache","pathsToTry","join","localesPath","path","stats","isFile","endsWith","translations","flattened","debug","isDirectory","files","extname","basename","keys","fallbackLocale","warn","fallbackTranslations","undefined","set","discoverLocales","validatedBasePath","entry","entryPath","preloadAllTranslations","supportedLocales","info","Promise","all","clearTranslationCache","delete","clear","getCachedTranslations","setCachedTranslations","getEnglishPluralCategory","absCount","getFrenchPluralCategory","getSlavicPluralCategory","mod10","mod100","getArabicPluralCategory","getPolishCzechPluralCategory","getRomanianPluralCategory","getHebrewPluralCategory","getPluralCategory","count","Math","abs","englishLanguages","interpolate","variables","replace","match","String","I18n","currentLocale","initialized","returnKeyOnMissing","logMissing","initialize","lazyLoad","getLocale","setLocale","getSupportedLocales","isSupported","normalized","some","supportedNorm","loadLocale","getTranslations","t","defaultValue","translate","tp","translatePlural","langTranslations","category","pluralKey","createContext","formatNumber","options","Intl","NumberFormat","format","formatCurrency","currency","style","formatDate","date","dateObj","Date","DateTimeFormat","formatRelativeTime","unit","RelativeTimeFormat","numeric","createContextFromRequest","bestMatch","getLanguageInfo","direction","code","globalI18n","initializeI18n","getI18n","createI18n","interpolateVariables","ctx","defaultMessage","i18n","translated","createTranslator","hasI18n","getLanguage","defaultLanguage","Locales","EN_US","EN_GB","EN_AU","EN_CA","EN_IN","ES_ES","ES_MX","FR_FR","FR_CA","DE_DE","DE_AT","DE_CH","IT_IT","PT_PT","PT_BR","RU_RU","ZH_CN","ZH_TW","ZH_HK","JA_JP","KO_KR","AR_SA","AR_AE","HI_IN","TA_IN","NL_NL","PL_PL","TR_TR","VI_VN","TH_TH","ID_ID","HE_IL","UK_UA","DEFAULT_I18N_CONFIG"],"mappings":"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","file":"chunk-IUJSIXMM.js","sourcesContent":["/**\n * I18n Module\n *\n * Comprehensive internationalization support for backend services.\n *\n * Features:\n * - Load translations from JSON files\n * - Accept-Language header parsing\n * - Translation with variable interpolation\n * - Pluralization support (CLDR rules)\n * - Locale-aware formatting (numbers, dates, currencies)\n * - Request context integration\n *\n * @example\n * ```typescript\n * import { I18n } from '@burdenoff/be-sdk/i18n';\n *\n * // Initialize\n * const i18n = new I18n({\n * defaultLocale: 'en-US',\n * localesPath: './locales',\n * });\n * await i18n.initialize();\n *\n * // Create context for a request\n * const ctx = i18n.createContextFromRequest(request);\n *\n * // Translate\n * const message = ctx.t('errors.notFound', { resource: 'Tag' });\n * // => \"Tag not found\"\n *\n * // Pluralize\n * const items = ctx.tp('items', 5, { count: 5 });\n * // => \"5 items\"\n * ```\n *\n * @packageDocumentation\n */\n\n// Core i18n class and functions\nexport { I18n, initializeI18n, getI18n, createI18n } from './i18n.js';\n\n// Context-based translation helpers (for use in resolvers/providers)\nexport {\n t,\n createTranslator,\n hasI18n,\n getLocale,\n getLanguage,\n type I18nCapableContext,\n type Translator,\n} from './helpers.js';\n\n// Types\nexport type {\n LocaleCode,\n LanguageCode,\n TranslationDictionary,\n FlatTranslationMap,\n TranslationVariables,\n PluralForms,\n TranslateFunction,\n PluralTranslateFunction,\n I18nConfig,\n ParsedLocale,\n I18nContext,\n II18n,\n TextDirection,\n LanguageInfo,\n} from './types.js';\n\n// Type helpers\nexport { RTL_LANGUAGES, getTextDirection } from './types.js';\n\n// Parser functions\nexport {\n parseLocaleString,\n parseAcceptLanguage,\n extractLocaleFromRequest,\n normalizeLocale,\n getLanguageFromLocale,\n getRegionFromLocale,\n findBestMatch,\n} from './parser.js';\n\n// Loader functions\nexport {\n flattenDictionary,\n loadTranslationFile,\n loadTranslationsForLocale,\n discoverLocales,\n preloadAllTranslations,\n clearTranslationCache,\n getCachedTranslations,\n setCachedTranslations,\n} from './loader.js';\n\n// ============================================================================\n// Re-exports for convenience\n// ============================================================================\n\n/**\n * Common locale codes as constants\n */\nexport const Locales = {\n // English\n EN_US: 'en-US' as const,\n EN_GB: 'en-GB' as const,\n EN_AU: 'en-AU' as const,\n EN_CA: 'en-CA' as const,\n EN_IN: 'en-IN' as const,\n // Spanish\n ES_ES: 'es-ES' as const,\n ES_MX: 'es-MX' as const,\n // French\n FR_FR: 'fr-FR' as const,\n FR_CA: 'fr-CA' as const,\n // German\n DE_DE: 'de-DE' as const,\n DE_AT: 'de-AT' as const,\n DE_CH: 'de-CH' as const,\n // Italian\n IT_IT: 'it-IT' as const,\n // Portuguese\n PT_PT: 'pt-PT' as const,\n PT_BR: 'pt-BR' as const,\n // Russian\n RU_RU: 'ru-RU' as const,\n // Chinese\n ZH_CN: 'zh-CN' as const,\n ZH_TW: 'zh-TW' as const,\n ZH_HK: 'zh-HK' as const,\n // Japanese\n JA_JP: 'ja-JP' as const,\n // Korean\n KO_KR: 'ko-KR' as const,\n // Arabic\n AR_SA: 'ar-SA' as const,\n AR_AE: 'ar-AE' as const,\n // Hindi\n HI_IN: 'hi-IN' as const,\n // Tamil\n TA_IN: 'ta-IN' as const,\n // Dutch\n NL_NL: 'nl-NL' as const,\n // Polish\n PL_PL: 'pl-PL' as const,\n // Turkish\n TR_TR: 'tr-TR' as const,\n // Vietnamese\n VI_VN: 'vi-VN' as const,\n // Thai\n TH_TH: 'th-TH' as const,\n // Indonesian\n ID_ID: 'id-ID' as const,\n // Hebrew\n HE_IL: 'he-IL' as const,\n // Ukrainian\n UK_UA: 'uk-UA' as const,\n} as const;\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_I18N_CONFIG = {\n defaultLocale: 'en-US',\n fallbackLocale: 'en-US',\n enableCache: true,\n lazyLoad: false,\n logMissing: true,\n returnKeyOnMissing: true,\n} as const;\n","/**\n * I18n Module Types\n *\n * Type definitions for internationalization support\n */\n\n/**\n * Supported locale codes (BCP 47 format)\n * Language-Region pattern: xx-XX\n */\nexport type LocaleCode =\n // English variants\n | 'en-US'\n | 'en-GB'\n | 'en-AU'\n | 'en-CA'\n | 'en-IN'\n // Spanish variants\n | 'es-ES'\n | 'es-MX'\n | 'es-AR'\n // French variants\n | 'fr-FR'\n | 'fr-CA'\n | 'fr-BE'\n // German variants\n | 'de-DE'\n | 'de-AT'\n | 'de-CH'\n // Italian\n | 'it-IT'\n // Portuguese variants\n | 'pt-PT'\n | 'pt-BR'\n // Russian\n | 'ru-RU'\n // Chinese variants\n | 'zh-CN'\n | 'zh-TW'\n | 'zh-HK'\n // Japanese\n | 'ja-JP'\n // Korean\n | 'ko-KR'\n // Arabic variants\n | 'ar-SA'\n | 'ar-AE'\n | 'ar-EG'\n // Hindi\n | 'hi-IN'\n // Bengali\n | 'bn-IN'\n | 'bn-BD'\n // Tamil\n | 'ta-IN'\n // Telugu\n | 'te-IN'\n // Malayalam\n | 'ml-IN'\n // Dutch\n | 'nl-NL'\n | 'nl-BE'\n // Polish\n | 'pl-PL'\n // Turkish\n | 'tr-TR'\n // Vietnamese\n | 'vi-VN'\n // Thai\n | 'th-TH'\n // Indonesian\n | 'id-ID'\n // Malay\n | 'ms-MY'\n // Swedish\n | 'sv-SE'\n // Norwegian\n | 'nb-NO'\n // Danish\n | 'da-DK'\n // Finnish\n | 'fi-FI'\n // Greek\n | 'el-GR'\n // Czech\n | 'cs-CZ'\n // Romanian\n | 'ro-RO'\n // Hungarian\n | 'hu-HU'\n // Hebrew\n | 'he-IL'\n // Ukrainian\n | 'uk-UA'\n // Generic fallback (allow any valid BCP 47)\n | string;\n\n/**\n * Language code (ISO 639-1)\n */\nexport type LanguageCode =\n | 'en'\n | 'es'\n | 'fr'\n | 'de'\n | 'it'\n | 'pt'\n | 'ru'\n | 'zh'\n | 'ja'\n | 'ko'\n | 'ar'\n | 'hi'\n | 'bn'\n | 'ta'\n | 'te'\n | 'ml'\n | 'nl'\n | 'pl'\n | 'tr'\n | 'vi'\n | 'th'\n | 'id'\n | 'ms'\n | 'sv'\n | 'nb'\n | 'da'\n | 'fi'\n | 'el'\n | 'cs'\n | 'ro'\n | 'hu'\n | 'he'\n | 'uk'\n | string;\n\n/**\n * Translation dictionary type\n * Supports nested keys like { errors: { notFound: \"...\" } }\n * Includes null to match JSON data which may contain null values\n */\nexport type TranslationDictionary = {\n [key: string]: string | TranslationDictionary | null;\n};\n\n/**\n * Flattened translation map\n */\nexport type FlatTranslationMap = Record<string, string>;\n\n/**\n * Translation variables for interpolation\n */\nexport type TranslationVariables = Record<string, string | number | boolean>;\n\n/**\n * Pluralization rules\n */\nexport interface PluralForms {\n zero?: string;\n one: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/**\n * Translation function type\n */\nexport type TranslateFunction = (key: string, variables?: TranslationVariables, defaultValue?: string) => string;\n\n/**\n * Plural translation function type\n */\nexport type PluralTranslateFunction = (key: string, count: number, variables?: TranslationVariables) => string;\n\n/**\n * I18n configuration options\n */\nexport interface I18nConfig {\n /** Default locale if none specified */\n defaultLocale: LocaleCode;\n /** Fallback locale when translation is missing */\n fallbackLocale?: LocaleCode;\n /** Path to locales directory */\n localesPath: string;\n /** Supported locales (if empty, all locales in directory are supported) */\n supportedLocales?: LocaleCode[];\n /** Whether to load translations lazily */\n lazyLoad?: boolean;\n /** Cache translations in memory */\n enableCache?: boolean;\n /** Namespace for this service (e.g., 'tags', 'auth') */\n namespace?: string;\n /** Log missing translations */\n logMissing?: boolean;\n /** Return key on missing translation instead of empty string */\n returnKeyOnMissing?: boolean;\n}\n\n/**\n * Parsed locale information\n */\nexport interface ParsedLocale {\n /** Full locale code (e.g., 'en-US') */\n locale: LocaleCode;\n /** Language code (e.g., 'en') */\n language: LanguageCode;\n /** Region code (e.g., 'US') */\n region?: string;\n /** Quality factor from Accept-Language header (0-1) */\n quality: number;\n}\n\n/**\n * I18n context for requests\n */\nexport interface I18nContext {\n /** Current locale */\n locale: LocaleCode;\n /** Language code */\n language: LanguageCode;\n /** Region code */\n region?: string;\n /** Geography: ISO 3166-1 alpha-2 country code (e.g., 'IN', 'US', 'DE') — from x-geo-country header */\n country?: string;\n /** Geography: ISO 4217 currency code (e.g., 'INR', 'USD', 'EUR') — from x-geo-currency header */\n currency?: string;\n /** Geography: IANA timezone (e.g., 'Asia/Kolkata', 'America/New_York') — from x-geo-timezone header */\n timezone?: string;\n /** Translation function */\n t: TranslateFunction;\n /** Plural translation function */\n tp: PluralTranslateFunction;\n /** Format number for locale */\n formatNumber: (value: number, options?: Intl.NumberFormatOptions) => string;\n /** Format currency for locale */\n formatCurrency: (value: number, currency: string) => string;\n /** Format date for locale */\n formatDate: (date: Date | string, options?: Intl.DateTimeFormatOptions) => string;\n /** Format relative time for locale */\n formatRelativeTime: (value: number, unit: Intl.RelativeTimeFormatUnit) => string;\n}\n\n/**\n * I18n instance interface\n */\nexport interface II18n {\n /** Get current locale */\n getLocale(): LocaleCode;\n /** Set current locale */\n setLocale(locale: LocaleCode): void;\n /** Get supported locales */\n getSupportedLocales(): LocaleCode[];\n /** Check if locale is supported */\n isSupported(locale: LocaleCode): boolean;\n /** Translate a key */\n t: TranslateFunction;\n /** Translate with pluralization */\n tp: PluralTranslateFunction;\n /** Create context for request */\n createContext(locale: LocaleCode): I18nContext;\n /** Load translations for a locale */\n loadLocale(locale: LocaleCode): Promise<void>;\n /** Get all translations for a locale */\n getTranslations(locale: LocaleCode): FlatTranslationMap | undefined;\n}\n\n/**\n * Language direction\n */\nexport type TextDirection = 'ltr' | 'rtl';\n\n/**\n * Language metadata\n */\nexport interface LanguageInfo {\n code: LanguageCode;\n name: string;\n nativeName: string;\n direction: TextDirection;\n locales: LocaleCode[];\n}\n\n/**\n * RTL languages\n */\nexport const RTL_LANGUAGES: LanguageCode[] = ['ar', 'he'];\n\n/**\n * Get text direction for a language\n */\nexport function getTextDirection(language: LanguageCode): TextDirection {\n return RTL_LANGUAGES.includes(language) ? 'rtl' : 'ltr';\n}\n","/**\n * I18n Parser Module\n *\n * Parses Accept-Language headers and locale strings\n */\n\nimport type { LocaleCode, LanguageCode, ParsedLocale } from './types.js';\n\n/**\n * Parse a single locale string (e.g., 'en-US', 'fr;q=0.9')\n */\nexport function parseLocaleString(localeStr: string): ParsedLocale | null {\n const trimmed = localeStr.trim();\n if (!trimmed || trimmed === '*') {\n return null;\n }\n\n // Parse quality factor if present (e.g., 'en-US;q=0.9')\n const [localePart, ...params] = trimmed.split(';');\n let quality = 1.0;\n\n for (const param of params) {\n const [key, value] = param.trim().split('=');\n if (key?.toLowerCase() === 'q' && value) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed) && parsed >= 0 && parsed <= 1) {\n quality = parsed;\n }\n }\n }\n\n const locale = localePart?.trim();\n if (!locale) {\n return null;\n }\n\n // Parse language and region\n const parts = locale.split('-');\n const language = parts[0]?.toLowerCase() as LanguageCode;\n const region = parts[1]?.toUpperCase();\n\n // Reconstruct proper locale code\n const normalizedLocale = region ? `${language}-${region}` : language;\n\n return {\n locale: normalizedLocale,\n language,\n region,\n quality,\n };\n}\n\n/**\n * Parse Accept-Language header\n *\n * Example: 'en-US,en;q=0.9,fr;q=0.8,de;q=0.7'\n *\n * @param header The Accept-Language header value\n * @returns Array of parsed locales sorted by quality (highest first)\n */\nexport function parseAcceptLanguage(header: string | null | undefined): ParsedLocale[] {\n if (!header || header.trim() === '') {\n return [];\n }\n\n const locales: ParsedLocale[] = [];\n\n // Split by comma and parse each part\n const parts = header.split(',');\n for (const part of parts) {\n const parsed = parseLocaleString(part);\n if (parsed) {\n locales.push(parsed);\n }\n }\n\n // Sort by quality factor (highest first)\n locales.sort((a, b) => b.quality - a.quality);\n\n return locales;\n}\n\n/**\n * Extract locale from request headers\n *\n * Checks in order:\n * 1. X-Locale header (explicit override)\n * 2. X-Language header (explicit override)\n * 3. Accept-Language header\n *\n * @param request Web API Request object\n * @param defaultLocale Default locale to return if none found\n * @returns The best matching locale\n */\nexport function extractLocaleFromRequest(request: Request, defaultLocale: LocaleCode = 'en-US'): ParsedLocale {\n // Check explicit locale header first\n const explicitLocale = request.headers.get('x-locale') || request.headers.get('x-language');\n if (explicitLocale) {\n const parsed = parseLocaleString(explicitLocale);\n if (parsed) {\n return parsed;\n }\n }\n\n // Parse Accept-Language header\n const acceptLanguage = request.headers.get('accept-language');\n const parsedLocales = parseAcceptLanguage(acceptLanguage);\n\n if (parsedLocales.length > 0) {\n return parsedLocales[0]!;\n }\n\n // Return default locale\n const [language, region] = defaultLocale.split('-');\n return {\n locale: defaultLocale,\n language: language as LanguageCode,\n region: region,\n quality: 1.0,\n };\n}\n\n/**\n * Normalize a locale code to standard format\n *\n * @param locale The locale to normalize\n * @returns Normalized locale (e.g., 'en-us' -> 'en-US')\n */\nexport function normalizeLocale(locale: string): LocaleCode {\n const parts = locale.trim().split(/[-_]/);\n const language = parts[0]?.toLowerCase();\n const region = parts[1]?.toUpperCase();\n\n if (region) {\n return `${language}-${region}`;\n }\n return language as LocaleCode;\n}\n\n/**\n * Get the language code from a locale\n */\nexport function getLanguageFromLocale(locale: LocaleCode): LanguageCode {\n return locale.split('-')[0] as LanguageCode;\n}\n\n/**\n * Get the region code from a locale\n */\nexport function getRegionFromLocale(locale: LocaleCode): string | undefined {\n const parts = locale.split('-');\n return parts[1];\n}\n\n/**\n * Find the best matching locale from available locales\n *\n * @param requested Requested locales (sorted by preference)\n * @param available Available locales\n * @param defaultLocale Default locale to use if no match\n * @returns The best matching locale\n */\nexport function findBestMatch(\n requested: ParsedLocale[],\n available: LocaleCode[],\n defaultLocale: LocaleCode\n): LocaleCode {\n const availableSet = new Set(available.map((l) => l.toLowerCase()));\n\n for (const req of requested) {\n // Try exact match first (e.g., 'en-US')\n if (availableSet.has(req.locale.toLowerCase())) {\n // Return with proper casing from available\n return available.find((l) => l.toLowerCase() === req.locale.toLowerCase()) || req.locale;\n }\n\n // Try language-only match (e.g., 'en')\n if (availableSet.has(req.language.toLowerCase())) {\n return available.find((l) => l.toLowerCase() === req.language.toLowerCase()) || req.language;\n }\n\n // Try to find any locale with the same language\n const langMatch = available.find((l) => getLanguageFromLocale(l).toLowerCase() === req.language.toLowerCase());\n if (langMatch) {\n return langMatch;\n }\n }\n\n return defaultLocale;\n}\n","/**\n * I18n Loader Module\n *\n * Loads and manages translation files from the filesystem\n */\n\nimport { readdir, stat } from 'fs/promises';\nimport { join, extname, basename, resolve, relative } from 'path';\nimport type { LocaleCode, TranslationDictionary, FlatTranslationMap, I18nConfig } from './types.js';\nimport { normalizeLocale, getLanguageFromLocale } from './parser.js';\nimport { logger } from '../logger/index.js';\n\n/**\n * Translation cache\n */\nconst translationCache = new Map<string, FlatTranslationMap>();\n\n/**\n * Validate that a file path is within the allowed base directory\n * Prevents directory traversal attacks\n *\n * @param filePath The file path to validate\n * @param baseDir The base directory that must contain the file\n * @returns The resolved absolute path if valid\n * @throws Error if path escapes the base directory\n */\nfunction validateFilePath(filePath: string, baseDir: string): string {\n const resolvedBase = resolve(baseDir);\n const resolvedPath = resolve(filePath);\n const relativePath = relative(resolvedBase, resolvedPath);\n\n // If relative path starts with '..' or is absolute, it's outside base directory\n if (relativePath.startsWith('..') || resolve(relativePath) === relativePath) {\n throw new Error(`Invalid file path: ${filePath} is outside base directory ${baseDir}`);\n }\n\n return resolvedPath;\n}\n\n/**\n * Safely read a file with path validation\n * Path is validated before reading to prevent directory traversal attacks\n */\nasync function safeReadFile(filePath: string, baseDir: string): Promise<string> {\n const validatedPath = validateFilePath(filePath, baseDir);\n return Bun.file(validatedPath).text();\n}\n\n/**\n * Safely stat a file with path validation\n * Path is validated before stat to prevent directory traversal attacks\n */\nasync function safeStat(filePath: string, baseDir: string): Promise<Awaited<ReturnType<typeof stat>> | null> {\n const validatedPath = validateFilePath(filePath, baseDir);\n return stat(validatedPath).catch(() => null);\n}\n\n/**\n * Safely read directory with path validation\n * Path is validated before readdir to prevent directory traversal attacks\n */\nasync function safeReaddir(dirPath: string, baseDir: string): Promise<string[]> {\n const validatedPath = validateFilePath(dirPath, baseDir);\n return readdir(validatedPath);\n}\n\n/**\n * Flatten a nested translation dictionary\n *\n * @param obj The nested dictionary\n * @param prefix Current key prefix\n * @returns Flattened key-value map\n */\nexport function flattenDictionary(obj: TranslationDictionary, prefix = ''): FlatTranslationMap {\n const result: FlatTranslationMap = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'string') {\n result[fullKey] = value;\n } else if (value !== null && typeof value === 'object') {\n // Check null first to avoid different-types-comparison warning\n // (typeof null === 'object' is a JavaScript quirk)\n Object.assign(result, flattenDictionary(value, fullKey));\n }\n }\n\n return result;\n}\n\n/**\n * Load a single translation file\n *\n * @param filePath Path to the translation file\n * @param baseDir Base directory for validation\n * @returns The loaded translations\n */\nexport async function loadTranslationFile(filePath: string, baseDir: string): Promise<TranslationDictionary> {\n try {\n const content = await safeReadFile(filePath, baseDir);\n const data = JSON.parse(content) as TranslationDictionary;\n return data;\n } catch (error) {\n logger.error(`[I18n] Failed to load translation file: ${filePath}`, error);\n return {};\n }\n}\n\n/**\n * Get cache key for translations\n */\nfunction getCacheKey(namespace: string | undefined, locale: LocaleCode): string {\n return namespace ? `${namespace}:${locale}` : locale;\n}\n\n/**\n * Load translations for a locale from a directory\n *\n * Supports multiple file formats:\n * - locales/en-US.json (single file per locale)\n * - locales/en-US/common.json (directory per locale with namespace files)\n * - locales/en.json (language-only fallback)\n *\n * @param config I18n configuration\n * @param locale The locale to load\n * @returns Flattened translations map\n */\nexport async function loadTranslationsForLocale(config: I18nConfig, locale: LocaleCode): Promise<FlatTranslationMap> {\n const cacheKey = getCacheKey(config.namespace, locale);\n\n // Check cache first\n if (config.enableCache !== false && translationCache.has(cacheKey)) {\n return translationCache.get(cacheKey)!;\n }\n\n const normalizedLocale = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalizedLocale);\n const result: FlatTranslationMap = {};\n\n // Try loading in order of specificity\n const pathsToTry = [\n // Most specific: full locale\n join(config.localesPath, `${normalizedLocale}.json`),\n // Directory format\n join(config.localesPath, normalizedLocale),\n // Language only fallback\n join(config.localesPath, `${language}.json`),\n // Language directory\n join(config.localesPath, language),\n ];\n\n for (const path of pathsToTry) {\n try {\n const stats = await safeStat(path, config.localesPath);\n if (!stats) continue;\n\n if (stats.isFile() && path.endsWith('.json')) {\n // Single file\n const translations = await loadTranslationFile(path, config.localesPath);\n const flattened = flattenDictionary(translations);\n Object.assign(result, flattened);\n logger.debug(`[I18n] Loaded translations from ${path}`);\n break;\n } else if (stats.isDirectory()) {\n // Directory with multiple namespace files\n const files = await safeReaddir(path, config.localesPath);\n for (const file of files) {\n if (extname(file) === '.json') {\n const namespace = basename(file, '.json');\n const filePath = join(path, file);\n const translations = await loadTranslationFile(filePath, config.localesPath);\n const flattened = flattenDictionary(translations, namespace);\n Object.assign(result, flattened);\n logger.debug(`[I18n] Loaded namespace ${namespace} from ${filePath}`);\n }\n }\n break;\n }\n } catch {\n // Continue trying next path\n }\n }\n\n // If nothing loaded and we have a fallback, try that\n if (Object.keys(result).length === 0 && config.fallbackLocale && config.fallbackLocale !== locale) {\n logger.warn(`[I18n] No translations found for ${locale}, trying fallback ${config.fallbackLocale}`);\n const fallbackTranslations = await loadTranslationsForLocale(\n { ...config, fallbackLocale: undefined },\n config.fallbackLocale\n );\n Object.assign(result, fallbackTranslations);\n }\n\n // Cache the result\n if (config.enableCache !== false) {\n translationCache.set(cacheKey, result);\n }\n\n return result;\n}\n\n/**\n * Discover available locales in a directory\n *\n * @param localesPath Path to locales directory\n * @returns Array of available locale codes\n */\nexport async function discoverLocales(localesPath: string): Promise<LocaleCode[]> {\n const locales: LocaleCode[] = [];\n\n try {\n const validatedBasePath = resolve(localesPath);\n const entries = await readdir(validatedBasePath);\n\n for (const entry of entries) {\n const entryPath = join(validatedBasePath, entry);\n const stats = await safeStat(entryPath, validatedBasePath);\n if (!stats) continue;\n\n if (stats.isFile() && entry.endsWith('.json')) {\n // Single file: en-US.json or en.json\n const locale = basename(entry, '.json');\n locales.push(normalizeLocale(locale));\n } else if (stats.isDirectory()) {\n // Directory: en-US/ or en/\n locales.push(normalizeLocale(entry));\n }\n }\n } catch (error) {\n logger.error(`[I18n] Failed to discover locales in ${localesPath}`, error);\n }\n\n return locales;\n}\n\n/**\n * Preload all translations for supported locales\n *\n * @param config I18n configuration\n */\nexport async function preloadAllTranslations(config: I18nConfig): Promise<void> {\n const locales = config.supportedLocales || (await discoverLocales(config.localesPath));\n\n logger.info(`[I18n] Preloading translations for ${locales.length} locales...`);\n\n await Promise.all(\n locales.map(async (locale) => {\n try {\n await loadTranslationsForLocale(config, locale);\n } catch (error) {\n logger.error(`[I18n] Failed to preload locale ${locale}`, error);\n }\n })\n );\n\n logger.info(`[I18n] Preloaded translations for: ${locales.join(', ')}`);\n}\n\n/**\n * Clear the translation cache\n *\n * @param namespace Optional namespace to clear (clears all if not provided)\n */\nexport function clearTranslationCache(namespace?: string): void {\n if (namespace) {\n for (const key of translationCache.keys()) {\n if (key.startsWith(`${namespace}:`)) {\n translationCache.delete(key);\n }\n }\n } else {\n translationCache.clear();\n }\n}\n\n/**\n * Get cached translations for a locale\n */\nexport function getCachedTranslations(\n namespace: string | undefined,\n locale: LocaleCode\n): FlatTranslationMap | undefined {\n return translationCache.get(getCacheKey(namespace, locale));\n}\n\n/**\n * Set translations in cache (useful for testing or dynamic loading)\n */\nexport function setCachedTranslations(\n namespace: string | undefined,\n locale: LocaleCode,\n translations: FlatTranslationMap\n): void {\n translationCache.set(getCacheKey(namespace, locale), translations);\n}\n","/**\n * I18n Class\n *\n * Main internationalization class providing translation and formatting functions\n */\n\nimport type {\n LocaleCode,\n LanguageCode,\n I18nConfig,\n I18nContext,\n II18n,\n FlatTranslationMap,\n TranslationVariables,\n TranslateFunction,\n PluralTranslateFunction,\n} from './types.js';\nimport { getTextDirection } from './types.js';\nimport { loadTranslationsForLocale, preloadAllTranslations, discoverLocales, getCachedTranslations } from './loader.js';\nimport {\n normalizeLocale,\n getLanguageFromLocale,\n getRegionFromLocale,\n findBestMatch,\n extractLocaleFromRequest,\n} from './parser.js';\nimport { logger } from '../logger/index.js';\n\n/**\n * Pluralization category based on CLDR rules\n */\ntype PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';\n\n/**\n * English and most Germanic/Romance languages (simple one/other)\n */\nfunction getEnglishPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n return 'other';\n}\n\n/**\n * French pluralization (0 or 1 = one, else other)\n */\nfunction getFrenchPluralCategory(absCount: number): PluralCategory {\n if (absCount === 0 || absCount === 1) return 'one';\n return 'other';\n}\n\n/**\n * Slavic languages (Russian, Ukrainian) - complex: one, few, many, other\n */\nfunction getSlavicPluralCategory(absCount: number): PluralCategory {\n const mod10 = absCount % 10;\n const mod100 = absCount % 100;\n\n if (mod10 === 1 && mod100 !== 11) return 'one';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'few';\n if (mod10 === 0 || (mod10 >= 5 && mod10 <= 9) || (mod100 >= 11 && mod100 <= 14)) return 'many';\n return 'other';\n}\n\n/**\n * Arabic pluralization (zero, one, two, few, many, other)\n */\nfunction getArabicPluralCategory(absCount: number): PluralCategory {\n if (absCount === 0) return 'zero';\n if (absCount === 1) return 'one';\n if (absCount === 2) return 'two';\n const mod100 = absCount % 100;\n if (mod100 >= 3 && mod100 <= 10) return 'few';\n if (mod100 >= 11 && mod100 <= 99) return 'many';\n return 'other';\n}\n\n/**\n * Polish/Czech pluralization (one, few, many)\n */\nfunction getPolishCzechPluralCategory(absCount: number): PluralCategory {\n const mod10 = absCount % 10;\n const mod100 = absCount % 100;\n\n if (absCount === 1) return 'one';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'few';\n return 'many';\n}\n\n/**\n * Romanian pluralization (one, few, other)\n */\nfunction getRomanianPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n const mod100 = absCount % 100;\n if (absCount === 0 || (mod100 >= 1 && mod100 <= 19)) return 'few';\n return 'other';\n}\n\n/**\n * Hebrew pluralization (one, two, other)\n */\nfunction getHebrewPluralCategory(absCount: number): PluralCategory {\n if (absCount === 1) return 'one';\n if (absCount === 2) return 'two';\n return 'other';\n}\n\n/**\n * Get plural category for a count in a given language\n * Based on CLDR plural rules: https://cldr.unicode.org/index/cldr-spec/plural-rules\n */\nfunction getPluralCategory(language: LanguageCode, count: number): PluralCategory {\n const absCount = Math.abs(count);\n\n // English and most Germanic/Romance languages\n const englishLanguages = [\n 'en',\n 'de',\n 'es',\n 'it',\n 'nl',\n 'sv',\n 'da',\n 'nb',\n 'fi',\n 'pt',\n 'el',\n 'hu',\n 'tr',\n 'id',\n 'ms',\n 'th',\n 'vi',\n 'ko',\n 'zh',\n 'ja',\n ];\n if (englishLanguages.includes(language)) {\n return getEnglishPluralCategory(absCount);\n }\n\n // French\n if (language === 'fr') {\n return getFrenchPluralCategory(absCount);\n }\n\n // Russian, Ukrainian\n if (language === 'ru' || language === 'uk') {\n return getSlavicPluralCategory(absCount);\n }\n\n // Arabic\n if (language === 'ar') {\n return getArabicPluralCategory(absCount);\n }\n\n // Polish, Czech\n if (language === 'pl' || language === 'cs') {\n return getPolishCzechPluralCategory(absCount);\n }\n\n // Romanian\n if (language === 'ro') {\n return getRomanianPluralCategory(absCount);\n }\n\n // Hebrew\n if (language === 'he') {\n return getHebrewPluralCategory(absCount);\n }\n\n // Default: simple singular/plural\n return getEnglishPluralCategory(absCount);\n}\n\n/**\n * Interpolate variables in a translation string\n *\n * Supports:\n * - {{variable}} - simple interpolation\n * - {{variable, number}} - number formatting (future)\n * - {{variable, date}} - date formatting (future)\n */\nfunction interpolate(text: string, variables?: TranslationVariables): string {\n if (!variables || !text) {\n return text;\n }\n\n // Use more specific pattern to avoid catastrophic backtracking\n // Matches {{ variableName }} with word characters (alphanumeric and underscore)\n return text.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, key: string) => {\n const value = variables[key.trim()];\n if (value !== undefined) {\n return String(value);\n }\n return match; // Keep original if variable not found\n });\n}\n\n/**\n * I18n Class\n *\n * Main class for internationalization functionality\n */\nexport class I18n implements II18n {\n private config: I18nConfig;\n private currentLocale: LocaleCode;\n private supportedLocales: LocaleCode[] = [];\n private initialized = false;\n\n constructor(config: I18nConfig) {\n this.config = {\n ...config,\n fallbackLocale: config.fallbackLocale || 'en-US',\n enableCache: config.enableCache !== false,\n returnKeyOnMissing: config.returnKeyOnMissing !== false,\n logMissing: config.logMissing !== false,\n };\n this.currentLocale = normalizeLocale(config.defaultLocale);\n }\n\n /**\n * Initialize the i18n instance\n * Discovers available locales and optionally preloads translations\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n // Discover available locales\n if (this.config.supportedLocales && this.config.supportedLocales.length > 0) {\n this.supportedLocales = this.config.supportedLocales;\n } else {\n this.supportedLocales = await discoverLocales(this.config.localesPath);\n }\n\n // Preload translations if not lazy loading\n if (!this.config.lazyLoad) {\n await preloadAllTranslations(this.config);\n }\n\n this.initialized = true;\n logger.info(`[I18n] Initialized with ${this.supportedLocales.length} locales, default: ${this.currentLocale}`);\n }\n\n /**\n * Get current locale\n */\n getLocale(): LocaleCode {\n return this.currentLocale;\n }\n\n /**\n * Set current locale\n */\n setLocale(locale: LocaleCode): void {\n this.currentLocale = normalizeLocale(locale);\n }\n\n /**\n * Get supported locales\n */\n getSupportedLocales(): LocaleCode[] {\n return [...this.supportedLocales];\n }\n\n /**\n * Check if a locale is supported\n */\n isSupported(locale: LocaleCode): boolean {\n const normalized = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalized);\n\n return this.supportedLocales.some((l) => {\n const supportedNorm = normalizeLocale(l);\n // Exact match or language match\n return supportedNorm === normalized || getLanguageFromLocale(supportedNorm) === language;\n });\n }\n\n /**\n * Load translations for a specific locale\n */\n async loadLocale(locale: LocaleCode): Promise<void> {\n await loadTranslationsForLocale(this.config, locale);\n }\n\n /**\n * Get all translations for a locale\n */\n getTranslations(locale: LocaleCode): FlatTranslationMap | undefined {\n return getCachedTranslations(this.config.namespace, locale);\n }\n\n /**\n * Translate a key\n */\n t: TranslateFunction = (key: string, variables?: TranslationVariables, defaultValue?: string): string => {\n return this.translate(this.currentLocale, key, variables, defaultValue);\n };\n\n /**\n * Translate with pluralization\n */\n tp: PluralTranslateFunction = (key: string, count: number, variables?: TranslationVariables): string => {\n return this.translatePlural(this.currentLocale, key, count, variables);\n };\n\n /**\n * Internal translate method\n */\n private translate(locale: LocaleCode, key: string, variables?: TranslationVariables, defaultValue?: string): string {\n const translations = getCachedTranslations(this.config.namespace, locale);\n let text = translations?.[key];\n\n // Try fallback locale if not found\n if (!text && this.config.fallbackLocale && locale !== this.config.fallbackLocale) {\n const fallbackTranslations = getCachedTranslations(this.config.namespace, this.config.fallbackLocale);\n text = fallbackTranslations?.[key];\n }\n\n // Try language-only fallback\n if (!text) {\n const language = getLanguageFromLocale(locale);\n if (language !== locale) {\n const langTranslations = getCachedTranslations(this.config.namespace, language);\n text = langTranslations?.[key];\n }\n }\n\n if (!text) {\n if (this.config.logMissing) {\n logger.warn(`[I18n] Missing translation for key: ${key} in locale: ${locale}`);\n }\n // Return default value, key, or empty string — interpolated.\n //\n // The caller's fallback is a real message, not a placeholder for one, so\n // it gets the same `{{var}}` substitution a found translation does.\n // Without this a missing key degrades to raw markup in user-facing output\n // (e.g. a careers confirmation email reading \"Hi {{name}}, thanks for\n // applying for the {{position}} role\"), which is worse than the untranslated\n // English it was meant to fall back to.\n return interpolate(defaultValue ?? (this.config.returnKeyOnMissing ? key : ''), variables);\n }\n\n return interpolate(text, variables);\n }\n\n /**\n * Internal translate with pluralization\n */\n private translatePlural(locale: LocaleCode, key: string, count: number, variables?: TranslationVariables): string {\n const language = getLanguageFromLocale(locale);\n const category = getPluralCategory(language, count);\n\n // Try plural-specific key first (e.g., 'items.one', 'items.other')\n const pluralKey = `${key}.${category}`;\n let text = this.translate(locale, pluralKey, undefined, '');\n\n // Fallback to 'other' if specific form not found\n if (!text && category !== 'other') {\n text = this.translate(locale, `${key}.other`, undefined, '');\n }\n\n // Final fallback to base key\n if (!text) {\n text = this.translate(locale, key, undefined, key);\n }\n\n return interpolate(text, { ...variables, count });\n }\n\n /**\n * Create an i18n context for a specific locale\n */\n createContext(locale: LocaleCode): I18nContext {\n const normalizedLocale = normalizeLocale(locale);\n const language = getLanguageFromLocale(normalizedLocale);\n const region = getRegionFromLocale(normalizedLocale);\n\n // Create bound translate functions for this locale\n const t: TranslateFunction = (key, variables, defaultValue) => {\n return this.translate(normalizedLocale, key, variables, defaultValue);\n };\n\n const tp: PluralTranslateFunction = (key, count, variables) => {\n return this.translatePlural(normalizedLocale, key, count, variables);\n };\n\n const formatNumber = (value: number, options?: Intl.NumberFormatOptions): string => {\n return new Intl.NumberFormat(normalizedLocale, options).format(value);\n };\n\n const formatCurrency = (value: number, currency: string): string => {\n return new Intl.NumberFormat(normalizedLocale, {\n style: 'currency',\n currency,\n }).format(value);\n };\n\n const formatDate = (date: Date | string, options?: Intl.DateTimeFormatOptions): string => {\n const dateObj = typeof date === 'string' ? new Date(date) : date;\n return new Intl.DateTimeFormat(normalizedLocale, options).format(dateObj);\n };\n\n const formatRelativeTime = (value: number, unit: Intl.RelativeTimeFormatUnit): string => {\n return new Intl.RelativeTimeFormat(normalizedLocale, { numeric: 'auto' }).format(value, unit);\n };\n\n return {\n locale: normalizedLocale,\n language,\n region,\n t,\n tp,\n formatNumber,\n formatCurrency,\n formatDate,\n formatRelativeTime,\n };\n }\n\n /**\n * Create context from a request\n */\n createContextFromRequest(request: Request): I18nContext {\n const parsed = extractLocaleFromRequest(request, this.config.defaultLocale);\n const bestMatch = findBestMatch([parsed], this.supportedLocales, this.config.defaultLocale);\n return this.createContext(bestMatch);\n }\n\n /**\n * Get language metadata\n */\n getLanguageInfo(locale: LocaleCode): {\n code: LanguageCode;\n direction: 'ltr' | 'rtl';\n locale: LocaleCode;\n region?: string;\n } {\n const language = getLanguageFromLocale(locale);\n const region = getRegionFromLocale(locale);\n const direction = getTextDirection(language);\n\n return {\n code: language,\n direction,\n locale,\n region,\n };\n }\n}\n\n/**\n * Singleton instance (optional, for simpler usage)\n */\nlet globalI18n: I18n | null = null;\n\n/**\n * Initialize global i18n instance\n */\nexport async function initializeI18n(config: I18nConfig): Promise<I18n> {\n globalI18n = new I18n(config);\n await globalI18n.initialize();\n return globalI18n;\n}\n\n/**\n * Get global i18n instance\n */\nexport function getI18n(): I18n | null {\n return globalI18n;\n}\n\n/**\n * Create a new i18n instance (for isolated use)\n */\nexport function createI18n(config: I18nConfig): I18n {\n return new I18n(config);\n}\n","/**\n * I18n Translation Helpers\n *\n * Provides utilities for getting translated messages from GraphQL/request context.\n * These helpers work with any context that has an optional `i18n` property.\n *\n * Falls back to the provided default message if i18n is not available or translation is missing.\n *\n * @example\n * ```typescript\n * import { t, createTranslator } from '@burdenoff/be-sdk';\n *\n * // Direct usage with context\n * const message = t(ctx, 'tags.errors.notFound', 'Tag not found');\n * const message = t(ctx, 'tags.errors.keyExists', 'Tag {{key}} already exists', { key: 'my-tag' });\n *\n * // Create a bound translator for a specific context\n * const translate = createTranslator(ctx);\n * const message = translate('tags.errors.notFound', 'Tag not found');\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { I18nContext, TranslationVariables } from './types.js';\n\n/**\n * Context with optional i18n\n * Works with any object that has an optional i18n property\n */\nexport interface I18nCapableContext {\n i18n?: I18nContext;\n}\n\n/**\n * Interpolate variables in a string\n *\n * @param text - Text with {{variable}} placeholders\n * @param variables - Variables to interpolate\n * @returns Interpolated string\n */\nfunction interpolateVariables(text: string, variables?: TranslationVariables): string {\n if (!variables) return text;\n\n return text.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key: string) => {\n const value = variables[key];\n return value !== undefined ? String(value) : match;\n });\n}\n\n/**\n * Get a translated message from context\n *\n * This is the primary function for getting translations in providers and resolvers.\n * It gracefully handles cases where i18n is not available by returning the default message.\n *\n * @param ctx - Context with optional i18n (GraphQL context, request context, etc.)\n * @param key - Translation key (e.g., 'tags.errors.notFound')\n * @param defaultMessage - Fallback message if translation not found\n * @param variables - Optional variables for interpolation\n * @returns Translated message or default message\n *\n * @example\n * ```typescript\n * // Simple usage\n * const message = t(ctx, 'tags.errors.notFound', 'Tag not found');\n *\n * // With variables\n * const message = t(ctx, 'tags.errors.keyAlreadyExists', 'Tag with key {{key}} already exists', { key: 'my-tag' });\n *\n * // In a GraphQL resolver\n * if (!userId) {\n * throw new Error(t(context, 'common.errors.notAuthenticated', 'User not authenticated'));\n * }\n * ```\n */\nexport function t(\n ctx: I18nCapableContext,\n key: string,\n defaultMessage: string,\n variables?: TranslationVariables\n): string {\n // If i18n is not available, interpolate and return default message\n if (!ctx.i18n?.t) {\n return interpolateVariables(defaultMessage, variables);\n }\n\n // Get translation with fallback to default\n const translated = ctx.i18n.t(key, variables, defaultMessage);\n\n // If translation returns the key (not found), use default message\n if (translated === key) {\n return interpolateVariables(defaultMessage, variables);\n }\n\n return translated;\n}\n\n/**\n * Translator function type\n */\nexport type Translator = (key: string, defaultMessage: string, variables?: TranslationVariables) => string;\n\n/**\n * Create a bound translator function for a specific context\n *\n * This is useful when you need to pass a translator to services or\n * when you want to avoid repeating the context parameter.\n *\n * @param ctx - Context with optional i18n\n * @returns Translate function bound to the context\n *\n * @example\n * ```typescript\n * // Create translator\n * const translate = createTranslator(ctx);\n *\n * // Use it multiple times\n * const msg1 = translate('tags.errors.notFound', 'Tag not found');\n * const msg2 = translate('tags.errors.keyExists', 'Key {{key}} exists', { key: 'foo' });\n *\n * // Pass to a service\n * await someService.process(data, { translate });\n * ```\n */\nexport function createTranslator(ctx: I18nCapableContext): Translator {\n return (key: string, defaultMessage: string, variables?: TranslationVariables) => {\n return t(ctx, key, defaultMessage, variables);\n };\n}\n\n/**\n * Check if context has i18n support\n *\n * @param ctx - Context to check\n * @returns True if i18n is available and initialized\n */\nexport function hasI18n(ctx: I18nCapableContext): ctx is I18nCapableContext & { i18n: I18nContext } {\n return ctx.i18n?.t !== undefined;\n}\n\n/**\n * Get the current locale from context\n *\n * @param ctx - Context with optional i18n\n * @param defaultLocale - Default locale if i18n not available\n * @returns Current locale code\n */\nexport function getLocale(ctx: I18nCapableContext, defaultLocale: string = 'en-US'): string {\n return ctx.i18n?.locale ?? defaultLocale;\n}\n\n/**\n * Get the current language from context\n *\n * @param ctx - Context with optional i18n\n * @param defaultLanguage - Default language if i18n not available\n * @returns Current language code\n */\nexport function getLanguage(ctx: I18nCapableContext, defaultLanguage: string = 'en'): string {\n return ctx.i18n?.language ?? defaultLanguage;\n}\n"]}