@kokimoki/kit 1.6.6 → 1.7.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.
@@ -1,166 +1,183 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Form = exports.FormArray = exports.FormGroup = exports.FloatField = exports.IntegerField = exports.EnumField = exports.TextField = exports.ImageField = exports.ConstField = exports.BooleanField = exports.Field = void 0;
3
+ exports.Form =
4
+ exports.FormArray =
5
+ exports.FormGroup =
6
+ exports.FloatField =
7
+ exports.IntegerField =
8
+ exports.EnumField =
9
+ exports.TextField =
10
+ exports.ImageField =
11
+ exports.ConstField =
12
+ exports.BooleanField =
13
+ exports.Field =
14
+ void 0;
4
15
  const defaultFieldOptions = {};
5
16
  class Field {
6
- options;
7
- constructor(options) {
8
- this.options = options;
9
- }
17
+ options;
18
+ constructor(options) {
19
+ this.options = options;
20
+ }
10
21
  }
11
22
  exports.Field = Field;
12
23
  class BooleanField extends Field {
13
- value;
14
- constructor(value, options = defaultFieldOptions) {
15
- super(options);
16
- this.value = value;
17
- }
18
- get schema() {
19
- return {
20
- type: "boolean",
21
- default: this.value,
22
- };
23
- }
24
+ value;
25
+ constructor(value, options = defaultFieldOptions) {
26
+ super(options);
27
+ this.value = value;
28
+ }
29
+ get schema() {
30
+ return {
31
+ type: "boolean",
32
+ default: this.value,
33
+ };
34
+ }
24
35
  }
25
36
  exports.BooleanField = BooleanField;
26
37
  class ConstField extends Field {
27
- value;
28
- constructor(value, options = defaultFieldOptions) {
29
- super(options);
30
- this.value = value;
31
- }
32
- get schema() {
33
- return {
34
- const: this.value,
35
- };
36
- }
38
+ value;
39
+ constructor(value, options = defaultFieldOptions) {
40
+ super(options);
41
+ this.value = value;
42
+ }
43
+ get schema() {
44
+ return {
45
+ const: this.value,
46
+ };
47
+ }
37
48
  }
38
49
  exports.ConstField = ConstField;
39
50
  class ImageField extends Field {
40
- value;
41
- constructor(value, options = defaultFieldOptions) {
42
- super(options);
43
- this.value = value;
44
- }
45
- get schema() {
46
- return {
47
- type: "string",
48
- default: this.value,
49
- };
50
- }
51
+ value;
52
+ constructor(value, options = defaultFieldOptions) {
53
+ super(options);
54
+ this.value = value;
55
+ }
56
+ get schema() {
57
+ return {
58
+ type: "string",
59
+ default: this.value,
60
+ };
61
+ }
51
62
  }
52
63
  exports.ImageField = ImageField;
53
64
  class TextField extends Field {
54
- value;
55
- constructor(value, options = defaultFieldOptions) {
56
- super(options);
57
- this.value = value;
58
- }
59
- get schema() {
60
- return {
61
- type: "string",
62
- default: this.value,
63
- };
64
- }
65
+ value;
66
+ constructor(value, options = defaultFieldOptions) {
67
+ super(options);
68
+ this.value = value;
69
+ }
70
+ get schema() {
71
+ return {
72
+ type: "string",
73
+ default: this.value,
74
+ };
75
+ }
65
76
  }
66
77
  exports.TextField = TextField;
67
78
  class EnumField extends Field {
68
- enumValues;
69
- value;
70
- constructor(enumValues, value, options = defaultFieldOptions) {
71
- super(options);
72
- this.enumValues = enumValues;
73
- this.value = value;
74
- }
75
- get schema() {
76
- return {
77
- enum: Object.keys(this.enumValues),
78
- };
79
- }
79
+ enumValues;
80
+ value;
81
+ constructor(enumValues, value, options = defaultFieldOptions) {
82
+ super(options);
83
+ this.enumValues = enumValues;
84
+ this.value = value;
85
+ }
86
+ get schema() {
87
+ return {
88
+ enum: Object.keys(this.enumValues),
89
+ };
90
+ }
80
91
  }
