@voxendar/shared 0.2.0 → 0.4.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 (91) hide show
  1. package/dist/capture/audio.d.ts +16 -0
  2. package/dist/capture/audio.d.ts.map +1 -0
  3. package/dist/capture/audio.js +22 -0
  4. package/dist/capture/audio.js.map +1 -0
  5. package/dist/capture/fields.d.ts +87 -0
  6. package/dist/capture/fields.d.ts.map +1 -0
  7. package/dist/capture/fields.js +171 -0
  8. package/dist/capture/fields.js.map +1 -0
  9. package/dist/constants.d.ts +1 -1
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/constants.js +1 -0
  12. package/dist/constants.js.map +1 -1
  13. package/dist/i18n/copy/ar-SA.d.ts +176 -0
  14. package/dist/i18n/copy/ar-SA.d.ts.map +1 -0
  15. package/dist/i18n/copy/ar-SA.js +194 -0
  16. package/dist/i18n/copy/ar-SA.js.map +1 -0
  17. package/dist/i18n/copy/de-DE.d.ts +176 -0
  18. package/dist/i18n/copy/de-DE.d.ts.map +1 -0
  19. package/dist/i18n/copy/de-DE.js +196 -0
  20. package/dist/i18n/copy/de-DE.js.map +1 -0
  21. package/dist/i18n/copy/en-US.d.ts +190 -0
  22. package/dist/i18n/copy/en-US.d.ts.map +1 -0
  23. package/dist/i18n/copy/en-US.js +223 -0
  24. package/dist/i18n/copy/en-US.js.map +1 -0
  25. package/dist/i18n/copy/es-MX.d.ts +176 -0
  26. package/dist/i18n/copy/es-MX.d.ts.map +1 -0
  27. package/dist/i18n/copy/es-MX.js +189 -0
  28. package/dist/i18n/copy/es-MX.js.map +1 -0
  29. package/dist/i18n/copy/fr-FR.d.ts +176 -0
  30. package/dist/i18n/copy/fr-FR.d.ts.map +1 -0
  31. package/dist/i18n/copy/fr-FR.js +190 -0
  32. package/dist/i18n/copy/fr-FR.js.map +1 -0
  33. package/dist/i18n/copy/he-IL.d.ts +176 -0
  34. package/dist/i18n/copy/he-IL.d.ts.map +1 -0
  35. package/dist/i18n/copy/he-IL.js +190 -0
  36. package/dist/i18n/copy/he-IL.js.map +1 -0
  37. package/dist/i18n/copy/hi-IN.d.ts +176 -0
  38. package/dist/i18n/copy/hi-IN.d.ts.map +1 -0
  39. package/dist/i18n/copy/hi-IN.js +191 -0
  40. package/dist/i18n/copy/hi-IN.js.map +1 -0
  41. package/dist/i18n/copy/ja-JP.d.ts +176 -0
  42. package/dist/i18n/copy/ja-JP.d.ts.map +1 -0
  43. package/dist/i18n/copy/ja-JP.js +192 -0
  44. package/dist/i18n/copy/ja-JP.js.map +1 -0
  45. package/dist/i18n/copy/ko-KR.d.ts +176 -0
  46. package/dist/i18n/copy/ko-KR.d.ts.map +1 -0
  47. package/dist/i18n/copy/ko-KR.js +192 -0
  48. package/dist/i18n/copy/ko-KR.js.map +1 -0
  49. package/dist/i18n/copy/pt-BR.d.ts +176 -0
  50. package/dist/i18n/copy/pt-BR.d.ts.map +1 -0
  51. package/dist/i18n/copy/pt-BR.js +187 -0
  52. package/dist/i18n/copy/pt-BR.js.map +1 -0
  53. package/dist/i18n/copy/ru-RU.d.ts +176 -0
  54. package/dist/i18n/copy/ru-RU.d.ts.map +1 -0
  55. package/dist/i18n/copy/ru-RU.js +191 -0
  56. package/dist/i18n/copy/ru-RU.js.map +1 -0
  57. package/dist/i18n/copy/zh-CN.d.ts +176 -0
  58. package/dist/i18n/copy/zh-CN.d.ts.map +1 -0
  59. package/dist/i18n/copy/zh-CN.js +189 -0
  60. package/dist/i18n/copy/zh-CN.js.map +1 -0
  61. package/dist/i18n/copy/zh-TW.d.ts +176 -0
  62. package/dist/i18n/copy/zh-TW.d.ts.map +1 -0
  63. package/dist/i18n/copy/zh-TW.js +196 -0
  64. package/dist/i18n/copy/zh-TW.js.map +1 -0
  65. package/dist/i18n/rtl.d.ts +27 -0
  66. package/dist/i18n/rtl.d.ts.map +1 -0
  67. package/dist/i18n/rtl.js +47 -0
  68. package/dist/i18n/rtl.js.map +1 -0
  69. package/dist/i18n/server-messages.d.ts +56 -0
  70. package/dist/i18n/server-messages.d.ts.map +1 -0
  71. package/dist/i18n/server-messages.js +163 -0
  72. package/dist/i18n/server-messages.js.map +1 -0
  73. package/dist/i18n/templates.d.ts +5 -0
  74. package/dist/i18n/templates.d.ts.map +1 -1
  75. package/dist/i18n/templates.js +5 -0
  76. package/dist/i18n/templates.js.map +1 -1
  77. package/dist/i18n/ui.d.ts +85 -0
  78. package/dist/i18n/ui.d.ts.map +1 -0
  79. package/dist/i18n/ui.js +151 -0
  80. package/dist/i18n/ui.js.map +1 -0
  81. package/dist/index.d.ts +5 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +5 -0
  84. package/dist/index.js.map +1 -1
  85. package/dist/schemas/capture.d.ts +8 -0
  86. package/dist/schemas/capture.d.ts.map +1 -1
  87. package/dist/schemas/capture.js +6 -0
  88. package/dist/schemas/capture.js.map +1 -1
  89. package/dist/schemas/enums.d.ts +2 -0
  90. package/dist/schemas/enums.d.ts.map +1 -1
  91. package/package.json +8 -3
