glost-core 0.5.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 (62) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/LICENSE +21 -0
  3. package/README.md +199 -0
  4. package/dist/__benchmarks__/document-creation.bench.d.ts +7 -0
  5. package/dist/__benchmarks__/document-creation.bench.d.ts.map +1 -0
  6. package/dist/__benchmarks__/document-creation.bench.js +71 -0
  7. package/dist/__benchmarks__/document-creation.bench.js.map +1 -0
  8. package/dist/__benchmarks__/traversal.bench.d.ts +7 -0
  9. package/dist/__benchmarks__/traversal.bench.d.ts.map +1 -0
  10. package/dist/__benchmarks__/traversal.bench.js +124 -0
  11. package/dist/__benchmarks__/traversal.bench.js.map +1 -0
  12. package/dist/cli/migrate.d.ts +8 -0
  13. package/dist/cli/migrate.d.ts.map +1 -0
  14. package/dist/cli/migrate.js +229 -0
  15. package/dist/cli/migrate.js.map +1 -0
  16. package/dist/errors.d.ts +168 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +300 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/guards.d.ts +103 -0
  21. package/dist/guards.d.ts.map +1 -0
  22. package/dist/guards.js +264 -0
  23. package/dist/guards.js.map +1 -0
  24. package/dist/index.d.ts +9 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +25 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/nodes.d.ts +227 -0
  29. package/dist/nodes.d.ts.map +1 -0
  30. package/dist/nodes.js +243 -0
  31. package/dist/nodes.js.map +1 -0
  32. package/dist/types.d.ts +442 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +51 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/utils.d.ts +247 -0
  37. package/dist/utils.d.ts.map +1 -0
  38. package/dist/utils.js +564 -0
  39. package/dist/utils.js.map +1 -0
  40. package/dist/validators.d.ts +1876 -0
  41. package/dist/validators.d.ts.map +1 -0
  42. package/dist/validators.js +302 -0
  43. package/dist/validators.js.map +1 -0
  44. package/package.json +73 -0
  45. package/src/__benchmarks__/document-creation.bench.ts +92 -0
  46. package/src/__benchmarks__/traversal.bench.ts +152 -0
  47. package/src/__tests__/README.md +20 -0
  48. package/src/__tests__/example.test.ts +43 -0
  49. package/src/__tests__/example.ts +186 -0
  50. package/src/__tests__/helpers.test.ts +178 -0
  51. package/src/__tests__/mock-data.ts +624 -0
  52. package/src/__tests__/performance.test.ts +317 -0
  53. package/src/__tests__/traversal.test.ts +170 -0
  54. package/src/cli/migrate.ts +294 -0
  55. package/src/errors.ts +394 -0
  56. package/src/guards.ts +341 -0
  57. package/src/index.ts +69 -0
  58. package/src/nodes.ts +409 -0
  59. package/src/types.ts +633 -0
  60. package/src/utils.ts +730 -0
  61. package/src/validators.ts +336 -0
  62. package/tsconfig.json +9 -0