81
92
  exports.EnumField = EnumField;
82
93
  class IntegerField extends Field {
83
- value;
84
- constructor(value, options = defaultFieldOptions) {
85
- super(options);
86
- this.value = value;
87
- }
88
- get schema() {
89
- return {
90
- type: "integer",
91
- default: this.value,
92
- };
93
- }
94
+ value;
95
+ constructor(value, options = defaultFieldOptions) {
96
+ super(options);
97
+ this.value = value;
98
+ }
99
+ get schema() {
100
+ return {
101
+ type: "integer",
102
+ default: this.value,
103
+ };
104
+ }
94
105
  }
95
106
  exports.IntegerField = IntegerField;
96
107
  class FloatField extends Field {
97
- value;
98
- constructor(value, options = defaultFieldOptions) {
99
- super(options);
100
- this.value = value;
101
- }
102
- get schema() {
103
- return {
104
- type: "number",
105
- default: this.value,
106
- };
107
- }
108
+ value;
109
+ constructor(value, options = defaultFieldOptions) {
110
+ super(options);
111
+ this.value = value;
112
+ }
113
+ get schema() {
114
+ return {
115
+ type: "number",
116
+ default: this.value,
117
+ };
118
+ }
108
119
  }
109
120
  exports.FloatField = FloatField;
110
121
  class FormGroup extends Field {
111
- requiredFields;
112
- optionalFields;
113
- constructor(requiredFields, optionalFields = {}, options = defaultFieldOptions) {
114
- super(options);
115
- this.requiredFields = requiredFields;
116
- this.optionalFields = optionalFields;
117
- }
118
- get value() {
119
- const value = Object.entries(this.requiredFields).reduce((acc, [key, field]) => {
120
- acc[key] = field.value;
121
- return acc;
122
- }, {});
123
- Object.entries(this.optionalFields).forEach(([key, field]) => {
124
- if (field.value !== undefined) {
125
- value[key] = field.value;
126
- }
127
- });
128
- return value;
129
- }
130
- get schema() {
131
- const properties = {};
132
- Object.entries(this.requiredFields).forEach(([key, field]) => {
133
- properties[key] = field.schema;
134
- });
135
- Object.entries(this.optionalFields).forEach(([key, field]) => {
136
- properties[key] = field.schema;
137
- });
138
- return {
139
- type: "object",
140
- properties,
141
- required: Object.keys(this.requiredFields),
142
- };
143
- }
122
+ requiredFields;
123
+ optionalFields;
124
+ constructor(
125
+ requiredFields,
126
+ optionalFields = {},
127
+ options = defaultFieldOptions,
128
+ ) {
129
+ super(options);
130
+ this.requiredFields = requiredFields;
131
+ this.optionalFields = optionalFields;
132
+ }
133
+ get value() {
134
+ const value = Object.entries(this.requiredFields).reduce(
135
+ (acc, [key, field]) => {
136
+ acc[key] = field.value;
137
+ return acc;
138
+ },
139
+ {},
140
+ );
141
+ Object.entries(this.optionalFields).forEach(([key, field]) => {
142
+ if (field.value !== undefined) {
143
+ value[key] = field.value;
144
+ }
145
+ });
146
+ return value;
147
+ }
148
+ get schema() {
149
+ const properties = {};
150
+ Object.entries(this.requiredFields).forEach(([key, field]) => {
151
+ properties[key] = field.schema;
152
+ });
153
+ Object.entries(this.optionalFields).forEach(([key, field]) => {
154
+ properties[key] = field.schema;
155
+ });
156
+ return {
157
+ type: "object",
158
+ properties,
159
+ required: Object.keys(this.requiredFields),
160
+ };
161
+ }
144
162
  }
145
163
  exports.FormGroup = FormGroup;
