@adriangalilea/utils 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +29 -5
  2. package/dist/bot/access-control.d.ts +106 -62
  3. package/dist/bot/access-control.d.ts.map +1 -1
  4. package/dist/bot/access-control.js +255 -146
  5. package/dist/bot/access-control.js.map +1 -1
  6. package/dist/bot/index.d.ts +3 -0
  7. package/dist/bot/index.d.ts.map +1 -1
  8. package/dist/bot/index.js +3 -0
  9. package/dist/bot/index.js.map +1 -1
  10. package/dist/bot/kit.d.ts.map +1 -1
  11. package/dist/bot/kit.js +6 -0
  12. package/dist/bot/kit.js.map +1 -1
  13. package/dist/bot/language.d.ts +305 -0
  14. package/dist/bot/language.d.ts.map +1 -0
  15. package/dist/bot/language.js +250 -0
  16. package/dist/bot/language.js.map +1 -0
  17. package/dist/bot/menu.d.ts +189 -0
  18. package/dist/bot/menu.d.ts.map +1 -0
  19. package/dist/bot/menu.js +331 -0
  20. package/dist/bot/menu.js.map +1 -0
  21. package/dist/bot/message-history.d.ts +259 -0
  22. package/dist/bot/message-history.d.ts.map +1 -0
  23. package/dist/bot/message-history.js +111 -0
  24. package/dist/bot/message-history.js.map +1 -0
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +2 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/say/index.d.ts +62 -0
  30. package/dist/say/index.d.ts.map +1 -0
  31. package/dist/say/index.js +59 -0
  32. package/dist/say/index.js.map +1 -0
  33. package/package.json +17 -1
  34. package/dist/currency/crypto-symbols-data.d.ts +0 -10
  35. package/dist/currency/crypto-symbols-data.d.ts.map +0 -1
  36. package/dist/currency/crypto-symbols-data.js +0 -13765
  37. package/dist/currency/crypto-symbols-data.js.map +0 -1
  38. package/dist/currency/crypto-symbols.d.ts +0 -20
  39. package/dist/currency/crypto-symbols.d.ts.map +0 -1
  40. package/dist/currency/crypto-symbols.js +0 -23
  41. package/dist/currency/crypto-symbols.js.map +0 -1
  42. package/dist/currency/download-crypto-list.d.ts +0 -10
  43. package/dist/currency/download-crypto-list.d.ts.map +0 -1
  44. package/dist/currency/download-crypto-list.js +0 -69
  45. package/dist/currency/download-crypto-list.js.map +0 -1
  46. package/dist/currency/index.d.ts +0 -84
  47. package/dist/currency/index.d.ts.map +0 -1
  48. package/dist/currency/index.js +0 -230
  49. package/dist/currency/index.js.map +0 -1
  50. package/dist/dir.d.ts +0 -40
  51. package/dist/dir.d.ts.map +0 -1
  52. package/dist/dir.js +0 -108
  53. package/dist/dir.js.map +0 -1
  54. package/dist/file.d.ts +0 -53
  55. package/dist/file.d.ts.map +0 -1
  56. package/dist/file.js +0 -211
  57. package/dist/file.js.map +0 -1
  58. package/dist/format.d.ts +0 -40
  59. package/dist/format.d.ts.map +0 -1
  60. package/dist/format.js +0 -83
  61. package/dist/format.js.map +0 -1
  62. package/dist/kev.d.ts +0 -149
  63. package/dist/kev.d.ts.map +0 -1
  64. package/dist/kev.js +0 -761
  65. package/dist/kev.js.map +0 -1
  66. package/dist/log.d.ts +0 -91
  67. package/dist/log.d.ts.map +0 -1
  68. package/dist/log.js +0 -300
  69. package/dist/log.js.map +0 -1
  70. package/dist/logger.d.ts +0 -91
  71. package/dist/logger.d.ts.map +0 -1
  72. package/dist/logger.js +0 -269
  73. package/dist/logger.js.map +0 -1
  74. package/dist/path.d.ts +0 -67
  75. package/dist/path.d.ts.map +0 -1
  76. package/dist/path.js +0 -107
  77. package/dist/path.js.map +0 -1
  78. package/dist/project.d.ts +0 -35
  79. package/dist/project.d.ts.map +0 -1
  80. package/dist/project.js +0 -154
  81. package/dist/project.js.map +0 -1
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Per-user rolling message history for GramIO bots — opt-in, with
3
+ * retention.
4
+ *
5
+ * Follows the same shared-session pattern as `bot/language`: the
6
+ * user creates a `session()` once at bot level, and each feature
7
+ * plugin (including this one) declares it as a dependency. gramio
8
+ * dedupes the runtime extension; the types flow.
9
+ *
10
+ * ## What this plugin owns
11
+ *
12
+ * - Appends each incoming user message to `ctx.session.history.items`
13
+ * - Prunes entries older than `retentionDays` or beyond `maxMessages`
14
+ * - Exposes a read-only pruned snapshot at `ctx.history` for handlers
15
+ *
16
+ * ## GDPR caveat — retention IS personal data
17
+ *
18
+ * Unlike `bot/language` (preference data, covered by Telegram's standard
19
+ * privacy policy), retaining user **message content** is the one thing
20
+ * the [standard policy](https://telegram.org/privacy-tpa) does NOT cover
21
+ * by default. If you extend `messageHistory`, you should:
22
+ *
23
+ * 1. Set a custom `privacy` URL on your `botMenu` describing what you
24
+ * retain and for how long.
25
+ * 2. Pass `personalData: { storage }` to your `botMenu` so 🗑 Forget
26
+ * and 📥 Export buttons appear — letting users see and delete
27
+ * the data you keep about them.
28
+ *
29
+ * These are not enforced by this plugin (would couple it to menu); they
30
+ * are documented as the bot author's legal responsibility.
31
+ *
32
+ * ## Storage layout
33
+ *
34
+ * Lives entirely inside the shared session record:
35
+ *
36
+ * storage[String(senderId)] = {
37
+ * ...other plugins' fields,
38
+ * history: { items: [HistoryEntry, ...] }
39
+ * }
40
+ *
41
+ * Peer deps: `gramio`, `@gramio/session`.
42
+ *
43
+ * @example
44
+ * import { Bot } from 'gramio'
45
+ * import { session } from '@gramio/session'
46
+ * import { redisStorage } from '@gramio/storage-redis'
47
+ * import { messageHistory } from '@adriangalilea/utils/bot/message-history'
48
+ *
49
+ * const userSession = session({ storage: redisStorage(), key: 'session', initial: () => ({}) })
50
+ *
51
+ * const history = messageHistory({
52
+ * session: userSession,
53
+ * maxMessages: 100,
54
+ * retentionDays: 7,
55
+ * })
56
+ *
57
+ * const bot = new Bot(process.env.BOT_TOKEN!)
58
+ * .extend(userSession)
59
+ * .extend(history.plugin)
60
+ * .command('replay', (ctx) => {
61
+ * const last = ctx.history.slice(-3).map((e) => e.text).join('\n---\n')
62
+ * return ctx.send(last || '(no history)')
63
+ * })
64
+ */
65
+ import { Plugin } from 'gramio';
66
+ // ─── helpers ───────────────────────────────────────────────────────
67
+ const prune = (items, maxMessages, retentionDays) => {
68
+ const cutoffSec = Math.floor(Date.now() / 1000) - retentionDays * 86400;
69
+ const fresh = items.filter((e) => e.date >= cutoffSec);
70
+ return fresh.slice(-maxMessages);
71
+ };
72
+ // ─── feature factory ───────────────────────────────────────────────
73
+ export const messageHistory = (opts) => {
74
+ if (opts.maxMessages <= 0)
75
+ throw new Error('messageHistory: maxMessages must be > 0');
76
+ if (opts.retentionDays <= 0)
77
+ throw new Error('messageHistory: retentionDays must be > 0');
78
+ const plugin = buildHistoryPlugin({
79
+ sessionPlugin: opts.session,
80
+ maxMessages: opts.maxMessages,
81
+ retentionDays: opts.retentionDays,
82
+ });
83
+ return { plugin };
84
+ };
85
+ // ─── plugin builder ────────────────────────────────────────────────
86
+ const buildHistoryPlugin = (args) => {
87
+ const { sessionPlugin, maxMessages, retentionDays } = args;
88
+ return new Plugin('@adriangalilea/utils/bot/message-history')
89
+ .extend(sessionPlugin)
90
+ // Record incoming messages with text. Service messages, edits,
91
+ // and callback queries don't append — only direct user input.
92
+ .on('message', async (ctx, next) => {
93
+ if (ctx.text !== undefined) {
94
+ const entry = {
95
+ messageId: ctx.id,
96
+ date: ctx.payload.date,
97
+ text: ctx.text,
98
+ };
99
+ const cur = ctx.session.history?.items ?? [];
100
+ ctx.session.history = {
101
+ items: [...prune(cur, maxMessages, retentionDays), entry].slice(-maxMessages),
102
+ };
103
+ }
104
+ return next();
105
+ })
106
+ // Pruned read-only view for handlers downstream.
107
+ .derive(['message', 'callback_query'], (ctx) => ({
108
+ history: prune(ctx.session.history?.items ?? [], maxMessages, retentionDays),
109
+ }));
110
+ };
111
+ //# sourceMappingURL=message-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-history.js","sourceRoot":"","sources":["../../src/bot/message-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,EAA0B,MAAM,EAAE,MAAM,QAAQ,CAAA;AA8CvD,sEAAsE;AAEtE,MAAM,KAAK,GAAG,CACZ,KAAqB,EACrB,WAAmB,EACnB,aAAqB,EACL,EAAE;IAClB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,GAAG,KAAK,CAAA;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAA;IACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAA;AAClC,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAA2B,EAAyB,EAAE;IACnF,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IACrF,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAEzF,MAAM,MAAM,GAAG,kBAAkB,CAAC;QAChC,aAAa,EAAE,IAAI,CAAC,OAAO;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,kBAAkB,GAAG,CAAC,IAI3B,EAAE,EAAE;IACH,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAA;IAE1D,OAAO,IAAI,MAAM,CACf,0CAA0C,CAC3C;SACE,MAAM,CAAC,aAAa,CAAC;QACtB,+DAA+D;QAC/D,8DAA8D;SAC7D,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAiB;gBAC1B,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAA;YACD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAA;YAC5C,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG;gBACpB,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAC7D,CAAC,WAAW,CACb;aACF,CAAA;QACH,CAAC;QACD,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,CAAC;QACF,iDAAiD;SAChD,MAAM,CAAC,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAkB,EAAE,CAAC,CAAC;QAC/D,OAAO,EAAE,KAAK,CACZ,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,EAChC,WAAW,EACX,aAAa,CACiB;KACjC,CAAC,CAAC,CAAA;AACP,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './universal/log.js';
8
8
  export * from './universal/format.js';
9
9
  export * from './universal/currency/index.js';
10
10
  export * from './offensive.js';
11
+ export * from './say/index.js';
11
12
  export * from './platform/file.js';
12
13
  export * from './platform/dir.js';
13
14
  export * from './platform/path.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGvD,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAG7C,cAAc,gBAAgB,CAAA;AAI9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGvD,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAG7C,cAAc,gBAAgB,CAAA;AAG9B,cAAc,gBAAgB,CAAA;AAI9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ export * from './universal/format.js';
10
10
  export * from './universal/currency/index.js';
11
11
  // Offensive programming - pure throws, zero dependencies
12
12
  export * from './offensive.js';
13
+ // Polyglot strings — TS-enforced multi-language values
14
+ export * from './say/index.js';
13
15
  // Platform-specific utilities
14
16
  // These will throw helpful errors in browser environment when used
15
17
  export * from './platform/file.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,wCAAwC;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAE7C,yDAAyD;AACzD,cAAc,gBAAgB,CAAA;AAE9B,8BAA8B;AAC9B,mEAAmE;AACnE,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,wCAAwC;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAE7C,yDAAyD;AACzD,cAAc,gBAAgB,CAAA;AAE9B,uDAAuD;AACvD,cAAc,gBAAgB,CAAA;AAE9B,8BAA8B;AAC9B,mEAAmE;AACnE,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `say` — TypeScript-enforced polyglot strings, framework-agnostic.
3
+ *
4
+ * A "polyglot value" is a plain object literal with one string per
5
+ * supported language:
6
+ *
7
+ * { en: 'Hello', es: 'Hola' }
8
+ *
9
+ * The keys are the source of truth. There is no JSON file, no key
10
+ * registry, no extraction tool, no namespaces. The TS compiler
11
+ * enforces completeness: add a language to the plugin's `supported`
12
+ * list and every call site without that key becomes a compile error.
13
+ *
14
+ * Two entry points:
15
+ *
16
+ * `say(value, lang)` — pure resolver, no context, returns string.
17
+ * Use it for 3rd-party SDKs / cron / email
18
+ * / anything outside a bot ctx.
19
+ *
20
+ * `ctx.say(value)` — bot-bound; uses `ctx.lang`. Provided by
21
+ * `bot/language` (see that plugin for the
22
+ * `ctx.say.send / .edit / .answer` methods).
23
+ *
24
+ * @example
25
+ * import { say, type Polyglot } from '@adriangalilea/utils/say'
26
+ *
27
+ * await pushover.send({
28
+ * message: say({ en: 'Drop!', es: '¡Drop!' }, user.lang),
29
+ * })
30
+ *
31
+ * // typing your own adapter:
32
+ * const notify = (msg: string | Polyglot<'en' | 'es'>, lang: 'en' | 'es') =>
33
+ * transport.send(typeof msg === 'string' ? msg : say(msg, lang))
34
+ */
35
+ /**
36
+ * A value that exists in N languages. `L` is the union of supported
37
+ * language tags (typically inferred from the object literal's keys).
38
+ *
39
+ * Authoring: `{ en: 'Hi', es: 'Hola' }` — TS infers `L = 'en' | 'es'`.
40
+ *
41
+ * Typing your own API: `function notify(msg: Polyglot<'en' | 'es'>)`
42
+ * — callers must provide both keys.
43
+ */
44
+ export type Polyglot<L extends string> = Readonly<Record<L, string>>;
45
+ /**
46
+ * Resolve a polyglot value to a string at `lang`.
47
+ *
48
+ * If `lang` is missing from `value`, returns the first available key
49
+ * (lexicographic). This is a structural fallback — it should never
50
+ * happen when `lang` is constrained by the same `L` as `value`'s
51
+ * keys; it exists only for the dynamic-string escape hatch.
52
+ *
53
+ * @example
54
+ * say({ en: 'Hi', es: 'Hola' }, 'es') // → 'Hola'
55
+ * say({ en: 'Hi', es: 'Hola' }, 'fr') // TS error: '"fr"' not in '"en" | "es"'
56
+ *
57
+ * @example // typing-loose escape hatch with `as Polyglot<string>`
58
+ * const raw: Polyglot<string> = JSON.parse(blob)
59
+ * say(raw, userLang) // dynamic, falls back if missing
60
+ */
61
+ export declare const say: <L extends string>(value: Polyglot<L>, lang: L) => string;
62
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/say/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,SAAS,MAAM,EAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,MAKnE,CAAA"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `say` — TypeScript-enforced polyglot strings, framework-agnostic.
3
+ *
4
+ * A "polyglot value" is a plain object literal with one string per
5
+ * supported language:
6
+ *
7
+ * { en: 'Hello', es: 'Hola' }
8
+ *
9
+ * The keys are the source of truth. There is no JSON file, no key
10
+ * registry, no extraction tool, no namespaces. The TS compiler
11
+ * enforces completeness: add a language to the plugin's `supported`
12
+ * list and every call site without that key becomes a compile error.
13
+ *
14
+ * Two entry points:
15
+ *
16
+ * `say(value, lang)` — pure resolver, no context, returns string.
17
+ * Use it for 3rd-party SDKs / cron / email
18
+ * / anything outside a bot ctx.
19
+ *
20
+ * `ctx.say(value)` — bot-bound; uses `ctx.lang`. Provided by
21
+ * `bot/language` (see that plugin for the
22
+ * `ctx.say.send / .edit / .answer` methods).
23
+ *
24
+ * @example
25
+ * import { say, type Polyglot } from '@adriangalilea/utils/say'
26
+ *
27
+ * await pushover.send({
28
+ * message: say({ en: 'Drop!', es: '¡Drop!' }, user.lang),
29
+ * })
30
+ *
31
+ * // typing your own adapter:
32
+ * const notify = (msg: string | Polyglot<'en' | 'es'>, lang: 'en' | 'es') =>
33
+ * transport.send(typeof msg === 'string' ? msg : say(msg, lang))
34
+ */
35
+ /**
36
+ * Resolve a polyglot value to a string at `lang`.
37
+ *
38
+ * If `lang` is missing from `value`, returns the first available key
39
+ * (lexicographic). This is a structural fallback — it should never
40
+ * happen when `lang` is constrained by the same `L` as `value`'s
41
+ * keys; it exists only for the dynamic-string escape hatch.
42
+ *
43
+ * @example
44
+ * say({ en: 'Hi', es: 'Hola' }, 'es') // → 'Hola'
45
+ * say({ en: 'Hi', es: 'Hola' }, 'fr') // TS error: '"fr"' not in '"en" | "es"'
46
+ *
47
+ * @example // typing-loose escape hatch with `as Polyglot<string>`
48
+ * const raw: Polyglot<string> = JSON.parse(blob)
49
+ * say(raw, userLang) // dynamic, falls back if missing
50
+ */
51
+ export const say = (value, lang) => {
52
+ const direct = value[lang];
53
+ if (typeof direct === 'string')
54
+ return direct;
55
+ for (const k in value)
56
+ return value[k];
57
+ return '';
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/say/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAaH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAmB,KAAkB,EAAE,IAAO,EAAU,EAAE;IAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAA;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,CAAM,CAAC,CAAA;IAC3C,OAAO,EAAE,CAAA;AACX,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adriangalilea/utils",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "TypeScript utilities - logger, currency, formatter, GramIO bot plugins, and more",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -28,6 +28,10 @@
28
28
  "types": "./dist/universal/currency/index.d.ts",
29
29
  "default": "./dist/universal/currency/index.js"
30
30
  },
31
+ "./say": {
32
+ "types": "./dist/say/index.d.ts",
33
+ "default": "./dist/say/index.js"
34
+ },
31
35
  "./bot": {
32
36
  "types": "./dist/bot/index.d.ts",
33
37
  "default": "./dist/bot/index.js"
@@ -40,6 +44,18 @@
40
44
  "types": "./dist/bot/coalesce.d.ts",
41
45
  "default": "./dist/bot/coalesce.js"
42
46
  },
47
+ "./bot/language": {
48
+ "types": "./dist/bot/language.d.ts",
49
+ "default": "./dist/bot/language.js"
50
+ },
51
+ "./bot/menu": {
52
+ "types": "./dist/bot/menu.d.ts",
53
+ "default": "./dist/bot/menu.js"
54
+ },
55
+ "./bot/message-history": {
56
+ "types": "./dist/bot/message-history.d.ts",
57
+ "default": "./dist/bot/message-history.js"
58
+ },
43
59
  "./bot/kit": {
44
60
  "types": "./dist/bot/kit.d.ts",
45
61
  "default": "./dist/bot/kit.js"
@@ -1,10 +0,0 @@
1
- /**
2
- * Generated on 2025-08-17T10:11:21.771Z
3
- * 13,754 cryptocurrency symbols from CoinGecko API
4
- *
5
- * Run 'npm run update-crypto' to refresh this list
6
- */
7
- export declare const cryptoSymbolsData: readonly string[];
8
- export declare const lastUpdated = "2025-08-17T10:11:21.771Z";
9
- export declare const symbolCount = 13754;
10
- //# sourceMappingURL=crypto-symbols-data.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-symbols-data.d.ts","sourceRoot":"","sources":["../../src/currency/crypto-symbols-data.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EA27a9C,CAAA;AAED,eAAO,MAAM,WAAW,6BAA6B,CAAA;AACrD,eAAO,MAAM,WAAW,QAAQ,CAAA"}