@kokimoki/app 2.1.0 → 3.0.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 (38) hide show
  1. package/README.md +72 -0
  2. package/dist/core/kokimoki-client.d.ts +75 -15
  3. package/dist/core/kokimoki-client.js +137 -22
  4. package/dist/index.d.ts +6 -1
  5. package/dist/index.js +4 -0
  6. package/dist/kokimoki.min.d.ts +322 -2
  7. package/dist/kokimoki.min.js +1884 -72
  8. package/dist/kokimoki.min.js.map +1 -1
  9. package/dist/llms.txt +6 -0
  10. package/dist/protocol/ws-message/reader.d.ts +1 -1
  11. package/dist/services/index.d.ts +1 -0
  12. package/dist/services/index.js +1 -0
  13. package/dist/services/kokimoki-ai.d.ts +185 -122
  14. package/dist/services/kokimoki-ai.js +201 -109
  15. package/dist/services/kokimoki-i18n.d.ts +259 -0
  16. package/dist/services/kokimoki-i18n.js +325 -0
  17. package/dist/stores/kokimoki-local-store.d.ts +1 -1
  18. package/dist/types/common.d.ts +9 -0
  19. package/dist/types/env.d.ts +36 -0
  20. package/dist/types/env.js +1 -0
  21. package/dist/types/index.d.ts +1 -0
  22. package/dist/types/index.js +1 -0
  23. package/dist/utils/kokimoki-client.d.ts +31 -0
  24. package/dist/utils/kokimoki-client.js +38 -0
  25. package/dist/utils/kokimoki-dev.d.ts +30 -0
  26. package/dist/utils/kokimoki-dev.js +75 -0
  27. package/dist/utils/kokimoki-env.d.ts +20 -0
  28. package/dist/utils/kokimoki-env.js +30 -0
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/docs/kokimoki-ai.instructions.md +316 -0
  32. package/docs/kokimoki-dynamic-stores.instructions.md +439 -0
  33. package/docs/kokimoki-i18n.instructions.md +285 -0
  34. package/docs/kokimoki-leaderboard.instructions.md +189 -0
  35. package/docs/kokimoki-sdk.instructions.md +221 -0
  36. package/docs/kokimoki-storage.instructions.md +162 -0
  37. package/llms.txt +43 -0
  38. package/package.json +9 -13
@@ -1,4 +1,5 @@
1
1
  import TypedEmitter from 'typed-emitter';
2
+ import i18next, { i18n } from 'i18next';
2
3
  import { Snapshot } from 'valtio/vanilla';
3
4
  import * as Y from 'yjs';
4
5
  export { proxy, ref, snapshot, subscribe, useSnapshot } from 'valtio';
@@ -10,6 +11,41 @@ interface Paginated<T> {
10
11
  total: number;
11
12
  }
12
13
 