146
164
  class FormArray extends Field {
147
- factory;
148
- value;
149
- constructor(factory, value, options = defaultFieldOptions) {
150
- super(options);
151
- this.factory = factory;
152
- this.value = value;
153
- }
154
- get schema() {
155
- const field = this.factory();
156
- return {
157
- type: "array",
158
- items: field.schema,
159
- default: this.value,
160
- };
161
- }
165
+ factory;
166
+ value;
167
+ constructor(factory, value, options = defaultFieldOptions) {
168
+ super(options);
169
+ this.factory = factory;
170
+ this.value = value;
171
+ }
172
+ get schema() {
173
+ const field = this.factory();
174
+ return {
175
+ type: "array",
176
+ items: field.schema,
177
+ default: this.value,
178
+ };
179
+ }
162
180
  }
163
181
  exports.FormArray = FormArray;
164
- class Form extends FormGroup {
165
- }
182
+ class Form extends FormGroup {}
166
183
  exports.Form = Form;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const KOKIMOKI_KIT_VERSION = "1.6.6";
1
+ export declare const KOKIMOKI_KIT_VERSION = "1.7.0";
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KOKIMOKI_KIT_VERSION = void 0;
4
- exports.KOKIMOKI_KIT_VERSION = "1.6.6";
4
+ exports.KOKIMOKI_KIT_VERSION = "1.7.0";
package/dist/zod.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { z, type ZodType } from "zod/v4";
package/dist/zod.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.z = void 0;
4
+ var v4_1 = require("zod/v4");
5
+ Object.defineProperty(exports, "z", { enumerable: true, get: function () { return v4_1.z; } });
@@ -0,0 +1,341 @@
1
+ ---
2
+ description: Vite plugin and development tools for Kokimoki apps
3
+ applyTo: "**/vite.config.{ts,js,mts,mjs}"
4
+ ---
5
+
6
+ # Kokimoki Kit
7
+
8
+ The `@kokimoki/kit` package provides the Vite plugin and development tools for building Kokimoki apps.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @kokimoki/kit
14
+ ```
15
+
16
+ ## Plugin Configuration
17
+
18
+ Add the plugin to your `vite.config.ts`:
19
+
20
+ ```typescript
21
+ import { defineConfig } from "vite";
22
+ import { kokimokiKitPlugin } from "@kokimoki/kit";
23
+ import { z } from "@kokimoki/kit";
24
+
25
+ export default defineConfig({
26
+ plugins: [
27
+ kokimokiKitPlugin({
28
+ // Required: Your concept ID from Kokimoki
29
+ conceptId: "your-concept-id",
30
+
31
+ // Required: Deploy configurations
32
+ deployCodes: [
33
+ {
34
+ name: "default",
35
+ description: "Default game mode",
36
+ clientContext: { mode: "standard" },
37
+ },
38
+ {
39
+ name: "tournament",
40
+ description: "Tournament mode with stricter rules",
41
+ clientContext: { mode: "tournament", maxPlayers: 100 },
42
+ },
43
+ ],
44
+
45
+ // Optional: Project config schema (validated in admin panel)
46
+ schema: z.object({
47
+ title: z.string(),
48
+ maxPlayers: z.number().min(2).max(100),
49
+ timeLimit: z.number().optional(),
50
+ }),
51
+
52
+ // Optional: Store schemas for validation
53
+ stores: [
54
+ {
55
+ pattern: "game",
56
+ schema: z.object({
57
+ status: z.enum(["waiting", "playing", "finished"]),
58
+ round: z.number(),
59
+ }),
60
+ },
61
+ {
62
+ pattern: "player-*",
63
+ schema: z.object({
64
+ name: z.string(),
65
+ score: z.number(),
66
+ }),
67
+ local: true, // Local store (per-client)
68
+ },
69
+ ],
70
+
71
+ // Optional: i18n configuration
72
+ i18nPath: "./src/i18n",
73
+ i18nPrimaryLng: "en", // Source language for AI translations
74
+
75
+ // Optional: Custom API endpoint
76
+ endpoint: "https://api.kokimoki.com",
77
+ host: "y-wss.kokimoki.com",
78
+
79
+ // Optional: Dev view layout (see Dev Frame section)
80
+ devView: [
81
+ [{ label: "host", clientContext: { mode: "host" } }],
82
+ [
83
+ { label: "player1", clientContext: { mode: "player" } },
84
+ { label: "player2", clientContext: { mode: "player" } },
85
+ ],
86
+ ],
87
+ }),
88
+ ],
89
+ });
90
+ ```
91
+
92
+ ## Configuration Options
93
+
94
+ ### Required Options
95
+
96
+ | Option | Type | Description |
97
+ | ------------- | -------- | --------------------------------- |
98
+ | `conceptId` | `string` | Your concept ID from Kokimoki |
99
+ | `deployCodes` | `array` | List of deployment configurations |
100
+
101
+ ### Optional Options
102
+
103
+ | Option | Type | Description |
104
+ | -------------------------- | ---------------- | -------------------------------------------------- |
105
+ | `schema` | `ZodType` | Zod schema for project configuration |
106
+ | `stores` | `array` | Store definitions with patterns and schemas |
107
+ | `i18nPath` | `string` | Path to i18n folder (e.g., `./src/i18n`) |
108
+ | `i18nPrimaryLng` | `string` | Source language code (default: `"en"`) |
109
+ | `endpoint` | `string` | API endpoint (default: `https://api.kokimoki.com`) |
110
+ | `host` | `string` | WebSocket host (default: `y-wss.kokimoki.com`) |
111
+ | `devView` | `array \| false` | Dev frame layout or `false` to disable |
112
+ | `defaultProjectConfigPath` | `string` | Path to default project config file |
113
+ | `defaultProjectStylePath` | `string` | Path to default project style file |
114
+
115
+ ## Dev Frame
116
+
117
+ The dev frame provides a multi-window view for testing different player modes simultaneously during development.
118
+
119
+ ### Configuration
120
+
121
+ ```typescript
122
+ devView: [
123
+ // Row 1: Host and presenter
124
+ [
125
+ { label: "host", clientContext: { mode: "host", playerCode: "admin" } },
126
+ { label: "presenter", clientContext: { mode: "presenter" } },
127
+ ],
128
+ // Row 2: Three players
129
+ [
130
+ { label: "player1", clientContext: { mode: "player" } },
131
+ { label: "player2", clientContext: { mode: "player" } },
132
+ { label: "player3", clientContext: { mode: "player" } },
133
+ ],
134
+ ];
135
+ ```
136
+
137
+ ### DevFrameCell Interface
138
+
139
+ ```typescript
140
+ interface DevFrameCell {
141
+ /** Label shown in the frame header (must be unique) */
142
+ label: string;
143
+ /** Client context passed to the app via URL */
144
+ clientContext: unknown;
145
+ }
146
+ ```
147
+
148
+ ### Features
149
+
150
+ - **Grid layout**: Each inner array is a row of frames
151
+ - **Unique labels**: Each cell must have a unique label
152
+ - **New tab button**: Open any frame in a separate tab
153
+ - **Reset button**: Clear frame's local storage and reload
154
+ - **Error overlay**: Shows errors with reload option
155
+
156
+ ### Disabling Dev Frame
157
+
158
+ Set `devView: false` to disable the dev frame entirely:
159
+
160
+ ```typescript
161
+ kokimokiKitPlugin({
162
+ conceptId: "...",
163
+ deployCodes: [...],
164
+ devView: false,
165
+ })
166
+ ```
167
+
168
+ ## Store Schemas
169
+
170
+ Define schemas to validate store state during development:
171
+
172
+ ```typescript
173
+ stores: [
174
+ // Global store - shared across all clients
175
+ {
176
+ pattern: "game",
177
+ schema: z.object({
178
+ status: z.enum(["waiting", "playing", "finished"]),
179
+ players: z.record(
180
+ z.string(),
181
+ z.object({
182
+ name: z.string(),
183
+ score: z.number(),
184
+ })
185
+ ),
186
+ }),
187
+ },
188
+
189
+ // Wildcard pattern - matches player-abc123, player-xyz789, etc.
190
+ {
191
+ pattern: "player-*",
192
+ schema: z.object({
193
+ name: z.string(),
194
+ avatar: z.string().optional(),
195
+ }),
196
+ local: true, // Local store (client-specific)
197
+ },
198
+
199
+ // Dynamic stores - chat rooms, teams, etc.
200
+ {
201
+ pattern: "chat-*",
202
+ schema: z.object({
203
+ messages: z.record(
204
+ z.string(),
205
+ z.object({
206
+ text: z.string(),
207
+ sender: z.string(),
208
+ })
209
+ ),
210
+ }),
211
+ },
212
+ ];
213
+ ```
214
+
215
+ ## i18n Integration
216
+
217
+ The plugin syncs translations to your dev app automatically.
218
+
219
+ ### Folder Structure
220
+
221
+ ```
222
+ src/i18n/
223
+ ├── en/
224
+ │ ├── ui.json
225
+ │ └── game.json
226
+ ├── et/
227
+ │ ├── ui.json
228
+ │ └── game.json
229
+ └── de/
230
+ ├── ui.json
231
+ └── game.json
232
+ ```
233
+
234
+ ### Configuration
235
+
236
+ ```typescript
237
+ kokimokiKitPlugin({
238
+ // ...
239
+ i18nPath: "./src/i18n",
240
+ i18nPrimaryLng: "en", // Source language for AI translations
241
+ });
242
+ ```
243
+
244
+ ### HMR Support
245
+
246
+ - Translation files are watched for changes
247
+ - Changes are synced to the dev app in real-time
248
+ - No need to restart the dev server
249
+
250
+ ## Zod Re-export
251
+
252
+ The kit re-exports Zod for convenience:
253
+
254
+ ```typescript
255
+ import { z } from "@kokimoki/kit";
256
+
257
+ const mySchema = z.object({
258
+ name: z.string(),
259
+ count: z.number(),
260
+ });
261
+ ```
262
+
263
+ ## Project Files
264
+
265
+ ### .kokimoki Directory
266
+
267
+ The plugin creates a `.kokimoki` directory in your project root:
268
+
269
+ ```
270
+ .kokimoki/
271
+ ├── app-id # Dev app ID (cached)
272
+ └── stores-hash # Hash of store schemas (for change detection)
273
+ ```
274
+
275
+ **Add to `.gitignore`:**
276
+
277
+ ```gitignore
278
+ .kokimoki/
279
+ ```
280
+
281
+ ### Credentials
282
+
283
+ Global credentials are stored in `~/.kokimoki`:
284
+
285
+ ```json
286
+ {
287
+ "apiKeys": {
288
+ "org-id-1": "api-key-1",
289
+ "org-id-2": "api-key-2"
290
+ }
291
+ }
292
+ ```
293
+
294
+ Use `npx @kokimoki/cli login` to authenticate.
295
+
296
+ ## Style Preprocessing
297
+
298
+ The plugin processes CSS files with theme color variables:
299
+
300
+ - Converts color names to hex values
301
+ - Generates RGB tuple variables for opacity support
302
+ - Processes palette color scales (50-900)
303
+
304
+ ### Supported Variables
305
+
306
+ ```css
307
+ :root {
308
+ --color-primary-500: #3b82f6;
309
+ --color-secondary-500: #10b981;
310
+ --on-primary: 255 255 255;
311
+ --on-secondary: 255 255 255;
312
+ }
313
+ ```
314
+
315
+ ## Production Build
316
+
317
+ During production builds, the plugin:
318
+
319
+ 1. Validates all store schemas
320
+ 2. Generates production loading screen
321
+ 3. Embeds i18n metadata for runtime loading
322
+ 4. Removes dev frame and development overlays
323
+
324
+ ## Error Handling
325
+
326
+ ### Common Errors
327
+
328
+ | Error | Cause | Solution |
329
+ | --------------------- | ------------------ | -------------------------------- |
330
+ | `CONCEPT_NOT_FOUND` | Invalid concept ID | Check your `conceptId` in config |
331
+ | `NO_CREDENTIALS` | Not logged in | Run `npx @kokimoki/cli login` |
332
+ | `DEV_APP_INIT_FAILED` | API error | Check network and API endpoint |
333
+
334
+ ### Store Schema Changes
335
+
336
+ If you change store schemas, the plugin detects this and shows a warning page with two options:
337
+
338
+ - **Keep Current State**: Dismiss the warning and continue with existing data
339
+ - **Reset State**: Clear the dev app state and localStorage to start fresh
340
+
341
+ No dev server restart is required.