sql-love 1.0.2 → 1.0.4
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 +52 -32
- package/dist/index.cjs +16 -0
- package/dist/index.d.ts +732 -9
- package/dist/index.mjs +16 -0
- package/package.json +29 -12
- package/.github/workflows/node.js.yml +0 -37
- package/.prettierrc.json +0 -13
- package/CHANGELOG.md +0 -39
- package/CONTRIBUTING.md +0 -85
- package/assets/sql-love-logo.png +0 -0
- package/codecov.yml +0 -7
- package/dist/index.js +0 -9
- package/dist/src/Parser/Parser.d.ts +0 -157
- package/dist/src/Parser/Parser.js +0 -304
- package/dist/src/SelectBuilder/SelectBuilder.d.ts +0 -379
- package/dist/src/SelectBuilder/SelectBuilder.js +0 -810
- package/dist/src/extractGrouped/extractGrouped.d.ts +0 -17
- package/dist/src/extractGrouped/extractGrouped.js +0 -31
- package/dist/src/extractIndexed/extractIndexed.d.ts +0 -12
- package/dist/src/extractIndexed/extractIndexed.js +0 -23
- package/dist/src/extractLookup/extractLookup.d.ts +0 -9
- package/dist/src/extractLookup/extractLookup.js +0 -21
- package/dist/src/getPagination/getPagination.d.ts +0 -16
- package/dist/src/getPagination/getPagination.js +0 -40
- package/dist/src/runMysql/runMysql.d.ts +0 -58
- package/dist/src/runMysql/runMysql.js +0 -61
- package/dist/src/runPrisma/runPrisma.d.ts +0 -41
- package/dist/src/runPrisma/runPrisma.js +0 -34
- package/dist/src/substrCount/substrCount.d.ts +0 -6
- package/dist/src/substrCount/substrCount.js +0 -14
- package/dist/src/toSafeJson/toSafeJson.d.ts +0 -25
- package/dist/src/toSafeJson/toSafeJson.js +0 -45
- package/index.ts +0 -19
- package/src/Parser/Parser.spec.ts +0 -226
- package/src/Parser/Parser.ts +0 -325
- package/src/SelectBuilder/SelectBuilder.spec.ts +0 -785
- package/src/SelectBuilder/SelectBuilder.ts +0 -914
- package/src/extractGrouped/extractGrouped.spec.ts +0 -43
- package/src/extractGrouped/extractGrouped.ts +0 -36
- package/src/extractIndexed/extractIndexed.spec.ts +0 -40
- package/src/extractIndexed/extractIndexed.ts +0 -28
- package/src/extractLookup/extractLookup.spec.ts +0 -38
- package/src/extractLookup/extractLookup.ts +0 -33
- package/src/getPagination/getPagination.spec.ts +0 -75
- package/src/getPagination/getPagination.ts +0 -42
- package/src/runMysql/runMysql.spec.ts +0 -286
- package/src/runMysql/runMysql.ts +0 -106
- package/src/runPrisma/runPrisma.spec.ts +0 -99
- package/src/runPrisma/runPrisma.ts +0 -75
- package/src/substrCount/substrCount.spec.ts +0 -29
- package/src/substrCount/substrCount.ts +0 -14
- package/src/toSafeJson/toSafeJson.spec.ts +0 -28
- package/src/toSafeJson/toSafeJson.ts +0 -56
- package/tsconfig.build.json +0 -10
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -11
package/src/runMysql/runMysql.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import type SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
2
|
-
import type { EngineStyle } from '../SelectBuilder/SelectBuilder';
|
|
3
|
-
import getPagination from '../getPagination/getPagination';
|
|
4
|
-
|
|
5
|
-
interface MysqlClient {
|
|
6
|
-
query: (
|
|
7
|
-
sql: string,
|
|
8
|
-
bindings: any[],
|
|
9
|
-
callback: (
|
|
10
|
-
err: Error | null,
|
|
11
|
-
results: Array<Record<string, any>>,
|
|
12
|
-
fields: any[]
|
|
13
|
-
) => void
|
|
14
|
-
) => void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface MysqlAsyncClient {
|
|
18
|
-
query: (
|
|
19
|
-
sql: string,
|
|
20
|
-
bindings: any[]
|
|
21
|
-
) => Promise<[Array<Record<string, any>>, any[]]>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function _queryToPromise(
|
|
25
|
-
mysqlClient: MysqlClient,
|
|
26
|
-
sql: string,
|
|
27
|
-
bindings: any[]
|
|
28
|
-
): Promise<[Array<Record<string, any>>, any[]]> {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
mysqlClient.query(sql, bindings, (err, rows, fields) => {
|
|
31
|
-
if (err) {
|
|
32
|
-
reject(err);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
resolve([rows, fields]);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Run the given query with mysql and return the results
|
|
42
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
43
|
-
* @param query The SelectBuilder query to run
|
|
44
|
-
*/
|
|
45
|
-
export async function runMysql(
|
|
46
|
-
mysqlClient: MysqlClient,
|
|
47
|
-
query: SelectBuilder
|
|
48
|
-
): Promise<[Array<Record<string, any>>, any[]]> {
|
|
49
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
50
|
-
return _queryToPromise(mysqlClient, sql, bindings);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Run the given query with mysql and return the results, count, and pagination
|
|
55
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
56
|
-
* @param query The SelectBuilder query to run
|
|
57
|
-
* @param options
|
|
58
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
59
|
-
*/
|
|
60
|
-
export async function runMysqlWithCount(
|
|
61
|
-
mysqlClient: MysqlClient,
|
|
62
|
-
query: SelectBuilder,
|
|
63
|
-
{ countExpr = '*' }: { countExpr?: string } = {}
|
|
64
|
-
) {
|
|
65
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
66
|
-
const [records, fields] = await _queryToPromise(mysqlClient, sql, bindings);
|
|
67
|
-
if (records.length > 0) {
|
|
68
|
-
const { sql, bindings } = query.compileCount({
|
|
69
|
-
engine: 'mysql',
|
|
70
|
-
countExpr,
|
|
71
|
-
});
|
|
72
|
-
const [rows] = await _queryToPromise(mysqlClient, sql, bindings);
|
|
73
|
-
const total = rows[0].found_rows;
|
|
74
|
-
return { records, total, pagination: getPagination(query, total), fields };
|
|
75
|
-
} else {
|
|
76
|
-
return { records, total: 0, pagination: getPagination(query, 0), fields };
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function runMysqlAsync(
|
|
81
|
-
mysqlClient: MysqlAsyncClient,
|
|
82
|
-
query: SelectBuilder
|
|
83
|
-
): Promise<[Array<Record<string, any>>, any[]]> {
|
|
84
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
85
|
-
return mysqlClient.query(sql, bindings);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export async function runMysqlAsyncWithCount(
|
|
89
|
-
mysqlClient: MysqlAsyncClient,
|
|
90
|
-
query: SelectBuilder,
|
|
91
|
-
{
|
|
92
|
-
engine = 'mysql',
|
|
93
|
-
countExpr = '*',
|
|
94
|
-
}: { engine?: EngineStyle; countExpr?: string } = {}
|
|
95
|
-
) {
|
|
96
|
-
const { sql, bindings } = query.compile({ engine });
|
|
97
|
-
const [records, fields] = await mysqlClient.query(sql, bindings);
|
|
98
|
-
if (records.length > 0) {
|
|
99
|
-
const { sql, bindings } = query.compileCount({ engine, countExpr });
|
|
100
|
-
const [rows] = await mysqlClient.query(sql, bindings);
|
|
101
|
-
const total = rows[0].found_rows;
|
|
102
|
-
return { records, total, pagination: getPagination(query, total), fields };
|
|
103
|
-
} else {
|
|
104
|
-
return { records, total: 0, pagination: getPagination(query, 0), fields };
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { vi } from 'vitest';
|
|
2
|
-
import SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
3
|
-
import { runPrisma, runPrismaWithCount } from './runPrisma';
|
|
4
|
-
|
|
5
|
-
describe('runPrisma', () => {
|
|
6
|
-
it('should invoke prisma.$queryRawUnsafe with correct args', async () => {
|
|
7
|
-
const mockResults = [
|
|
8
|
-
{ id: 1, name: 'John', dept: 'Marketing' },
|
|
9
|
-
{ id: 2, name: 'Jane', dept: 'Marketing' },
|
|
10
|
-
];
|
|
11
|
-
const prisma = {
|
|
12
|
-
$queryRawUnsafe: vi.fn(() => mockResults),
|
|
13
|
-
};
|
|
14
|
-
const query = new SelectBuilder('SELECT * FROM users');
|
|
15
|
-
query.where('dept', 'Marketing');
|
|
16
|
-
// @ts-expect-error
|
|
17
|
-
const results = await runPrisma(prisma, query);
|
|
18
|
-
expect(prisma.$queryRawUnsafe).toHaveBeenCalledWith(
|
|
19
|
-
'SELECT\n *\nFROM users\nWHERE dept = ?',
|
|
20
|
-
'Marketing'
|
|
21
|
-
);
|
|
22
|
-
expect(results).toBe(mockResults);
|
|
23
|
-
});
|
|
24
|
-
it('should also run with count', async () => {
|
|
25
|
-
const mockResults1 = [
|
|
26
|
-
{ id: 1, name: 'John', dept: 'Marketing' },
|
|
27
|
-
{ id: 2, name: 'Jane', dept: 'Marketing' },
|
|
28
|
-
];
|
|
29
|
-
const mockResults2 = [{ found_rows: 9 }];
|
|
30
|
-
let callCount = 0;
|
|
31
|
-
const prisma = {
|
|
32
|
-
$queryRawUnsafe: vi.fn(() => {
|
|
33
|
-
if (++callCount === 1) {
|
|
34
|
-
return mockResults1;
|
|
35
|
-
}
|
|
36
|
-
return mockResults2;
|
|
37
|
-
}),
|
|
38
|
-
};
|
|
39
|
-
const query = new SelectBuilder('SELECT * FROM users')
|
|
40
|
-
.where('dept', 'Marketing')
|
|
41
|
-
.limit(2)
|
|
42
|
-
.page(5);
|
|
43
|
-
const { records, total, pagination } = await runPrismaWithCount(
|
|
44
|
-
// @ts-expect-error
|
|
45
|
-
prisma,
|
|
46
|
-
query
|
|
47
|
-
);
|
|
48
|
-
// @ts-expect-error
|
|
49
|
-
expect(prisma.$queryRawUnsafe.mock.calls[0][0]).toBe(
|
|
50
|
-
'SELECT\n *\nFROM users\nWHERE dept = ?\nOFFSET 8\nLIMIT 2'
|
|
51
|
-
);
|
|
52
|
-
// @ts-expect-error
|
|
53
|
-
expect(prisma.$queryRawUnsafe.mock.calls[0][1]).toBe('Marketing');
|
|
54
|
-
expect(records).toBe(mockResults1);
|
|
55
|
-
expect(total).toBe(9);
|
|
56
|
-
expect(pagination).toEqual({
|
|
57
|
-
page: 5,
|
|
58
|
-
prevPage: 4,
|
|
59
|
-
nextPage: null,
|
|
60
|
-
perPage: 2,
|
|
61
|
-
numPages: 5,
|
|
62
|
-
total: 9,
|
|
63
|
-
isFirst: false,
|
|
64
|
-
isLast: true,
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
it('should handle when recordset is empty', async () => {
|
|
68
|
-
const prisma = {
|
|
69
|
-
$queryRawUnsafe: vi.fn(() => []),
|
|
70
|
-
};
|
|
71
|
-
const query = new SelectBuilder('SELECT * FROM users')
|
|
72
|
-
.where('dept', 'Marketing')
|
|
73
|
-
.limit(2)
|
|
74
|
-
.page(5);
|
|
75
|
-
const { records, total, pagination } = await runPrismaWithCount(
|
|
76
|
-
// @ts-expect-error
|
|
77
|
-
prisma,
|
|
78
|
-
query
|
|
79
|
-
);
|
|
80
|
-
// @ts-expect-error
|
|
81
|
-
expect(prisma.$queryRawUnsafe.mock.calls[0][0]).toBe(
|
|
82
|
-
'SELECT\n *\nFROM users\nWHERE dept = ?\nOFFSET 8\nLIMIT 2'
|
|
83
|
-
);
|
|
84
|
-
// @ts-expect-error
|
|
85
|
-
expect(prisma.$queryRawUnsafe.mock.calls[0][1]).toBe('Marketing');
|
|
86
|
-
expect(records).toStrictEqual([]);
|
|
87
|
-
expect(total).toBe(0);
|
|
88
|
-
expect(pagination).toEqual({
|
|
89
|
-
page: null,
|
|
90
|
-
prevPage: null,
|
|
91
|
-
nextPage: null,
|
|
92
|
-
perPage: 2,
|
|
93
|
-
numPages: 0,
|
|
94
|
-
total: 0,
|
|
95
|
-
isFirst: false,
|
|
96
|
-
isLast: false,
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
2
|
-
import type { EngineStyle } from '../SelectBuilder/SelectBuilder';
|
|
3
|
-
import getPagination from '../getPagination/getPagination';
|
|
4
|
-
import { toSafeJsonValue } from '../toSafeJson/toSafeJson';
|
|
5
|
-
|
|
6
|
-
interface PrismaClient {
|
|
7
|
-
$queryRawUnsafe: (
|
|
8
|
-
sql: string,
|
|
9
|
-
...bindings: any[]
|
|
10
|
-
) => Promise<Array<Record<string, any>>>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Run the given query with prisma and return the results
|
|
15
|
-
* @param prisma The prisma client instance
|
|
16
|
-
* @param query The SelectBuilder query to run
|
|
17
|
-
* @param options
|
|
18
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
19
|
-
*/
|
|
20
|
-
export async function runPrisma<
|
|
21
|
-
T extends Array<Record<string, any>> = Array<Record<string, any>>,
|
|
22
|
-
>(
|
|
23
|
-
prisma: PrismaClient,
|
|
24
|
-
query: SelectBuilder,
|
|
25
|
-
{ engine = undefined }: { engine?: EngineStyle } = {}
|
|
26
|
-
): Promise<T> {
|
|
27
|
-
const { sql, bindings } = query.compile({ engine });
|
|
28
|
-
return prisma.$queryRawUnsafe(sql, ...bindings) as unknown as Promise<T>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Run the given query with prisma and return the results, count, and pagination
|
|
33
|
-
* @param prisma The prisma client instance
|
|
34
|
-
* @param query The SelectBuilder query to run
|
|
35
|
-
* @param options
|
|
36
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
37
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
38
|
-
*/
|
|
39
|
-
export async function runPrismaWithCount<
|
|
40
|
-
T extends Array<Record<string, any>> = Array<Record<string, any>>,
|
|
41
|
-
>(
|
|
42
|
-
prisma: PrismaClient,
|
|
43
|
-
query: SelectBuilder,
|
|
44
|
-
{
|
|
45
|
-
engine = undefined,
|
|
46
|
-
countExpr = '*',
|
|
47
|
-
}: { engine?: EngineStyle; countExpr?: string } = {}
|
|
48
|
-
): Promise<{
|
|
49
|
-
records: T;
|
|
50
|
-
total: number;
|
|
51
|
-
pagination: {
|
|
52
|
-
page: number;
|
|
53
|
-
prevPage: number;
|
|
54
|
-
nextPage: number;
|
|
55
|
-
perPage: number;
|
|
56
|
-
numPages: number;
|
|
57
|
-
total: number;
|
|
58
|
-
isFirst: boolean;
|
|
59
|
-
isLast: boolean;
|
|
60
|
-
};
|
|
61
|
-
}> {
|
|
62
|
-
const { sql, bindings } = query.compile({ engine });
|
|
63
|
-
const records = (await prisma.$queryRawUnsafe(
|
|
64
|
-
sql,
|
|
65
|
-
...bindings
|
|
66
|
-
)) as unknown as T;
|
|
67
|
-
if (records.length > 0) {
|
|
68
|
-
const { sql, bindings } = query.compileCount({ engine, countExpr });
|
|
69
|
-
const result = await prisma.$queryRawUnsafe(sql, ...bindings);
|
|
70
|
-
const total = toSafeJsonValue(result[0].found_rows);
|
|
71
|
-
return { records, total, pagination: getPagination(query, total) };
|
|
72
|
-
} else {
|
|
73
|
-
return { records, total: 0, pagination: getPagination(query, 0) };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import substrCount from './substrCount';
|
|
2
|
-
|
|
3
|
-
describe('substrCount', function () {
|
|
4
|
-
it('should see 0', function () {
|
|
5
|
-
const haystack = 'hello world';
|
|
6
|
-
const needle = '?';
|
|
7
|
-
expect(substrCount(haystack, needle)).toBe(0);
|
|
8
|
-
});
|
|
9
|
-
it('should see 0 from empty string', function () {
|
|
10
|
-
const haystack = '';
|
|
11
|
-
const needle = '?';
|
|
12
|
-
expect(substrCount(haystack, needle)).toBe(0);
|
|
13
|
-
});
|
|
14
|
-
it('should see 1', function () {
|
|
15
|
-
const haystack = 'hello world?';
|
|
16
|
-
const needle = '?';
|
|
17
|
-
expect(substrCount(haystack, needle)).toBe(1);
|
|
18
|
-
});
|
|
19
|
-
it('should see 2 adjacent', function () {
|
|
20
|
-
const haystack = 'hello world??';
|
|
21
|
-
const needle = '?';
|
|
22
|
-
expect(substrCount(haystack, needle)).toBe(2);
|
|
23
|
-
});
|
|
24
|
-
it('should see 3', function () {
|
|
25
|
-
const haystack = '?hello world??';
|
|
26
|
-
const needle = '?';
|
|
27
|
-
expect(substrCount(haystack, needle)).toBe(3);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Count the number of times a substring appears in a string
|
|
3
|
-
* @param haystack
|
|
4
|
-
* @param needle
|
|
5
|
-
*/
|
|
6
|
-
export default function substrCount(haystack: string, needle: string) {
|
|
7
|
-
let count = 0;
|
|
8
|
-
let pos = haystack.indexOf(needle);
|
|
9
|
-
while (pos !== -1) {
|
|
10
|
-
count += 1;
|
|
11
|
-
pos = haystack.indexOf(needle, pos + 1);
|
|
12
|
-
}
|
|
13
|
-
return count;
|
|
14
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { toSafeJsonRecords, toSafeJsonString } from './toSafeJson';
|
|
2
|
-
|
|
3
|
-
describe('toSafeJsonString()', () => {
|
|
4
|
-
it('should convert small BigInt to Number', () => {
|
|
5
|
-
const records = [{ found_rows: 30n }];
|
|
6
|
-
const json = toSafeJsonString(records);
|
|
7
|
-
expect(json).toBe('[{"found_rows":30}]');
|
|
8
|
-
});
|
|
9
|
-
it('should convert large BigInt to String', () => {
|
|
10
|
-
const myBigInt = BigInt(String(Number.MAX_SAFE_INTEGER) + '0');
|
|
11
|
-
const records = [{ found_rows: myBigInt }];
|
|
12
|
-
const json = toSafeJsonString(records);
|
|
13
|
-
expect(json).toBe(`[{"found_rows":"${myBigInt.toString()}"}]`);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
describe('jsonSafePrisma()', () => {
|
|
17
|
-
it('should convert small BigInt to Number', () => {
|
|
18
|
-
const records = [{ found_rows: 30n }];
|
|
19
|
-
const json = toSafeJsonRecords(records);
|
|
20
|
-
expect(json).toStrictEqual([{ found_rows: 30 }]);
|
|
21
|
-
});
|
|
22
|
-
it('should convert large BigInt to String', () => {
|
|
23
|
-
const myBigInt = BigInt(String(Number.MAX_SAFE_INTEGER) + '0');
|
|
24
|
-
const records = [{ found_rows: myBigInt }];
|
|
25
|
-
const json = toSafeJsonRecords(records);
|
|
26
|
-
expect(json).toStrictEqual([{ found_rows: myBigInt.toString() }]);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
type SafeValue<T> = T extends BigInt ? number | string : T;
|
|
2
|
-
type SafeRecord<T> = Record<string, SafeValue<T>>;
|
|
3
|
-
type SafeRecords<T> = Array<SafeRecord<T>>;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Convert a value to a value that can be safely serialized to JSON
|
|
7
|
-
* @param value
|
|
8
|
-
*/
|
|
9
|
-
export function toSafeJsonValue<T>(value: T): SafeValue<T> {
|
|
10
|
-
if (typeof value === 'bigint') {
|
|
11
|
-
const asNumber = Number(value);
|
|
12
|
-
// Use double equals instead of triple equals below to check if the BigInt
|
|
13
|
-
// is too big to fit in a JS Number.
|
|
14
|
-
// If so, then return it as a string, otherwise return it as a Number
|
|
15
|
-
// @ts-expect-error
|
|
16
|
-
return value == asNumber ? asNumber : value.toString();
|
|
17
|
-
}
|
|
18
|
-
return value as SafeValue<T>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Convert a record to one that can be safely serialized to JSON
|
|
23
|
-
* @param record
|
|
24
|
-
*/
|
|
25
|
-
export function toSafeJsonRecord<T extends Record<string, any>>(
|
|
26
|
-
record: T
|
|
27
|
-
): SafeRecord<T> {
|
|
28
|
-
const newRecord: SafeValue<T> = {} as any;
|
|
29
|
-
for (const key in record) {
|
|
30
|
-
/* v8 ignore next 3 */
|
|
31
|
-
if (!Object.prototype.hasOwnProperty.call(record, key)) {
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
newRecord[key] = toSafeJsonValue(record[key]);
|
|
35
|
-
}
|
|
36
|
-
return newRecord;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Convert a recordset to one that can be safely serialized to JSON
|
|
41
|
-
* @param records
|
|
42
|
-
*/
|
|
43
|
-
export function toSafeJsonRecords<T extends Record<string, any>>(
|
|
44
|
-
records: T[]
|
|
45
|
-
): SafeRecords<T> {
|
|
46
|
-
return records.map(toSafeJsonRecord);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* JSON stringify a value or data structure, ensuring first that all values are
|
|
51
|
-
* safe to serialize
|
|
52
|
-
* @param records
|
|
53
|
-
*/
|
|
54
|
-
export function toSafeJsonString(records: Array<Record<string, any>>) {
|
|
55
|
-
return JSON.stringify(records, (_, value: any) => toSafeJsonValue(value));
|
|
56
|
-
}
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "ESNext",
|
|
4
|
-
"target": "ESNext",
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"removeComments": false,
|
|
8
|
-
"noEmit": false,
|
|
9
|
-
"pretty": true,
|
|
10
|
-
"isolatedModules": true,
|
|
11
|
-
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
12
|
-
"sourceMap": false,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"moduleResolution": "node",
|
|
15
|
-
"allowSyntheticDefaultImports": true,
|
|
16
|
-
"types": ["vitest/globals"]
|
|
17
|
-
},
|
|
18
|
-
"include": [
|
|
19
|
-
"src/**/*.ts"
|
|
20
|
-
],
|
|
21
|
-
"files": ["index.ts"]
|
|
22
|
-
}
|