@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.
Files changed (64) hide show
  1. package/README.md +1 -2
  2. package/dist/core/kokimoki-client.d.ts +4 -4
  3. package/dist/core/kokimoki-client.js +4 -4
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.js +1 -2
  6. package/dist/utils/valtio.d.ts +2 -5
  7. package/dist/utils/valtio.js +4 -2
  8. package/dist/version.d.ts +1 -1
  9. package/dist/version.js +1 -1
  10. package/docs/kokimoki-ai.instructions.md +4 -2
  11. package/docs/kokimoki-dynamic-stores.instructions.md +3 -3
  12. package/docs/kokimoki-i18n.instructions.md +1 -1
  13. package/docs/kokimoki-sdk.instructions.md +46 -7
  14. package/package.json +15 -2
  15. package/dist/fields.d.ts +0 -110
  16. package/dist/fields.js +0 -158
  17. package/dist/kokimoki-ai.d.ts +0 -153
  18. package/dist/kokimoki-ai.js +0 -164
  19. package/dist/kokimoki-awareness.d.ts +0 -21
  20. package/dist/kokimoki-awareness.js +0 -48
  21. package/dist/kokimoki-client-refactored.d.ts +0 -80
  22. package/dist/kokimoki-client-refactored.js +0 -400
  23. package/dist/kokimoki-client.d.ts +0 -362
  24. package/dist/kokimoki-client.js +0 -823
  25. package/dist/kokimoki-leaderboard.d.ts +0 -175
  26. package/dist/kokimoki-leaderboard.js +0 -203
  27. package/dist/kokimoki-local-store.d.ts +0 -11
  28. package/dist/kokimoki-local-store.js +0 -40
  29. package/dist/kokimoki-queue.d.ts +0 -0
  30. package/dist/kokimoki-queue.js +0 -38
  31. package/dist/kokimoki-req-res.d.ts +0 -0
  32. package/dist/kokimoki-req-res.js +0 -198
  33. package/dist/kokimoki-schema.d.ts +0 -113
  34. package/dist/kokimoki-schema.js +0 -162
  35. package/dist/kokimoki-storage.d.ts +0 -156
  36. package/dist/kokimoki-storage.js +0 -208
  37. package/dist/kokimoki-store.d.ts +0 -23
  38. package/dist/kokimoki-store.js +0 -117
  39. package/dist/kokimoki-transaction.d.ts +0 -18
  40. package/dist/kokimoki-transaction.js +0 -143
  41. package/dist/kokimoki.min.d.ts +0 -1244
  42. package/dist/kokimoki.min.js +0 -19108
  43. package/dist/kokimoki.min.js.map +0 -1
  44. package/dist/llms.txt +0 -665
  45. package/dist/message-queue.d.ts +0 -8
  46. package/dist/message-queue.js +0 -19
  47. package/dist/room-subscription-mode.d.ts +0 -5
  48. package/dist/room-subscription-mode.js +0 -6
  49. package/dist/room-subscription.d.ts +0 -15
  50. package/dist/room-subscription.js +0 -52
  51. package/dist/synced-schema.d.ts +0 -74
  52. package/dist/synced-schema.js +0 -83
  53. package/dist/synced-store.d.ts +0 -10
  54. package/dist/synced-store.js +0 -9
  55. package/dist/synced-types.d.ts +0 -47
  56. package/dist/synced-types.js +0 -67
  57. package/dist/ws-message-reader.d.ts +0 -11
  58. package/dist/ws-message-reader.js +0 -36
  59. package/dist/ws-message-type copy.d.ts +0 -6
  60. package/dist/ws-message-type copy.js +0 -7
  61. package/dist/ws-message-type.d.ts +0 -11
  62. package/dist/ws-message-type.js +0 -12
  63. package/dist/ws-message-writer.d.ts +0 -9
  64. package/dist/ws-message-writer.js +0 -45
