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
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Group database rows by a column value
|
|
3
|
-
* @param field The database column to group by
|
|
4
|
-
* @param records Records from the database
|
|
5
|
-
* @example
|
|
6
|
-
* extractGrouped('org', users); // result:
|
|
7
|
-
* {
|
|
8
|
-
* "Marketing": [
|
|
9
|
-
* { id: 1, name: "John", org: "Marketing" },
|
|
10
|
-
* { id: 2, name: "Jane", org: "Marketing" },
|
|
11
|
-
* ],
|
|
12
|
-
* "Finance": [
|
|
13
|
-
* { id: 3, name: "Jose", org: "Finance" },
|
|
14
|
-
* ],
|
|
15
|
-
* }
|
|
16
|
-
*/
|
|
17
|
-
export default function extractGrouped<DbRecord extends Record<string, any>>(field: keyof DbRecord, records: DbRecord[]): Record<string, DbRecord[]>;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Group database rows by a column value
|
|
3
|
-
* @param field The database column to group by
|
|
4
|
-
* @param records Records from the database
|
|
5
|
-
* @example
|
|
6
|
-
* extractGrouped('org', users); // result:
|
|
7
|
-
* {
|
|
8
|
-
* "Marketing": [
|
|
9
|
-
* { id: 1, name: "John", org: "Marketing" },
|
|
10
|
-
* { id: 2, name: "Jane", org: "Marketing" },
|
|
11
|
-
* ],
|
|
12
|
-
* "Finance": [
|
|
13
|
-
* { id: 3, name: "Jose", org: "Finance" },
|
|
14
|
-
* ],
|
|
15
|
-
* }
|
|
16
|
-
*/
|
|
17
|
-
export default function extractGrouped(field, records) {
|
|
18
|
-
let idx = 0;
|
|
19
|
-
const grouped = {};
|
|
20
|
-
for (const record of records) {
|
|
21
|
-
if (!(field in record)) {
|
|
22
|
-
throw new Error(`Column "${String(field)}" is not present in record ${idx}`);
|
|
23
|
-
}
|
|
24
|
-
if (!grouped[record[field]]) {
|
|
25
|
-
grouped[record[field]] = [];
|
|
26
|
-
}
|
|
27
|
-
grouped[record[field]].push(record);
|
|
28
|
-
idx++;
|
|
29
|
-
}
|
|
30
|
-
return grouped;
|
|
31
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Index each database row by a column value
|
|
3
|
-
* @param field The database column to index by
|
|
4
|
-
* @param records Records from the database
|
|
5
|
-
* @example
|
|
6
|
-
* extractIndexed('id', users); // result:
|
|
7
|
-
* {
|
|
8
|
-
* "1": { id: 1, name: "John" },
|
|
9
|
-
* "2": { id: 2, name: "Jane" },
|
|
10
|
-
* }
|
|
11
|
-
*/
|
|
12
|
-
export default function extractIndexed<DbRecord extends Record<string, any>>(field: keyof DbRecord, records: DbRecord[]): Record<string, DbRecord>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Index each database row by a column value
|
|
3
|
-
* @param field The database column to index by
|
|
4
|
-
* @param records Records from the database
|
|
5
|
-
* @example
|
|
6
|
-
* extractIndexed('id', users); // result:
|
|
7
|
-
* {
|
|
8
|
-
* "1": { id: 1, name: "John" },
|
|
9
|
-
* "2": { id: 2, name: "Jane" },
|
|
10
|
-
* }
|
|
11
|
-
*/
|
|
12
|
-
export default function extractIndexed(field, records) {
|
|
13
|
-
let idx = 0;
|
|
14
|
-
const indexed = {};
|
|
15
|
-
for (const record of records) {
|
|
16
|
-
if (!(field in record)) {
|
|
17
|
-
throw new Error(`Column "${String(field)}" is not present in record ${idx}`);
|
|
18
|
-
}
|
|
19
|
-
indexed[record[field]] = record;
|
|
20
|
-
idx++;
|
|
21
|
-
}
|
|
22
|
-
return indexed;
|
|
23
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Given an array of records, extract an object with keyField-valueField pairs
|
|
3
|
-
* @param records An array of records
|
|
4
|
-
* @param keyField The field to use as the key
|
|
5
|
-
* @param valueField The field to use as the value
|
|
6
|
-
*/
|
|
7
|
-
export default function extractLookup<T extends Array<Record<K | V, any>>, K extends keyof T[number], V extends keyof T[number]>(keyField: K, valueField: V, records: T): {
|
|
8
|
-
[key in T[number][K]]: T[number][V];
|
|
9
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Given an array of records, extract an object with keyField-valueField pairs
|
|
3
|
-
* @param records An array of records
|
|
4
|
-
* @param keyField The field to use as the key
|
|
5
|
-
* @param valueField The field to use as the value
|
|
6
|
-
*/
|
|
7
|
-
export default function extractLookup(keyField, valueField, records) {
|
|
8
|
-
const lookup = {};
|
|
9
|
-
let idx = 0;
|
|
10
|
-
for (const record of records) {
|
|
11
|
-
if (!(keyField in record)) {
|
|
12
|
-
throw new Error(`Column "${String(keyField)}" is not present in record ${idx}`);
|
|
13
|
-
}
|
|
14
|
-
if (!(valueField in record)) {
|
|
15
|
-
throw new Error(`Column "${String(valueField)}" is not present in record ${idx}`);
|
|
16
|
-
}
|
|
17
|
-
idx++;
|
|
18
|
-
lookup[String(record[keyField])] = record[valueField];
|
|
19
|
-
}
|
|
20
|
-
return lookup;
|
|
21
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
2
|
-
/**
|
|
3
|
-
* Given a foundRows number of records and a limit, return the foundRows number of pages
|
|
4
|
-
* @param query The query that was just run
|
|
5
|
-
* @param total The number of records if there were no limit
|
|
6
|
-
*/
|
|
7
|
-
export default function getPagination(query: SelectBuilder, total: BigInt | number): {
|
|
8
|
-
page: number;
|
|
9
|
-
prevPage: number;
|
|
10
|
-
nextPage: number;
|
|
11
|
-
perPage: number;
|
|
12
|
-
numPages: number;
|
|
13
|
-
total: number;
|
|
14
|
-
isFirst: boolean;
|
|
15
|
-
isLast: boolean;
|
|
16
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Given a foundRows number of records and a limit, return the foundRows number of pages
|
|
3
|
-
* @param query The query that was just run
|
|
4
|
-
* @param total The number of records if there were no limit
|
|
5
|
-
*/
|
|
6
|
-
export default function getPagination(query, total) {
|
|
7
|
-
total = Number(total) || 0;
|
|
8
|
-
const perPage = Number(query._limit) || null;
|
|
9
|
-
let page = null;
|
|
10
|
-
if (total === 0) {
|
|
11
|
-
page = null;
|
|
12
|
-
}
|
|
13
|
-
else if (query._page) {
|
|
14
|
-
page = Number(query._page);
|
|
15
|
-
}
|
|
16
|
-
else if (query._limit && query._offset) {
|
|
17
|
-
page = Math.floor(Number(query._offset) / Number(query._limit)) + 1;
|
|
18
|
-
}
|
|
19
|
-
else if (query._limit && !query._offset) {
|
|
20
|
-
page = 1;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
page = null;
|
|
24
|
-
}
|
|
25
|
-
const numPages = total === 0 || perPage === null ? 0 : Math.ceil(total / perPage) || 0;
|
|
26
|
-
const isFirst = page === 1;
|
|
27
|
-
const isLast = numPages > 0 && page === numPages;
|
|
28
|
-
const prevPage = numPages === 0 ? null : page - 1 || null;
|
|
29
|
-
const nextPage = numPages > 0 && page + 1 <= numPages ? page + 1 : null;
|
|
30
|
-
return {
|
|
31
|
-
page,
|
|
32
|
-
prevPage,
|
|
33
|
-
nextPage,
|
|
34
|
-
perPage,
|
|
35
|
-
numPages,
|
|
36
|
-
total,
|
|
37
|
-
isFirst,
|
|
38
|
-
isLast,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
2
|
-
import type { EngineStyle } from '../SelectBuilder/SelectBuilder';
|
|
3
|
-
interface MysqlClient {
|
|
4
|
-
query: (sql: string, bindings: any[], callback: (err: Error | null, results: Array<Record<string, any>>, fields: any[]) => void) => void;
|
|
5
|
-
}
|
|
6
|
-
interface MysqlAsyncClient {
|
|
7
|
-
query: (sql: string, bindings: any[]) => Promise<[Array<Record<string, any>>, any[]]>;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Run the given query with mysql and return the results
|
|
11
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
12
|
-
* @param query The SelectBuilder query to run
|
|
13
|
-
*/
|
|
14
|
-
export declare function runMysql(mysqlClient: MysqlClient, query: SelectBuilder): Promise<[Array<Record<string, any>>, any[]]>;
|
|
15
|
-
/**
|
|
16
|
-
* Run the given query with mysql and return the results, count, and pagination
|
|
17
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
18
|
-
* @param query The SelectBuilder query to run
|
|
19
|
-
* @param options
|
|
20
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
21
|
-
*/
|
|
22
|
-
export declare function runMysqlWithCount(mysqlClient: MysqlClient, query: SelectBuilder, { countExpr }?: {
|
|
23
|
-
countExpr?: string;
|
|
24
|
-
}): Promise<{
|
|
25
|
-
records: Record<string, any>[];
|
|
26
|
-
total: any;
|
|
27
|
-
pagination: {
|
|
28
|
-
page: number;
|
|
29
|
-
prevPage: number;
|
|
30
|
-
nextPage: number;
|
|
31
|
-
perPage: number;
|
|
32
|
-
numPages: number;
|
|
33
|
-
total: number;
|
|
34
|
-
isFirst: boolean;
|
|
35
|
-
isLast: boolean;
|
|
36
|
-
};
|
|
37
|
-
fields: any[];
|
|
38
|
-
}>;
|
|
39
|
-
export declare function runMysqlAsync(mysqlClient: MysqlAsyncClient, query: SelectBuilder): Promise<[Array<Record<string, any>>, any[]]>;
|
|
40
|
-
export declare function runMysqlAsyncWithCount(mysqlClient: MysqlAsyncClient, query: SelectBuilder, { engine, countExpr, }?: {
|
|
41
|
-
engine?: EngineStyle;
|
|
42
|
-
countExpr?: string;
|
|
43
|
-
}): Promise<{
|
|
44
|
-
records: Record<string, any>[];
|
|
45
|
-
total: any;
|
|
46
|
-
pagination: {
|
|
47
|
-
page: number;
|
|
48
|
-
prevPage: number;
|
|
49
|
-
nextPage: number;
|
|
50
|
-
perPage: number;
|
|
51
|
-
numPages: number;
|
|
52
|
-
total: number;
|
|
53
|
-
isFirst: boolean;
|
|
54
|
-
isLast: boolean;
|
|
55
|
-
};
|
|
56
|
-
fields: any[];
|
|
57
|
-
}>;
|
|
58
|
-
export {};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import getPagination from '../getPagination/getPagination';
|
|
2
|
-
function _queryToPromise(mysqlClient, sql, bindings) {
|
|
3
|
-
return new Promise((resolve, reject) => {
|
|
4
|
-
mysqlClient.query(sql, bindings, (err, rows, fields) => {
|
|
5
|
-
if (err) {
|
|
6
|
-
reject(err);
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
resolve([rows, fields]);
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Run the given query with mysql and return the results
|
|
15
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
16
|
-
* @param query The SelectBuilder query to run
|
|
17
|
-
*/
|
|
18
|
-
export async function runMysql(mysqlClient, query) {
|
|
19
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
20
|
-
return _queryToPromise(mysqlClient, sql, bindings);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Run the given query with mysql and return the results, count, and pagination
|
|
24
|
-
* @param mysqlClient A client created with mysql.createConnection() or mysql.createPool()
|
|
25
|
-
* @param query The SelectBuilder query to run
|
|
26
|
-
* @param options
|
|
27
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
28
|
-
*/
|
|
29
|
-
export async function runMysqlWithCount(mysqlClient, query, { countExpr = '*' } = {}) {
|
|
30
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
31
|
-
const [records, fields] = await _queryToPromise(mysqlClient, sql, bindings);
|
|
32
|
-
if (records.length > 0) {
|
|
33
|
-
const { sql, bindings } = query.compileCount({
|
|
34
|
-
engine: 'mysql',
|
|
35
|
-
countExpr,
|
|
36
|
-
});
|
|
37
|
-
const [rows] = await _queryToPromise(mysqlClient, sql, bindings);
|
|
38
|
-
const total = rows[0].found_rows;
|
|
39
|
-
return { records, total, pagination: getPagination(query, total), fields };
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
return { records, total: 0, pagination: getPagination(query, 0), fields };
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export async function runMysqlAsync(mysqlClient, query) {
|
|
46
|
-
const { sql, bindings } = query.compile({ engine: 'mysql' });
|
|
47
|
-
return mysqlClient.query(sql, bindings);
|
|
48
|
-
}
|
|
49
|
-
export async function runMysqlAsyncWithCount(mysqlClient, query, { engine = 'mysql', countExpr = '*', } = {}) {
|
|
50
|
-
const { sql, bindings } = query.compile({ engine });
|
|
51
|
-
const [records, fields] = await mysqlClient.query(sql, bindings);
|
|
52
|
-
if (records.length > 0) {
|
|
53
|
-
const { sql, bindings } = query.compileCount({ engine, countExpr });
|
|
54
|
-
const [rows] = await mysqlClient.query(sql, bindings);
|
|
55
|
-
const total = rows[0].found_rows;
|
|
56
|
-
return { records, total, pagination: getPagination(query, total), fields };
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
return { records, total: 0, pagination: getPagination(query, 0), fields };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type SelectBuilder from '../SelectBuilder/SelectBuilder';
|
|
2
|
-
import type { EngineStyle } from '../SelectBuilder/SelectBuilder';
|
|
3
|
-
interface PrismaClient {
|
|
4
|
-
$queryRawUnsafe: (sql: string, ...bindings: any[]) => Promise<Array<Record<string, any>>>;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Run the given query with prisma and return the results
|
|
8
|
-
* @param prisma The prisma client instance
|
|
9
|
-
* @param query The SelectBuilder query to run
|
|
10
|
-
* @param options
|
|
11
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
12
|
-
*/
|
|
13
|
-
export declare function runPrisma<T extends Array<Record<string, any>> = Array<Record<string, any>>>(prisma: PrismaClient, query: SelectBuilder, { engine }?: {
|
|
14
|
-
engine?: EngineStyle;
|
|
15
|
-
}): Promise<T>;
|
|
16
|
-
/**
|
|
17
|
-
* Run the given query with prisma and return the results, count, and pagination
|
|
18
|
-
* @param prisma The prisma client instance
|
|
19
|
-
* @param query The SelectBuilder query to run
|
|
20
|
-
* @param options
|
|
21
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
22
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
23
|
-
*/
|
|
24
|
-
export declare function runPrismaWithCount<T extends Array<Record<string, any>> = Array<Record<string, any>>>(prisma: PrismaClient, query: SelectBuilder, { engine, countExpr, }?: {
|
|
25
|
-
engine?: EngineStyle;
|
|
26
|
-
countExpr?: string;
|
|
27
|
-
}): Promise<{
|
|
28
|
-
records: T;
|
|
29
|
-
total: number;
|
|
30
|
-
pagination: {
|
|
31
|
-
page: number;
|
|
32
|
-
prevPage: number;
|
|
33
|
-
nextPage: number;
|
|
34
|
-
perPage: number;
|
|
35
|
-
numPages: number;
|
|
36
|
-
total: number;
|
|
37
|
-
isFirst: boolean;
|
|
38
|
-
isLast: boolean;
|
|
39
|
-
};
|
|
40
|
-
}>;
|
|
41
|
-
export {};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import getPagination from '../getPagination/getPagination';
|
|
2
|
-
import { toSafeJsonValue } from '../toSafeJson/toSafeJson';
|
|
3
|
-
/**
|
|
4
|
-
* Run the given query with prisma and return the results
|
|
5
|
-
* @param prisma The prisma client instance
|
|
6
|
-
* @param query The SelectBuilder query to run
|
|
7
|
-
* @param options
|
|
8
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
9
|
-
*/
|
|
10
|
-
export async function runPrisma(prisma, query, { engine = undefined } = {}) {
|
|
11
|
-
const { sql, bindings } = query.compile({ engine });
|
|
12
|
-
return prisma.$queryRawUnsafe(sql, ...bindings);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Run the given query with prisma and return the results, count, and pagination
|
|
16
|
-
* @param prisma The prisma client instance
|
|
17
|
-
* @param query The SelectBuilder query to run
|
|
18
|
-
* @param options
|
|
19
|
-
* @param options.engine The engine style to use ("mssql" | "mysql" | "oracle" | "pg")
|
|
20
|
-
* @param options.countExpr The SQL expression to use for the count (default "*")
|
|
21
|
-
*/
|
|
22
|
-
export async function runPrismaWithCount(prisma, query, { engine = undefined, countExpr = '*', } = {}) {
|
|
23
|
-
const { sql, bindings } = query.compile({ engine });
|
|
24
|
-
const records = (await prisma.$queryRawUnsafe(sql, ...bindings));
|
|
25
|
-
if (records.length > 0) {
|
|
26
|
-
const { sql, bindings } = query.compileCount({ engine, countExpr });
|
|
27
|
-
const result = await prisma.$queryRawUnsafe(sql, ...bindings);
|
|
28
|
-
const total = toSafeJsonValue(result[0].found_rows);
|
|
29
|
-
return { records, total, pagination: getPagination(query, total) };
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
return { records, total: 0, pagination: getPagination(query, 0) };
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -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, needle) {
|
|
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,25 +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
|
-
* Convert a value to a value that can be safely serialized to JSON
|
|
6
|
-
* @param value
|
|
7
|
-
*/
|
|
8
|
-
export declare function toSafeJsonValue<T>(value: T): SafeValue<T>;
|
|
9
|
-
/**
|
|
10
|
-
* Convert a record to one that can be safely serialized to JSON
|
|
11
|
-
* @param record
|
|
12
|
-
*/
|
|
13
|
-
export declare function toSafeJsonRecord<T extends Record<string, any>>(record: T): SafeRecord<T>;
|
|
14
|
-
/**
|
|
15
|
-
* Convert a recordset to one that can be safely serialized to JSON
|
|
16
|
-
* @param records
|
|
17
|
-
*/
|
|
18
|
-
export declare function toSafeJsonRecords<T extends Record<string, any>>(records: T[]): SafeRecords<T>;
|
|
19
|
-
/**
|
|
20
|
-
* JSON stringify a value or data structure, ensuring first that all values are
|
|
21
|
-
* safe to serialize
|
|
22
|
-
* @param records
|
|
23
|
-
*/
|
|
24
|
-
export declare function toSafeJsonString(records: Array<Record<string, any>>): string;
|
|
25
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convert a value to a value that can be safely serialized to JSON
|
|
3
|
-
* @param value
|
|
4
|
-
*/
|
|
5
|
-
export function toSafeJsonValue(value) {
|
|
6
|
-
if (typeof value === 'bigint') {
|
|
7
|
-
const asNumber = Number(value);
|
|
8
|
-
// Use double equals instead of triple equals below to check if the BigInt
|
|
9
|
-
// is too big to fit in a JS Number.
|
|
10
|
-
// If so, then return it as a string, otherwise return it as a Number
|
|
11
|
-
// @ts-expect-error
|
|
12
|
-
return value == asNumber ? asNumber : value.toString();
|
|
13
|
-
}
|
|
14
|
-
return value;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Convert a record to one that can be safely serialized to JSON
|
|
18
|
-
* @param record
|
|
19
|
-
*/
|
|
20
|
-
export function toSafeJsonRecord(record) {
|
|
21
|
-
const newRecord = {};
|
|
22
|
-
for (const key in record) {
|
|
23
|
-
/* v8 ignore next 3 */
|
|
24
|
-
if (!Object.prototype.hasOwnProperty.call(record, key)) {
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
newRecord[key] = toSafeJsonValue(record[key]);
|
|
28
|
-
}
|
|
29
|
-
return newRecord;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Convert a recordset to one that can be safely serialized to JSON
|
|
33
|
-
* @param records
|
|
34
|
-
*/
|
|
35
|
-
export function toSafeJsonRecords(records) {
|
|
36
|
-
return records.map(toSafeJsonRecord);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* JSON stringify a value or data structure, ensuring first that all values are
|
|
40
|
-
* safe to serialize
|
|
41
|
-
* @param records
|
|
42
|
-
*/
|
|
43
|
-
export function toSafeJsonString(records) {
|
|
44
|
-
return JSON.stringify(records, (_, value) => toSafeJsonValue(value));
|
|
45
|
-
}
|
package/index.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export { default as Parser } from './src/Parser/Parser';
|
|
2
|
-
export { default as SelectBuilder } from './src/SelectBuilder/SelectBuilder';
|
|
3
|
-
export { default as extractGrouped } from './src/extractGrouped/extractGrouped';
|
|
4
|
-
export { default as extractIndexed } from './src/extractIndexed/extractIndexed';
|
|
5
|
-
export { default as extractLookup } from './src/extractLookup/extractLookup';
|
|
6
|
-
export { default as getPagination } from './src/getPagination/getPagination';
|
|
7
|
-
export {
|
|
8
|
-
runMysql,
|
|
9
|
-
runMysqlAsync,
|
|
10
|
-
runMysqlAsyncWithCount,
|
|
11
|
-
runMysqlWithCount,
|
|
12
|
-
} from './src/runMysql/runMysql';
|
|
13
|
-
export { runPrisma, runPrismaWithCount } from './src/runPrisma/runPrisma';
|
|
14
|
-
export {
|
|
15
|
-
toSafeJsonRecord,
|
|
16
|
-
toSafeJsonRecords,
|
|
17
|
-
toSafeJsonString,
|
|
18
|
-
toSafeJsonValue,
|
|
19
|
-
} from './src/toSafeJson/toSafeJson';
|