@kokimoki/app 3.1.3 → 3.1.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.
- package/README.md +1 -2
- package/dist/core/kokimoki-client.d.ts +4 -4
- package/dist/core/kokimoki-client.js +4 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/utils/valtio.d.ts +2 -5
- package/dist/utils/valtio.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/kokimoki-ai.instructions.md +4 -2
- package/docs/kokimoki-dynamic-stores.instructions.md +3 -3
- package/docs/kokimoki-i18n.instructions.md +1 -1
- package/docs/kokimoki-sdk.instructions.md +46 -7
- package/package.json +15 -2
- package/dist/fields.d.ts +0 -110
- package/dist/fields.js +0 -158
- package/dist/kokimoki-ai.d.ts +0 -153
- package/dist/kokimoki-ai.js +0 -164
- package/dist/kokimoki-awareness.d.ts +0 -21
- package/dist/kokimoki-awareness.js +0 -48
- package/dist/kokimoki-client-refactored.d.ts +0 -80
- package/dist/kokimoki-client-refactored.js +0 -400
- package/dist/kokimoki-client.d.ts +0 -362
- package/dist/kokimoki-client.js +0 -823
- package/dist/kokimoki-leaderboard.d.ts +0 -175
- package/dist/kokimoki-leaderboard.js +0 -203
- package/dist/kokimoki-local-store.d.ts +0 -11
- package/dist/kokimoki-local-store.js +0 -40
- package/dist/kokimoki-queue.d.ts +0 -0
- package/dist/kokimoki-queue.js +0 -38
- package/dist/kokimoki-req-res.d.ts +0 -0
- package/dist/kokimoki-req-res.js +0 -198
- package/dist/kokimoki-schema.d.ts +0 -113
- package/dist/kokimoki-schema.js +0 -162
- package/dist/kokimoki-storage.d.ts +0 -156
- package/dist/kokimoki-storage.js +0 -208
- package/dist/kokimoki-store.d.ts +0 -23
- package/dist/kokimoki-store.js +0 -117
- package/dist/kokimoki-transaction.d.ts +0 -18
- package/dist/kokimoki-transaction.js +0 -143
- package/dist/kokimoki.min.d.ts +0 -1244
- package/dist/kokimoki.min.js +0 -19108
- package/dist/kokimoki.min.js.map +0 -1
- package/dist/llms.txt +0 -665
- package/dist/message-queue.d.ts +0 -8
- package/dist/message-queue.js +0 -19
- package/dist/room-subscription-mode.d.ts +0 -5
- package/dist/room-subscription-mode.js +0 -6
- package/dist/room-subscription.d.ts +0 -15
- package/dist/room-subscription.js +0 -52
- package/dist/synced-schema.d.ts +0 -74
- package/dist/synced-schema.js +0 -83
- package/dist/synced-store.d.ts +0 -10
- package/dist/synced-store.js +0 -9
- package/dist/synced-types.d.ts +0 -47
- package/dist/synced-types.js +0 -67
- package/dist/ws-message-reader.d.ts +0 -11
- package/dist/ws-message-reader.js +0 -36
- package/dist/ws-message-type copy.d.ts +0 -6
- package/dist/ws-message-type copy.js +0 -7
- package/dist/ws-message-type.d.ts +0 -11
- package/dist/ws-message-type.js +0 -12
- package/dist/ws-message-writer.d.ts +0 -9
- package/dist/ws-message-writer.js +0 -45
package/dist/kokimoki.min.d.ts
DELETED
|
@@ -1,1244 +0,0 @@
|
|
|
1
|
-
import TypedEmitter from 'typed-emitter';
|
|
2
|
-
import i18next, { i18n } from 'i18next';
|
|
3
|
-
import { Snapshot } from 'valtio/vanilla';
|
|
4
|
-
import * as Y from 'yjs';
|
|
5
|
-
export { proxy, ref, snapshot, subscribe, useSnapshot } from 'valtio';
|
|
6
|
-
export { derive, underive } from 'derive-valtio';
|
|
7
|
-
export { devtools, subscribeKey, useProxy, watch } from 'valtio/utils';
|
|
8
|
-
|
|
9
|
-
interface Paginated<T> {
|
|
10
|
-
items: T[];
|
|
11
|
-
total: number;
|
|
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
|
-
|
|
49
|
-
type KokimokiClientEvents = {
|
|
50
|
-
connected: () => void;
|
|
51
|
-
disconnected: () => void;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
interface Upload {
|
|
55
|
-
id: string;
|
|
56
|
-
appId: string;
|
|
57
|
-
clientId: string;
|
|
58
|
-
createdAt: Date;
|
|
59
|
-
name: string;
|
|
60
|
-
url: string;
|
|
61
|
-
size: number;
|
|
62
|
-
mimeType: string;
|
|
63
|
-
completed: boolean;
|
|
64
|
-
tags: string[];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Kokimoki AI Integration Service
|
|
69
|
-
*
|
|
70
|
-
* Provides built-in AI capabilities for game applications without requiring API keys or setup.
|
|
71
|
-
* Includes text generation, structured JSON output, and image modification.
|
|
72
|
-
*
|
|
73
|
-
* **Key Features:**
|
|
74
|
-
* - Multiple AI models (GPT-4, GPT-5, Gemini variants)
|
|
75
|
-
* - Text generation with configurable creativity (temperature)
|
|
76
|
-
* - Structured JSON output for game data
|
|
77
|
-
* - AI-powered image modifications
|
|
78
|
-
* - No API keys or configuration required
|
|
79
|
-
*
|
|
80
|
-
* **Common Use Cases:**
|
|
81
|
-
* - Generate dynamic game content (quests, dialogues, stories)
|
|
82
|
-
* - Create AI opponents or NPCs with personalities
|
|
83
|
-
* - Generate quiz questions or trivia
|
|
84
|
-
* - Create game assets (character stats, item descriptions)
|
|
85
|
-
* - Transform user-uploaded images
|
|
86
|
-
* - Generate procedural content
|
|
87
|
-
*
|
|
88
|
-
* Access via `kmClient.ai`
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```typescript
|
|
92
|
-
* // Generate story text
|
|
93
|
-
* const story = await kmClient.ai.chat({
|
|
94
|
-
* systemPrompt: 'You are a fantasy story writer',
|
|
95
|
-
* userPrompt: 'Write a short quest description',
|
|
96
|
-
* temperature: 0.8
|
|
97
|
-
* });
|
|
98
|
-
*
|
|
99
|
-
* // Generate structured game data
|
|
100
|
-
* interface Enemy {
|
|
101
|
-
* name: string;
|
|
102
|
-
* health: number;
|
|
103
|
-
* attack: number;
|
|
104
|
-
* }
|
|
105
|
-
* const enemy = await kmClient.ai.generateJson<Enemy>({
|
|
106
|
-
* userPrompt: 'Create a level 5 goblin warrior'
|
|
107
|
-
* });
|
|
108
|
-
*
|
|
109
|
-
* // Transform image
|
|
110
|
-
* const modified = await kmClient.ai.modifyImage(
|
|
111
|
-
* imageUrl,
|
|
112
|
-
* 'Make it look like pixel art'
|
|
113
|
-
* );
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
declare class KokimokiAiService {
|
|
117
|
-
private readonly client;
|
|
118
|
-
constructor(client: KokimokiClient);
|
|
119
|
-
/**
|
|
120
|
-
* Generate a chat response from the AI model.
|
|
121
|
-
*
|
|
122
|
-
* Sends a chat request to the AI service and returns the generated response.
|
|
123
|
-
* Supports multiple AI models including GPT and Gemini variants with configurable
|
|
124
|
-
* parameters for fine-tuning the response behavior.
|
|
125
|
-
*
|
|
126
|
-
* @param req The chat request parameters.
|
|
127
|
-
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
128
|
-
* Available models:
|
|
129
|
-
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
130
|
-
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
131
|
-
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
132
|
-
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
133
|
-
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
134
|
-
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
135
|
-
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
136
|
-
* - `gemini-3-flash-preview`: Google Gemini 3 Flash preview
|
|
137
|
-
* - `gemini-3-pro-preview`: Google Gemini 3 Pro preview
|
|
138
|
-
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
139
|
-
* This helps define the AI's role, personality, and constraints.
|
|
140
|
-
* @param req.userPrompt The user's message or question to send to the AI.
|
|
141
|
-
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
142
|
-
* Lower values make output more focused and deterministic,
|
|
143
|
-
* higher values make it more creative and varied.
|
|
144
|
-
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
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.
|
|
148
|
-
*
|
|
149
|
-
* @returns A promise that resolves to an object containing the AI-generated response.
|
|
150
|
-
* @returns {string} content The text content of the AI's response.
|
|
151
|
-
*
|
|
152
|
-
* @throws An error object if the API request fails.
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```typescript
|
|
156
|
-
* const response = await client.ai.chat({
|
|
157
|
-
* model: "gpt-4o",
|
|
158
|
-
* systemPrompt: "You are a helpful coding assistant.",
|
|
159
|
-
* userPrompt: "Explain what TypeScript is in one sentence.",
|
|
160
|
-
* temperature: 0.7,
|
|
161
|
-
* maxTokens: 100
|
|
162
|
-
* });
|
|
163
|
-
* console.log(response.content);
|
|
164
|
-
* ```
|
|
165
|
-
*/
|
|
166
|
-
chat(req: {
|
|
167
|
-
model?: "gpt-4o" | "gpt-4o-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gemini-2.5-flash-lite" | "gemini-2.5-flash" | "gemini-3-flash-preview" | "gemini-3-pro-preview";
|
|
168
|
-
systemPrompt?: string;
|
|
169
|
-
userPrompt: string;
|
|
170
|
-
temperature?: number;
|
|
171
|
-
maxTokens?: number;
|
|
172
|
-
responseMimeType?: string;
|
|
173
|
-
/** Image URLs to include with the user prompt (Gemini models only) */
|
|
174
|
-
imageUrls?: string[];
|
|
175
|
-
}): Promise<{
|
|
176
|
-
content: string;
|
|
177
|
-
}>;
|
|
178
|
-
/**
|
|
179
|
-
* Generate structured JSON output from the AI model.
|
|
180
|
-
*
|
|
181
|
-
* Sends a chat request to the AI service with the expectation of receiving
|
|
182
|
-
* a JSON-formatted response. This is useful for scenarios where the output
|
|
183
|
-
* needs to be parsed or processed programmatically.
|
|
184
|
-
*
|
|
185
|
-
* **Important:** Your prompt must include the word "json" and should describe
|
|
186
|
-
* the expected output schema (field names, types, and structure) to ensure
|
|
187
|
-
* the AI generates properly formatted responses.
|
|
188
|
-
*
|
|
189
|
-
* @param req The chat request parameters.
|
|
190
|
-
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
191
|
-
* Available models:
|
|
192
|
-
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
193
|
-
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
194
|
-
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
195
|
-
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
196
|
-
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
197
|
-
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
198
|
-
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
199
|
-
* - `gemini-3-flash-preview`: Google Gemini 3 Flash preview
|
|
200
|
-
* - `gemini-3-pro-preview`: Google Gemini 3 Pro preview
|
|
201
|
-
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
202
|
-
* This helps define the AI's role, personality, and constraints.
|
|
203
|
-
* @param req.userPrompt The user's message or question to send to the AI.
|
|
204
|
-
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
205
|
-
* Lower values make output more focused and deterministic,
|
|
206
|
-
* higher values make it more creative and varied.
|
|
207
|
-
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
208
|
-
* Controls the length of the AI's output.
|
|
209
|
-
* @param req.imageUrls Optional. Image URLs to include with the user prompt (Gemini models only).
|
|
210
|
-
* Allows the AI to analyze images and generate structured JSON based on them.
|
|
211
|
-
*
|
|
212
|
-
* @returns A promise that resolves to the parsed JSON object generated by the AI.
|
|
213
|
-
*
|
|
214
|
-
* @throws An error object if the API request fails or if the response is not valid JSON.
|
|
215
|
-
*/
|
|
216
|
-
generateJson<T extends object>(req: {
|
|
217
|
-
model?: "gpt-4o" | "gpt-4o-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gemini-2.5-flash-lite" | "gemini-2.5-flash" | "gemini-3-flash-preview" | "gemini-3-pro-preview";
|
|
218
|
-
systemPrompt?: string;
|
|
219
|
-
userPrompt: string;
|
|
220
|
-
temperature?: number;
|
|
221
|
-
maxTokens?: number;
|
|
222
|
-
/** Image URLs to include with the user prompt (Gemini models only) */
|
|
223
|
-
imageUrls?: string[];
|
|
224
|
-
}): Promise<T>;
|
|
225
|
-
/**
|
|
226
|
-
* Modify an image using the AI service.
|
|
227
|
-
* @param baseImageUrl The URL of the base image to modify.
|
|
228
|
-
* @param prompt The modification prompt to apply to the image.
|
|
229
|
-
* @param tags Optional. Tags to associate with the image.
|
|
230
|
-
* @returns A promise that resolves to the modified image upload information.
|
|
231
|
-
*/
|
|
232
|
-
modifyImage(baseImageUrl: string, prompt: string, tags?: string[], model?: 'gemini-2.5-flash-image' | 'gemini-3-pro-image-preview'): Promise<Upload>;
|
|
233
|
-
}
|
|
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
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Kokimoki Leaderboard Service
|
|
472
|
-
*
|
|
473
|
-
* Provides efficient player ranking and score tracking with database indexes and optimized queries.
|
|
474
|
-
* Ideal for games with large numbers of players and competitive scoring.
|
|
475
|
-
*
|
|
476
|
-
* **Key Features:**
|
|
477
|
-
* - Efficient ranking with database indexes
|
|
478
|
-
* - Support for ascending (lowest-is-best) and descending (highest-is-best) sorting
|
|
479
|
-
* - Pagination for large leaderboards
|
|
480
|
-
* - Public and private metadata for entries
|
|
481
|
-
* - Insert (preserve all attempts) or upsert (keep latest only) modes
|
|
482
|
-
*
|
|
483
|
-
* **When to use Leaderboard API vs Global Store:**
|
|
484
|
-
*
|
|
485
|
-
* Use the **Leaderboard API** when:
|
|
486
|
-
* - You have a large number of entries (hundreds to thousands of players)
|
|
487
|
-
* - You need efficient ranking and sorting with database indexes
|
|
488
|
-
* - You want pagination and optimized queries for top scores
|
|
489
|
-
* - Memory and network efficiency are important
|
|
490
|
-
*
|
|
491
|
-
* Use a **Global Store** when:
|
|
492
|
-
* - You have a small number of players (typically under 100)
|
|
493
|
-
* - You need real-time updates and live leaderboard changes
|
|
494
|
-
* - You want to combine player scores with other game state
|
|
495
|
-
* - The leaderboard is temporary (session-based or reset frequently)
|
|
496
|
-
*
|
|
497
|
-
* Access via `kmClient.leaderboard`
|
|
498
|
-
*
|
|
499
|
-
* @example
|
|
500
|
-
* ```typescript
|
|
501
|
-
* // Submit a high score
|
|
502
|
-
* const { rank } = await kmClient.leaderboard.upsertEntry(
|
|
503
|
-
* 'high-scores',
|
|
504
|
-
* 'desc',
|
|
505
|
-
* 1500,
|
|
506
|
-
* { playerName: 'Alice' },
|
|
507
|
-
* {}
|
|
508
|
-
* );
|
|
509
|
-
*
|
|
510
|
-
* // Get top 10
|
|
511
|
-
* const { items } = await kmClient.leaderboard.listEntries('high-scores', 'desc', 0, 10);
|
|
512
|
-
*
|
|
513
|
-
* // Get player's best
|
|
514
|
-
* const best = await kmClient.leaderboard.getBestEntry('high-scores', 'desc');
|
|
515
|
-
* ```
|
|
516
|
-
*/
|
|
517
|
-
declare class KokimokiLeaderboardService {
|
|
518
|
-
private readonly client;
|
|
519
|
-
constructor(client: KokimokiClient);
|
|
520
|
-
/**
|
|
521
|
-
* Add a new entry to a leaderboard.
|
|
522
|
-
*
|
|
523
|
-
* Creates a new entry each time it's called, preserving all attempts. Use this when you want
|
|
524
|
-
* to track every score submission (e.g., all game attempts).
|
|
525
|
-
*
|
|
526
|
-
* @param leaderboardName The name of the leaderboard to add the entry to
|
|
527
|
-
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
528
|
-
* "desc" for highest-is-best (e.g., points)
|
|
529
|
-
* @param score The numeric score value
|
|
530
|
-
* @param metadata Public metadata visible to all players (e.g., player name, level)
|
|
531
|
-
* @param privateMetadata Private metadata only accessible via API calls (e.g., session ID)
|
|
532
|
-
* @returns A promise resolving to an object with the entry's rank
|
|
533
|
-
*
|
|
534
|
-
* @example
|
|
535
|
-
* ```typescript
|
|
536
|
-
* const { rank } = await kmClient.leaderboard.insertEntry(
|
|
537
|
-
* 'high-scores',
|
|
538
|
-
* 'desc',
|
|
539
|
-
* 1500,
|
|
540
|
-
* { playerName: 'Alice', level: 10 },
|
|
541
|
-
* { sessionId: 'abc123' }
|
|
542
|
-
* );
|
|
543
|
-
* console.log(`New rank: ${rank}`);
|
|
544
|
-
* ```
|
|
545
|
-
*/
|
|
546
|
-
insertEntry<MetadataT, PrivateMetadataT>(leaderboardName: string, sortDir: "asc" | "desc", score: number, metadata: MetadataT, privateMetadata: PrivateMetadataT): Promise<{
|
|
547
|
-
rank: number;
|
|
548
|
-
}>;
|
|
549
|
-
/**
|
|
550
|
-
* Add or update the latest entry for the current client in a leaderboard.
|
|
551
|
-
*
|
|
552
|
-
* Replaces the previous entry if one exists for this client. Use this when you only want
|
|
553
|
-
* to keep the latest or best score per player (e.g., daily high score).
|
|
554
|
-
*
|
|
555
|
-
* @param leaderboardName The name of the leaderboard to upsert the entry in
|
|
556
|
-
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
557
|
-
* "desc" for highest-is-best (e.g., points)
|
|
558
|
-
* @param score The numeric score value
|
|
559
|
-
* @param metadata Public metadata visible to all players (e.g., player name, completion time)
|
|
560
|
-
* @param privateMetadata Private metadata only accessible via API calls (e.g., device ID)
|
|
561
|
-
* @returns A promise resolving to an object with the entry's updated rank
|
|
562
|
-
*
|
|
563
|
-
* @example
|
|
564
|
-
* ```typescript
|
|
565
|
-
* const { rank } = await kmClient.leaderboard.upsertEntry(
|
|
566
|
-
* 'daily-scores',
|
|
567
|
-
* 'desc',
|
|
568
|
-
* 2000,
|
|
569
|
-
* { playerName: 'Bob', completionTime: 120 },
|
|
570
|
-
* { deviceId: 'xyz789' }
|
|
571
|
-
* );
|
|
572
|
-
* console.log(`Updated rank: ${rank}`);
|
|
573
|
-
* ```
|
|
574
|
-
*/
|
|
575
|
-
upsertEntry<MetadataT, PrivateMetadataT>(leaderboardName: string, sortDir: "asc" | "desc", score: number, metadata: MetadataT, privateMetadata: PrivateMetadataT): Promise<{
|
|
576
|
-
rank: number;
|
|
577
|
-
}>;
|
|
578
|
-
/**
|
|
579
|
-
* List entries in a leaderboard with pagination.
|
|
580
|
-
*
|
|
581
|
-
* Retrieves a sorted list of leaderboard entries. Use skip and limit parameters for
|
|
582
|
-
* pagination (e.g., showing top 10, or implementing "load more" functionality).
|
|
583
|
-
*
|
|
584
|
-
* @param leaderboardName The name of the leaderboard to query
|
|
585
|
-
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
586
|
-
* "desc" for highest-is-best (e.g., points)
|
|
587
|
-
* @param skip Number of entries to skip for pagination (default: 0)
|
|
588
|
-
* @param limit Maximum number of entries to return (default: 100)
|
|
589
|
-
* @returns A promise resolving to a paginated list of entries with rank, score, and metadata
|
|
590
|
-
*
|
|
591
|
-
* @example
|
|
592
|
-
* ```typescript
|
|
593
|
-
* // Get top 10 scores
|
|
594
|
-
* const { items, total } = await kmClient.leaderboard.listEntries(
|
|
595
|
-
* 'weekly-scores',
|
|
596
|
-
* 'desc',
|
|
597
|
-
* 0,
|
|
598
|
-
* 10
|
|
599
|
-
* );
|
|
600
|
-
*
|
|
601
|
-
* items.forEach(entry => {
|
|
602
|
-
* console.log(`Rank ${entry.rank}: ${entry.metadata.playerName} - ${entry.score}`);
|
|
603
|
-
* });
|
|
604
|
-
* ```
|
|
605
|
-
*/
|
|
606
|
-
listEntries<MetadataT>(leaderboardName: string, sortDir: "asc" | "desc", skip?: number, limit?: number): Promise<Paginated<{
|
|
607
|
-
rank: number;
|
|
608
|
-
score: number;
|
|
609
|
-
metadata: MetadataT;
|
|
610
|
-
}>>;
|
|
611
|
-
/**
|
|
612
|
-
* Get the best entry for a specific client in a leaderboard.
|
|
613
|
-
*
|
|
614
|
-
* Retrieves the highest-ranked entry for a client based on the sort direction.
|
|
615
|
-
* Defaults to the current client if no clientId is provided.
|
|
616
|
-
*
|
|
617
|
-
* @param leaderboardName The name of the leaderboard to query
|
|
618
|
-
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
619
|
-
* "desc" for highest-is-best (e.g., points)
|
|
620
|
-
* @param clientId The client ID to get the best entry for (optional, defaults to current client)
|
|
621
|
-
* @returns A promise resolving to the best entry with rank, score, and metadata
|
|
622
|
-
*
|
|
623
|
-
* @example
|
|
624
|
-
* ```typescript
|
|
625
|
-
* // Get current client's best entry
|
|
626
|
-
* const myBest = await kmClient.leaderboard.getBestEntry('all-time-high', 'desc');
|
|
627
|
-
* console.log(`My best: Rank ${myBest.rank}, Score ${myBest.score}`);
|
|
628
|
-
*
|
|
629
|
-
* // Get another player's best entry
|
|
630
|
-
* const otherBest = await kmClient.leaderboard.getBestEntry(
|
|
631
|
-
* 'all-time-high',
|
|
632
|
-
* 'desc',
|
|
633
|
-
* 'other-client-id'
|
|
634
|
-
* );
|
|
635
|
-
* ```
|
|
636
|
-
*/
|
|
637
|
-
getBestEntry<MetadataT>(leaderboardName: string, sortDir: "asc" | "desc", clientId?: string): Promise<{
|
|
638
|
-
rank: number;
|
|
639
|
-
score: number;
|
|
640
|
-
metadata: MetadataT;
|
|
641
|
-
}>;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
/**
|
|
645
|
-
* Kokimoki Storage Service
|
|
646
|
-
*
|
|
647
|
-
* Provides file upload and management capabilities for game applications. Ideal for media files
|
|
648
|
-
* (images, videos, audio) and other data not suitable for real-time stores (JSON, text files).
|
|
649
|
-
*
|
|
650
|
-
* **Key Features:**
|
|
651
|
-
* - Upload files to cloud storage with CDN delivery
|
|
652
|
-
* - Tag-based organization and filtering
|
|
653
|
-
* - Query uploads by client, MIME type, or tags
|
|
654
|
-
* - Pagination support for large collections
|
|
655
|
-
* - Public CDN URLs for direct access
|
|
656
|
-
*
|
|
657
|
-
* **Common Use Cases:**
|
|
658
|
-
* - Player avatars and profile images
|
|
659
|
-
* - Game screenshots and replays
|
|
660
|
-
* - User-generated content
|
|
661
|
-
* - Asset uploads (levels, maps, custom skins)
|
|
662
|
-
* - JSON configuration files
|
|
663
|
-
*
|
|
664
|
-
* Access via `kmClient.storage`
|
|
665
|
-
*
|
|
666
|
-
* @example
|
|
667
|
-
* ```typescript
|
|
668
|
-
* // Upload an image
|
|
669
|
-
* const upload = await kmClient.storage.upload('avatar.jpg', imageBlob, ['profile']);
|
|
670
|
-
*
|
|
671
|
-
* // Query user's uploads
|
|
672
|
-
* const myUploads = await kmClient.storage.listUploads({
|
|
673
|
-
* clientId: kmClient.id
|
|
674
|
-
* });
|
|
675
|
-
*
|
|
676
|
-
* // Use in store
|
|
677
|
-
* await kmClient.transact([store], (state) => {
|
|
678
|
-
* state.playerAvatar = upload.url;
|
|
679
|
-
* });
|
|
680
|
-
* ```
|
|
681
|
-
*/
|
|
682
|
-
declare class KokimokiStorageService {
|
|
683
|
-
private readonly client;
|
|
684
|
-
constructor(client: KokimokiClient);
|
|
685
|
-
private createUpload;
|
|
686
|
-
private uploadChunks;
|
|
687
|
-
private completeUpload;
|
|
688
|
-
/**
|
|
689
|
-
* Upload a file to cloud storage.
|
|
690
|
-
*
|
|
691
|
-
* Uploads a file (Blob) to Kokimoki storage and returns an Upload object with a public CDN URL.
|
|
692
|
-
* Files are automatically chunked for efficient upload. The returned URL can be used directly
|
|
693
|
-
* in your application (e.g., in img tags or store state).
|
|
694
|
-
*
|
|
695
|
-
* @param name The filename for the upload
|
|
696
|
-
* @param blob The Blob object containing the file data
|
|
697
|
-
* @param tags Optional array of tags for organizing and filtering uploads (default: [])
|
|
698
|
-
* @returns A promise resolving to the Upload object with CDN URL and metadata
|
|
699
|
-
*
|
|
700
|
-
* @example
|
|
701
|
-
* ```typescript
|
|
702
|
-
* // Upload image with tags
|
|
703
|
-
* const upload = await kmClient.storage.upload(
|
|
704
|
-
* 'avatar.jpg',
|
|
705
|
-
* imageBlob,
|
|
706
|
-
* ['profile', 'avatar']
|
|
707
|
-
* );
|
|
708
|
-
*
|
|
709
|
-
* // Use the CDN URL
|
|
710
|
-
* console.log(upload.url); // https://cdn.kokimoki.com/...
|
|
711
|
-
*
|
|
712
|
-
* // Store in game state
|
|
713
|
-
* await kmClient.transact([store], (state) => {
|
|
714
|
-
* state.players[kmClient.id].avatar = upload.url;
|
|
715
|
-
* });
|
|
716
|
-
* ```
|
|
717
|
-
*/
|
|
718
|
-
upload(name: string, blob: Blob, tags?: string[]): Promise<Upload>;
|
|
719
|
-
/**
|
|
720
|
-
* Update metadata for an existing upload.
|
|
721
|
-
*
|
|
722
|
-
* Allows you to replace the tags associated with an upload. Useful for reorganizing
|
|
723
|
-
* or recategorizing uploaded files.
|
|
724
|
-
*
|
|
725
|
-
* @param id The upload ID to update
|
|
726
|
-
* @param update Object containing the new tags array
|
|
727
|
-
* @returns A promise resolving to the updated Upload object
|
|
728
|
-
*
|
|
729
|
-
* @example
|
|
730
|
-
* ```typescript
|
|
731
|
-
* // Update tags
|
|
732
|
-
* const updated = await kmClient.storage.updateUpload(upload.id, {
|
|
733
|
-
* tags: ['archived', 'old-profile']
|
|
734
|
-
* });
|
|
735
|
-
* ```
|
|
736
|
-
*/
|
|
737
|
-
updateUpload(id: string, update: {
|
|
738
|
-
tags?: string[];
|
|
739
|
-
}): Promise<Upload>;
|
|
740
|
-
/**
|
|
741
|
-
* Query uploaded files with filtering and pagination.
|
|
742
|
-
*
|
|
743
|
-
* Retrieves a list of uploads matching the specified criteria. Supports filtering by
|
|
744
|
-
* client (uploader), MIME types, and tags. Use pagination for large collections.
|
|
745
|
-
*
|
|
746
|
-
* @param filter Optional filter criteria
|
|
747
|
-
* @param filter.clientId Filter by uploader's client ID
|
|
748
|
-
* @param filter.mimeTypes Filter by MIME types (e.g., ['image/jpeg', 'image/png'])
|
|
749
|
-
* @param filter.tags Filter by tags (all specified tags must match)
|
|
750
|
-
* @param skip Number of results to skip for pagination (default: 0)
|
|
751
|
-
* @param limit Maximum number of results to return (default: 100)
|
|
752
|
-
* @returns A promise resolving to paginated Upload results with total count
|
|
753
|
-
*
|
|
754
|
-
* @example
|
|
755
|
-
* ```typescript
|
|
756
|
-
* // Get current user's images
|
|
757
|
-
* const myImages = await kmClient.storage.listUploads({
|
|
758
|
-
* clientId: kmClient.id,
|
|
759
|
-
* mimeTypes: ['image/jpeg', 'image/png']
|
|
760
|
-
* });
|
|
761
|
-
*
|
|
762
|
-
* // Get all profile avatars
|
|
763
|
-
* const avatars = await kmClient.storage.listUploads({
|
|
764
|
-
* tags: ['profile', 'avatar']
|
|
765
|
-
* });
|
|
766
|
-
*
|
|
767
|
-
* // Pagination
|
|
768
|
-
* const page2 = await kmClient.storage.listUploads({}, 10, 10);
|
|
769
|
-
* ```
|
|
770
|
-
*/
|
|
771
|
-
listUploads(filter?: {
|
|
772
|
-
clientId?: string;
|
|
773
|
-
mimeTypes?: string[];
|
|
774
|
-
tags?: string[];
|
|
775
|
-
}, skip?: number, limit?: number): Promise<Paginated<Upload>>;
|
|
776
|
-
/**
|
|
777
|
-
* Permanently delete an uploaded file.
|
|
778
|
-
*
|
|
779
|
-
* Removes the file from cloud storage and the CDN. The URL will no longer be accessible.
|
|
780
|
-
* This operation cannot be undone.
|
|
781
|
-
*
|
|
782
|
-
* @param id The upload ID to delete
|
|
783
|
-
* @returns A promise resolving to deletion confirmation
|
|
784
|
-
*
|
|
785
|
-
* @example
|
|
786
|
-
* ```typescript
|
|
787
|
-
* // Delete an upload
|
|
788
|
-
* const result = await kmClient.storage.deleteUpload(upload.id);
|
|
789
|
-
* console.log(`Deleted: ${result.deletedCount} file(s)`);
|
|
790
|
-
* ```
|
|
791
|
-
*/
|
|
792
|
-
deleteUpload(id: string): Promise<{
|
|
793
|
-
acknowledged: boolean;
|
|
794
|
-
deletedCount: number;
|
|
795
|
-
}>;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
declare class KokimokiStore<T extends object> {
|
|
799
|
-
readonly roomName: string;
|
|
800
|
-
readonly defaultValue: T;
|
|
801
|
-
readonly mode: RoomSubscriptionMode;
|
|
802
|
-
readonly doc: Y.Doc;
|
|
803
|
-
readonly proxy: T;
|
|
804
|
-
readonly docRoot: Y.Map<unknown>;
|
|
805
|
-
readonly connections: {
|
|
806
|
-
connectionIds: Set<string>;
|
|
807
|
-
clientIds: Set<string>;
|
|
808
|
-
};
|
|
809
|
-
private _unsubscribeConnectionsHandler;
|
|
810
|
-
constructor(roomName: string, defaultValue: T, mode?: RoomSubscriptionMode);
|
|
811
|
-
get(): Snapshot<T>;
|
|
812
|
-
subscribe(set: (value: Snapshot<T>) => void): () => void;
|
|
813
|
-
onJoin(client: KokimokiClient<any>): Promise<void>;
|
|
814
|
-
onBeforeLeave(_client: KokimokiClient): Promise<void>;
|
|
815
|
-
onLeave(_client: KokimokiClient): Promise<void>;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
declare class KokimokiLocalStore<T extends object> extends KokimokiStore<T> {
|
|
819
|
-
private readonly localRoomName;
|
|
820
|
-
private _stateKey?;
|
|
821
|
-
private get stateKey();
|
|
822
|
-
constructor(localRoomName: string, defaultState: T);
|
|
823
|
-
getInitialUpdate(appId: string, clientId: string): {
|
|
824
|
-
roomHash: number;
|
|
825
|
-
initialUpdate: Uint8Array<ArrayBufferLike> | undefined;
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
type Mutable<T> = {
|
|
830
|
-
-readonly [K in keyof T]: T[K] extends object ? Mutable<T[K]> : T[K];
|
|
831
|
-
};
|
|
832
|
-
type StoreValue<S> = S extends KokimokiStore<infer U> ? Mutable<U> : never;
|
|
833
|
-
declare const KokimokiClient_base: {
|
|
834
|
-
new (): TypedEmitter<KokimokiClientEvents>;
|
|
835
|
-
};
|
|
836
|
-
/**
|
|
837
|
-
* Kokimoki Client - Real-time Collaborative Game Development SDK
|
|
838
|
-
*
|
|
839
|
-
* The main entry point for building multiplayer games and collaborative applications.
|
|
840
|
-
* Provides real-time state synchronization, AI integration, cloud storage, leaderboards,
|
|
841
|
-
* and more - all without complex backend setup.
|
|
842
|
-
*
|
|
843
|
-
* **Core Capabilities:**
|
|
844
|
-
* - **Real-time Stores**: Synchronized state with automatic conflict resolution (powered by Valtio + Y.js)
|
|
845
|
-
* - **Atomic Transactions**: Update multiple stores consistently with automatic batching
|
|
846
|
-
* - **AI Integration**: Built-in text generation, structured JSON output, and image modification
|
|
847
|
-
* - **Cloud Storage**: File uploads with CDN delivery and tag-based organization
|
|
848
|
-
* - **Leaderboards**: Efficient player ranking with database indexes and pagination
|
|
849
|
-
* - **Presence Tracking**: Real-time connection status for all players
|
|
850
|
-
* - **Time Sync**: Server-synchronized timestamps across all clients
|
|
851
|
-
* - **Webhooks**: Send data to external services for backend processing
|
|
852
|
-
*
|
|
853
|
-
* **Quick Start:**
|
|
854
|
-
* ```typescript
|
|
855
|
-
* import { KokimokiClient } from '@kokimoki/app';
|
|
856
|
-
*
|
|
857
|
-
* // Initialize the client
|
|
858
|
-
* const kmClient = new KokimokiClient(
|
|
859
|
-
* 'your-host.kokimoki.com',
|
|
860
|
-
* 'your-app-id',
|
|
861
|
-
* 'optional-access-code'
|
|
862
|
-
* );
|
|
863
|
-
*
|
|
864
|
-
* // Connect to the server
|
|
865
|
-
* await kmClient.connect();
|
|
866
|
-
*
|
|
867
|
-
* // Create a synchronized store
|
|
868
|
-
* interface GameState {
|
|
869
|
-
* players: Record<string, { name: string; score: number }>;
|
|
870
|
-
* round: number;
|
|
871
|
-
* }
|
|
872
|
-
*
|
|
873
|
-
* const gameStore = kmClient.store<GameState>('game', {
|
|
874
|
-
* players: {},
|
|
875
|
-
* round: 1
|
|
876
|
-
* });
|
|
877
|
-
*
|
|
878
|
-
* // Update state atomically
|
|
879
|
-
* await kmClient.transact([gameStore], ([game]) => {
|
|
880
|
-
* game.players[kmClient.id] = { name: 'Player 1', score: 0 };
|
|
881
|
-
* game.round = 2;
|
|
882
|
-
* });
|
|
883
|
-
*
|
|
884
|
-
* // Use in React components with Valtio
|
|
885
|
-
* import { useSnapshot } from 'valtio';
|
|
886
|
-
*
|
|
887
|
-
* function GameComponent() {
|
|
888
|
-
* const game = useSnapshot(gameStore.proxy);
|
|
889
|
-
* return <div>Round: {game.round}</div>;
|
|
890
|
-
* }
|
|
891
|
-
* ```
|
|
892
|
-
*
|
|
893
|
-
* **Key Features:**
|
|
894
|
-
*
|
|
895
|
-
* **1. Real-time State Management**
|
|
896
|
-
* - Create global stores shared across all players: `kmClient.store()`
|
|
897
|
-
* - Create local stores for client-side data: `kmClient.localStore()`
|
|
898
|
-
* - Automatic synchronization and conflict resolution
|
|
899
|
-
* - Use `useSnapshot()` from Valtio for reactive React components
|
|
900
|
-
*
|
|
901
|
-
* **2. Atomic Transactions**
|
|
902
|
-
* ```typescript
|
|
903
|
-
* // Update multiple stores atomically
|
|
904
|
-
* await kmClient.transact([playerStore, gameStore], ([player, game]) => {
|
|
905
|
-
* player.score += 10;
|
|
906
|
-
* game.lastUpdate = kmClient.serverTimestamp();
|
|
907
|
-
* });
|
|
908
|
-
* ```
|
|
909
|
-
*
|
|
910
|
-
* **3. AI Integration (No API keys required)**
|
|
911
|
-
* ```typescript
|
|
912
|
-
* // Generate text
|
|
913
|
-
* const story = await kmClient.ai.chat({
|
|
914
|
-
* model: 'gpt-4o',
|
|
915
|
-
* userPrompt: 'Write a quest description',
|
|
916
|
-
* temperature: 0.8
|
|
917
|
-
* });
|
|
918
|
-
*
|
|
919
|
-
* // Generate structured data
|
|
920
|
-
* interface Quest { title: string; reward: number; }
|
|
921
|
-
* const quest = await kmClient.ai.generateJson<Quest>({
|
|
922
|
-
* userPrompt: 'Create a level 5 quest'
|
|
923
|
-
* });
|
|
924
|
-
*
|
|
925
|
-
* // Modify images
|
|
926
|
-
* const modified = await kmClient.ai.modifyImage(url, 'Make it pixel art');
|
|
927
|
-
* ```
|
|
928
|
-
*
|
|
929
|
-
* **4. Cloud Storage**
|
|
930
|
-
* ```typescript
|
|
931
|
-
* // Upload files with tags
|
|
932
|
-
* const upload = await kmClient.storage.upload('avatar.jpg', blob, ['profile']);
|
|
933
|
-
*
|
|
934
|
-
* // Query uploads
|
|
935
|
-
* const images = await kmClient.storage.listUploads({
|
|
936
|
-
* clientId: kmClient.id,
|
|
937
|
-
* mimeTypes: ['image/jpeg', 'image/png']
|
|
938
|
-
* });
|
|
939
|
-
* ```
|
|
940
|
-
*
|
|
941
|
-
* **5. Leaderboards**
|
|
942
|
-
* ```typescript
|
|
943
|
-
* // Submit score (replaces previous entry)
|
|
944
|
-
* await kmClient.leaderboard.upsertEntry(
|
|
945
|
-
* 'high-scores',
|
|
946
|
-
* 'desc',
|
|
947
|
-
* 1500,
|
|
948
|
-
* { playerName: 'Alice' },
|
|
949
|
-
* {}
|
|
950
|
-
* );
|
|
951
|
-
*
|
|
952
|
-
* // Get top 10
|
|
953
|
-
* const top10 = await kmClient.leaderboard.listEntries('high-scores', 'desc', 0, 10);
|
|
954
|
-
* ```
|
|
955
|
-
*
|
|
956
|
-
* **6. Presence Tracking**
|
|
957
|
-
* ```typescript
|
|
958
|
-
* // Track online players
|
|
959
|
-
* const onlineClientIds = useSnapshot(gameStore.connections).clientIds;
|
|
960
|
-
* const isPlayerOnline = onlineClientIds.has(playerId);
|
|
961
|
-
* ```
|
|
962
|
-
*
|
|
963
|
-
* **Best Practices:**
|
|
964
|
-
* - Always use `kmClient.serverTimestamp()` for time-sensitive operations
|
|
965
|
-
* - Prefer Records over Arrays: `Record<string, T>` with timestamp keys
|
|
966
|
-
* - Use `kmClient.transact()` for all state updates to ensure atomicity
|
|
967
|
-
* - Tag uploads for easy filtering and organization
|
|
968
|
-
* - Use local stores for client-side settings and preferences
|
|
969
|
-
* - Leverage TypeScript generics for type-safe stores
|
|
970
|
-
*
|
|
971
|
-
* **Events:**
|
|
972
|
-
* - `connected`: Fired when client connects/reconnects to server
|
|
973
|
-
* - `disconnected`: Fired when connection is lost
|
|
974
|
-
*
|
|
975
|
-
* @template ClientContextT The type of client context data (custom user data from your backend)
|
|
976
|
-
*
|
|
977
|
-
* @example
|
|
978
|
-
* ```typescript
|
|
979
|
-
* // Listen for connection events
|
|
980
|
-
* kmClient.on('connected', () => {
|
|
981
|
-
* console.log('Connected to Kokimoki!');
|
|
982
|
-
* });
|
|
983
|
-
*
|
|
984
|
-
* kmClient.on('disconnected', () => {
|
|
985
|
-
* console.log('Connection lost, will auto-reconnect...');
|
|
986
|
-
* });
|
|
987
|
-
* ```
|
|
988
|
-
*/
|
|
989
|
-
declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
990
|
-
readonly host: string;
|
|
991
|
-
readonly appId: string;
|
|
992
|
-
readonly code: string;
|
|
993
|
-
private _wsUrl;
|
|
994
|
-
private _apiUrl;
|
|
995
|
-
private _id?;
|
|
996
|
-
private _connectionId?;
|
|
997
|
-
private _token?;
|
|
998
|
-
private _apiHeaders?;
|
|
999
|
-
private _serverTimeOffset;
|
|
1000
|
-
private _clientContext?;
|
|
1001
|
-
private _ws?;
|
|
1002
|
-
private _subscriptionsByName;
|
|
1003
|
-
private _subscriptionsByHash;
|
|
1004
|
-
private _subscribeReqPromises;
|
|
1005
|
-
private _unsubscribeReqPromises;
|
|
1006
|
-
private _transactionPromises;
|
|
1007
|
-
private _connected;
|
|
1008
|
-
private _connectPromise?;
|
|
1009
|
-
private _messageId;
|
|
1010
|
-
private _autoReconnect;
|
|
1011
|
-
private _reconnectTimeout;
|
|
1012
|
-
private _pingInterval;
|
|
1013
|
-
private _clientTokenKey;
|
|
1014
|
-
private _editorContext;
|
|
1015
|
-
private _ai?;
|
|
1016
|
-
private _i18n?;
|
|
1017
|
-
private _storage?;
|
|
1018
|
-
private _leaderboard?;
|
|
1019
|
-
constructor(host: string, appId: string, code?: string);
|
|
1020
|
-
get id(): string;
|
|
1021
|
-
get connectionId(): string;
|
|
1022
|
-
get token(): string;
|
|
1023
|
-
get apiUrl(): string;
|
|
1024
|
-
get apiHeaders(): Headers;
|
|
1025
|
-
get clientContext(): ClientContextT & ({} | null);
|
|
1026
|
-
/**
|
|
1027
|
-
* Indicates whether the client is currently connected to the server.
|
|
1028
|
-
*/
|
|
1029
|
-
get connected(): boolean;
|
|
1030
|
-
get ws(): WebSocket;
|
|
1031
|
-
/**
|
|
1032
|
-
* Indicates whether the client is running in editor/development mode.
|
|
1033
|
-
*/
|
|
1034
|
-
get isEditor(): boolean;
|
|
1035
|
-
/**
|
|
1036
|
-
* Establishes a connection to the Kokimoki server.
|
|
1037
|
-
*
|
|
1038
|
-
* Handles authentication, WebSocket setup, and automatic reconnection.
|
|
1039
|
-
* If already connecting, returns the existing connection promise.
|
|
1040
|
-
*
|
|
1041
|
-
* @returns A promise that resolves when the connection is established.
|
|
1042
|
-
* @throws Error if the connection fails.
|
|
1043
|
-
*/
|
|
1044
|
-
connect(): Promise<void>;
|
|
1045
|
-
private handleInitMessage;
|
|
1046
|
-
private handleBinaryMessage;
|
|
1047
|
-
private handleErrorMessage;
|
|
1048
|
-
private handleSubscribeResMessage;
|
|
1049
|
-
private handleUnsubscribeResMessage;
|
|
1050
|
-
private handleRoomUpdateMessage;
|
|
1051
|
-
/**
|
|
1052
|
-
* Gets the current server timestamp, accounting for client-server time offset.
|
|
1053
|
-
*
|
|
1054
|
-
* @returns The current server timestamp in milliseconds.
|
|
1055
|
-
*/
|
|
1056
|
-
serverTimestamp(): number;
|
|
1057
|
-
/**
|
|
1058
|
-
* Sends a Y.js update to a specific room.
|
|
1059
|
-
*
|
|
1060
|
-
* @param room - The name of the room to update.
|
|
1061
|
-
* @param update - The Y.js update as a Uint8Array.
|
|
1062
|
-
* @returns A promise that resolves with the server response.
|
|
1063
|
-
*/
|
|
1064
|
-
patchRoomState(room: string, update: Uint8Array): Promise<any>;
|
|
1065
|
-
private sendSubscribeReq;
|
|
1066
|
-
private sendUnsubscribeReq;
|
|
1067
|
-
/**
|
|
1068
|
-
* Joins a store by subscribing to its corresponding room.
|
|
1069
|
-
*
|
|
1070
|
-
* If already joined, this method does nothing. For local stores, initializes
|
|
1071
|
-
* the store locally. For remote stores, sends a subscription request to the server.
|
|
1072
|
-
*
|
|
1073
|
-
* @param store - The KokimokiStore to join.
|
|
1074
|
-
* @template T - The type of the store's state object.
|
|
1075
|
-
*/
|
|
1076
|
-
join<T extends object>(store: KokimokiStore<T>): Promise<void>;
|
|
1077
|
-
/**
|
|
1078
|
-
* Leaves a store by unsubscribing from its corresponding room.
|
|
1079
|
-
*
|
|
1080
|
-
* Triggers the store's `onBeforeLeave` and `onLeave` lifecycle hooks.
|
|
1081
|
-
*
|
|
1082
|
-
* @param store - The KokimokiStore to leave.
|
|
1083
|
-
* @template T - The type of the store's state object.
|
|
1084
|
-
*/
|
|
1085
|
-
leave<T extends object>(store: KokimokiStore<T>): Promise<void>;
|
|
1086
|
-
/**
|
|
1087
|
-
* Executes a transaction across one or more stores.
|
|
1088
|
-
*
|
|
1089
|
-
* Provides proxies to the stores that track changes. All changes are batched
|
|
1090
|
-
* and sent to the server atomically. The transaction ensures consistency across
|
|
1091
|
-
* multiple stores.
|
|
1092
|
-
*
|
|
1093
|
-
* @param stores - Array of stores to include in the transaction.
|
|
1094
|
-
* @param handler - Function that receives store proxies and performs modifications.
|
|
1095
|
-
* @returns A promise that resolves with the return value of the handler.
|
|
1096
|
-
* @template TStores - Tuple type of the stores array.
|
|
1097
|
-
* @template ReturnT - The return type of the handler function.
|
|
1098
|
-
*
|
|
1099
|
-
* @example
|
|
1100
|
-
* ```ts
|
|
1101
|
-
* await client.transact([playerStore, gameStore], ([player, game]) => {
|
|
1102
|
-
* player.score += 10;
|
|
1103
|
-
* game.lastUpdate = Date.now();
|
|
1104
|
-
* });
|
|
1105
|
-
* ```
|
|
1106
|
-
*/
|
|
1107
|
-
transact<TStores extends readonly KokimokiStore<any>[], ReturnT = void>(stores: [...TStores], handler: (proxies: {
|
|
1108
|
-
[K in keyof TStores]: StoreValue<TStores[K]>;
|
|
1109
|
-
}) => ReturnT | Promise<ReturnT>): Promise<ReturnT>;
|
|
1110
|
-
/**
|
|
1111
|
-
* Closes the client connection and cleans up resources.
|
|
1112
|
-
*
|
|
1113
|
-
* Disables automatic reconnection, closes the WebSocket, and clears all intervals.
|
|
1114
|
-
*/
|
|
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>;
|
|
1135
|
-
/**
|
|
1136
|
-
* Gets the internal room hash identifier for a store.
|
|
1137
|
-
*
|
|
1138
|
-
* @param store - The store to get the room hash for.
|
|
1139
|
-
* @returns The room hash as a number.
|
|
1140
|
-
* @throws Error if the store hasn't been joined.
|
|
1141
|
-
* @template T - The type of the store's state object.
|
|
1142
|
-
*/
|
|
1143
|
-
getRoomHash<T extends object>(store: KokimokiStore<T>): number;
|
|
1144
|
-
/**
|
|
1145
|
-
* Creates a new remote store synchronized with the server.
|
|
1146
|
-
*
|
|
1147
|
-
* @param name - The name of the room/store.
|
|
1148
|
-
* @param defaultState - The initial state of the store.
|
|
1149
|
-
* @param autoJoin - Whether to automatically join the store (default: true).
|
|
1150
|
-
* @returns A new KokimokiStore instance.
|
|
1151
|
-
* @template T - The type of the store's state object.
|
|
1152
|
-
*
|
|
1153
|
-
* @example
|
|
1154
|
-
* ```ts
|
|
1155
|
-
* const gameStore = client.store('game', { players: [], score: 0 });
|
|
1156
|
-
* ```
|
|
1157
|
-
*/
|
|
1158
|
-
store<T extends object>(name: string, defaultState: T, autoJoin?: boolean): KokimokiStore<T>;
|
|
1159
|
-
/**
|
|
1160
|
-
* Creates a new local store that persists only in the client's browser.
|
|
1161
|
-
*
|
|
1162
|
-
* Local stores are automatically joined and are not synchronized with the server.
|
|
1163
|
-
* Data is stored locally per client and app.
|
|
1164
|
-
*
|
|
1165
|
-
* @param name - The name of the local store.
|
|
1166
|
-
* @param defaultState - The initial state of the store.
|
|
1167
|
-
* @returns A new KokimokiLocalStore instance.
|
|
1168
|
-
* @template T - The type of the store's state object.
|
|
1169
|
-
*
|
|
1170
|
-
* @example
|
|
1171
|
-
* ```ts
|
|
1172
|
-
* const settingsStore = client.localStore('settings', { volume: 0.5, theme: 'dark' });
|
|
1173
|
-
* ```
|
|
1174
|
-
*/
|
|
1175
|
-
localStore<T extends object>(name: string, defaultState: T): KokimokiLocalStore<T>;
|
|
1176
|
-
/**
|
|
1177
|
-
* Sends app data to the server via webhook for external processing.
|
|
1178
|
-
*
|
|
1179
|
-
* @param event - The name of the webhook event.
|
|
1180
|
-
* @param data - The data to send with the webhook.
|
|
1181
|
-
* @returns A promise that resolves with the job ID.
|
|
1182
|
-
* @template T - The type of the data being sent.
|
|
1183
|
-
*
|
|
1184
|
-
* @example
|
|
1185
|
-
* ```ts
|
|
1186
|
-
* await client.sendWebhook('game-ended', { winner: 'player1', score: 100 });
|
|
1187
|
-
* ```
|
|
1188
|
-
*/
|
|
1189
|
-
sendWebhook<T>(event: string, data: T): Promise<{
|
|
1190
|
-
jobId: string;
|
|
1191
|
-
}>;
|
|
1192
|
-
/**
|
|
1193
|
-
* Access AI capabilities including text generation, structured JSON output, and image modification.
|
|
1194
|
-
*/
|
|
1195
|
-
get ai(): KokimokiAiService;
|
|
1196
|
-
/**
|
|
1197
|
-
* Access i18n URL resolution and translation loading utilities.
|
|
1198
|
-
*/
|
|
1199
|
-
get i18n(): KokimokiI18nService;
|
|
1200
|
-
/**
|
|
1201
|
-
* Access file upload and management for media files, images, and user-generated content.
|
|
1202
|
-
*/
|
|
1203
|
-
get storage(): KokimokiStorageService;
|
|
1204
|
-
/**
|
|
1205
|
-
* Access player ranking and score tracking with efficient queries and pagination.
|
|
1206
|
-
*/
|
|
1207
|
-
get leaderboard(): KokimokiLeaderboardService;
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
declare enum RoomSubscriptionMode {
|
|
1211
|
-
Read = "r",
|
|
1212
|
-
Write = "w",
|
|
1213
|
-
ReadWrite = "b"
|
|
1214
|
-
}
|
|
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
|
-
|
|
1239
|
-
declare module "valtio" {
|
|
1240
|
-
function useSnapshot<T extends object>(p: T): T;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
export { KokimokiClient, KokimokiStore, getKmEnv };
|
|
1244
|
-
export type { AllLanguagesStatus, I18nOptions, KokimokiClientEvents, KokimokiEnv, LanguageStatus, NamespaceStatus, Paginated, RequestTranslationResult, TranslationStatus, Upload };
|