package/README.md CHANGED
@@ -52,8 +52,7 @@ See the [docs](./docs/) folder for detailed instructions:
52
52
  ## Usage with React
53
53
 
54
54
  ```tsx
55
- import { useSnapshot } from "valtio";
56
- import { getKmClient } from "@kokimoki/app";
55
+ import { getKmClient, useSnapshot } from "@kokimoki/app";
57
56
 
58
57
  const kmClient = getKmClient();
59
58
  const gameStore = kmClient.store("game", { count: 0 });
@@ -78,8 +78,8 @@ declare const KokimokiClient_base: new () => TypedEmitter<KokimokiClientEvents>;
78
78
  * game.round = 2;
79
79
  * });
80
80
  *
81
- * // Use in React components with Valtio
82
- * import { useSnapshot } from 'valtio';
81
+ * // Use in React components (useSnapshot is re-exported from valtio)
82
+ * import { useSnapshot } from '@kokimoki/app';
83
83
  *
84
84
  * function GameComponent() {
85
85
  * const game = useSnapshot(gameStore.proxy);
@@ -93,7 +93,7 @@ declare const KokimokiClient_base: new () => TypedEmitter<KokimokiClientEvents>;
93
93
  * - Create global stores shared across all players: `kmClient.store()`
94
94
  * - Create local stores for client-side data: `kmClient.localStore()`
95
95
  * - Automatic synchronization and conflict resolution
96
- * - Use `useSnapshot()` from Valtio for reactive React components
96
+ * - Use `useSnapshot()` from `@kokimoki/app` for reactive React components (re-exported from valtio)
97
97
  *
98
98
  * **2. Atomic Transactions**
99
99
  * ```typescript
@@ -240,7 +240,7 @@ export declare class KokimokiClient<ClientContextT = any> extends KokimokiClient
240
240
  *
241
241
  * @example
242
242
  * ```typescript
243
- * import { useSnapshot } from 'valtio';
243
+ * import { useSnapshot } from '@kokimoki/app';
244
244
  *
245
245
  * const kmClient = getKmClient();
246
246
  *
@@ -56,8 +56,8 @@ export const APP_META_STORE_NAME = "__km/app-meta";
56
56
  * game.round = 2;
57
57
  * });
58
58
  *
59
- * // Use in React components with Valtio
60
- * import { useSnapshot } from 'valtio';
59
+ * // Use in React components (useSnapshot is re-exported from valtio)
60
+ * import { useSnapshot } from '@kokimoki/app';
61
61
  *
62
62
  * function GameComponent() {
63
63
  * const game = useSnapshot(gameStore.proxy);
@@ -71,7 +71,7 @@ export const APP_META_STORE_NAME = "__km/app-meta";
71
71
  * - Create global stores shared across all players: `kmClient.store()`
72
72
  * - Create local stores for client-side data: `kmClient.localStore()`
73
73
  * - Automatic synchronization and conflict resolution
74
- * - Use `useSnapshot()` from Valtio for reactive React components
74
+ * - Use `useSnapshot()` from `@kokimoki/app` for reactive React components (re-exported from valtio)
75
75
  *
76
76
  * **2. Atomic Transactions**
77
77
  * ```typescript