@@ -0,0 +1,624 @@
1
+ import {
2
+ createGLOSTWordNode,
3
+ createGLOSTSentenceNode,
4
+ createGLOSTParagraphNode,
5
+ createGLOSTRootNode
6
+ } from 'glost-core';
7
+
8
+ import type {
9
+ GLOSTWord} from '../types.js';
10
+
11
+ // ============================================================================
12
+ // Enhanced Thai Example with Extras
13
+ // ============================================================================
14
+
15
+ const thaiWordsWithExtras: GLOSTWord[] = [
16
+ createGLOSTWordNode({
17
+ value: 'สวัสดี',
18
+ transcription: {
19
+ rtgs: {
20
+ text: 'sà-wàt-dii',
21
+ system: 'rtgs',
22
+ tone: 2,
23
+ syllables: ['sa', 'wat', 'dii']
24
+ },
25
+ aua: {
26
+ text: 'sa-wat-dee',
27
+ system: 'aua',
28
+ syllables: ['sa', 'wat', 'dee']
29
+ },
30
+ paiboon: {
31
+ text: 'sa-wat-dee',
32
+ system: 'paiboon',
33
+ syllables: ['sa', 'wat', 'dee']
34
+ },
35
+ ipa: {
36
+ text: 'sa.wàt.diː',
37
+ system: 'ipa',
38
+ syllables: ['sa', 'wat', 'diː']
39
+ }
40
+ },
41
+ metadata: {
42
+ meaning: 'hello, hi',
43
+ partOfSpeech: 'interjection',
44
+ usage: 'greeting, formal and informal'
45
+ },
46
+ lang: 'th',
47
+ script: 'thai',
48
+ extras: {
49
+ translations: {
50
+ en: 'hello, hi',
51
+ ja: 'こんにちは',
52
+ zh: '你好',
53
+ ko: '안녕하세요'
54
+ },
55
+ metadata: {
56
+ difficulty: 'beginner',
57
+ frequency: 'very-common',
58
+ culturalNotes: 'Standard greeting used throughout the day',
59
+ related: ['สวัสดีตอนเช้า', 'สวัสดีตอนเย็น', 'สวัสดีตอนค่ำ'],
60
+ examples: ['สวัสดีครับ', 'สวัสดีค่ะ', 'สวัสดีทุกคน']
61
+ }
62
+ }
63
+ }),
64
+ createGLOSTWordNode({
65
+ value: 'ครับ',
66
+ transcription: {
67
+ rtgs: {
68
+ text: 'khráp',
69
+ system: 'rtgs',
70
+ tone: 2,
71
+ syllables: ['khrap']
72
+ },
73
+ aua: {
74
+ text: 'krap',
75
+ system: 'aua',
76
+ syllables: ['krap']
77
+ },
78
+ paiboon: {
79
+ text: 'krap',
80
+ system: 'paiboon',
81
+ syllables: ['krap']
82
+ },
83
+ ipa: {
84
+ text: 'kʰráp',
85
+ system: 'ipa',
86
+ syllables: ['khrap']
87
+ }
88
+ },
89
+ metadata: {
90
+ meaning: 'polite particle for male speakers',
91
+ partOfSpeech: 'particle',
92
+ usage: 'sentence ending, formal speech'
93
+ },
94
+ lang: 'th',
95
+ script: 'thai',
96
+ extras: {
97
+ translations: {
98
+ en: 'polite particle (male)',
99
+ ja: '丁寧語の助詞(男性)',
100
+ zh: '礼貌助词(男性)',
101
+ ko: '정중한 조사 (남성)'
102
+ },
103
+ metadata: {
104
+ difficulty: 'beginner',
105
+ frequency: 'very-common',
106
+ culturalNotes: 'Used by male speakers to show politeness',
107
+ related: ['ค่ะ', 'ครับ', 'จ้ะ'],
108
+ examples: ['ขอบคุณครับ', 'ไม่เป็นไรครับ', 'ครับครับ']
109
+ }
110
+ }
111
+ }),
112
+ createGLOSTWordNode({
113
+ value: 'ผม',
114
+ transcription: {
115
+ rtgs: {
116
+ text: 'phǒm',
117
+ system: 'rtgs',
118
+ tone: 3,
119
+ syllables: ['phom']
120
+ },
121
+ aua: {
122
+ text: 'pom',
123
+ system: 'aua',
124
+ syllables: ['pom']
125
+ },
126
+ paiboon: {
127
+ text: 'pom',
128
+ system: 'paiboon',
129
+ syllables: ['pom']
130
+ },
131
+ ipa: {
132
+ text: 'pʰǒm',
133
+ system: 'ipa',
134
+ syllables: ['phom']
135
+ }
136
+ },
137
+ metadata: {
138
+ meaning: 'I, me (male)',
139
+ partOfSpeech: 'pronoun',
140
+ usage: 'first person singular, male speaker'
141
+ },
142
+ lang: 'th',
143
+ script: 'thai',
144
+ extras: {
145
+ translations: {
146
+ en: 'I, me (male)',
147
+ ja: '私(男性)',
148
+ zh: '我(男性)',
149
+ ko: '나, 저 (남성)'
150
+ },
151
+ metadata: {
152
+ difficulty: 'beginner',
153
+ frequency: 'common',
154
+ culturalNotes: 'First person pronoun used by male speakers',
155
+ related: ['ดิฉัน', 'ฉัน', 'เรา'],
156
+ examples: ['ผมชื่อ...', 'ผมชอบ...', 'ผมจะไป...']
157
+ }
158
+ }
159
+ }),
160
+ createGLOSTWordNode({
161
+ value: 'ชื่อ',
162
+ transcription: {
163
+ rtgs: {
164
+ text: 'chûue',
165
+ system: 'rtgs',
166
+ tone: 3,
167
+ syllables: ['chue']
168
+ },
169
+ aua: {
170
+ text: 'chue',
171
+ system: 'aua',
172
+ syllables: ['chue']
173
+ },
174
+ paiboon: {
175
+ text: 'chue',
176
+ system: 'paiboon',
177
+ syllables: ['chue']
178
+ },
179
+ ipa: {
180
+ text: 'tɕʰûː',
181
+ system: 'ipa',
182
+ syllables: ['chue']
183
+ }
184
+ },
185
+ metadata: {
186
+ meaning: 'name',
187
+ partOfSpeech: 'noun',
188
+ usage: 'noun, can be used as verb \'to be named\''
189
+ },
190
+ lang: 'th',
191
+ script: 'thai',
192
+ extras: {
193
+ translations: {
194
+ en: 'name',
195
+ ja: '名前',
196
+ zh: '名字',
197
+ ko: '이름'
198
+ },
199
+ metadata: {
200
+ difficulty: 'beginner',
201
+ frequency: 'common',
202
+ culturalNotes: 'Can function as both noun and verb',
203
+ related: ['นาม', 'ชื่อจริง', 'ชื่อเล่น'],
204
+ examples: ['ชื่ออะไรครับ', 'ชื่อของผมคือ...', 'ตั้งชื่อ']
205
+ }
206
+ }
207
+ }),
208
+ createGLOSTWordNode({
209
+ value: 'สมชาย',
210
+ transcription: {
211
+ rtgs: {
212
+ text: 'sǒm-chaai',
213
+ system: 'rtgs',
214
+ tone: 3,
215
+ syllables: ['som', 'chaai']
216
+ },
217
+ aua: {
218
+ text: 'som-chai',
219
+ system: 'aua',
220
+ syllables: ['som', 'chai']
221
+ },
222
+ paiboon: {
223
+ text: 'som-chai',
224
+ system: 'paiboon',
225
+ syllables: ['som', 'chai']
226
+ },
227
+ ipa: {
228
+ text: 'sǒm.tɕʰaːj',
229
+ system: 'ipa',
230
+ syllables: ['som', 'chaai']
231
+ }
232
+ },
233
+ metadata: {
234
+ meaning: 'male given name',
235
+ partOfSpeech: 'proper noun',
236
+ usage: 'personal name, common Thai male name'
237
+ },
238
+ lang: 'th',
239
+ script: 'thai',
240
+ extras: {
241
+ translations: {
242
+ en: 'Somchai (male name)',
243
+ ja: 'ソムチャイ(男性名)',
244
+ zh: '颂猜(男性名)',
245
+ ko: '솜차이 (남성 이름)'
246
+ },
247
+ metadata: {
248
+ difficulty: 'intermediate',
249
+ frequency: 'uncommon',
250
+ culturalNotes: 'Common traditional Thai male name meaning "man of merit"',
251
+ related: ['ชาย', 'สม', 'ชื่อไทย'],
252
+ examples: ['คุณสมชาย', 'สมชายเป็นคนดี', 'เพื่อนของสมชาย']
253
+ }
254
+ }
255
+ })
256
+ ];
257
+
258
+ // ============================================================================
259
+ // Enhanced Japanese Example with Extras
260
+ // ============================================================================
261
+
262
+ const japaneseWordsWithExtras: GLOSTWord[] = [
263
+ createGLOSTWordNode({
264
+ value: '私',
265
+ transcription: {
266
+ romaji: {
267
+ text: 'watashi',
268
+ system: 'romaji',
269
+ syllables: ['wa', 'ta', 'shi']
270
+ },
271
+ furigana: {
272
+ text: 'わたし',
273
+ system: 'furigana',
274
+ syllables: ['wa', 'ta', 'shi']
275
+ },
276
+ ipa: {
277
+ text: 'ɰataɕi',
278
+ system: 'ipa',
279
+ syllables: ['wa', 'ta', 'shi']
280
+ }
281
+ },
282
+ metadata: {
283
+ meaning: 'I, me',
284
+ partOfSpeech: 'pronoun',
285
+ usage: 'first person singular, formal and informal'
286
+ },
287
+ lang: 'ja',
288
+ script: 'mixed',
289
+ extras: {
290
+ translations: {
291
+ en: 'I, me',
292
+ th: 'ผม/ดิฉัน',
293
+ zh: '我',
294
+ ko: '나, 저'
295
+ },
296
+ metadata: {
297
+ difficulty: 'beginner',
298
+ frequency: 'very-common',
299
+ culturalNotes: 'Polite first person pronoun, gender-neutral',
300
+ related: ['僕', '俺', 'あたし'],
301
+ examples: ['私は学生です', '私の名前は...', '私も行きます']
302
+ }
303
+ }
304
+ }),
305
+ createGLOSTWordNode({
306
+ value: 'の',
307
+ transcription: {
308
+ romaji: {
309
+ text: 'no',
310
+ system: 'romaji',
311
+ syllables: ['no']
312
+ },
313
+ furigana: {
314
+ text: 'の',
315
+ system: 'furigana',
316
+ syllables: ['no']
317
+ },
318
+ ipa: {
319
+ text: 'no',
320
+ system: 'ipa',
321
+ syllables: ['no']
322
+ }
323
+ },
324
+ metadata: {
325
+ meaning: 'possessive particle',
326
+ partOfSpeech: 'particle',
327
+ usage: 'indicates possession or relationship'
328
+ },
329
+ lang: 'ja',
330
+ script: 'mixed',
331
+ extras: {
332
+ translations: {
333
+ en: 'possessive particle',
334
+ th: 'คำบุพบทแสดงความเป็นเจ้าของ',
335
+ zh: '的',
336
+ ko: '의'
337
+ },
338
+ metadata: {
339
+ difficulty: 'beginner',
340
+ frequency: 'very-common',
341
+ culturalNotes: 'Essential particle for showing possession',
342
+ related: ['が', 'は', 'を'],
343
+ examples: ['私の本', '日本の文化', '友達の家']
344
+ }
345
+ }
346
+ }),
347
+ createGLOSTWordNode({
348
+ value: '名前',
349
+ transcription: {
350
+ romaji: {
351
+ text: 'namae',
352
+ system: 'romaji',
353
+ syllables: ['na', 'mae']
354
+ },
355
+ furigana: {
356
+ text: 'なまえ',
357
+ system: 'furigana',
358
+ syllables: ['na', 'mae']
359
+ },
360
+ ipa: {
361
+ text: 'namae',
362
+ system: 'ipa',
363
+ syllables: ['na', 'mae']
364
+ }
365
+ },
366
+ metadata: {
367
+ meaning: 'name',
368
+ partOfSpeech: 'noun',
369
+ usage: 'noun, refers to a person\'s name'
370
+ },
371
+ lang: 'ja',
372
+ script: 'mixed',
373
+ extras: {
374
+ translations: {
375
+ en: 'name',
376
+ th: 'ชื่อ',
377
+ zh: '名字',
378
+ ko: '이름'
379
+ },
380
+ metadata: {
381
+ difficulty: 'beginner',
382
+ frequency: 'common',
383
+ culturalNotes: 'Basic vocabulary for introductions',
384
+ related: ['氏名', 'フルネーム', 'ニックネーム'],
385
+ examples: ['お名前は?', '名前を教えてください', '美しい名前']
386
+ }
387
+ }
388
+ }),
389
+ createGLOSTWordNode({
390
+ value: 'は',
391
+ transcription: {
392
+ romaji: {
393
+ text: 'wa',
394
+ system: 'romaji',
395
+ syllables: ['wa']
396
+ },
397
+ furigana: {
398
+ text: 'は',
399
+ system: 'furigana',
400
+ syllables: ['wa']
401
+ },
402
+ ipa: {
403
+ text: 'ɰa',
404
+ system: 'ipa',
405
+ syllables: ['wa']
406
+ }
407
+ },
408
+ metadata: {
409
+ meaning: 'topic particle',
410
+ partOfSpeech: 'particle',
411
+ usage: 'marks the topic of the sentence'
412
+ },
413
+ lang: 'ja',
414
+ script: 'mixed',
415
+ extras: {
416
+ translations: {
417
+ en: 'topic particle',
418
+ th: 'คำบุพบทแสดงหัวข้อ',
419
+ zh: '话题助词',
420
+ ko: '주제 조사'
421
+ },
422
+ metadata: {
423
+ difficulty: 'beginner',
424
+ frequency: 'very-common',
425
+ culturalNotes: 'One of the most important particles in Japanese',
426
+ related: ['が', 'を', 'に'],
427
+ examples: ['私は学生です', 'これは本です', '日本は美しい国です']
428
+ }
429
+ }
430
+ }),
431
+ createGLOSTWordNode({
432
+ value: '田中',
433
+ transcription: {
434
+ romaji: {
435
+ text: 'tanaka',
436
+ system: 'romaji',
437
+ syllables: ['ta', 'na', 'ka']
438
+ },
439
+ furigana: {
440
+ text: 'たなか',
441
+ system: 'furigana',
442
+ syllables: ['ta', 'na', 'ka']
443
+ },
444
+ ipa: {
445
+ text: 'tanaka',
446
+ system: 'ipa',
447
+ syllables: ['ta', 'na', 'ka']
448
+ }
449
+ },
450
+ metadata: {
451
+ meaning: 'surname Tanaka',
452
+ partOfSpeech: 'proper noun',
453
+ usage: 'family name, very common Japanese surname'
454
+ },
455
+ lang: 'ja',
456
+ script: 'mixed',
457
+ extras: {
458
+ translations: {
459
+ en: 'Tanaka (surname)',
460
+ th: 'ทานากะ (นามสกุล)',
461
+ zh: '田中(姓氏)',
462
+ ko: '다나카 (성)'
463
+ },
464
+ metadata: {
465
+ difficulty: 'beginner',
466
+ frequency: 'common',
467
+ culturalNotes: 'One of the most common Japanese surnames',
468
+ related: ['佐藤', '鈴木', '高橋'],
469
+ examples: ['田中さん', '田中先生', '田中家']
470
+ }
471
+ }
472
+ }),
473
+ createGLOSTWordNode({
474
+ value: 'です',
475
+ transcription: {
476
+ romaji: {
477
+ text: 'desu',
478
+ system: 'romaji',
479
+ syllables: ['de', 'su']
480
+ },
481
+ furigana: {
482
+ text: 'です',
483
+ system: 'furigana',
484
+ syllables: ['de', 'su']
485
+ },
486
+ ipa: {
487
+ text: 'desɯ',
488
+ system: 'ipa',
489
+ syllables: ['de', 'su']
490
+ }
491
+ },
492
+ metadata: {
493
+ meaning: 'copula (is, am, are)',
494
+ partOfSpeech: 'copula',
495
+ usage: 'polite form of the copula, formal speech'
496
+ },
497
+ lang: 'ja',
498
+ script: 'mixed',
499
+ extras: {
500
+ translations: {
501
+ en: 'is, am, are (polite)',
502
+ th: 'เป็น, คือ (สุภาพ)',
503
+ zh: '是(敬语)',
504
+ ko: '입니다 (존댓말)'
505
+ },
506
+ metadata: {
507
+ difficulty: 'beginner',
508
+ frequency: 'very-common',
509
+ culturalNotes: 'Polite copula used in formal situations',
510
+ related: ['だ', 'である', 'でございます'],
511
+ examples: ['私は学生です', 'これは本です', '田中さんです']
512
+ }
513
+ }
514
+ })
515
+ ];
516
+
517
+ // ============================================================================
518
+ // Create Enhanced Document Structure
519
+ // ============================================================================
520
+
521
+ const thaiSentenceWithExtras = createGLOSTSentenceNode({
522
+ originalText: 'สวัสดีครับ ผมชื่อสมชาย',
523
+ lang: 'th',
524
+ script: 'thai',
525
+ children: thaiWordsWithExtras
526
+ });
527
+
528
+ const japaneseSentenceWithExtras = createGLOSTSentenceNode({
529
+ originalText: '私の名前は田中です。',
530
+ lang: 'ja',
531
+ script: 'mixed',
532
+ children: japaneseWordsWithExtras
533
+ });
534
+
535
+ const thaiParagraphWithExtras = createGLOSTParagraphNode([thaiSentenceWithExtras]);
536
+ const japaneseParagraphWithExtras = createGLOSTParagraphNode([japaneseSentenceWithExtras]);
537
+
538
+ export const thaiDocumentWithExtras = createGLOSTRootNode({
539
+ lang: 'th',
540
+ script: 'thai',
541
+ children: [thaiParagraphWithExtras],
542
+ metadata: {
543
+ title: 'Thai Greeting Example with Extras',
544
+ description: 'Enhanced Thai example with i18n translations and metadata'
545
+ }
546
+ });
547
+
548
+ export const japaneseDocumentWithExtras = createGLOSTRootNode({
549
+ lang: 'ja',
550
+ script: 'mixed',
551
+ children: [japaneseParagraphWithExtras],
552
+ metadata: {
553
+ title: 'Japanese Greeting Example with Extras',
554
+ description: 'Enhanced Japanese example with i18n translations and metadata'
555
+ }
556
+ });
557
+
558
+ // ============================================================================
559
+ // Utility Functions for Working with Extras
560
+ // ============================================================================
561
+
562
+ /**
563
+ * Get quick translation for a word in a specific language
564
+ */
565
+ export function getQuickTranslation(word: GLOSTWord, targetLang: string): string | undefined {
566
+ return word.extras?.translations?.[targetLang];
567
+ }
568
+
569
+ /**
570
+ * Get all available translations for a word
571
+ */
572
+ export function getAllTranslations(word: GLOSTWord): Record<string, string> {
573
+ const translations = word.extras?.translations;
574
+ if (!translations) return {};
575
+
576
+ const result: Record<string, string> = {};
577
+ Object.entries(translations).forEach(([lang, text]) => {
578
+ if (text !== undefined) {
579
+ result[lang] = text;
580
+ }
581
+ });
582
+ return result;
583
+ }
584
+
585
+ /**
586
+ * Get difficulty level for a word
587
+ */
588
+ export function getDifficulty(word: GLOSTWord): string | undefined {
589
+ return word.extras?.metadata?.difficulty;
590
+ }
591
+
592
+ /**
593
+ * Get cultural notes for a word
594
+ */
595
+ export function getCulturalNotes(word: GLOSTWord): string | undefined {
596
+ return word.extras?.metadata?.culturalNotes;
597
+ }
598
+
599
+ /**
600
+ * Get related words for a word
601
+ */
602
+ export function getRelatedWords(word: GLOSTWord): string[] {
603
+ return word.extras?.metadata?.related || [];
604
+ }
605
+
606
+ /**
607
+ * Get example sentences for a word
608
+ */
609
+ export function getExamples(word: GLOSTWord): string[] {
610
+ return word.extras?.metadata?.examples || [];
611
+ }
612
+
613
+ // ============================================================================
614
+ // Export All Mock Data
615
+ // ============================================================================
616
+
617
+ export {
618
+ thaiWordsWithExtras,
619
+ japaneseWordsWithExtras,
620
+ thaiSentenceWithExtras,
621
+ japaneseSentenceWithExtras,
622
+ thaiParagraphWithExtras,
623
+ japaneseParagraphWithExtras
624
+ };