@simplix-react/mock 0.0.2 → 0.0.3
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 +4 -3
- package/dist/index.d.ts +2 -20
- package/dist/index.js +9 -13
- package/package.json +17 -16
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Peer dependencies:
|
|
|
22
22
|
## Quick Example
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
import {
|
|
25
|
+
import { defineApi, simpleQueryBuilder } from "@simplix-react/contract";
|
|
26
26
|
import {
|
|
27
27
|
setupMockWorker,
|
|
28
28
|
deriveMockHandlers,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
import { z } from "zod";
|
|
32
32
|
|
|
33
33
|
// 1. Define your contract
|
|
34
|
-
const projectContract =
|
|
34
|
+
const projectContract = defineApi({
|
|
35
35
|
domain: "project",
|
|
36
36
|
basePath: "/api",
|
|
37
37
|
entities: {
|
|
@@ -41,12 +41,13 @@ const projectContract = defineContract({
|
|
|
41
41
|
id: z.string(),
|
|
42
42
|
title: z.string(),
|
|
43
43
|
status: z.enum(["todo", "done"]),
|
|
44
|
-
createdAt: z.
|
|
44
|
+
createdAt: z.string(),
|
|
45
45
|
}),
|
|
46
46
|
createSchema: z.object({ title: z.string() }),
|
|
47
47
|
updateSchema: z.object({ status: z.enum(["todo", "done"]).optional() }),
|
|
48
48
|
},
|
|
49
49
|
},
|
|
50
|
+
queryBuilder: simpleQueryBuilder,
|
|
50
51
|
});
|
|
51
52
|
|
|
52
53
|
// 2. Derive handlers and bootstrap
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { PGlite } from '@electric-sql/pglite';
|
|
2
2
|
import * as msw from 'msw';
|
|
3
|
-
import {
|
|
4
|
-
import { z } from 'zod';
|
|
3
|
+
import { AnyEntityDef, AnyOperationDef, ApiContractConfig } from '@simplix-react/contract';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Initializes a singleton PGlite instance with the given data directory.
|
|
@@ -140,8 +139,6 @@ interface MockServerConfig {
|
|
|
140
139
|
*/
|
|
141
140
|
declare function setupMockWorker(config: MockServerConfig): Promise<void>;
|
|
142
141
|
|
|
143
|
-
type AnyEntityDef = EntityDefinition<z.ZodTypeAny, z.ZodTypeAny, z.ZodTypeAny>;
|
|
144
|
-
type AnyOperationDef = OperationDefinition<z.ZodTypeAny, z.ZodTypeAny>;
|
|
145
142
|
/**
|
|
146
143
|
* Provides per-entity configuration for mock handler generation.
|
|
147
144
|
*
|
|
@@ -337,21 +334,6 @@ type DbRow = Record<string, unknown>;
|
|
|
337
334
|
* ```
|
|
338
335
|
*/
|
|
339
336
|
declare function toCamelCase(str: string): string;
|
|
340
|
-
/**
|
|
341
|
-
* Converts a camelCase string to snake_case.
|
|
342
|
-
*
|
|
343
|
-
* @param str - The camelCase input string.
|
|
344
|
-
* @returns The snake_case equivalent.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* ```ts
|
|
348
|
-
* import { toSnakeCase } from "@simplix-react/mock";
|
|
349
|
-
*
|
|
350
|
-
* toSnakeCase("createdAt"); // "created_at"
|
|
351
|
-
* toSnakeCase("projectId"); // "project_id"
|
|
352
|
-
* ```
|
|
353
|
-
*/
|
|
354
|
-
declare function toSnakeCase(str: string): string;
|
|
355
337
|
/**
|
|
356
338
|
* Maps a single database row from snake_case columns to a camelCase object.
|
|
357
339
|
*
|
|
@@ -568,4 +550,4 @@ declare function executeSql(db: PGlite, sql: string): Promise<void>;
|
|
|
568
550
|
*/
|
|
569
551
|
declare function addColumnIfNotExists(db: PGlite, tableName: string, columnName: string, columnDef: string): Promise<void>;
|
|
570
552
|
|
|
571
|
-
export { type DbRow, type MockEntityConfig, type MockError, type MockResult, type MockServerConfig, type SetClauseResult, addColumnIfNotExists, buildSetClause, columnExists, deriveMockHandlers, executeSql, getPGliteInstance, initPGlite, mapPgError, mapRow, mapRows, mockFailure, mockSuccess, resetPGliteInstance, setupMockWorker, tableExists, toCamelCase
|
|
553
|
+
export { type DbRow, type MockEntityConfig, type MockError, type MockResult, type MockServerConfig, type SetClauseResult, addColumnIfNotExists, buildSetClause, columnExists, deriveMockHandlers, executeSql, getPGliteInstance, initPGlite, mapPgError, mapRow, mapRows, mockFailure, mockSuccess, resetPGliteInstance, setupMockWorker, tableExists, toCamelCase };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { http, HttpResponse } from 'msw';
|
|
2
|
+
import { camelToSnake } from '@simplix-react/contract';
|
|
2
3
|
|
|
3
4
|
// src/pglite.ts
|
|
4
5
|
var instance = null;
|
|
@@ -47,9 +48,6 @@ async function setupMockWorker(config) {
|
|
|
47
48
|
function toCamelCase(str) {
|
|
48
49
|
return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
49
50
|
}
|
|
50
|
-
function toSnakeCase(str) {
|
|
51
|
-
return str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
52
|
-
}
|
|
53
51
|
function mapRow(row) {
|
|
54
52
|
const result = {};
|
|
55
53
|
for (const [key, value] of Object.entries(row)) {
|
|
@@ -65,15 +63,13 @@ function mapRow(row) {
|
|
|
65
63
|
function mapRows(rows) {
|
|
66
64
|
return rows.map((row) => mapRow(row));
|
|
67
65
|
}
|
|
68
|
-
|
|
69
|
-
// src/sql/query-building.ts
|
|
70
66
|
function buildSetClause(input, startIndex = 1) {
|
|
71
67
|
const parts = [];
|
|
72
68
|
const values = [];
|
|
73
69
|
let index = startIndex;
|
|
74
70
|
for (const [key, value] of Object.entries(input)) {
|
|
75
71
|
if (value === void 0) continue;
|
|
76
|
-
const column =
|
|
72
|
+
const column = camelToSnake(key);
|
|
77
73
|
if (typeof value === "object" && value !== null && !(value instanceof Date)) {
|
|
78
74
|
parts.push(`${column} = $${index}::jsonb`);
|
|
79
75
|
values.push(JSON.stringify(value));
|
|
@@ -145,7 +141,7 @@ function deriveMockHandlers(config, mockConfig) {
|
|
|
145
141
|
const { basePath, entities } = config;
|
|
146
142
|
for (const [name, entity] of Object.entries(entities)) {
|
|
147
143
|
const entityConfig = mockConfig?.[name];
|
|
148
|
-
const tableName = entityConfig?.tableName ??
|
|
144
|
+
const tableName = entityConfig?.tableName ?? camelToSnake(name) + "s";
|
|
149
145
|
const defaultLimit = entityConfig?.defaultLimit ?? 50;
|
|
150
146
|
const maxLimit = entityConfig?.maxLimit ?? 100;
|
|
151
147
|
const defaultSort = entityConfig?.defaultSort ?? "created_at DESC";
|
|
@@ -155,7 +151,7 @@ function deriveMockHandlers(config, mockConfig) {
|
|
|
155
151
|
handlers.push(
|
|
156
152
|
http.get(listPath, async ({ request, params: routeParams }) => {
|
|
157
153
|
const parentId = routeParams[entity.parent.param];
|
|
158
|
-
const parentColumn =
|
|
154
|
+
const parentColumn = camelToSnake(entity.parent.param);
|
|
159
155
|
const searchParams = parseSearchParams(request.url);
|
|
160
156
|
return toResponse(
|
|
161
157
|
await queryListWithParams(
|
|
@@ -265,7 +261,7 @@ async function queryListWithParams(tableName, parentColumn, parentId, searchPara
|
|
|
265
261
|
paramIndex++;
|
|
266
262
|
}
|
|
267
263
|
for (const [key, value] of Object.entries(searchParams.filters)) {
|
|
268
|
-
const column =
|
|
264
|
+
const column = camelToSnake(key);
|
|
269
265
|
conditions.push(`${column} = $${paramIndex}`);
|
|
270
266
|
values.push(value);
|
|
271
267
|
paramIndex++;
|
|
@@ -275,7 +271,7 @@ async function queryListWithParams(tableName, parentColumn, parentId, searchPara
|
|
|
275
271
|
if (searchParams.sort) {
|
|
276
272
|
const sortParts = searchParams.sort.split(",").map((s) => {
|
|
277
273
|
const [field, dir] = s.trim().split(":");
|
|
278
|
-
const column =
|
|
274
|
+
const column = camelToSnake(field);
|
|
279
275
|
const direction = dir === "desc" ? "DESC" : "ASC";
|
|
280
276
|
return `${column} ${direction}`;
|
|
281
277
|
});
|
|
@@ -333,7 +329,7 @@ async function queryByIdWithRelations(tableName, id, relations) {
|
|
|
333
329
|
const row = mainResult.rows[0];
|
|
334
330
|
const mapped = mapRow(row);
|
|
335
331
|
for (const [relationName, relation] of Object.entries(relations)) {
|
|
336
|
-
const localColumn =
|
|
332
|
+
const localColumn = camelToSnake(relation.localKey);
|
|
337
333
|
const fkValue = row[localColumn];
|
|
338
334
|
if (fkValue) {
|
|
339
335
|
const foreignKey = relation.foreignKey ?? "id";
|
|
@@ -367,7 +363,7 @@ async function insertRow(tableName, dto) {
|
|
|
367
363
|
}
|
|
368
364
|
for (const [key, value] of Object.entries(dto)) {
|
|
369
365
|
if (value === void 0) continue;
|
|
370
|
-
const column =
|
|
366
|
+
const column = camelToSnake(key);
|
|
371
367
|
columns.push(column);
|
|
372
368
|
if (typeof value === "object" && value !== null && !(value instanceof Date)) {
|
|
373
369
|
placeholders.push(`$${index}::jsonb`);
|
|
@@ -472,4 +468,4 @@ async function addColumnIfNotExists(db, tableName, columnName, columnDef) {
|
|
|
472
468
|
}
|
|
473
469
|
}
|
|
474
470
|
|
|
475
|
-
export { addColumnIfNotExists, buildSetClause, columnExists, deriveMockHandlers, executeSql, getPGliteInstance, initPGlite, mapPgError, mapRow, mapRows, mockFailure, mockSuccess, resetPGliteInstance, setupMockWorker, tableExists, toCamelCase
|
|
471
|
+
export { addColumnIfNotExists, buildSetClause, columnExists, deriveMockHandlers, executeSql, getPGliteInstance, initPGlite, mapPgError, mapRow, mapRows, mockFailure, mockSuccess, resetPGliteInstance, setupMockWorker, tableExists, toCamelCase };
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplix-react/mock",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Auto-generated MSW handlers and PGlite repositories from @simplix-react/contract",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
6
7
|
"exports": {
|
|
7
8
|
".": {
|
|
8
9
|
"types": "./dist/index.d.ts",
|
|
@@ -15,19 +16,11 @@
|
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
|
17
18
|
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsup",
|
|
20
|
-
"dev": "tsup --watch",
|
|
21
|
-
"typecheck": "tsc --noEmit",
|
|
22
|
-
"lint": "eslint src",
|
|
23
|
-
"test": "vitest run --passWithNoTests",
|
|
24
|
-
"clean": "rm -rf dist .turbo"
|
|
25
|
-
},
|
|
26
19
|
"peerDependencies": {
|
|
27
20
|
"@electric-sql/pglite": ">=0.2.0",
|
|
28
|
-
"@simplix-react/contract": "workspace:*",
|
|
29
21
|
"msw": ">=2.0.0",
|
|
30
|
-
"zod": ">=4.0.0"
|
|
22
|
+
"zod": ">=4.0.0",
|
|
23
|
+
"@simplix-react/contract": "0.0.3"
|
|
31
24
|
},
|
|
32
25
|
"peerDependenciesMeta": {
|
|
33
26
|
"@electric-sql/pglite": {
|
|
@@ -39,14 +32,22 @@
|
|
|
39
32
|
},
|
|
40
33
|
"devDependencies": {
|
|
41
34
|
"@electric-sql/pglite": "^0.3.14",
|
|
42
|
-
"@simplix-react/config-eslint": "workspace:*",
|
|
43
|
-
"@simplix-react/config-typescript": "workspace:*",
|
|
44
|
-
"@simplix-react/contract": "workspace:*",
|
|
45
35
|
"eslint": "^9.39.2",
|
|
46
36
|
"msw": "^2.7.0",
|
|
47
37
|
"tsup": "^8.5.1",
|
|
48
38
|
"typescript": "^5.9.3",
|
|
49
39
|
"vitest": "^3.0.0",
|
|
50
|
-
"zod": "^4.0.0"
|
|
40
|
+
"zod": "^4.0.0",
|
|
41
|
+
"@simplix-react/config-eslint": "0.0.1",
|
|
42
|
+
"@simplix-react/contract": "0.0.3",
|
|
43
|
+
"@simplix-react/config-typescript": "0.0.1"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsup",
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"lint": "eslint src",
|
|
50
|
+
"test": "vitest run --passWithNoTests",
|
|
51
|
+
"clean": "rm -rf dist .turbo"
|
|
51
52
|
}
|
|
52
|
-
}
|
|
53
|
+
}
|