@@ -0,0 +1,85 @@
1
+ /**
2
+ * UI copy (Milestone 1.9.7) — the mechanism behind the app's own words.
3
+ *
4
+ * Until this existed, `language` drove ASR, the LLM's output language, the spoken
5
+ * confirmation, the reminder templates and the voice ranking — and **nothing about the
6
+ * interface**. The M1.5 walkthrough showed the seam on screen: the confirmation was
7
+ * spoken in French (*"Demain, à quatorze heures… C'est bien ça ?"*) while the card's
8
+ * labels and its red `400` were English. This is that seam.
9
+ *
10
+ * Three properties are deliberate:
11
+ *
12
+ * 1. **The English table is the key set.** `UiKey` is derived from it (`./copy/en-US.ts`)
13
+ * and every other language is typed `Record<UiKey, string>`, so a missing key is a
14
+ * **compile error**, not a sentence that quietly turns English — the same rule the
15
+ * reminder templates enforce with a test, applied here by the type system.
16
+ * 2. **One file per language** in `./copy/`; this module is only the mechanism
17
+ * (resolution, lookup, interpolation, the two allowlists). A language is therefore
18
+ * added, reviewed, or handed to a translator on its own — and the tables live in
19
+ * `shared` rather than in the app because the server also writes sentences that reach
20
+ * the screen (`./server-messages.ts`, next door).
21
+ * 3. **Every string the member reads is in those tables**, including the labels that feel
22
+ * like data — card field names, the Today/Tomorrow chips, colour names, avatar names.
23
+ * A person should not read the app's sentence about their own event in a language they
24
+ * did not choose, and "Lavender — light periwinkle" is such a sentence.
25
+ *
26
+ * And nothing here falls back to English silently for a language we ship: see
27
+ * `PENDING_UI_LANGUAGES`, which names the ones still missing, and `ui.test.ts`, which
28
+ * asserts that list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
29
+ */
30
+ import { SUPPORTED_LANGUAGES } from "../constants";
31
+ import { type CopyTable, type UiKey } from "./copy/en-US";
32
+ export type Language = (typeof SUPPORTED_LANGUAGES)[number];
33
+ export type { CopyTable, UiKey };
34
+ export type UiParams = Record<string, string | number>;
35
+ /**
36
+ * Keys where English is the right answer in *every* language: brand names, an example
37
+ * invite code, and a developer diagnostic. The guard both skips these and asserts they
38
+ * really do match English everywhere — which is why the list must stay short.
39
+ */
40
+ export declare const UNTRANSLATED_BY_DESIGN: readonly UiKey[];
41
+ /**
42
+ * Keys where a *specific* language may legitimately coincide with English: French says
43
+ * *Date* and *Notes* exactly as English does, German says *Neutral* and *Person*. Keyed by
44
+ * language on purpose — a global allowlist would excuse a copy-paste in Spanish or Korean
45
+ * too, and the point of the guard is to catch exactly that.
46
+ *
47
+ * Adding an entry is a claim about that language, so it is reviewed like the copy is.
48
+ */
49
+ export declare const MAY_READ_AS_ENGLISH: Readonly<Partial<Record<Language, readonly UiKey[]>>>;
50
+ /** The English table: the copy of record, and what every lookup falls back to. */
51
+ export declare const UI_COPY_EN: CopyTable;
52
+ /** Which language has which table. `en-US` is the floor; see `PENDING_UI_LANGUAGES`. */
53
+ export declare const UI_COPY: Partial<Record<Language, CopyTable>>;
54
+ /**
55
+ * Launch languages whose UI copy is not written yet. They fall back to English until their
56
+ * tables land — a decision the diff shows rather than a silent fallback, because the guard
57
+ * test asserts this list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
58
+ *
59
+ * **Empty since 2026-09-29**, when wave 2 filled the last nine tables. It stays exported,
60
+ * and the guard stays switched on, because the *thirteenth* language is the one this list
61
+ * exists for — and on **2026-10-21 that happened**: `zh-TW` arrived with its table in the
62
+ * same commit, so this list stayed empty. The mechanism was never needed; the guard still
63
+ * proved the gap was zero rather than assumed it.
64
+ */
65
+ export declare const PENDING_UI_LANGUAGES: readonly Language[];
66
+ /**
67
+ * The mechanism. `resolveUiLanguage` deliberately mirrors `resolveTemplateKey` in
68
+ * `templates.ts`: exact tag → base language → `en-US`. Two tables with two different
69
+ * fallback policies would be a bug waiting for the first `pt-PT` member.
70
+ */
71
+ export declare function resolveUiLanguage(language: string | null | undefined): Language | null;
72
+ /**
73
+ * The copy table for a language, complete or English. A language listed in
74
+ * `PENDING_UI_LANGUAGES` has no table yet and lands on English — the guard test asserts
75
+ * that list is explicit, so this can never be the silent path it looks like.
76
+ */
77
+ export declare function uiCopyFor(language: string | null | undefined): CopyTable;
78
+ /** One sentence, in one language. */
79
+ export declare function translate(language: string | null | undefined, key: UiKey, params?: UiParams): string;
80
+ /**
81
+ * Bind a language once and reuse it — what the app's `useT()` wraps, so a screen writes
82
+ * `t("card.confirm")` and never threads the language through every call.
83
+ */
84
+ export declare function createTranslator(language: string | null | undefined): (key: UiKey, params?: UiParams) => string;
85
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/i18n/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAM,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAgB9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACjC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,KAAK,EAMlD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC,CAGrF,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,UAAU,EAAE,SAAc,CAAC;AAExC,wFAAwF;AACxF,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAcxD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,QAAQ,EAAO,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAStF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAGxE;AAUD,qCAAqC;AACrC,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,EAAE,KAAK,EACV,MAAM,CAAC,EAAE,QAAQ,GAChB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,QAAQ,KAAK,MAAM,CAG3C"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PENDING_UI_LANGUAGES = exports.UI_COPY = exports.UI_COPY_EN = exports.MAY_READ_AS_ENGLISH = exports.UNTRANSLATED_BY_DESIGN = void 0;
4
+ exports.resolveUiLanguage = resolveUiLanguage;
5
+ exports.uiCopyFor = uiCopyFor;
6
+ exports.translate = translate;
7
+ exports.createTranslator = createTranslator;
8
+ /**
9
+ * UI copy (Milestone 1.9.7) — the mechanism behind the app's own words.
10
+ *
11
+ * Until this existed, `language` drove ASR, the LLM's output language, the spoken
12
+ * confirmation, the reminder templates and the voice ranking — and **nothing about the
13
+ * interface**. The M1.5 walkthrough showed the seam on screen: the confirmation was
14
+ * spoken in French (*"Demain, à quatorze heures… C'est bien ça ?"*) while the card's
15
+ * labels and its red `400` were English. This is that seam.
16
+ *
17
+ * Three properties are deliberate:
18
+ *
19
+ * 1. **The English table is the key set.** `UiKey` is derived from it (`./copy/en-US.ts`)
20
+ * and every other language is typed `Record<UiKey, string>`, so a missing key is a
21
+ * **compile error**, not a sentence that quietly turns English — the same rule the
22
+ * reminder templates enforce with a test, applied here by the type system.
23
+ * 2. **One file per language** in `./copy/`; this module is only the mechanism
24
+ * (resolution, lookup, interpolation, the two allowlists). A language is therefore
25
+ * added, reviewed, or handed to a translator on its own — and the tables live in
26
+ * `shared` rather than in the app because the server also writes sentences that reach
27
+ * the screen (`./server-messages.ts`, next door).
28
+ * 3. **Every string the member reads is in those tables**, including the labels that feel
29
+ * like data — card field names, the Today/Tomorrow chips, colour names, avatar names.
30
+ * A person should not read the app's sentence about their own event in a language they
31
+ * did not choose, and "Lavender — light periwinkle" is such a sentence.
32
+ *
33
+ * And nothing here falls back to English silently for a language we ship: see
34
+ * `PENDING_UI_LANGUAGES`, which names the ones still missing, and `ui.test.ts`, which
35
+ * asserts that list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
36
+ */
37
+ const constants_1 = require("../constants");
38
+ const en_US_1 = require("./copy/en-US");
39
+ const fr_FR_1 = require("./copy/fr-FR");
40
+ const zh_CN_1 = require("./copy/zh-CN");
41
+ // zh-TW sits after zh-CN everywhere for the same reason: `resolveUiLanguage("zh")` picks the
42
+ // *first* `zh-` entry, and a bare `zh` has always meant Simplified. Order is the fallback.
43
+ const zh_TW_1 = require("./copy/zh-TW");
44
+ const es_MX_1 = require("./copy/es-MX");
45
+ const de_DE_1 = require("./copy/de-DE");
46
+ const pt_BR_1 = require("./copy/pt-BR");
47
+ const ru_RU_1 = require("./copy/ru-RU");
48
+ const ar_SA_1 = require("./copy/ar-SA");
49
+ const hi_IN_1 = require("./copy/hi-IN");
50
+ const he_IL_1 = require("./copy/he-IL");
51
+ const ja_JP_1 = require("./copy/ja-JP");
52
+ const ko_KR_1 = require("./copy/ko-KR");
53
+ /**
54
+ * Keys where English is the right answer in *every* language: brand names, an example
55
+ * invite code, and a developer diagnostic. The guard both skips these and asserts they
56
+ * really do match English everywhere — which is why the list must stay short.
57
+ */
58
+ exports.UNTRANSLATED_BY_DESIGN = [
59
+ "login.configWarning",
60
+ "setup.invitePlaceholder",
61
+ "channel.sms",
62
+ "channel.whatsapp",
63
+ "channel.telegram",
64
+ ];
65
+ /**
66
+ * Keys where a *specific* language may legitimately coincide with English: French says
67
+ * *Date* and *Notes* exactly as English does, German says *Neutral* and *Person*. Keyed by
68
+ * language on purpose — a global allowlist would excuse a copy-paste in Spanish or Korean
69
+ * too, and the point of the guard is to catch exactly that.
70
+ *
71
+ * Adding an entry is a claim about that language, so it is reviewed like the copy is.
72
+ */
73
+ exports.MAY_READ_AS_ENGLISH = {
74
+ "fr-FR": ["card.date", "card.notes"],
75
+ "de-DE": ["avatar.generic_01", "avatar.generic_02"],
76
+ };
77
+ /** The English table: the copy of record, and what every lookup falls back to. */
78
+ exports.UI_COPY_EN = en_US_1.EN;
79
+ /** Which language has which table. `en-US` is the floor; see `PENDING_UI_LANGUAGES`. */
80
+ exports.UI_COPY = {
81
+ "en-US": en_US_1.EN,
82
+ "zh-CN": zh_CN_1.ZH,
83
+ "zh-TW": zh_TW_1.TW,
84
+ "es-MX": es_MX_1.ES,
85
+ "fr-FR": fr_FR_1.FR,
86
+ "de-DE": de_DE_1.DE,
87
+ "pt-BR": pt_BR_1.PT,
88
+ "ru-RU": ru_RU_1.RU,
89
+ "ar-SA": ar_SA_1.AR,
90
+ "hi-IN": hi_IN_1.HI,
91
+ "he-IL": he_IL_1.HE,
92
+ "ja-JP": ja_JP_1.JA,
93
+ "ko-KR": ko_KR_1.KO,
94
+ };
95
+ /**
96
+ * Launch languages whose UI copy is not written yet. They fall back to English until their
97
+ * tables land — a decision the diff shows rather than a silent fallback, because the guard
98
+ * test asserts this list is exactly the gap between `SUPPORTED_LANGUAGES` and `UI_COPY`.
99
+ *
100
+ * **Empty since 2026-09-29**, when wave 2 filled the last nine tables. It stays exported,
101
+ * and the guard stays switched on, because the *thirteenth* language is the one this list
102
+ * exists for — and on **2026-10-21 that happened**: `zh-TW` arrived with its table in the
103
+ * same commit, so this list stayed empty. The mechanism was never needed; the guard still
104
+ * proved the gap was zero rather than assumed it.
105
+ */
106
+ exports.PENDING_UI_LANGUAGES = [];
107
+ /**
108
+ * The mechanism. `resolveUiLanguage` deliberately mirrors `resolveTemplateKey` in
109
+ * `templates.ts`: exact tag → base language → `en-US`. Two tables with two different
110
+ * fallback policies would be a bug waiting for the first `pt-PT` member.
111
+ */
112
+ function resolveUiLanguage(language) {
113
+ if (!language)
114
+ return null;
115
+ const exact = constants_1.SUPPORTED_LANGUAGES.find((candidate) => candidate === language);
116
+ if (exact)
117
+ return exact;
118
+ const base = language.split("-")[0] ?? "";
119
+ if (base.length >= 2) {
120
+ return constants_1.SUPPORTED_LANGUAGES.find((candidate) => candidate.startsWith(`${base}-`)) ?? null;
121
+ }
122
+ return null;
123
+ }
124
+ /**
125
+ * The copy table for a language, complete or English. A language listed in
126
+ * `PENDING_UI_LANGUAGES` has no table yet and lands on English — the guard test asserts
127
+ * that list is explicit, so this can never be the silent path it looks like.
128
+ */
129
+ function uiCopyFor(language) {
130
+ const resolved = resolveUiLanguage(language);
131
+ return (resolved ? exports.UI_COPY[resolved] : undefined) ?? exports.UI_COPY_EN;
132
+ }
133
+ /** `{name}` → the value. A placeholder with no value is left visible, not blanked. */
134
+ function interpolate(text, params) {
135
+ if (!params)
136
+ return text;
137
+ return text.replace(/\{(\w+)\}/g, (whole, key) => key in params ? String(params[key]) : whole);
138
+ }
139
+ /** One sentence, in one language. */
140
+ function translate(language, key, params) {
141
+ return interpolate(uiCopyFor(language)[key], params);
142
+ }
143
+ /**
144
+ * Bind a language once and reuse it — what the app's `useT()` wraps, so a screen writes
145
+ * `t("card.confirm")` and never threads the language through every call.
146
+ */
147
+ function createTranslator(language) {
148
+ const copy = uiCopyFor(language);
149
+ return (key, params) => interpolate(copy[key], params);
150
+ }
151
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/i18n/ui.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,7 +6,12 @@ export * from "./schemas/event";
6
6
  export * from "./schemas/circle";