@@ -218,7 +218,7 @@ export class KokimokiClient extends EventEmitter {
218
218
  *
219
219
  * @example
220
220
  * ```typescript
221
- * import { useSnapshot } from 'valtio';
221
+ * import { useSnapshot } from '@kokimoki/app';
222
222
  *
223
223
  * const kmClient = getKmClient();
224
224
  *
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- export { KokimokiClient } from "./core";
2
- export { APP_META_STORE_NAME } from "./core/kokimoki-client";
1
+ export { APP_META_STORE_NAME, KokimokiClient } from "./core/kokimoki-client";
3
2
  export type { AppMetaState } from "./core/kokimoki-client";
4
3
  export { KokimokiStore } from "./stores";
5
4
  export type { KokimokiClientEvents, KokimokiEnv, Paginated, PollOptions, Upload, } from "./types";
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- export { KokimokiClient } from "./core";
2
- export { APP_META_STORE_NAME } from "./core/kokimoki-client";
1
+ export { APP_META_STORE_NAME, KokimokiClient } from "./core/kokimoki-client";
3
2
  export { KokimokiStore } from "./stores";
4
3
  export { getKmClient } from "./utils/kokimoki-client";
5
4
  export { getKmEnv } from "./utils/kokimoki-env";
@@ -1,7 +1,4 @@
1
- import "valtio";
2
- declare module "valtio" {
3
- function useSnapshot<T extends object>(p: T): T;
4
- }
5
- export { proxy, ref, snapshot, subscribe, useSnapshot } from "valtio";
1
+ export { proxy, ref, snapshot, subscribe } from "valtio";
2
+ export declare const useSnapshot: <T extends object>(p: T) => T;
6
3
  export { derive, underive } from "derive-valtio";
7
4
  export { devtools, subscribeKey, useProxy, watch } from "valtio/utils";
@@ -1,6 +1,8 @@
1
- import "valtio";
1
+ import { useSnapshot as _useSnapshot } from "valtio";
2
2
  // Core Valtio exports
3
- export { proxy, ref, snapshot, subscribe, useSnapshot } from "valtio";
3
+ export { proxy, ref, snapshot, subscribe } from "valtio";
4
+ // Loosen useSnapshot return type (valtio returns DeepReadonly<T>, which is too strict)
5
+ export const useSnapshot = _useSnapshot;
4
6
  // Valtio utilities
5
7
  export { derive, underive } from "derive-valtio";
6
8
  export { devtools, subscribeKey, useProxy, watch } from "valtio/utils";
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const KOKIMOKI_APP_VERSION = "3.1.3";
1
+ export declare const KOKIMOKI_APP_VERSION = "3.1.5";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Auto-generated file. Do not edit manually.
2
- export const KOKIMOKI_APP_VERSION = '3.1.3';
2
+ export const KOKIMOKI_APP_VERSION = '3.1.5';
@@ -86,7 +86,7 @@ Submits a JSON generation job with Zod schema validation. Use `getJob<T>()` to w
86
86
  **Example:**
87
87
 
88
88
  ```typescript
89
- import { z } from "zod/v4";
89
+ import { z } from "@kokimoki/app";
90
90
 
91
91
  // Define schema with Zod
92
92
  const enemySchema = z.object({
@@ -205,6 +205,8 @@ if (job.status === "completed") {
205
205
  ### Example: Persist Jobs Across Page Reloads
206
206
 
207
207
  ```typescript
208
+ import { snapshot } from "@kokimoki/app";
209
+
208
210
  // Store jobId in local store for persistence
209
211
  const { jobId } = await kmClient.ai.generateJson({
210
212
  schema: questSchema,
@@ -216,7 +218,7 @@ await kmClient.transact([localStore], ([state]) => {
216
218
  });
217
219
 
218
220
  // On page load, resume polling if job is pending
219
- const pendingJobId = localStore.proxy.pendingQuestJobId;
221
+ const pendingJobId = snapshot(localStore.proxy).pendingQuestJobId;
220
222
  if (pendingJobId) {
221
223
  const quest = await kmClient.ai.pollJson(pendingJobId, {
222
224
  schema: questSchema,
@@ -133,7 +133,7 @@ export function useDynamicStore<T extends object>(
133
133
  ## Basic Usage
134
134
 
135
135
  ```tsx
136
- import { useSnapshot } from "valtio";
136
+ import { useSnapshot } from "@kokimoki/app";
137
137
  import { useDynamicStore } from "@/hooks/useDynamicStore";
138
138
 
139
139
  interface RoomState {
@@ -350,7 +350,7 @@ const BreakoutRoom = ({ roomId }: { roomId: string }) => {
350
350
 
351
351
  ## File Organization
352
352
 
353
- **ALWAYS** organize dynamic store code using the standard store/actions pattern:
353
+ **ALWAYS** organize dynamic store code using the standard state/actions pattern:
354
354
 
355
355
  **State definition** (`src/state/chat-store.ts`):
356
356
 
@@ -408,7 +408,7 @@ export const chatActions = {
408
408
  **Usage in component** (`src/views/chat-view.tsx`):
409
409
 
410
410
  ```tsx
411
- import { useSnapshot } from "valtio";
411
+ import { useSnapshot } from "@kokimoki/app";
412
412
  import { useDynamicStore } from "@/hooks/useDynamicStore";
413
413
  import { createChatState, type ChatState } from "@/state/chat-store";
414
414
  import { chatActions } from "@/state/actions/chat-actions";
@@ -141,7 +141,7 @@ type TranslationStatus = "available" | "processing" | "failed";
141
141
  ```typescript
142
142
  const status = await kmClient.i18n.requestTranslation("de");
143
143
 
144
- if (status === "already_available") {
144
+ if (status === "available") {
145
145
  // Already translated, switch immediately
146
146
  i18next.changeLanguage("de");
147
147
  } else {
@@ -16,7 +16,9 @@ The Kokimoki SDK is a comprehensive development toolkit for building real-time c
16
16
  - Use `kmClient.transact` for atomic state updates across single store or multiple stores
17
17
  - Use `kmClient.storage.upload` and related API methods to handle file uploads (media, JSON, etc.) in application
18
18
  - Use `kmClient.serverTimestamp()` for time-related matters as this will be synced among players
19
- - Use `useSnapshot` hook from `valtio` to get reactive state inside React components
19
+ - Use `useSnapshot` hook to get reactive state inside React components — import from `@kokimoki/app` (re-exports valtio)
20
+ - Use `snapshot` function to read immutable state outside React components (in actions, event handlers, etc.) — import from `@kokimoki/app` — **NEVER** read directly from `store.proxy.field`
21
+ - Use `z` and `ZodType` from `@kokimoki/app` for schema definitions (re-exports zod)
20
22
  - Use AI integration API methods: `kmClient.ai.generateText`, `kmClient.ai.generateJson`, and `kmClient.ai.generateImage` with corresponding poll methods for AI capabilities
21
23
  - Use i18n API methods: `kmClient.i18n.createI18n`, `kmClient.i18n.init`, and `kmClient.i18n.requestTranslation` for internationalization with AI-powered translations
22
24
  - Use leaderboard API methods: `kmClient.leaderboard.insertEntry`, `kmClient.leaderboard.upsertEntry`, `kmClient.leaderboard.listEntries`, and `kmClient.leaderboard.getBestEntry` to add leaderboard capabilities to application
@@ -118,13 +120,13 @@ await kmClient.transact([store1, store2], ([state1, state2]) => {
118
120
 
119
121
  ### Reactive State in Components
120
122
 
121
- - Use `useSnapshot` hook from `valtio` to get reactive state inside React components
123
+ - Use `useSnapshot` hook to get reactive state inside React components (import from `@kokimoki/app`)
122
124
  - The component will re-render when the store state changes
123
125
 
124
126
  **Example: Using State in Components**
125
127
 
126
128
  ```tsx
127
- import { useSnapshot } from "valtio";
129
+ import { useSnapshot } from "@kokimoki/app";
128
130
  import { store } from "../store";
129
131
 
130
132
  const Component = () => {
@@ -140,6 +142,44 @@ const Component = () => {
140
142
  };
141
143
  ```
142
144
 
145
+ ### Reading State Outside Components
146
+
147
+ When reading state **outside React components** (in store actions, event handlers, initialization logic), use `snapshot()` from `@kokimoki/app` to get an immutable copy.
148
+ **NEVER** read directly from `store.proxy` — the proxy is mutable and values can change between read and use.
149
+
150
+ ```typescript
151
+ import { snapshot } from "@kokimoki/app";
152
+
153
+ // WRONG — mutable proxy, value can change unexpectedly
154
+ const value = store.proxy.someField;
155
+
156
+ // CORRECT — immutable snapshot, safe to use
157
+ const value = snapshot(store.proxy).someField;
158
+ ```
159
+
160
+ **Example: Reading state in an store actions**
161
+
162
+ ```typescript
163
+ import { snapshot } from "@kokimoki/app";
164
+
165
+ // Action function that reads state and updates it based on conditions
166
+ async function doSomething() {
167
+ const { count, completed } = snapshot(store.proxy);
168
+
169
+ if (count > 10 && !completed) {
170
+ await kmClient.transact([store], ([state]) => {
171
+ state.completed = true;
172
+ });
173
+ }
174
+ }
175
+ ```
176
+
177
+ ### Common Patterns
178
+
179
+ - **Inside React components** → `useSnapshot(store.proxy)` (reactive, triggers re-renders)
180
+ - **Outside React components** → `snapshot(store.proxy)` (immutable, read-only)
181
+ - **Writing state** → Always use `kmClient.transact()` (never assign to proxy directly)
182
+
143
183
  ## Dynamic Stores
144
184
 
145
185
  For room-based state isolation (teams, chat rooms, breakout rooms), see [Dynamic Stores](./kokimoki-dynamic-stores.instructions.md).
@@ -166,7 +206,7 @@ Each Kokimoki store has a `connections` property that provides real-time presenc
166
206
  ### Example: Track Online Players
167
207
 
168
208
  ```tsx
169
- import { useSnapshot } from "valtio";
209
+ import { useSnapshot } from "@kokimoki/app";
170
210
  import { globalStore } from "@/state/stores/global-store";
171
211
 
172
212
  const Component = () => {
@@ -186,7 +226,7 @@ const Component = () => {
186
226
  ### Example: Display Player List with Online Status
187
227
 
188
228
  ```tsx
189
- import { useSnapshot } from "valtio";
229
+ import { useSnapshot } from "@kokimoki/app";
190
230
  import { globalStore } from "@/state/stores/global-store";
191
231
 
192
232
  const PlayerList = () => {
@@ -231,8 +271,7 @@ Store names with the `__km/` prefix are reserved for SDK internal use. Do not cr
231
271
  ### Using App Meta
232
272
 
233
273
  ```tsx
234
- import { getKmClient } from "@kokimoki/app";
235
- import { useSnapshot } from "valtio";
274
+ import { useSnapshot, getKmClient } from "@kokimoki/app";
236
275
 
237
276
  const kmClient = getKmClient();
238
277
 
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "@kokimoki/app",
3
- "version": "3.1.3",
3
+ "version": "3.1.5",
4
4
  "type": "module",
5
5
  "description": "Kokimoki app",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./llms.txt": "./llms.txt"
14
+ },
8
15
  "files": [
9
16
  "dist",
10
17
  "docs",
@@ -19,17 +26,23 @@
19
26
  "prebuild": "node scripts/generate-version.js",
20
27
  "build": "tsc",
21
28
  "dev": "tsc -w",
22
- "docs": "typedoc src/index.ts"
29
+ "docs": "typedoc src/index.ts",
30
+ "lint": "eslint .",
31
+ "typecheck": "tsc --noEmit"
23
32
  },
24
33
  "author": "Loquiz OÜ",
25
34
  "license": "Apache-2.0",
26
35
  "devDependencies": {
36
+ "eslint-config": "*",
27
37
  "@types/chai": "^4",
28
38
  "@types/mocha": "^10",
29
39
  "@types/node": "^18",
30
40
  "@types/ws": "^8.5.5",
31
41
  "bson-objectid": "^2.0.4",
32
42
  "chai": "^4",
43
+ "eslint": "^9.39.1",
44
+ "eslint-plugin-chai-friendly": "^1.1.0",
45
+ "eslint-plugin-valtio": "^0.8.0",
33
46
  "mocha": "^10",
34
47
  "ts-node": "^10",
35
48
  "tsx": "^4",
package/dist/fields.d.ts DELETED
@@ -1,110 +0,0 @@
1
- export interface FieldOptions {
2
- label?: string;
3
- }
4
- export declare abstract class Field<T> {
5
- readonly options: FieldOptions;
6
- constructor(options: FieldOptions);
7
- abstract get value(): T;
8
- abstract get schema(): any;
9
- }
10
- export declare class BooleanField extends Field<boolean> {
11
- value: boolean;
12
- constructor(value: boolean, options?: FieldOptions);
13
- get schema(): {
14
- type: string;
15
- default: boolean;
16
- };
17
- }
18
- export declare class ConstField<T extends string> extends Field<
19
- string extends T ? never : T
20
- > {
21
- value: string extends T ? never : T;
22
- constructor(value: string extends T ? never : T, options?: FieldOptions);
23
- get schema(): {
24
- const: string extends T ? never : T;
25
- };
26
- }
27
- export declare class ImageField extends Field<string> {
28
- value: string;
29
- constructor(value: string, options?: FieldOptions);
30
- get schema(): {
31
- type: string;
32
- default: string;
33
- };
34
- }
35
- export declare class TextField extends Field<string> {
36
- value: string;
37
- constructor(value: string, options?: FieldOptions);
38
- get schema(): {
39
- type: string;
40
- default: string;
41
- };
42
- }
43
- export declare class EnumField<T extends Record<string, string>> extends Field<
44
- keyof T
45
- > {
46
- enumValues: T;
47
- value: keyof T;
48
- constructor(enumValues: T, value: keyof T, options?: FieldOptions);
49
- get schema(): {
50
- enum: string[];
51
- };
52
- }
53
- export declare class IntegerField extends Field<number> {
54
- value: number;
55
- constructor(value: number, options?: FieldOptions);
56
- get schema(): {
57
- type: string;
58
- default: number;
59
- };
60
- }
61
- export declare class FloatField extends Field<number> {
62
- value: number;
63
- constructor(value: number, options?: FieldOptions);
64
- get schema(): {
65
- type: string;
66
- default: number;
67
- };
68
- }
69
- export declare class FormGroup<
70
- T extends Record<string, Field<any>>,
71
- O extends Record<string, Field<any>>,
72
- > extends Field<
73
- {
74
- [key in keyof T]: T[key]["value"];
75
- } & Partial<{
76
- [key in keyof O]: O[key]["value"];
77
- }>
78
- > {
79
- requiredFields: T;
80
- optionalFields: O;
81
- constructor(requiredFields: T, optionalFields?: O, options?: FieldOptions);
82
- get value(): {
83
- [key in keyof T]: T[key]["value"];
84
- } & Partial<{
85
- [key in keyof O]: O[key]["value"];
86
- }>;
87
- get schema(): {
88
- type: string;
89
- properties: any;
90
- required: string[];
91
- };
92
- }
93
- export declare class FormArray<T> extends Field<T[]> {
94
- private factory;
95
- value: Field<T>["value"][];
96
- constructor(
97
- factory: () => Field<T>,
98
- value: Field<T>["value"][],
99
- options?: FieldOptions,
100
- );
101
- get schema(): {
102
- type: string;
103
- items: any;
104
- default: T[];
105
- };
106
- }
107
- export declare class Form<
108
- R extends Record<string, Field<any>>,
109
- O extends Record<string, Field<any>>,
110
- > extends FormGroup<R, O> {}
package/dist/fields.js DELETED
@@ -1,158 +0,0 @@
1
- const defaultFieldOptions = {};
2
- export class Field {
3
- options;
4
- constructor(options) {
5
- this.options = options;
6
- }
7
- }
8
- export class BooleanField extends Field {
9
- value;
10
- constructor(value, options = defaultFieldOptions) {
11
- super(options);
12
- this.value = value;
13
- }
14
- get schema() {
15
- return {
16
- type: "boolean",
17
- default: this.value,
18
- };
19
- }
20
- }
21
- export class ConstField extends Field {
22
- value;
23
- constructor(value, options = defaultFieldOptions) {
24
- super(options);
25
- this.value = value;
26
- }
27
- get schema() {
28
- return {
29
- const: this.value,
30
- };
31
- }
32
- }
33
- export class ImageField extends Field {
34
- value;
35
- constructor(value, options = defaultFieldOptions) {
36
- super(options);
37
- this.value = value;
38
- }
39
- get schema() {
40
- return {
41
- type: "string",
42
- default: this.value,
43
- };
44
- }
45
- }
46
- export class TextField extends Field {
47
- value;
48
- constructor(value, options = defaultFieldOptions) {
49
- super(options);
50
- this.value = value;
51
- }
52
- get schema() {
53
- return {
54
- type: "string",
55
- default: this.value,
56
- };
57
- }
58
- }
59
- export class EnumField extends Field {
60
- enumValues;
61
- value;
62
- constructor(enumValues, value, options = defaultFieldOptions) {
63
- super(options);
64
- this.enumValues = enumValues;
65
- this.value = value;
66
- }
67
- get schema() {
68
- return {
69
- enum: Object.keys(this.enumValues),
70
- };
71
- }
72
- }
73
- export class IntegerField extends Field {
74
- value;
75
- constructor(value, options = defaultFieldOptions) {
76
- super(options);
77
- this.value = value;
78
- }
79
- get schema() {
80
- return {
81
- type: "integer",
82
- default: this.value,
83
- };
84
- }
85
- }
86
- export class FloatField extends Field {
87
- value;
88
- constructor(value, options = defaultFieldOptions) {
89
- super(options);
90
- this.value = value;
91
- }
92
- get schema() {
93
- return {
94
- type: "number",
95
- default: this.value,
96
- };
97
- }
98
- }
99
- export class FormGroup extends Field {
100
- requiredFields;
101
- optionalFields;
102
- constructor(
103
- requiredFields,
104
- optionalFields = {},
105
- options = defaultFieldOptions,
106
- ) {
107
- super(options);
108
- this.requiredFields = requiredFields;
109
- this.optionalFields = optionalFields;
110
- }
111
- get value() {
112
- const value = Object.entries(this.requiredFields).reduce(
113
- (acc, [key, field]) => {
114
- acc[key] = field.value;
115
- return acc;
116
- },
117
- {},
118
- );
119
- Object.entries(this.optionalFields).forEach(([key, field]) => {
120
- if (field.value !== undefined) {
121
- value[key] = field.value;
122
- }
123
- });
124
- return value;
125
- }
126
- get schema() {
127
- const properties = {};
128
- Object.entries(this.requiredFields).forEach(([key, field]) => {
129
- properties[key] = field.schema;
130
- });
131
- Object.entries(this.optionalFields).forEach(([key, field]) => {
132
- properties[key] = field.schema;
133
- });
134
- return {
135
- type: "object",
136
- properties,
137
- required: Object.keys(this.requiredFields),
138
- };
139
- }
140
- }
141
- export class FormArray extends Field {
142
- factory;
143
- value;
144
- constructor(factory, value, options = defaultFieldOptions) {
145
- super(options);
146
- this.factory = factory;
147
- this.value = value;
148
- }
149
- get schema() {
150
- const field = this.factory();
151
- return {
152
- type: "array",
153
- items: field.schema,
154
- default: this.value,
155
- };
156
- }
157
- }
158
- export class Form extends FormGroup {}