use-l5 0.0.1
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 +117 -0
- package/dist/module.d.mts +12 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +39 -0
- package/dist/runtime/composables/useL5.d.ts +10 -0
- package/dist/runtime/composables/useL5.js +77 -0
- package/dist/runtime/constant/baseParams.const.d.ts +3 -0
- package/dist/runtime/constant/baseParams.const.js +18 -0
- package/dist/runtime/types/index.d.ts +33 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/runtime/utils/buildQueryForApi.d.ts +2 -0
- package/dist/runtime/utils/buildQueryForApi.js +45 -0
- package/dist/runtime/utils/buildQueryForUrl.d.ts +3 -0
- package/dist/runtime/utils/buildQueryForUrl.js +17 -0
- package/dist/runtime/utils/isEqualArray.d.ts +1 -0
- package/dist/runtime/utils/isEqualArray.js +8 -0
- package/dist/runtime/utils/parseFiltersFromQuery.d.ts +3 -0
- package/dist/runtime/utils/parseFiltersFromQuery.js +19 -0
- package/dist/runtime/utils/parseValueFromQuery.d.ts +3 -0
- package/dist/runtime/utils/parseValueFromQuery.js +34 -0
- package/dist/types.d.mts +5 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# use-l5
|
|
2
|
+
|
|
3
|
+
Nuxt-модуль с типизированным `useL5`-композаблом для парсинга фильтров, синхронизации с query в роуте и сборки параметров для API/URL.
|
|
4
|
+
|
|
5
|
+
## Возможности
|
|
6
|
+
|
|
7
|
+
- типизированная схема фильтров на основе конструкторов `String/Number/Boolean`
|
|
8
|
+
- двусторонняя синхронизация с `route.query` (опционально)
|
|
9
|
+
- генерация параметров для API и URL
|
|
10
|
+
- базовые параметры пагинации и сортировки
|
|
11
|
+
|
|
12
|
+
## Установка
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx nuxi module add use-l5
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
или
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add use-l5
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Настройка модуля
|
|
25
|
+
|
|
26
|
+
`nuxt.config.ts`:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
export default defineNuxtConfig({
|
|
30
|
+
modules: ['use-l5'],
|
|
31
|
+
useL5: {
|
|
32
|
+
syncWithRoute: true,
|
|
33
|
+
urlUpdateStrategy: 'replace',
|
|
34
|
+
boolToNumber: true
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Базовое использование
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { useL5 } from '#imports'
|
|
43
|
+
|
|
44
|
+
const schema = {
|
|
45
|
+
q: String,
|
|
46
|
+
category: [String],
|
|
47
|
+
inStock: Boolean,
|
|
48
|
+
price: Number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { filters, queryForApi, updateFilters, updateDefaults } = useL5(schema, {
|
|
52
|
+
defaults: {
|
|
53
|
+
category: [],
|
|
54
|
+
inStock: false
|
|
55
|
+
},
|
|
56
|
+
syncWithRoute: true,
|
|
57
|
+
urlUpdateStrategy: 'push'
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
updateFilters({ q: 'mac', category: ['laptops'] })
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Параметры `useL5`
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
interface Options<S> {
|
|
67
|
+
defaults?: Partial<InferFromL5Schema<S>>
|
|
68
|
+
syncWithRoute?: boolean
|
|
69
|
+
excludeFromSearch?: (keyof S)[]
|
|
70
|
+
apiIncludes?: string[]
|
|
71
|
+
excludeFromQueryBuilder?: (keyof S)[]
|
|
72
|
+
boolToNumber?: boolean
|
|
73
|
+
queryAliases?: Partial<Record<keyof S, string>>
|
|
74
|
+
transformInput?: (query: Partial<S>) => Partial<S>
|
|
75
|
+
transformOutput?: (filters: Filters<S>) => Record<keyof S & keyof BaseParams, unknown>
|
|
76
|
+
urlUpdateStrategy?: 'replace' | 'push'
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Базовые параметры (BaseParams)
|
|
81
|
+
|
|
82
|
+
Всегда доступны и участвуют в сборке запросов:
|
|
83
|
+
|
|
84
|
+
- `page` (по умолчанию 1)
|
|
85
|
+
- `limit` (по умолчанию 10)
|
|
86
|
+
- `sortedBy` (по умолчанию `id`)
|
|
87
|
+
- `orderBy` (по умолчанию `desc`)
|
|
88
|
+
- `searchJoin` (по умолчанию `and`)
|
|
89
|
+
- `searchFields` (по умолчанию `null`)
|
|
90
|
+
- `search` (по умолчанию `null`)
|
|
91
|
+
|
|
92
|
+
## Утилиты
|
|
93
|
+
|
|
94
|
+
Модуль автоматически добавляет импорты:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { buildQueryForApi, parseFiltersFromQuery } from '#imports'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- `buildQueryForApi(filters, options)` — сборка параметров для API
|
|
101
|
+
- `parseFiltersFromQuery(schema, query, { defaults })` — парсинг query в фильтры
|
|
102
|
+
|
|
103
|
+
## Возврат `useL5`
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
interface UseL5Return<S> {
|
|
107
|
+
filters: Ref<Filters<S>>
|
|
108
|
+
queryForApi: ShallowRef<Record<string, unknown>>
|
|
109
|
+
updateFilters: (newFilters: Partial<Filters<S>>, options?: { urlUpdateStrategy?: 'replace' | 'push' }) => void
|
|
110
|
+
updateDefaults: (newDefaults: Partial<InferFromL5Schema<S>>) => void
|
|
111
|
+
defaultsRef: Ref<Partial<InferFromL5Schema<S>>>
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Лицензия
|
|
116
|
+
|
|
117
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
export { BaseParams, Filters, InferFromL5Schema, InferL5, L5Node, Options, Primitive, SchemaDefinition } from '../dist/runtime/types/index.js';
|
|
3
|
+
|
|
4
|
+
interface ModuleOptions {
|
|
5
|
+
syncWithRoute?: boolean;
|
|
6
|
+
urlUpdateStrategy?: 'replace' | 'push';
|
|
7
|
+
boolToNumber?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
10
|
+
|
|
11
|
+
export { _default as default };
|
|
12
|
+
export type { ModuleOptions };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addImportsDir, addImports } from '@nuxt/kit';
|
|
2
|
+
|
|
3
|
+
const module$1 = defineNuxtModule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "use-l5",
|
|
6
|
+
configKey: "useL5",
|
|
7
|
+
compatibility: {
|
|
8
|
+
nuxt: ">=3.16"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
// Default configuration options of the Nuxt module
|
|
12
|
+
defaults: {},
|
|
13
|
+
setup(_options, _nuxt) {
|
|
14
|
+
const publicConfig = _nuxt.options.runtimeConfig.public ?? {};
|
|
15
|
+
const existing = publicConfig.useL5 ?? {};
|
|
16
|
+
const mergedOptions = {
|
|
17
|
+
...existing,
|
|
18
|
+
..._options
|
|
19
|
+
};
|
|
20
|
+
_nuxt.options.runtimeConfig.public = {
|
|
21
|
+
...publicConfig,
|
|
22
|
+
useL5: mergedOptions
|
|
23
|
+
};
|
|
24
|
+
const resolver = createResolver(import.meta.url);
|
|
25
|
+
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
26
|
+
addImports({
|
|
27
|
+
name: "buildQueryForApi",
|
|
28
|
+
as: "buildQueryForApi",
|
|
29
|
+
from: resolver.resolve("./runtime/utils/buildQueryForApi")
|
|
30
|
+
});
|
|
31
|
+
addImports({
|
|
32
|
+
name: "parseFiltersFromQuery",
|
|
33
|
+
as: "parseFiltersFromQuery",
|
|
34
|
+
from: resolver.resolve("./runtime/utils/parseFiltersFromQuery")
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { module$1 as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Ref, ShallowRef } from 'vue';
|
|
2
|
+
import type { Filters, InferFromL5Schema, Options, SchemaDefinition } from '../types/index.js';
|
|
3
|
+
export interface UseL5Return<S extends SchemaDefinition> {
|
|
4
|
+
filters: Ref<Filters<S>>;
|
|
5
|
+
queryForApi: ShallowRef<Record<string, unknown>>;
|
|
6
|
+
updateFilters: (newFilters: Partial<Filters<S>>, _options?: Partial<Pick<Options<S>, 'urlUpdateStrategy'>>) => void;
|
|
7
|
+
updateDefaults: (newDefaults: Partial<InferFromL5Schema<S>>) => void;
|
|
8
|
+
defaultsRef: Ref<Partial<InferFromL5Schema<S>>>;
|
|
9
|
+
}
|
|
10
|
+
export declare function useL5<S extends SchemaDefinition>(scheme: S, options?: Options<S>): UseL5Return<S>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shallowRef,
|
|
3
|
+
ref,
|
|
4
|
+
useRoute,
|
|
5
|
+
useRouter,
|
|
6
|
+
watch,
|
|
7
|
+
useRuntimeConfig
|
|
8
|
+
} from "#imports";
|
|
9
|
+
import { parseFiltersFromQuery } from "../utils/parseFiltersFromQuery.js";
|
|
10
|
+
import { buildQueryForApi } from "../utils/buildQueryForApi.js";
|
|
11
|
+
import { buildQueryForUrl } from "../utils/buildQueryForUrl.js";
|
|
12
|
+
export function useL5(scheme, options = {}) {
|
|
13
|
+
const config = useRuntimeConfig();
|
|
14
|
+
const moduleOptions = config.public?.useL5 ?? {};
|
|
15
|
+
const route = useRoute();
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const mergedOptions = { ...moduleOptions, ...options };
|
|
18
|
+
const { syncWithRoute = false, urlUpdateStrategy = "push" } = mergedOptions;
|
|
19
|
+
const defaultsRef = ref(mergedOptions.defaults ?? {});
|
|
20
|
+
const query = syncWithRoute ? route.query : {};
|
|
21
|
+
const filters = ref(
|
|
22
|
+
parseFiltersFromQuery(scheme, query, {
|
|
23
|
+
defaults: defaultsRef.value
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
const queryForApi = shallowRef(
|
|
27
|
+
buildQueryForApi(filters.value, mergedOptions)
|
|
28
|
+
);
|
|
29
|
+
function updateFilters(newFilters, _options = {}) {
|
|
30
|
+
const {
|
|
31
|
+
urlUpdateStrategy: localUrlUpdateStrategy = urlUpdateStrategy
|
|
32
|
+
} = _options;
|
|
33
|
+
for (const key in newFilters) {
|
|
34
|
+
filters.value[key] = newFilters[key];
|
|
35
|
+
}
|
|
36
|
+
if (!syncWithRoute) {
|
|
37
|
+
queryForApi.value = buildQueryForApi(filters.value, mergedOptions);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const query2 = buildQueryForUrl(filters.value, {
|
|
41
|
+
...mergedOptions,
|
|
42
|
+
defaults: defaultsRef.value
|
|
43
|
+
});
|
|
44
|
+
const method = localUrlUpdateStrategy === "replace" ? router.replace : router.push;
|
|
45
|
+
method.call(router, { query: query2 });
|
|
46
|
+
}
|
|
47
|
+
function updateDefaults(newDefaults) {
|
|
48
|
+
defaultsRef.value = {
|
|
49
|
+
...defaultsRef.value,
|
|
50
|
+
...newDefaults
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function startWatchingForRoute() {
|
|
54
|
+
watch(
|
|
55
|
+
() => route.query,
|
|
56
|
+
(newQuery) => {
|
|
57
|
+
filters.value = parseFiltersFromQuery(scheme, newQuery, {
|
|
58
|
+
defaults: defaultsRef.value
|
|
59
|
+
});
|
|
60
|
+
queryForApi.value = buildQueryForApi(
|
|
61
|
+
filters.value,
|
|
62
|
+
mergedOptions
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (syncWithRoute) {
|
|
68
|
+
startWatchingForRoute();
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
filters,
|
|
72
|
+
queryForApi,
|
|
73
|
+
updateFilters,
|
|
74
|
+
updateDefaults,
|
|
75
|
+
defaultsRef
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const BASE_PARAMS_DEFAULTS = {
|
|
2
|
+
page: 1,
|
|
3
|
+
limit: 10,
|
|
4
|
+
sortedBy: "id",
|
|
5
|
+
orderBy: "desc",
|
|
6
|
+
searchJoin: "and",
|
|
7
|
+
searchFields: null,
|
|
8
|
+
search: null
|
|
9
|
+
};
|
|
10
|
+
export const BASE_PARAMS_DEFAULTS_TYPE_MAP = {
|
|
11
|
+
page: Number,
|
|
12
|
+
limit: Number,
|
|
13
|
+
sortedBy: String,
|
|
14
|
+
orderBy: String,
|
|
15
|
+
searchJoin: String,
|
|
16
|
+
searchFields: String,
|
|
17
|
+
search: String
|
|
18
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type Primitive = string | number | boolean | null | undefined;
|
|
2
|
+
export type L5Node = StringConstructor | NumberConstructor | BooleanConstructor | [L5Node] | {
|
|
3
|
+
[k: string]: L5Node;
|
|
4
|
+
};
|
|
5
|
+
export type InferL5<T> = T extends StringConstructor ? string | null : T extends NumberConstructor ? number | null : T extends BooleanConstructor ? boolean : T extends [infer U] ? InferL5<U>[] : T extends Record<string, unknown> ? {
|
|
6
|
+
[K in keyof T]: InferL5<T[K]>;
|
|
7
|
+
} : never;
|
|
8
|
+
export type SchemaDefinition = Record<string, L5Node>;
|
|
9
|
+
export type InferFromL5Schema<S extends SchemaDefinition> = {
|
|
10
|
+
[K in keyof S]: InferL5<S[K]>;
|
|
11
|
+
};
|
|
12
|
+
export type Filters<S extends SchemaDefinition> = InferL5<S> & BaseParams;
|
|
13
|
+
export interface Options<S extends SchemaDefinition> {
|
|
14
|
+
defaults?: Partial<InferFromL5Schema<S>>;
|
|
15
|
+
syncWithRoute?: boolean;
|
|
16
|
+
excludeFromSearch?: (keyof S)[];
|
|
17
|
+
apiIncludes?: string[];
|
|
18
|
+
excludeFromQueryBuilder?: (keyof S)[];
|
|
19
|
+
boolToNumber?: boolean;
|
|
20
|
+
queryAliases?: Partial<Record<keyof S, string>>;
|
|
21
|
+
transformInput?: (query: Partial<S>) => Partial<S>;
|
|
22
|
+
transformOutput?: (filters: Filters<S>) => Record<keyof S & keyof BaseParams, unknown>;
|
|
23
|
+
urlUpdateStrategy?: 'replace' | 'push';
|
|
24
|
+
}
|
|
25
|
+
export interface BaseParams {
|
|
26
|
+
page: number;
|
|
27
|
+
limit: number;
|
|
28
|
+
sortedBy: string;
|
|
29
|
+
orderBy: string;
|
|
30
|
+
searchJoin: string;
|
|
31
|
+
searchFields: string | null;
|
|
32
|
+
search: string | null;
|
|
33
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BASE_PARAMS_DEFAULTS } from "../constant/baseParams.const.js";
|
|
2
|
+
import { pick } from "es-toolkit";
|
|
3
|
+
const BASE_PARAMS_KEYS = Object.keys(BASE_PARAMS_DEFAULTS);
|
|
4
|
+
export function buildQueryForApi(_filters, options) {
|
|
5
|
+
let filters = { ..._filters };
|
|
6
|
+
const result = pick(filters, BASE_PARAMS_KEYS);
|
|
7
|
+
const {
|
|
8
|
+
excludeFromSearch = [],
|
|
9
|
+
apiIncludes = [],
|
|
10
|
+
excludeFromQueryBuilder = [],
|
|
11
|
+
queryAliases,
|
|
12
|
+
transformOutput
|
|
13
|
+
} = options;
|
|
14
|
+
if (transformOutput) {
|
|
15
|
+
filters = transformOutput(_filters);
|
|
16
|
+
}
|
|
17
|
+
const allExcludeKeys = [...BASE_PARAMS_KEYS, ...excludeFromSearch];
|
|
18
|
+
if (options.boolToNumber) {
|
|
19
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
20
|
+
if (typeof value === "boolean") {
|
|
21
|
+
filters[key] = Number(value);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
allExcludeKeys.forEach((key) => {
|
|
26
|
+
const alias = queryAliases?.[key] ?? key;
|
|
27
|
+
result[alias] = filters[key];
|
|
28
|
+
});
|
|
29
|
+
result.search = Object.entries(filters).filter(([key, value]) => {
|
|
30
|
+
if (BASE_PARAMS_KEYS.includes(key)) return false;
|
|
31
|
+
if (excludeFromSearch.includes(key)) return false;
|
|
32
|
+
if (excludeFromQueryBuilder.includes(key)) return false;
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
return value.length > 0;
|
|
35
|
+
}
|
|
36
|
+
return value !== null;
|
|
37
|
+
}).map(([key, value]) => {
|
|
38
|
+
const alias = queryAliases?.[key] ?? key;
|
|
39
|
+
return `${alias}:${Array.isArray(value) ? value.join(",") : value}`;
|
|
40
|
+
}).join(";");
|
|
41
|
+
if (apiIncludes.length) {
|
|
42
|
+
result.include = apiIncludes.join(",");
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BASE_PARAMS_DEFAULTS } from "../constant/baseParams.const.js";
|
|
2
|
+
import { toMerged } from "es-toolkit/object";
|
|
3
|
+
import { isEqualArray } from "./isEqualArray.js";
|
|
4
|
+
export function buildQueryForUrl(filters, options) {
|
|
5
|
+
const defaults = toMerged(BASE_PARAMS_DEFAULTS, options.defaults ?? {});
|
|
6
|
+
return Object.entries(filters).filter(([key, value]) => {
|
|
7
|
+
if (value === null || value === void 0) return false;
|
|
8
|
+
const defaultValue = defaults?.[key];
|
|
9
|
+
if (Array.isArray(value) && Array.isArray(defaultValue)) {
|
|
10
|
+
return !isEqualArray(value, defaultValue);
|
|
11
|
+
}
|
|
12
|
+
return value !== defaultValue;
|
|
13
|
+
}).reduce((acc, [k, v]) => {
|
|
14
|
+
acc[k] = v;
|
|
15
|
+
return acc;
|
|
16
|
+
}, {});
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isEqualArray(first: unknown[], second: unknown[]): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { isEqual } from "es-toolkit/predicate";
|
|
2
|
+
export function isEqualArray(first, second) {
|
|
3
|
+
if (first === second) return true;
|
|
4
|
+
if (first.length !== second.length) return false;
|
|
5
|
+
const normalizedFirst = [...first].sort();
|
|
6
|
+
const normalizedSecond = [...second].sort();
|
|
7
|
+
return isEqual(normalizedFirst, normalizedSecond);
|
|
8
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Filters, SchemaDefinition, Options } from '../types/index.js';
|
|
2
|
+
import type { LocationQuery } from 'vue-router';
|
|
3
|
+
export declare function parseFiltersFromQuery<S extends SchemaDefinition>(scheme: S, query: LocationQuery, options: Required<Pick<Options<S>, 'defaults'>>): Filters<S>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { parseValueFromQuery } from "./parseValueFromQuery.js";
|
|
2
|
+
import { BASE_PARAMS_DEFAULTS, BASE_PARAMS_DEFAULTS_TYPE_MAP } from "../constant/baseParams.const.js";
|
|
3
|
+
export function parseFiltersFromQuery(scheme, query, options) {
|
|
4
|
+
const result = {};
|
|
5
|
+
Object.keys(scheme).forEach((key) => {
|
|
6
|
+
if (!scheme[key]) return;
|
|
7
|
+
let value = query[key];
|
|
8
|
+
value ??= options.defaults[key];
|
|
9
|
+
result[key] = parseValueFromQuery(value, scheme[key]);
|
|
10
|
+
});
|
|
11
|
+
for (const key in BASE_PARAMS_DEFAULTS_TYPE_MAP) {
|
|
12
|
+
const typedKey = key;
|
|
13
|
+
let value = query[typedKey];
|
|
14
|
+
value ??= options.defaults[key];
|
|
15
|
+
value ??= BASE_PARAMS_DEFAULTS[typedKey];
|
|
16
|
+
result[key] = parseValueFromQuery(value, BASE_PARAMS_DEFAULTS_TYPE_MAP[typedKey]);
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { L5Node, Primitive } from '../types/index.js';
|
|
2
|
+
import type { LocationQueryValue } from 'vue-router';
|
|
3
|
+
export declare function parseValueFromQuery(value: LocationQueryValue | LocationQueryValue[] | Primitive | Primitive[], node: L5Node): Primitive | Primitive[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function asArray(value) {
|
|
2
|
+
if (!value) return [];
|
|
3
|
+
if (Array.isArray(value)) return value;
|
|
4
|
+
return [value];
|
|
5
|
+
}
|
|
6
|
+
export function parseValueFromQuery(value, node) {
|
|
7
|
+
let isArray = false;
|
|
8
|
+
if (Array.isArray(node)) {
|
|
9
|
+
node = node[0];
|
|
10
|
+
isArray = true;
|
|
11
|
+
}
|
|
12
|
+
switch (node) {
|
|
13
|
+
case String:
|
|
14
|
+
if (isArray) {
|
|
15
|
+
return asArray(value).map((i) => String(i));
|
|
16
|
+
}
|
|
17
|
+
if (!value) return null;
|
|
18
|
+
return String(value);
|
|
19
|
+
case Number:
|
|
20
|
+
if (isArray) {
|
|
21
|
+
return asArray(value).map((i) => {
|
|
22
|
+
i = Number(i);
|
|
23
|
+
return Number.isNaN(i) ? null : i;
|
|
24
|
+
}).filter((i) => i);
|
|
25
|
+
}
|
|
26
|
+
if (!value) return null;
|
|
27
|
+
value = Number(value);
|
|
28
|
+
return Number.isNaN(value) ? null : value;
|
|
29
|
+
case Boolean:
|
|
30
|
+
if (!value) return false;
|
|
31
|
+
return ["1", "true"].includes(value.toString());
|
|
32
|
+
default:
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { type BaseParams, type Filters, type InferFromL5Schema, type InferL5, type L5Node, type Options, type Primitive, type SchemaDefinition } from '../dist/runtime/types/index.js'
|
|
2
|
+
|
|
3
|
+
export { default } from './module.mjs'
|
|
4
|
+
|
|
5
|
+
export { type ModuleOptions } from './module.mjs'
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "use-l5",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Nuxt-модуль с типизированным useL5-композаблом для парсинга фильтров, синхронизации с query в роуте и сборки параметров для API/URL",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Kirill Merkulov",
|
|
7
|
+
"url": "https://github.com/merkulovka"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/merkulovka/use-l5#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/merkulovka/use-l5.git"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/types.d.mts",
|
|
19
|
+
"import": "./dist/module.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./runtime/*": {
|
|
22
|
+
"types": "./dist/runtime/*",
|
|
23
|
+
"import": "./dist/runtime/*"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/module.mjs",
|
|
27
|
+
"typesVersions": {
|
|
28
|
+
"*": {
|
|
29
|
+
".": [
|
|
30
|
+
"./dist/types.d.mts"
|
|
31
|
+
],
|
|
32
|
+
"runtime/*": [
|
|
33
|
+
"./dist/runtime/*"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"prepack": "nuxt-module-build build",
|
|
42
|
+
"dev": "npm run dev:prepare && nuxi dev playground",
|
|
43
|
+
"dev:build": "nuxi build playground",
|
|
44
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
45
|
+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
46
|
+
"lint": "eslint .",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest watch",
|
|
49
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@nuxt/kit": "^4.2.1",
|
|
53
|
+
"es-toolkit": "^1.42.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@nuxt/devtools": "^3.1.0",
|
|
57
|
+
"@nuxt/eslint-config": "^1.10.0",
|
|
58
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
59
|
+
"@nuxt/schema": "^4.2.1",
|
|
60
|
+
"@nuxt/test-utils": "^3.20.1",
|
|
61
|
+
"@types/node": "latest",
|
|
62
|
+
"changelogen": "^0.6.2",
|
|
63
|
+
"eslint": "^9.39.1",
|
|
64
|
+
"nuxt": "^4.2.1",
|
|
65
|
+
"typescript": "~5.9.3",
|
|
66
|
+
"vitest": "^4.0.10",
|
|
67
|
+
"vue-tsc": "^3.1.4"
|
|
68
|
+
},
|
|
69
|
+
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
|
|
70
|
+
}
|