7
7
  export * from "./schemas/member";
8
8
  export * from "./schemas/capture";
9
+ export * from "./capture/fields";
10
+ export * from "./capture/audio";
9
11
  export * from "./schemas/reminder";
10
12
  export * from "./reminders/math";
11
13
  export * from "./i18n/templates";
14
+ export * from "./i18n/ui";
15
+ export * from "./i18n/rtl";
16
+ export * from "./i18n/server-messages";
12
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -22,7 +22,12 @@ __exportStar(require("./schemas/event"), exports);
22
22
  __exportStar(require("./schemas/circle"), exports);
23
23
  __exportStar(require("./schemas/member"), exports);
24
24
  __exportStar(require("./schemas/capture"), exports);
25
+ __exportStar(require("./capture/fields"), exports);
26
+ __exportStar(require("./capture/audio"), exports);
25
27
  __exportStar(require("./schemas/reminder"), exports);
26
28
  __exportStar(require("./reminders/math"), exports);
27
29
  __exportStar(require("./i18n/templates"), exports);
30
+ __exportStar(require("./i18n/ui"), exports);
31
+ __exportStar(require("./i18n/rtl"), exports);
32
+ __exportStar(require("./i18n/server-messages"), exports);
28
33
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,kDAAgC;AAChC,uDAAqC;AACrC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC;AAClC,qDAAmC;AACnC,mDAAiC;AACjC,mDAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,kDAAgC;AAChC,uDAAqC;AACrC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC;AAClC,mDAAiC;AACjC,kDAAgC;AAChC,qDAAmC;AACnC,mDAAiC;AACjC,mDAAiC;AACjC,4CAA0B;AAC1B,6CAA2B;AAC3B,yDAAuC"}
@@ -47,6 +47,12 @@ export declare const CaptureSchema: z.ZodObject<{
47
47
  editedFields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
48
48
  googleEventId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
49
  createdAt: z.ZodAny;
50
+ /**
51
+ * When the member confirmed or discarded it (M1.5). Optional because captures
52
+ * written before this existed have no such instant, and because a capture sitting
53
+ * in `pending_confirmation` has not been decided at all.
54
+ */
55
+ decidedAt: z.ZodOptional<z.ZodAny>;
50
56
  }, "strip", z.ZodTypeAny, {
51
57
  status: "pending_confirmation" | "confirmed" | "discarded";
52
58
  memberId: string;
@@ -67,6 +73,7 @@ export declare const CaptureSchema: z.ZodObject<{
67
73
  editedFields: string[];
68
74
  createdAt?: any;
69
75
  googleEventId?: string | null | undefined;
76
+ decidedAt?: any;
70
77
  }, {
71
78
  status: "pending_confirmation" | "confirmed" | "discarded";
72
79
  memberId: string;
@@ -87,6 +94,7 @@ export declare const CaptureSchema: z.ZodObject<{
87
94
  createdAt?: any;
88
95
  editedFields?: string[] | undefined;
89
96
  googleEventId?: string | null | undefined;
97
+ decidedAt?: any;
90
98
  }>;
91
99
  export type Capture = z.infer<typeof CaptureSchema>;
92
100
  //# sourceMappingURL=capture.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMxB,0DAA0D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI1D,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMxB,0DAA0D;;;;IAI1D;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
@@ -20,5 +20,11 @@ exports.CaptureSchema = zod_1.z.object({
20
20
  editedFields: zod_1.z.array(zod_1.z.string()).default([]),
21
21
  googleEventId: zod_1.z.string().nullish(),
22
22
  createdAt: primitives_1.firestoreTimestamp,
23
+ /**
24
+ * When the member confirmed or discarded it (M1.5). Optional because captures
25
+ * written before this existed have no such instant, and because a capture sitting
26
+ * in `pending_confirmation` has not been decided at all.
27
+ */
28
+ decidedAt: primitives_1.firestoreTimestamp.optional(),
23
29
  });
24
30
  //# sourceMappingURL=capture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mCAA4D;AAC5D,6CAAkD;AAClD,mCAA2C;AAE3C;;;;GAIG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,uBAAe,CAAC;IAC/B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,cAAc,EAAE,wBAAgB,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,wBAAgB,CAAC;IAChC,0DAA0D;IAC1D,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACnC,SAAS,EAAE,+BAAkB;CAC9B,CAAC,CAAC"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/schemas/capture.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mCAA4D;AAC5D,6CAAkD;AAClD,mCAA2C;AAE3C;;;;GAIG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,uBAAe,CAAC;IAC/B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,cAAc,EAAE,wBAAgB,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,wBAAgB,CAAC;IAChC,0DAA0D;IAC1D,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACnC,SAAS,EAAE,+BAAkB;IAC7B;;;;OAIG;IACH,SAAS,EAAE,+BAAkB,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC"}
@@ -8,4 +8,6 @@ export declare const CONFIDENCE_LEVELS: readonly ["high", "medium", "low"];
8
8
  export declare const NOTIFY_CHANNELS: readonly ["sms", "whatsapp", "telegram"];
9
9
  export declare const REMINDER_STATUSES: readonly ["sent", "failed", "skipped"];
10
10
  export declare const VOICE_STYLE_PRESETS: readonly ["professional", "warm_casual", "friendly_brief"];
11
+ /** The preset a member chose; `member.ts` validates against the list above. */
12
+ export type VoiceStylePreset = (typeof VOICE_STYLE_PRESETS)[number];
11
13
  //# sourceMappingURL=enums.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/schemas/enums.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,eAAO,MAAM,UAAU,gCAAiC,CAAC;AACzD,eAAO,MAAM,eAAe,qCAAsC,CAAC;AACnE,eAAO,MAAM,gBAAgB,6DAA8D,CAAC;AAC5F,eAAO,MAAM,gBAAgB,4CAA6C,CAAC;AAC3E,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,eAAO,MAAM,iBAAiB,oCAAqC,CAAC;AACpE,eAAO,MAAM,eAAe,0CAA2C,CAAC;AACxE,eAAO,MAAM,iBAAiB,wCAAyC,CAAC;AACxE,eAAO,MAAM,mBAAmB,4DAA6D,CAAC"}
1
+ {"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../src/schemas/enums.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,eAAO,MAAM,UAAU,gCAAiC,CAAC;AACzD,eAAO,MAAM,eAAe,qCAAsC,CAAC;AACnE,eAAO,MAAM,gBAAgB,6DAA8D,CAAC;AAC5F,eAAO,MAAM,gBAAgB,4CAA6C,CAAC;AAC3E,eAAO,MAAM,YAAY,qCAAsC,CAAC;AAChE,eAAO,MAAM,iBAAiB,oCAAqC,CAAC;AACpE,eAAO,MAAM,eAAe,0CAA2C,CAAC;AACxE,eAAO,MAAM,iBAAiB,wCAAyC,CAAC;AACxE,eAAO,MAAM,mBAAmB,4DAA6D,CAAC;AAC9F,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@voxendar/shared",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
5
8
  "description": "Shared contracts, schemas, constants and pure logic for Voxendar/Tellie (consumed by functions/ and app/)",
6
9
  "main": "dist/index.js",
7
10
  "types": "dist/index.d.ts",
@@ -11,13 +14,15 @@
11
14
  "scripts": {
12
15
  "build": "tsc -p tsconfig.json",
13
16
  "typecheck": "tsc --noEmit -p tsconfig.json",
14
- "test": "vitest run"
17
+ "test": "vitest run",
18
+ "prepare": "npm run build",
19
+ "prepublishOnly": "npm test"
15
20
  },
16
21
  "dependencies": {
17
22
  "zod": "^3.23.8"
18
23
  },
19
24
  "devDependencies": {
20
- "@types/node": "^20.14.0",
25
+ "@types/node": "^22.20.5",
21
26
  "typescript": "^5.5.4",
22
27
  "vitest": "^2.1.9"
23
28
  }