14
+ /**
15
+ * Kokimoki environment configuration injected into the HTML by @kokimoki/kit.
16
+ *
17
+ * Parsed from `#kokimoki-env` script tag at runtime.
18
+ * In production, placeholder values (%KM_*%) are replaced by the server.
19
+ */
20
+ interface KokimokiEnv {
21
+ /** Whether running in development mode */
22
+ dev: boolean;
23
+ /** Whether running in test/preview mode (no real deploy code) */
24
+ test: boolean;
25
+ /** WebSocket server host */
26
+ host: string;
27
+ /** Application identifier */
28
+ appId: string;
29
+ /** Base URL for routing */
30
+ base: string;
31
+ /** Base URL for static assets (CDN in production) */
32
+ assets: string;
33
+ /** Deploy code slug (production only) */
34
+ code?: string;
35
+ /** Client context JSON string - mode, player/presenter codes (production only) */
36
+ clientContext?: string;
37
+ /** App configuration JSON string (production, legacy) */
38
+ config?: string;
39
+ /** Parsed app configuration object (dev only) */
40
+ configObject?: unknown;
41
+ /** List of i18n namespace names */
42
+ i18nNamespaces?: string[];
43
+ /** List of i18n language codes */
44
+ i18nLanguages?: string[];
45
+ /** Path to i18n files (e.g., "km-i18n") */
46
+ i18nPath?: string;
47
+ }
48
+
13
49
  type KokimokiClientEvents = {
14
50
  connected: () => void;
15
51
  disconnected: () => void;
@@ -107,6 +143,8 @@ declare class KokimokiAiService {
107
143
  * higher values make it more creative and varied.
108
144
  * @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
109
145
  * Controls the length of the AI's output.
146
+ * @param req.imageUrls Optional. Image URLs to include with the user prompt (Gemini models only).
147
+ * Allows the AI to analyze and respond based on the provided images.
110
148
  *
111
149
  * @returns A promise that resolves to an object containing the AI-generated response.
112
150
  * @returns {string} content The text content of the AI's response.
@@ -194,6 +232,241 @@ declare class KokimokiAiService {
194
232
  modifyImage(baseImageUrl: string, prompt: string, tags?: string[], model?: 'gemini-2.5-flash-image' | 'gemini-3-pro-image-preview'): Promise<Upload>;
195
233
  }
196
234
 
235
+ /**
236
+ * Options for creating an i18n instance.
237
+ */
238
+ interface I18nOptions {
239
+ /** Fallback language code (default: same as lng passed to init) */
240
+ fallbackLng?: string;
241
+ /** Default namespace (default: first namespace in the list) */
242
+ defaultNS?: string;
243
+ /** Array of i18next plugins to use (e.g., initReactI18next) */
244
+ use?: Parameters<typeof i18next.use>[0][];
245
+ }
246
+ /**
247
+ * Status of a single namespace translation.
248
+ */
249
+ type NamespaceStatus = "available" | "processing" | "failed" | "not_available";
250
+ /**
251
+ * Aggregated status of a language across all namespaces.
252
+ */
253
+ type LanguageStatus = "available" | "processing" | "failed" | "partial";
254
+ /**
255
+ * Translation status for a specific language.
256
+ */
257
+ interface TranslationStatus {
258
+ /** Overall status of the language */
259
+ status: "available" | "processing" | "not_available";
260
+ /** Status per namespace */
261
+ namespaces: Record<string, NamespaceStatus>;
262
+ }
263
+ /**
264
+ * Status of all languages that have been requested.
265
+ */
266
+ interface AllLanguagesStatus {
267
+ /** Array of language statuses */
268
+ languages: {
269
+ lng: string;
270
+ status: LanguageStatus;
271
+ }[];
272
+ }
273
+ /**
274
+ * Result of requesting a translation.
275
+ */
276
+ interface RequestTranslationResult {
277
+ /** Status of the request */
278
+ status: "started" | "already_processing" | "already_available";
279
+ }
280
+ /**
281
+ * Kokimoki i18n Service
282
+ *
283
+ * Provides translation loading via HTTP backend. Both development and production
284
+ * use HTTP to load translations consistently.
285
+ *
286
+ * In development, translations are served by @kokimoki/kit's dev server middleware.
287
+ * In production, translations are served from the assets CDN.
288
+ *
289
+ * **Key Features:**
290
+ * - Pre-configured i18next instance creation
291
+ * - Consistent HTTP-based loading in dev and prod
292
+ * - URL resolution for translation namespaces
293
+ * - AI-powered translation requests
294
+ *
295
+ * Access via `kmClient.i18n`
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * // Setup with React
300
+ * import { initReactI18next } from 'react-i18next';
301
+ *
302
+ * export const i18n = kmClient.i18n.createI18n({
303
+ * use: [initReactI18next]
304
+ * });
305
+ *
306
+ * // Initialize with primary language
307
+ * await kmClient.i18n.init('en');
308
+ *
309
+ * // Request AI translation for another language
310
+ * const result = await kmClient.i18n.requestTranslation('de');
311
+ * // Then poll getTranslationStatus('de') until available
312
+ * ```
313
+ */
314
+ declare class KokimokiI18nService {
315
+ private readonly client;
316
+ private initPromise;
317
+ private instance;
318
+ private options;
319
+ constructor(client: KokimokiClient);
320
+ /**
321
+ * Create and configure an i18next instance.
322
+ *
323
+ * This sets up the instance with plugins but does NOT initialize it.
324
+ * Call `init(lng)` to initialize with a specific language.
325
+ *
326
+ * @param options - Configuration options (plugins, fallback, defaultNS)
327
+ * @returns Configured i18next instance (not yet initialized)
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * // With React
332
+ * import { initReactI18next } from 'react-i18next';
333
+ *
334
+ * export const i18n = kmClient.i18n.createI18n({
335
+ * use: [initReactI18next]
336
+ * });
337
+ *
338
+ * // Later, when you know the language:
339
+ * await kmClient.i18n.init('en');
340
+ *
341
+ * // Then in components:
342
+ * const { t } = useTranslation('game');
343
+ * ```
344
+ */
345
+ createI18n(options?: I18nOptions): i18n;
346
+ /**
347
+ * Initialize the i18next instance with a specific language.
348
+ *
349
+ * Must call `createI18n()` first to set up the instance.
350
+ *
351
+ * @param lng - The language code to initialize with (e.g., 'en', 'de')
352
+ * @returns Promise that resolves when i18n is ready
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * // Create instance first
357
+ * const i18n = kmClient.i18n.createI18n({ use: [initReactI18next] });
358
+ *
359
+ * // Then initialize when you know the language
360
+ * await kmClient.i18n.init('en');
361
+ * ```
362
+ */
363
+ init(lng: string): Promise<void>;
364
+ /**
365
+ * Get the URL for a translation namespace.
366
+ *
367
+ * Returns the appropriate URL based on environment:
368
+ * - Development: `/__kokimoki/i18n/{lng}/{ns}.json`
369
+ * - Production: `{assets}/km-i18n/{lng}/{ns}.json`
370
+ *
371
+ * @param lng - Language code (e.g., 'en', 'et', 'de')
372
+ * @param ns - Namespace (e.g., 'ui', 'game', 'setup')
373
+ * @returns Full URL to the translation JSON file
374
+ *
375
+ * @example
376
+ * ```typescript
377
+ * const url = kmClient.i18n.getNamespaceUrl('en', 'game');
378
+ * // Dev: "/__kokimoki/i18n/en/game.json"
379
+ * // Prod: "https://cdn.kokimoki.com/build-123/km-i18n/en/game.json"
380
+ * ```
381
+ */
382
+ getNamespaceUrl(lng: string, ns: string): string;
383
+ /**
384
+ * Get the list of available namespaces.
385
+ *
386
+ * @returns Array of namespace names configured in @kokimoki/kit
387
+ */
388
+ getNamespaces(): string[];
389
+ /**
390
+ * Get the list of available languages.
391
+ *
392
+ * @returns Array of language codes configured in @kokimoki/kit
393
+ */
394
+ getLanguages(): string[];
395
+ /**
396
+ * Get the status of all languages that have been requested for AI translation.
397
+ *
398
+ * Only available in production. In development, returns an empty array.
399
+ *
400
+ * @returns Promise with array of language statuses
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * const { languages } = await kmClient.i18n.getAllLanguagesStatus();
405
+ * // [{ lng: 'de', status: 'available' }, { lng: 'fr', status: 'processing' }]
406
+ * ```
407
+ */
408
+ getAllLanguagesStatus(): Promise<AllLanguagesStatus>;
409
+ /**
410
+ * Get the translation status for a specific language.
411
+ *
412
+ * Returns the overall status and per-namespace status for the given language.
413
+ * In development, returns 'available' for local languages and 'not_available' for others.
414
+ * In production, queries the API for the actual status.
415
+ *
416
+ * @param lng - Target language code (e.g., 'de', 'fr', 'es')
417
+ * @returns Promise with translation status
418
+ *
419
+ * @example
420
+ * ```typescript
421
+ * const status = await kmClient.i18n.getTranslationStatus('de');
422
+ * if (status.status === 'available') {
423
+ * // All translations ready, can switch language
424
+ * i18next.changeLanguage('de');
425
+ * } else if (status.status === 'processing') {
426
+ * // Show loading indicator
427
+ * } else {
428
+ * // Request translation
429
+ * await kmClient.i18n.requestTranslation('de');
430
+ * }
431
+ * ```
432
+ */
433
+ getTranslationStatus(lng: string): Promise<TranslationStatus>;
434
+ /**
435
+ * Request AI translation for a target language.
436
+ *
437
+ * Triggers background AI translation jobs for all namespaces that are not yet available.
438
+ * Uses the build's configured primary language as the source.
439
+ *
440
+ * In development, returns 'already_available' for local languages and throws an error for others.
441
+ * In production, triggers the API to start translation.
442
+ *
443
+ * @param lng - Target language code (e.g., 'de', 'fr', 'es')
444
+ * @returns Promise with the result of the request
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * const result = await kmClient.i18n.requestTranslation('de');
449
+ *
450
+ * if (result.status === 'started') {
451
+ * // Translation started, poll for status
452
+ * const checkStatus = async () => {
453
+ * const status = await kmClient.i18n.getTranslationStatus('de');
454
+ * if (status.status === 'available') {
455
+ * i18next.changeLanguage('de');
456
+ * } else if (status.status === 'processing') {
457
+ * setTimeout(checkStatus, 2000);
458
+ * }
459
+ * };
460
+ * checkStatus();
461
+ * } else if (result.status === 'already_available') {
462
+ * // Already translated, switch immediately
463
+ * i18next.changeLanguage('de');
464
+ * }
465
+ * ```
466
+ */
467
+ requestTranslation(lng: string): Promise<RequestTranslationResult>;
468
+ }
469
+
197
470
  /**
198
471
  * Kokimoki Leaderboard Service
199
472
  *
@@ -740,6 +1013,7 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
740
1013
  private _clientTokenKey;
741
1014
  private _editorContext;
742
1015
  private _ai?;
1016
+ private _i18n?;
743
1017
  private _storage?;
744
1018
  private _leaderboard?;
745
1019
  constructor(host: string, appId: string, code?: string);
@@ -839,6 +1113,25 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
839
1113
  * Disables automatic reconnection, closes the WebSocket, and clears all intervals.
840
1114
  */
841
1115
  close(): Promise<void>;
1116
+ /**
1117
+ * Waits for all subscriptions to be fully joined.
1118
+ *
1119
+ * This is useful when you need to ensure all stores have completed their initial
1120
+ * synchronization before proceeding (e.g., before running tests or taking snapshots).
1121
+ *
1122
+ * @param timeout - Maximum time to wait in milliseconds (default: 5000ms).
1123
+ * @returns A promise that resolves when all subscriptions are joined, or when timeout is reached.
1124
+ *
1125
+ * @example
1126
+ * ```ts
1127
+ * // Wait for all stores to sync before starting game
1128
+ * await client.waitForSubscriptions();
1129
+ *
1130
+ * // Wait with custom timeout
1131
+ * await client.waitForSubscriptions(10000);
1132
+ * ```
1133
+ */
1134
+ waitForSubscriptions(timeout?: number): Promise<void>;
842
1135
  /**
843
1136
  * Gets the internal room hash identifier for a store.
844
1137
  *
@@ -900,6 +1193,10 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
900
1193
  * Access AI capabilities including text generation, structured JSON output, and image modification.
901
1194
  */
902
1195
  get ai(): KokimokiAiService;
1196
+ /**
1197
+ * Access i18n URL resolution and translation loading utilities.
1198
+ */
1199
+ get i18n(): KokimokiI18nService;
903
1200
  /**
904
1201
  * Access file upload and management for media files, images, and user-generated content.
905
1202
  */
@@ -916,9 +1213,32 @@ declare enum RoomSubscriptionMode {
916
1213
  ReadWrite = "b"
917
1214
  }
918
1215
 
1216
+ /**
1217
+ * Parses and returns the Kokimoki environment configuration.
1218
+ *
1219
+ * The environment is injected into the HTML by @kokimoki/kit as a JSON script tag
1220
+ * with id `kokimoki-env`. In production, placeholder values are replaced by the server.
1221
+ *
1222
+ * @returns The parsed KokimokiEnv object
1223
+ * @throws Error if the kokimoki-env element is not found
1224
+ *
1225
+ * @example
1226
+ * ```typescript
1227
+ * import { getKmEnv } from '@kokimoki/app';
1228
+ *
1229
+ * const env = getKmEnv();
1230
+ * console.log(env.dev); // true in development
1231
+ * console.log(env.assets); // CDN URL in production
1232
+ *
1233
+ * // Cast i18n to your app's type if needed
1234
+ * const i18n = env.i18n as typeof i18nResources;
1235
+ * ```
1236
+ */
1237
+ declare function getKmEnv(): KokimokiEnv;
1238
+
919
1239
  declare module "valtio" {
920
1240
  function useSnapshot<T extends object>(p: T): T;
921
1241
  }
922
1242
 
923
- export { KokimokiClient, KokimokiStore };
924
- export type { KokimokiClientEvents, Paginated, Upload };
1243
+ export { KokimokiClient, KokimokiStore, getKmEnv };
1244
+ export type { AllLanguagesStatus, I18nOptions, KokimokiClientEvents, KokimokiEnv, LanguageStatus, NamespaceStatus, Paginated, RequestTranslationResult, TranslationStatus, Upload };