@cloudcome/utils-core 1.9.2 → 1.11.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.
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{query.cjs → qs.cjs} +1 -1
- package/dist/qs.cjs.map +1 -0
- package/dist/{query.mjs → qs.mjs} +1 -1
- package/dist/qs.mjs.map +1 -0
- package/dist/types.d.ts +13 -0
- package/package.json +7 -7
- package/dist/query.cjs.map +0 -1
- package/dist/query.mjs.map +0 -1
- /package/dist/{query.d.ts → qs.d.ts} +0 -0
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/qs.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qs.cjs","sources":["../src/qs.ts"],"sourcesContent":["import { objectEach } from './object';\nimport { isArray, isBoolean, isDate, isNull, isNullish, isNumber, isString, isUndefined } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 查询字符串解析函数\n * @template T - 解析后返回的对象类型\n * @callback QSReader\n * @param {string} value - 查询字符串的值\n * @param {string} key - 查询字符串的键\n * @param {T} qsObject - 当前解析的对象\n * @returns {unknown} 解析后的值,如果返回 undefined 或 null 则不会添加到对象中\n * @example\n * const parser: QSReader<MyObject> = (value, key, obj) => {\n * if (key === 'date') return new Date(value);\n * return value;\n * };\n */\nexport type QSReader<T extends AnyObject> = (value: string, key: string, qsObject: T) => unknown;\n\n/**\n * 解析查询字符串为对象\n * @template T - 返回的对象类型\n * @param {string} queryString - 要解析的查询字符串\n * @param {QSReader<T>} [parser] - 自定义解析函数\n * @returns {T} 解析后的对象\n * @example\n * const obj = qsParse('name=John&age=30');\n * // { name: 'John', age: '30' }\n *\n * const obj2 = qsParse('date=2023-01-01', (val, key) => {\n * if (key === 'date') return new Date(val);\n * return val;\n * });\n * // { date: Date('2023-01-01') }\n */\nexport function qsParse<T extends AnyObject>(queryString: string, parser?: QSReader<T>): T {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams(queryString.replace(/^.*\\?/, ''));\n const qsObject = {} as T;\n\n for (const [key, val] of sp.entries()) {\n const valFinal = parser ? parser(val, key, qsObject) : val;\n\n if (isNullish(valFinal)) continue;\n\n if (Object.hasOwn(qsObject, key)) {\n // @ts-expect-error\n if (!isArray(qsObject[key])) qsObject[key] = [qsObject[key]];\n (qsObject[key] as unknown[]).push(val);\n } else {\n // @ts-expect-error\n qsObject[key] = valFinal;\n }\n }\n\n return qsObject;\n}\n\n/**\n * 查询字符串序列化函数\n * @template T - 要序列化的对象类型\n * @callback QSWriter\n * @param {unknown} value - 要序列化的值\n * @param {string} key - 对象的键\n * @param {T} query - 当前序列化的对象\n * @returns {string | null} 序列化后的字符串,如果返回 null 则忽略该键值对\n * @example\n * const writer: QSWriter<MyObject> = (val, key) => {\n * if (val instanceof Date) return val.toISOString();\n * return String(val);\n * };\n */\nexport type QSWriter<T extends AnyObject = AnyObject> = (value: unknown, key: string, query: T) => string | null;\nconst defaultWriter: QSWriter<AnyObject> = (val: unknown) => {\n if (isString(val)) return val;\n if (isNumber(val)) return String(val);\n if (isBoolean(val)) return val ? 'true' : 'false';\n if (isDate(val)) return val.toISOString();\n return null;\n};\n\n/**\n * 将对象序列化为查询字符串\n * @template T - 要序列化的对象类型\n * @param {T} qsObject - 要序列化的对象\n * @param {QSWriter<T>} [stringify=defaultWriter] - 自定义序列化函数\n * @returns {string} 序列化后的查询字符串\n * @example\n * const str = qsStringify({ name: 'John', age: 30 });\n * // 'name=John&age=30'\n *\n * const str2 = qsStringify({ date: new Date('2023-01-01') });\n * // 'date=2023-01-01T00:00:00.000Z'\n */\nexport function qsStringify<T extends AnyObject>(qsObject: T, stringify: QSWriter<T> = defaultWriter): string {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams();\n const pushPairs = (val: unknown, key: string) => {\n const valFinal = stringify(val, String(key), qsObject);\n if (isNullish(valFinal)) return;\n\n sp.append(key, valFinal);\n };\n\n objectEach(qsObject, (val, key: string) => {\n if (isArray(val)) {\n for (const it of val) {\n pushPairs(it, key);\n }\n } else {\n pushPairs(val, key);\n }\n });\n\n return sp.toString();\n}\n"],"names":["isNullish","isArray","isString","isNumber","isBoolean","isDate","objectEach"],"mappings":";;;;AAoCgB,SAAA,QAA6B,aAAqB,QAAyB;AAGnF,QAAA,KAAK,IAAI,WAAW,gBAAgB,YAAY,QAAQ,SAAS,EAAE,CAAC;AAC1E,QAAM,WAAW,CAAC;AAElB,aAAW,CAAC,KAAK,GAAG,KAAK,GAAG,WAAW;AACrC,UAAM,WAAW,SAAS,OAAO,KAAK,KAAK,QAAQ,IAAI;AAEnD,QAAAA,KAAAA,UAAU,QAAQ,EAAG;AAEzB,QAAI,OAAO,OAAO,UAAU,GAAG,GAAG;AAEhC,UAAI,CAACC,KAAA,QAAQ,SAAS,GAAG,CAAC,EAAY,UAAA,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC;AAC1D,eAAS,GAAG,EAAgB,KAAK,GAAG;AAAA,IAAA,OAChC;AAEL,eAAS,GAAG,IAAI;AAAA,IAAA;AAAA,EAClB;AAGK,SAAA;AACT;AAiBA,MAAM,gBAAqC,CAAC,QAAiB;AACvD,MAAAC,KAAA,SAAS,GAAG,EAAU,QAAA;AAC1B,MAAIC,KAAS,SAAA,GAAG,EAAG,QAAO,OAAO,GAAG;AACpC,MAAIC,KAAU,UAAA,GAAG,EAAG,QAAO,MAAM,SAAS;AAC1C,MAAIC,KAAO,OAAA,GAAG,EAAG,QAAO,IAAI,YAAY;AACjC,SAAA;AACT;AAegB,SAAA,YAAiC,UAAa,YAAyB,eAAuB;AAGtG,QAAA,KAAK,IAAI,WAAW,gBAAgB;AACpC,QAAA,YAAY,CAAC,KAAc,QAAgB;AAC/C,UAAM,WAAW,UAAU,KAAK,OAAO,GAAG,GAAG,QAAQ;AACjD,QAAAL,KAAAA,UAAU,QAAQ,EAAG;AAEtB,OAAA,OAAO,KAAK,QAAQ;AAAA,EACzB;AAEWM,OAAAA,WAAA,UAAU,CAAC,KAAK,QAAgB;AACrC,QAAAL,KAAAA,QAAQ,GAAG,GAAG;AAChB,iBAAW,MAAM,KAAK;AACpB,kBAAU,IAAI,GAAG;AAAA,MAAA;AAAA,IACnB,OACK;AACL,gBAAU,KAAK,GAAG;AAAA,IAAA;AAAA,EACpB,CACD;AAED,SAAO,GAAG,SAAS;AACrB;;;"}
|
package/dist/qs.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qs.mjs","sources":["../src/qs.ts"],"sourcesContent":["import { objectEach } from './object';\nimport { isArray, isBoolean, isDate, isNull, isNullish, isNumber, isString, isUndefined } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 查询字符串解析函数\n * @template T - 解析后返回的对象类型\n * @callback QSReader\n * @param {string} value - 查询字符串的值\n * @param {string} key - 查询字符串的键\n * @param {T} qsObject - 当前解析的对象\n * @returns {unknown} 解析后的值,如果返回 undefined 或 null 则不会添加到对象中\n * @example\n * const parser: QSReader<MyObject> = (value, key, obj) => {\n * if (key === 'date') return new Date(value);\n * return value;\n * };\n */\nexport type QSReader<T extends AnyObject> = (value: string, key: string, qsObject: T) => unknown;\n\n/**\n * 解析查询字符串为对象\n * @template T - 返回的对象类型\n * @param {string} queryString - 要解析的查询字符串\n * @param {QSReader<T>} [parser] - 自定义解析函数\n * @returns {T} 解析后的对象\n * @example\n * const obj = qsParse('name=John&age=30');\n * // { name: 'John', age: '30' }\n *\n * const obj2 = qsParse('date=2023-01-01', (val, key) => {\n * if (key === 'date') return new Date(val);\n * return val;\n * });\n * // { date: Date('2023-01-01') }\n */\nexport function qsParse<T extends AnyObject>(queryString: string, parser?: QSReader<T>): T {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams(queryString.replace(/^.*\\?/, ''));\n const qsObject = {} as T;\n\n for (const [key, val] of sp.entries()) {\n const valFinal = parser ? parser(val, key, qsObject) : val;\n\n if (isNullish(valFinal)) continue;\n\n if (Object.hasOwn(qsObject, key)) {\n // @ts-expect-error\n if (!isArray(qsObject[key])) qsObject[key] = [qsObject[key]];\n (qsObject[key] as unknown[]).push(val);\n } else {\n // @ts-expect-error\n qsObject[key] = valFinal;\n }\n }\n\n return qsObject;\n}\n\n/**\n * 查询字符串序列化函数\n * @template T - 要序列化的对象类型\n * @callback QSWriter\n * @param {unknown} value - 要序列化的值\n * @param {string} key - 对象的键\n * @param {T} query - 当前序列化的对象\n * @returns {string | null} 序列化后的字符串,如果返回 null 则忽略该键值对\n * @example\n * const writer: QSWriter<MyObject> = (val, key) => {\n * if (val instanceof Date) return val.toISOString();\n * return String(val);\n * };\n */\nexport type QSWriter<T extends AnyObject = AnyObject> = (value: unknown, key: string, query: T) => string | null;\nconst defaultWriter: QSWriter<AnyObject> = (val: unknown) => {\n if (isString(val)) return val;\n if (isNumber(val)) return String(val);\n if (isBoolean(val)) return val ? 'true' : 'false';\n if (isDate(val)) return val.toISOString();\n return null;\n};\n\n/**\n * 将对象序列化为查询字符串\n * @template T - 要序列化的对象类型\n * @param {T} qsObject - 要序列化的对象\n * @param {QSWriter<T>} [stringify=defaultWriter] - 自定义序列化函数\n * @returns {string} 序列化后的查询字符串\n * @example\n * const str = qsStringify({ name: 'John', age: 30 });\n * // 'name=John&age=30'\n *\n * const str2 = qsStringify({ date: new Date('2023-01-01') });\n * // 'date=2023-01-01T00:00:00.000Z'\n */\nexport function qsStringify<T extends AnyObject>(qsObject: T, stringify: QSWriter<T> = defaultWriter): string {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams();\n const pushPairs = (val: unknown, key: string) => {\n const valFinal = stringify(val, String(key), qsObject);\n if (isNullish(valFinal)) return;\n\n sp.append(key, valFinal);\n };\n\n objectEach(qsObject, (val, key: string) => {\n if (isArray(val)) {\n for (const it of val) {\n pushPairs(it, key);\n }\n } else {\n pushPairs(val, key);\n }\n });\n\n return sp.toString();\n}\n"],"names":[],"mappings":";;AAoCgB,SAAA,QAA6B,aAAqB,QAAyB;AAGnF,QAAA,KAAK,IAAI,WAAW,gBAAgB,YAAY,QAAQ,SAAS,EAAE,CAAC;AAC1E,QAAM,WAAW,CAAC;AAElB,aAAW,CAAC,KAAK,GAAG,KAAK,GAAG,WAAW;AACrC,UAAM,WAAW,SAAS,OAAO,KAAK,KAAK,QAAQ,IAAI;AAEnD,QAAA,UAAU,QAAQ,EAAG;AAEzB,QAAI,OAAO,OAAO,UAAU,GAAG,GAAG;AAEhC,UAAI,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAY,UAAA,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC;AAC1D,eAAS,GAAG,EAAgB,KAAK,GAAG;AAAA,IAAA,OAChC;AAEL,eAAS,GAAG,IAAI;AAAA,IAAA;AAAA,EAClB;AAGK,SAAA;AACT;AAiBA,MAAM,gBAAqC,CAAC,QAAiB;AACvD,MAAA,SAAS,GAAG,EAAU,QAAA;AAC1B,MAAI,SAAS,GAAG,EAAG,QAAO,OAAO,GAAG;AACpC,MAAI,UAAU,GAAG,EAAG,QAAO,MAAM,SAAS;AAC1C,MAAI,OAAO,GAAG,EAAG,QAAO,IAAI,YAAY;AACjC,SAAA;AACT;AAegB,SAAA,YAAiC,UAAa,YAAyB,eAAuB;AAGtG,QAAA,KAAK,IAAI,WAAW,gBAAgB;AACpC,QAAA,YAAY,CAAC,KAAc,QAAgB;AAC/C,UAAM,WAAW,UAAU,KAAK,OAAO,GAAG,GAAG,QAAQ;AACjD,QAAA,UAAU,QAAQ,EAAG;AAEtB,OAAA,OAAO,KAAK,QAAQ;AAAA,EACzB;AAEW,aAAA,UAAU,CAAC,KAAK,QAAgB;AACrC,QAAA,QAAQ,GAAG,GAAG;AAChB,iBAAW,MAAM,KAAK;AACpB,kBAAU,IAAI,GAAG;AAAA,MAAA;AAAA,IACnB,OACK;AACL,gBAAU,KAAK,GAAG;AAAA,IAAA;AAAA,EACpB,CACD;AAED,SAAO,GAAG,SAAS;AACrB;"}
|
package/dist/types.d.ts
CHANGED
|
@@ -139,4 +139,17 @@ export type IsOnlyProperty<T, P> = keyof T extends P ? true : false;
|
|
|
139
139
|
* ```
|
|
140
140
|
*/
|
|
141
141
|
export type HasProperty<T, K> = K extends keyof T ? true : false;
|
|
142
|
+
/**
|
|
143
|
+
* 精确匹配类型
|
|
144
|
+
* @description 检查类型 T 是否精确匹配给定的形状 Shape。如果 T 包含 Shape 中不存在的额外属性,则不匹配。
|
|
145
|
+
* @template T - 要检查的类型
|
|
146
|
+
* @template Shape - 期望的形状/结构
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* type Result1 = Exact<{ a: 1 }, { a: 1 }>; // { a: 1 }
|
|
150
|
+
* type Result2 = Exact<{ a: 1; b: 2 }, { a: 1 }>; // never
|
|
151
|
+
* type Result3 = Exact<{ a: 1 }, { a: 1; b: 2 }>; // never
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export type Exact<T, Shape> = T extends Shape ? (Exclude<keyof T, keyof Shape> extends never ? T : never) : never;
|
|
142
155
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcome/utils-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "cloudcome core utils",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -104,10 +104,10 @@
|
|
|
104
104
|
"import": "./dist/promise.mjs",
|
|
105
105
|
"require": "./dist/promise.cjs"
|
|
106
106
|
},
|
|
107
|
-
"./
|
|
108
|
-
"types": "./dist/
|
|
109
|
-
"import": "./dist/
|
|
110
|
-
"require": "./dist/
|
|
107
|
+
"./qs": {
|
|
108
|
+
"types": "./dist/qs.d.ts",
|
|
109
|
+
"import": "./dist/qs.mjs",
|
|
110
|
+
"require": "./dist/qs.cjs"
|
|
111
111
|
},
|
|
112
112
|
"./regexp": {
|
|
113
113
|
"types": "./dist/regexp.d.ts",
|
|
@@ -221,8 +221,8 @@
|
|
|
221
221
|
"promise": [
|
|
222
222
|
"./dist/promise.d.ts"
|
|
223
223
|
],
|
|
224
|
-
"
|
|
225
|
-
"./dist/
|
|
224
|
+
"qs": [
|
|
225
|
+
"./dist/qs.d.ts"
|
|
226
226
|
],
|
|
227
227
|
"regexp": [
|
|
228
228
|
"./dist/regexp.d.ts"
|
package/dist/query.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.cjs","sources":["../src/query.ts"],"sourcesContent":["import { objectEach } from './object';\nimport { isArray, isBoolean, isDate, isNull, isNullish, isNumber, isString, isUndefined } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 查询字符串解析函数\n * @template T - 解析后返回的对象类型\n * @callback QSReader\n * @param {string} value - 查询字符串的值\n * @param {string} key - 查询字符串的键\n * @param {T} qsObject - 当前解析的对象\n * @returns {unknown} 解析后的值,如果返回 undefined 或 null 则不会添加到对象中\n * @example\n * const parser: QSReader<MyObject> = (value, key, obj) => {\n * if (key === 'date') return new Date(value);\n * return value;\n * };\n */\nexport type QSReader<T extends AnyObject> = (value: string, key: string, qsObject: T) => unknown;\n\n/**\n * 解析查询字符串为对象\n * @template T - 返回的对象类型\n * @param {string} queryString - 要解析的查询字符串\n * @param {QSReader<T>} [parser] - 自定义解析函数\n * @returns {T} 解析后的对象\n * @example\n * const obj = qsParse('name=John&age=30');\n * // { name: 'John', age: '30' }\n *\n * const obj2 = qsParse('date=2023-01-01', (val, key) => {\n * if (key === 'date') return new Date(val);\n * return val;\n * });\n * // { date: Date('2023-01-01') }\n */\nexport function qsParse<T extends AnyObject>(queryString: string, parser?: QSReader<T>): T {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams(queryString.replace(/^.*\\?/, ''));\n const qsObject = {} as T;\n\n for (const [key, val] of sp.entries()) {\n const valFinal = parser ? parser(val, key, qsObject) : val;\n\n if (isNullish(valFinal)) continue;\n\n if (Object.hasOwn(qsObject, key)) {\n // @ts-expect-error\n if (!isArray(qsObject[key])) qsObject[key] = [qsObject[key]];\n (qsObject[key] as unknown[]).push(val);\n } else {\n // @ts-expect-error\n qsObject[key] = valFinal;\n }\n }\n\n return qsObject;\n}\n\n/**\n * 查询字符串序列化函数\n * @template T - 要序列化的对象类型\n * @callback QSWriter\n * @param {unknown} value - 要序列化的值\n * @param {string} key - 对象的键\n * @param {T} query - 当前序列化的对象\n * @returns {string | null} 序列化后的字符串,如果返回 null 则忽略该键值对\n * @example\n * const writer: QSWriter<MyObject> = (val, key) => {\n * if (val instanceof Date) return val.toISOString();\n * return String(val);\n * };\n */\nexport type QSWriter<T extends AnyObject = AnyObject> = (value: unknown, key: string, query: T) => string | null;\nconst defaultWriter: QSWriter<AnyObject> = (val: unknown) => {\n if (isString(val)) return val;\n if (isNumber(val)) return String(val);\n if (isBoolean(val)) return val ? 'true' : 'false';\n if (isDate(val)) return val.toISOString();\n return null;\n};\n\n/**\n * 将对象序列化为查询字符串\n * @template T - 要序列化的对象类型\n * @param {T} qsObject - 要序列化的对象\n * @param {QSWriter<T>} [stringify=defaultWriter] - 自定义序列化函数\n * @returns {string} 序列化后的查询字符串\n * @example\n * const str = qsStringify({ name: 'John', age: 30 });\n * // 'name=John&age=30'\n *\n * const str2 = qsStringify({ date: new Date('2023-01-01') });\n * // 'date=2023-01-01T00:00:00.000Z'\n */\nexport function qsStringify<T extends AnyObject>(qsObject: T, stringify: QSWriter<T> = defaultWriter): string {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams();\n const pushPairs = (val: unknown, key: string) => {\n const valFinal = stringify(val, String(key), qsObject);\n if (isNullish(valFinal)) return;\n\n sp.append(key, valFinal);\n };\n\n objectEach(qsObject, (val, key: string) => {\n if (isArray(val)) {\n for (const it of val) {\n pushPairs(it, key);\n }\n } else {\n pushPairs(val, key);\n }\n });\n\n return sp.toString();\n}\n"],"names":["isNullish","isArray","isString","isNumber","isBoolean","isDate","objectEach"],"mappings":";;;;AAoCgB,SAAA,QAA6B,aAAqB,QAAyB;AAGnF,QAAA,KAAK,IAAI,WAAW,gBAAgB,YAAY,QAAQ,SAAS,EAAE,CAAC;AAC1E,QAAM,WAAW,CAAC;AAElB,aAAW,CAAC,KAAK,GAAG,KAAK,GAAG,WAAW;AACrC,UAAM,WAAW,SAAS,OAAO,KAAK,KAAK,QAAQ,IAAI;AAEnD,QAAAA,KAAAA,UAAU,QAAQ,EAAG;AAEzB,QAAI,OAAO,OAAO,UAAU,GAAG,GAAG;AAEhC,UAAI,CAACC,KAAA,QAAQ,SAAS,GAAG,CAAC,EAAY,UAAA,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC;AAC1D,eAAS,GAAG,EAAgB,KAAK,GAAG;AAAA,IAAA,OAChC;AAEL,eAAS,GAAG,IAAI;AAAA,IAAA;AAAA,EAClB;AAGK,SAAA;AACT;AAiBA,MAAM,gBAAqC,CAAC,QAAiB;AACvD,MAAAC,KAAA,SAAS,GAAG,EAAU,QAAA;AAC1B,MAAIC,KAAS,SAAA,GAAG,EAAG,QAAO,OAAO,GAAG;AACpC,MAAIC,KAAU,UAAA,GAAG,EAAG,QAAO,MAAM,SAAS;AAC1C,MAAIC,KAAO,OAAA,GAAG,EAAG,QAAO,IAAI,YAAY;AACjC,SAAA;AACT;AAegB,SAAA,YAAiC,UAAa,YAAyB,eAAuB;AAGtG,QAAA,KAAK,IAAI,WAAW,gBAAgB;AACpC,QAAA,YAAY,CAAC,KAAc,QAAgB;AAC/C,UAAM,WAAW,UAAU,KAAK,OAAO,GAAG,GAAG,QAAQ;AACjD,QAAAL,KAAAA,UAAU,QAAQ,EAAG;AAEtB,OAAA,OAAO,KAAK,QAAQ;AAAA,EACzB;AAEWM,OAAAA,WAAA,UAAU,CAAC,KAAK,QAAgB;AACrC,QAAAL,KAAAA,QAAQ,GAAG,GAAG;AAChB,iBAAW,MAAM,KAAK;AACpB,kBAAU,IAAI,GAAG;AAAA,MAAA;AAAA,IACnB,OACK;AACL,gBAAU,KAAK,GAAG;AAAA,IAAA;AAAA,EACpB,CACD;AAED,SAAO,GAAG,SAAS;AACrB;;;"}
|
package/dist/query.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.mjs","sources":["../src/query.ts"],"sourcesContent":["import { objectEach } from './object';\nimport { isArray, isBoolean, isDate, isNull, isNullish, isNumber, isString, isUndefined } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 查询字符串解析函数\n * @template T - 解析后返回的对象类型\n * @callback QSReader\n * @param {string} value - 查询字符串的值\n * @param {string} key - 查询字符串的键\n * @param {T} qsObject - 当前解析的对象\n * @returns {unknown} 解析后的值,如果返回 undefined 或 null 则不会添加到对象中\n * @example\n * const parser: QSReader<MyObject> = (value, key, obj) => {\n * if (key === 'date') return new Date(value);\n * return value;\n * };\n */\nexport type QSReader<T extends AnyObject> = (value: string, key: string, qsObject: T) => unknown;\n\n/**\n * 解析查询字符串为对象\n * @template T - 返回的对象类型\n * @param {string} queryString - 要解析的查询字符串\n * @param {QSReader<T>} [parser] - 自定义解析函数\n * @returns {T} 解析后的对象\n * @example\n * const obj = qsParse('name=John&age=30');\n * // { name: 'John', age: '30' }\n *\n * const obj2 = qsParse('date=2023-01-01', (val, key) => {\n * if (key === 'date') return new Date(val);\n * return val;\n * });\n * // { date: Date('2023-01-01') }\n */\nexport function qsParse<T extends AnyObject>(queryString: string, parser?: QSReader<T>): T {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams(queryString.replace(/^.*\\?/, ''));\n const qsObject = {} as T;\n\n for (const [key, val] of sp.entries()) {\n const valFinal = parser ? parser(val, key, qsObject) : val;\n\n if (isNullish(valFinal)) continue;\n\n if (Object.hasOwn(qsObject, key)) {\n // @ts-expect-error\n if (!isArray(qsObject[key])) qsObject[key] = [qsObject[key]];\n (qsObject[key] as unknown[]).push(val);\n } else {\n // @ts-expect-error\n qsObject[key] = valFinal;\n }\n }\n\n return qsObject;\n}\n\n/**\n * 查询字符串序列化函数\n * @template T - 要序列化的对象类型\n * @callback QSWriter\n * @param {unknown} value - 要序列化的值\n * @param {string} key - 对象的键\n * @param {T} query - 当前序列化的对象\n * @returns {string | null} 序列化后的字符串,如果返回 null 则忽略该键值对\n * @example\n * const writer: QSWriter<MyObject> = (val, key) => {\n * if (val instanceof Date) return val.toISOString();\n * return String(val);\n * };\n */\nexport type QSWriter<T extends AnyObject = AnyObject> = (value: unknown, key: string, query: T) => string | null;\nconst defaultWriter: QSWriter<AnyObject> = (val: unknown) => {\n if (isString(val)) return val;\n if (isNumber(val)) return String(val);\n if (isBoolean(val)) return val ? 'true' : 'false';\n if (isDate(val)) return val.toISOString();\n return null;\n};\n\n/**\n * 将对象序列化为查询字符串\n * @template T - 要序列化的对象类型\n * @param {T} qsObject - 要序列化的对象\n * @param {QSWriter<T>} [stringify=defaultWriter] - 自定义序列化函数\n * @returns {string} 序列化后的查询字符串\n * @example\n * const str = qsStringify({ name: 'John', age: 30 });\n * // 'name=John&age=30'\n *\n * const str2 = qsStringify({ date: new Date('2023-01-01') });\n * // 'date=2023-01-01T00:00:00.000Z'\n */\nexport function qsStringify<T extends AnyObject>(qsObject: T, stringify: QSWriter<T> = defaultWriter): string {\n // 添加 globalThis 是便于对接外部环境 URL 的自行实现\n // 例如在 uni-app、微信小程序等运行环境。\n const sp = new globalThis.URLSearchParams();\n const pushPairs = (val: unknown, key: string) => {\n const valFinal = stringify(val, String(key), qsObject);\n if (isNullish(valFinal)) return;\n\n sp.append(key, valFinal);\n };\n\n objectEach(qsObject, (val, key: string) => {\n if (isArray(val)) {\n for (const it of val) {\n pushPairs(it, key);\n }\n } else {\n pushPairs(val, key);\n }\n });\n\n return sp.toString();\n}\n"],"names":[],"mappings":";;AAoCgB,SAAA,QAA6B,aAAqB,QAAyB;AAGnF,QAAA,KAAK,IAAI,WAAW,gBAAgB,YAAY,QAAQ,SAAS,EAAE,CAAC;AAC1E,QAAM,WAAW,CAAC;AAElB,aAAW,CAAC,KAAK,GAAG,KAAK,GAAG,WAAW;AACrC,UAAM,WAAW,SAAS,OAAO,KAAK,KAAK,QAAQ,IAAI;AAEnD,QAAA,UAAU,QAAQ,EAAG;AAEzB,QAAI,OAAO,OAAO,UAAU,GAAG,GAAG;AAEhC,UAAI,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAY,UAAA,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC;AAC1D,eAAS,GAAG,EAAgB,KAAK,GAAG;AAAA,IAAA,OAChC;AAEL,eAAS,GAAG,IAAI;AAAA,IAAA;AAAA,EAClB;AAGK,SAAA;AACT;AAiBA,MAAM,gBAAqC,CAAC,QAAiB;AACvD,MAAA,SAAS,GAAG,EAAU,QAAA;AAC1B,MAAI,SAAS,GAAG,EAAG,QAAO,OAAO,GAAG;AACpC,MAAI,UAAU,GAAG,EAAG,QAAO,MAAM,SAAS;AAC1C,MAAI,OAAO,GAAG,EAAG,QAAO,IAAI,YAAY;AACjC,SAAA;AACT;AAegB,SAAA,YAAiC,UAAa,YAAyB,eAAuB;AAGtG,QAAA,KAAK,IAAI,WAAW,gBAAgB;AACpC,QAAA,YAAY,CAAC,KAAc,QAAgB;AAC/C,UAAM,WAAW,UAAU,KAAK,OAAO,GAAG,GAAG,QAAQ;AACjD,QAAA,UAAU,QAAQ,EAAG;AAEtB,OAAA,OAAO,KAAK,QAAQ;AAAA,EACzB;AAEW,aAAA,UAAU,CAAC,KAAK,QAAgB;AACrC,QAAA,QAAQ,GAAG,GAAG;AAChB,iBAAW,MAAM,KAAK;AACpB,kBAAU,IAAI,GAAG;AAAA,MAAA;AAAA,IACnB,OACK;AACL,gBAAU,KAAK,GAAG;AAAA,IAAA;AAAA,EACpB,CACD;AAED,SAAO,GAAG,SAAS;AACrB;"}
|
|
File without changes
|