fuma 0.2.6 → 0.3.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/dist/api/client.d.ts +3 -0
- package/dist/api/client.js +24 -0
- package/dist/api/config.d.ts +46 -0
- package/dist/api/config.js +7 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +3 -0
- package/dist/api/server.d.ts +11 -0
- package/dist/api/server.js +17 -0
- package/dist/{Meta.svelte → private/Meta.svelte} +4 -4
- package/dist/private/api.d.ts +61 -0
- package/dist/private/api.js +10 -0
- package/dist/private/constant.d.ts +14 -0
- package/dist/private/constant.js +6 -0
- package/dist/private/model.d.ts +78 -0
- package/dist/private/model.js +25 -0
- package/dist/server/auth.js +1 -1
- package/dist/server/parseFormData.js +21 -1
- package/dist/server/parseQuery.d.ts +1 -10
- package/dist/server/parseQuery.js +4 -5
- package/dist/server/try.js +0 -1
- package/dist/ui/drawer/Drawer.svelte +19 -11
- package/dist/ui/drawer/Drawer.svelte.d.ts +42 -7
- package/dist/ui/drawer/layers.d.ts +2 -1
- package/dist/ui/drawer/layers.js +5 -4
- package/dist/ui/form/Form.svelte +43 -24
- package/dist/ui/form/Form.svelte.d.ts +20 -12
- package/dist/ui/form/FormInput.svelte.d.ts +4 -0
- package/dist/ui/form/form.d.ts +20 -12
- package/dist/ui/form/form.js +34 -26
- package/dist/ui/form/formInput.d.ts +3 -1
- package/dist/ui/input/FormControl.svelte.d.ts +1 -1
- package/dist/ui/input/InputBoolean.svelte +4 -2
- package/dist/ui/input/InputBoolean.svelte.d.ts +2 -2
- package/dist/ui/input/InputCheckboxs.svelte.d.ts +2 -2
- package/dist/ui/input/InputCheckboxsMenu.svelte +5 -5
- package/dist/ui/input/InputCheckboxsMenu.svelte.d.ts +2 -2
- package/dist/ui/input/InputCombo.svelte.d.ts +2 -2
- package/dist/ui/input/InputDate.svelte +10 -7
- package/dist/ui/input/InputDate.svelte.d.ts +1 -1
- package/dist/ui/input/InputDatetime.svelte +24 -12
- package/dist/ui/input/InputDatetime.svelte.d.ts +2 -2
- package/dist/ui/input/InputNumber.svelte +12 -11
- package/dist/ui/input/InputNumber.svelte.d.ts +1 -1
- package/dist/ui/input/InputPassword.svelte.d.ts +2 -2
- package/dist/ui/input/InputRadio.svelte.d.ts +2 -2
- package/dist/ui/input/InputRelation.svelte +10 -3
- package/dist/ui/input/InputRelation.svelte.d.ts +2 -0
- package/dist/ui/input/InputRelations.svelte +10 -3
- package/dist/ui/input/InputRelations.svelte.d.ts +2 -0
- package/dist/ui/input/InputSelect.svelte +4 -2
- package/dist/ui/input/InputText.svelte.d.ts +2 -2
- package/dist/ui/input/textRich/InputTextRich.svelte.d.ts +1 -1
- package/dist/ui/input/textRich/extensions.js +1 -1
- package/dist/ui/input/types.d.ts +2 -2
- package/dist/ui/login/Login.svelte +7 -3
- package/dist/ui/table/field.d.ts +1 -1
- package/dist/ui/table/head/TableHeadNumber.svelte +1 -1
- package/dist/utils/constant.d.ts +4 -0
- package/dist/utils/constant.js +4 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/jsonParse.d.ts +1 -1
- package/dist/utils/jsonParse.js +5 -3
- package/dist/utils/options.d.ts +2 -1
- package/dist/validation/form.d.ts +6 -5
- package/dist/validation/form.js +8 -8
- package/dist/validation/zod.d.ts +109 -55
- package/dist/validation/zod.js +11 -31
- package/package.json +13 -3
- /package/dist/{Meta.svelte.d.ts → private/Meta.svelte.d.ts} +0 -0
- /package/dist/{server → private}/prisma.d.ts +0 -0
- /package/dist/{server → private}/prisma.js +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import axios, {} from 'axios';
|
|
2
|
+
import * as devalue from 'devalue';
|
|
3
|
+
export function useApiClient(prismaConfig, axiosConfig = {}) {
|
|
4
|
+
const _axios = axios.create({ baseURL: '/api', ...axiosConfig });
|
|
5
|
+
function useSearch(model) {
|
|
6
|
+
return async (search) => {
|
|
7
|
+
const config = { params: { search, model } };
|
|
8
|
+
const { data, headers } = await _axios.get('', config);
|
|
9
|
+
ensureJson(headers);
|
|
10
|
+
return devalue.unflatten(data);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const api = Object.keys(prismaConfig).reduce((acc, model) => ({
|
|
14
|
+
...acc,
|
|
15
|
+
[model]: useSearch(model)
|
|
16
|
+
}), {});
|
|
17
|
+
return api;
|
|
18
|
+
}
|
|
19
|
+
function ensureJson(headers) {
|
|
20
|
+
const contentType = headers['content-type'];
|
|
21
|
+
if (contentType !== 'application/json') {
|
|
22
|
+
throw new Error(`Response Content-type is '${contentType}' instead 'application/json'`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { OperationPayload, GetResult } from '@prisma/client/runtime/library.js';
|
|
2
|
+
export type Operation = 'findFirst' | 'findFirstOrThrow' | 'findUnique' | 'findUniqueOrThrow' | 'findMany' | 'create' | 'createMany' | 'update' | 'updateMany' | 'upsert' | 'delete' | 'deleteMany' | 'aggregate' | 'count' | 'groupBy';
|
|
3
|
+
export type TypeMap = {
|
|
4
|
+
model: {
|
|
5
|
+
[M: string]: {
|
|
6
|
+
payload: OperationPayload;
|
|
7
|
+
operations: {
|
|
8
|
+
[O in Operation]: {
|
|
9
|
+
args: {};
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export type Result<T extends TypeMap, M extends keyof T['model'], Query extends {}, Payload extends T['model'][M]['payload'] = T['model'][M]['payload']> = GetResult<Payload, Query, 'findMany'>;
|
|
16
|
+
export type Query<T extends TypeMap, M extends keyof T['model'], O extends Operation = 'findMany'> = T['model'][M]['operations'][O]['args'];
|
|
17
|
+
export type QueryToResult<T extends TypeMap, M extends keyof T['model'], O extends Operation = 'findMany', Q extends Query<T, M, O> = {}> = (query: Q) => Promise<Result<T, M, Q>>;
|
|
18
|
+
export type ApiPrismaClient<T extends TypeMap> = {
|
|
19
|
+
[M in keyof T['model']]: {
|
|
20
|
+
[O in Operation]: QueryToResult<T, M, O>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* @example
|
|
25
|
+
* const config = {
|
|
26
|
+
* user: (contains) => ({ where: { username: { contains } } }),
|
|
27
|
+
* } satisfies ApiConfig<Prisma.TypeMap>
|
|
28
|
+
*/
|
|
29
|
+
export type ApiConfig<T extends TypeMap> = {
|
|
30
|
+
[M in keyof T['model']]?: (search: string) => Query<T, M, 'findMany'>;
|
|
31
|
+
};
|
|
32
|
+
export type ApiClient<T extends TypeMap, C extends ApiConfig<T>> = {
|
|
33
|
+
[M in keyof C]: C[M] extends (...args: any) => infer Q ? (search: string) => Promise<Result<T, M & string, Q & {}>> : never;
|
|
34
|
+
};
|
|
35
|
+
export type ModelApiQuery = {
|
|
36
|
+
model: string;
|
|
37
|
+
search?: string;
|
|
38
|
+
take?: number;
|
|
39
|
+
skip?: number;
|
|
40
|
+
};
|
|
41
|
+
export declare const modelApiQuery: {
|
|
42
|
+
model: import("zod").ZodString;
|
|
43
|
+
search: import("zod").ZodDefault<import("zod").ZodString>;
|
|
44
|
+
take: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
45
|
+
skip: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
46
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RequestHandler } from '@sveltejs/kit';
|
|
2
|
+
import { type ApiConfig, type TypeMap } from './config.js';
|
|
3
|
+
interface BasicPrismaClient {
|
|
4
|
+
[K: string]: any;
|
|
5
|
+
$connect: any;
|
|
6
|
+
$transaction: any;
|
|
7
|
+
}
|
|
8
|
+
export declare function apiServer<T extends TypeMap>(config: ApiConfig<T>, client: BasicPrismaClient): {
|
|
9
|
+
GET: RequestHandler;
|
|
10
|
+
};
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { error } from '@sveltejs/kit';
|
|
2
|
+
import { json } from '../server/json.js';
|
|
3
|
+
import { parseQuery } from '../server/parseQuery.js';
|
|
4
|
+
import { modelApiQuery } from './config.js';
|
|
5
|
+
export function apiServer(config, client) {
|
|
6
|
+
return {
|
|
7
|
+
async GET(event) {
|
|
8
|
+
const { model, search, take, skip } = parseQuery(event.url, modelApiQuery);
|
|
9
|
+
if (!(model in config))
|
|
10
|
+
error(400, `Model "${model}" is not exposed in this API.`);
|
|
11
|
+
const baseQuery = { take, skip };
|
|
12
|
+
//@ts-ignore
|
|
13
|
+
const result = await client[model].findMany({ ...baseQuery, ...config[model](search) });
|
|
14
|
+
return json(result);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script>import {} from "svelte";
|
|
2
2
|
import { slide } from "svelte/transition";
|
|
3
3
|
import { mdiEyeOffOutline, mdiEyeOutline } from "@mdi/js";
|
|
4
|
-
import { Card } from "
|
|
5
|
-
import { Table } from "
|
|
6
|
-
import { Icon } from "
|
|
4
|
+
import { Card } from "../ui/card/index.js";
|
|
5
|
+
import { Table } from "../ui/table/index.js";
|
|
6
|
+
import { Icon } from "../ui/icon/index.js";
|
|
7
7
|
export let name = "";
|
|
8
8
|
export let description = "";
|
|
9
9
|
export let component;
|
|
@@ -27,7 +27,7 @@ function updateComponentMeta(c) {
|
|
|
27
27
|
}
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
|
-
<Card class="mx-auto
|
|
30
|
+
<Card class="mx-auto mb-6 max-w-4xl">
|
|
31
31
|
<div slot="title" class="flex items-center gap-4">
|
|
32
32
|
<span class="grow">{name}</span>
|
|
33
33
|
<button class="btn btn-square btn-sm" on:click={() => (isPropsVisible = !isPropsVisible)}>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Prisma } from '@prisma/client';
|
|
2
|
+
export declare const apiConfig: {
|
|
3
|
+
Tag: (search: string) => {
|
|
4
|
+
where: {
|
|
5
|
+
name: {
|
|
6
|
+
contains: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
Post: (search: string) => {
|
|
11
|
+
where: {
|
|
12
|
+
tags: {
|
|
13
|
+
some: {
|
|
14
|
+
name: {
|
|
15
|
+
contains: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
include: {
|
|
21
|
+
tags: true;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
PostType: (search: string) => {
|
|
25
|
+
where: {
|
|
26
|
+
name: {
|
|
27
|
+
contains: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export declare const api: import("../api/config.js").ApiClient<Prisma.TypeMap<import("@prisma/client/runtime/library").DefaultArgs>, {
|
|
33
|
+
Tag: (search: string) => {
|
|
34
|
+
where: {
|
|
35
|
+
name: {
|
|
36
|
+
contains: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
Post: (search: string) => {
|
|
41
|
+
where: {
|
|
42
|
+
tags: {
|
|
43
|
+
some: {
|
|
44
|
+
name: {
|
|
45
|
+
contains: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
include: {
|
|
51
|
+
tags: true;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
PostType: (search: string) => {
|
|
55
|
+
where: {
|
|
56
|
+
name: {
|
|
57
|
+
contains: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useApiClient } from '../api/client.js';
|
|
2
|
+
export const apiConfig = {
|
|
3
|
+
Tag: (search) => ({ where: { name: { contains: search } } }),
|
|
4
|
+
Post: (search) => ({
|
|
5
|
+
where: { tags: { some: { name: { contains: search } } } },
|
|
6
|
+
include: { tags: true }
|
|
7
|
+
}),
|
|
8
|
+
PostType: (search) => ({ where: { name: { contains: search } } })
|
|
9
|
+
};
|
|
10
|
+
export const api = useApiClient(apiConfig);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { mdiAccountGroup, mdiFileLockOutline, mdiWeb } from '@mdi/js';
|
|
2
|
+
export const POST_PUBLICATION = {
|
|
3
|
+
private: { label: 'Private', icon: mdiFileLockOutline },
|
|
4
|
+
friends: { label: 'Friends', icon: mdiAccountGroup },
|
|
5
|
+
public: { label: 'Public', icon: mdiWeb }
|
|
6
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export declare const modelPost: {
|
|
2
|
+
title: import("zod").ZodString;
|
|
3
|
+
content: import("zod").ZodString;
|
|
4
|
+
isFavourite: import("zod").ZodBoolean;
|
|
5
|
+
likeCount: import("zod").ZodNumber;
|
|
6
|
+
writingAt: import("zod").ZodDate;
|
|
7
|
+
writingDuration: import("zod").ZodDate;
|
|
8
|
+
isInteressing: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
9
|
+
viewCounter: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
10
|
+
publishedAt: import("zod").ZodOptional<import("zod").ZodDate>;
|
|
11
|
+
publishedAtTime: import("zod").ZodOptional<import("zod").ZodDate>;
|
|
12
|
+
publication: import("zod").ZodEnum<["private", "friends", "public"]>;
|
|
13
|
+
type: import("zod").ZodEffects<import("zod").ZodObject<{
|
|
14
|
+
id: import("zod").ZodString;
|
|
15
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
16
|
+
id: string;
|
|
17
|
+
}, {
|
|
18
|
+
id: string;
|
|
19
|
+
}>, {
|
|
20
|
+
connect: {
|
|
21
|
+
id: string;
|
|
22
|
+
};
|
|
23
|
+
}, {
|
|
24
|
+
id: string;
|
|
25
|
+
}>;
|
|
26
|
+
tags: import("zod").ZodEffects<import("zod").ZodArray<import("zod").ZodObject<{
|
|
27
|
+
id: import("zod").ZodString;
|
|
28
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
29
|
+
id: string;
|
|
30
|
+
}, {
|
|
31
|
+
id: string;
|
|
32
|
+
}>, "many">, Partial<Record<"set" | "delete" | "connect" | "disconnect", {
|
|
33
|
+
id: string;
|
|
34
|
+
}[]>>, {
|
|
35
|
+
id: string;
|
|
36
|
+
}[]>;
|
|
37
|
+
};
|
|
38
|
+
export declare const modelPostUpdate: {
|
|
39
|
+
id: import("zod").ZodString;
|
|
40
|
+
tags: import("zod").ZodEffects<import("zod").ZodArray<import("zod").ZodObject<{
|
|
41
|
+
id: import("zod").ZodString;
|
|
42
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
43
|
+
id: string;
|
|
44
|
+
}, {
|
|
45
|
+
id: string;
|
|
46
|
+
}>, "many">, Partial<Record<"set" | "delete" | "connect" | "disconnect", {
|
|
47
|
+
id: string;
|
|
48
|
+
}[]>>, {
|
|
49
|
+
id: string;
|
|
50
|
+
}[]>;
|
|
51
|
+
title: import("zod").ZodString;
|
|
52
|
+
content: import("zod").ZodString;
|
|
53
|
+
isFavourite: import("zod").ZodBoolean;
|
|
54
|
+
likeCount: import("zod").ZodNumber;
|
|
55
|
+
writingAt: import("zod").ZodDate;
|
|
56
|
+
writingDuration: import("zod").ZodDate;
|
|
57
|
+
isInteressing: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
58
|
+
viewCounter: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
59
|
+
publishedAt: import("zod").ZodOptional<import("zod").ZodDate>;
|
|
60
|
+
publishedAtTime: import("zod").ZodOptional<import("zod").ZodDate>;
|
|
61
|
+
publication: import("zod").ZodEnum<["private", "friends", "public"]>;
|
|
62
|
+
type: import("zod").ZodEffects<import("zod").ZodObject<{
|
|
63
|
+
id: import("zod").ZodString;
|
|
64
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
65
|
+
id: string;
|
|
66
|
+
}, {
|
|
67
|
+
id: string;
|
|
68
|
+
}>, {
|
|
69
|
+
connect: {
|
|
70
|
+
id: string;
|
|
71
|
+
};
|
|
72
|
+
}, {
|
|
73
|
+
id: string;
|
|
74
|
+
}>;
|
|
75
|
+
};
|
|
76
|
+
export declare const modelTag: {
|
|
77
|
+
name: import("zod").ZodString;
|
|
78
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { toTuple, z } from '../validation/zod.js';
|
|
2
|
+
import { POST_PUBLICATION } from './constant.js';
|
|
3
|
+
export const modelPost = {
|
|
4
|
+
title: z.string().min(1, 'Required'),
|
|
5
|
+
content: z.string().min(10),
|
|
6
|
+
isFavourite: z.boolean(),
|
|
7
|
+
likeCount: z.number(),
|
|
8
|
+
writingAt: z.date(),
|
|
9
|
+
writingDuration: z.date(),
|
|
10
|
+
isInteressing: z.boolean().optional(),
|
|
11
|
+
viewCounter: z.number().optional(),
|
|
12
|
+
publishedAt: z.date().optional(),
|
|
13
|
+
publishedAtTime: z.date().optional(),
|
|
14
|
+
publication: z.enum(toTuple(POST_PUBLICATION)),
|
|
15
|
+
type: z.relation.connect,
|
|
16
|
+
tags: z.relations.connect
|
|
17
|
+
};
|
|
18
|
+
export const modelPostUpdate = {
|
|
19
|
+
...modelPost,
|
|
20
|
+
id: z.string(),
|
|
21
|
+
tags: z.relations.set
|
|
22
|
+
};
|
|
23
|
+
export const modelTag = {
|
|
24
|
+
name: z.string().min(1, 'Required')
|
|
25
|
+
};
|
package/dist/server/auth.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Lucia } from 'lucia';
|
|
2
2
|
import { dev } from '$app/environment';
|
|
3
3
|
import { PrismaAdapter } from '@lucia-auth/adapter-prisma';
|
|
4
|
-
import { prisma } from '
|
|
4
|
+
import { prisma } from '../private/prisma.js';
|
|
5
5
|
const adapter = new PrismaAdapter(prisma.session, prisma.user);
|
|
6
6
|
export const lucia = new Lucia(adapter, {
|
|
7
7
|
sessionCookie: {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { USE_COERCE_BOOLEAN, USE_COERCE_DATE, USE_COERCE_JSON, USE_COERCE_NUMBER } from '../utils/constant.js';
|
|
2
|
+
import { jsonParse } from '../utils/jsonParse.js';
|
|
1
3
|
import z from 'zod';
|
|
2
4
|
export async function parseFormData(requestOrFormData, shapes, validation) {
|
|
3
5
|
const formData = requestOrFormData instanceof Request ? await requestOrFormData.formData() : requestOrFormData;
|
|
@@ -5,7 +7,8 @@ export async function parseFormData(requestOrFormData, shapes, validation) {
|
|
|
5
7
|
const shema = z.object(firstShap).superRefine(validation || (() => { }));
|
|
6
8
|
unionShaps.forEach((shap) => shema.or(z.object(shap)));
|
|
7
9
|
const formDataFlateObject = Object.fromEntries(formData);
|
|
8
|
-
const
|
|
10
|
+
const formDataFlateObjectCoerced = coerceFlateData(formDataFlateObject);
|
|
11
|
+
const formDataObject = flateToNeestedObject(formDataFlateObjectCoerced);
|
|
9
12
|
const parsed = shema.safeParse(formDataObject);
|
|
10
13
|
if (parsed.success === false) {
|
|
11
14
|
const issueToPOJO = (issue) => ({
|
|
@@ -21,6 +24,23 @@ export async function parseFormData(requestOrFormData, shapes, validation) {
|
|
|
21
24
|
}
|
|
22
25
|
return { data: parsed.data, formData };
|
|
23
26
|
}
|
|
27
|
+
function coerceFlateData(flateData) {
|
|
28
|
+
const coerceMap = {
|
|
29
|
+
[USE_COERCE_JSON]: (value) => jsonParse(value, {}),
|
|
30
|
+
[USE_COERCE_DATE]: (value) => (value ? new Date(value) : undefined),
|
|
31
|
+
[USE_COERCE_NUMBER]: (value) => (value === '' || value === null ? null : +value),
|
|
32
|
+
[USE_COERCE_BOOLEAN]: (value) => value === 'true'
|
|
33
|
+
};
|
|
34
|
+
function coerceValue(value) {
|
|
35
|
+
if (typeof value !== 'string')
|
|
36
|
+
return value;
|
|
37
|
+
const coerce = Object.entries(coerceMap).find(([TOKEN]) => value.startsWith(TOKEN));
|
|
38
|
+
if (!coerce)
|
|
39
|
+
return value;
|
|
40
|
+
return coerce[1](value.replace(coerce[0], ''));
|
|
41
|
+
}
|
|
42
|
+
return Object.entries(flateData).reduce((acc, [key, value]) => ({ ...acc, [key]: coerceValue(value) }), {});
|
|
43
|
+
}
|
|
24
44
|
function flateToNeestedObject(flatObject) {
|
|
25
45
|
const obj = {};
|
|
26
46
|
Object.entries(flatObject).forEach(([key, value]) => {
|
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
/// <reference types="@sveltejs/kit" />
|
|
2
1
|
import type { ZodRawShape } from 'zod';
|
|
3
|
-
export declare function parseQuery<Type extends ZodRawShape>(url: URL, shape: Type): {
|
|
4
|
-
err: import("@sveltejs/kit").ActionFailure<{
|
|
5
|
-
issues: import("zod").ZodIssue[];
|
|
6
|
-
}>;
|
|
7
|
-
data?: undefined;
|
|
8
|
-
} | {
|
|
9
|
-
data: { [k_1 in keyof import("zod").objectUtil.addQuestionMarks<import("zod").baseObjectOutputType<Type>, { [k in keyof import("zod").baseObjectOutputType<Type>]: undefined extends import("zod").baseObjectOutputType<Type>[k] ? never : k; }[keyof Type]>]: import("zod").objectUtil.addQuestionMarks<import("zod").baseObjectOutputType<Type>, { [k_2 in keyof import("zod").baseObjectOutputType<Type>]: undefined extends import("zod").baseObjectOutputType<Type>[k_2] ? never : k_2; }[keyof Type]>[k_1]; };
|
|
10
|
-
err?: undefined;
|
|
11
|
-
};
|
|
2
|
+
export declare function parseQuery<Type extends ZodRawShape>(url: URL, shape: Type): { [k_1 in keyof import("zod").objectUtil.addQuestionMarks<import("zod").baseObjectOutputType<Type>, { [k in keyof import("zod").baseObjectOutputType<Type>]: undefined extends import("zod").baseObjectOutputType<Type>[k] ? never : k; }[keyof Type]>]: import("zod").objectUtil.addQuestionMarks<import("zod").baseObjectOutputType<Type>, { [k_2 in keyof import("zod").baseObjectOutputType<Type>]: undefined extends import("zod").baseObjectOutputType<Type>[k_2] ? never : k_2; }[keyof Type]>[k_1]; };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { error } from '@sveltejs/kit';
|
|
2
2
|
import { z } from '../validation/zod.js';
|
|
3
3
|
export function parseQuery(url, shape) {
|
|
4
4
|
const queryRaw = {};
|
|
@@ -8,8 +8,7 @@ export function parseQuery(url, shape) {
|
|
|
8
8
|
queryRaw[name] = param;
|
|
9
9
|
});
|
|
10
10
|
const parsed = z.object(shape).safeParse(queryRaw);
|
|
11
|
-
if (parsed.success === false)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return { data: parsed.data };
|
|
11
|
+
if (parsed.success === false)
|
|
12
|
+
error(400, { message: parsed.error.message });
|
|
13
|
+
return parsed.data;
|
|
15
14
|
}
|
package/dist/server/try.js
CHANGED
|
@@ -8,19 +8,22 @@ import { subscibeDrawerLayers } from "./layers.js";
|
|
|
8
8
|
import { contextContainer } from "../context.js";
|
|
9
9
|
export let title = "";
|
|
10
10
|
export let key;
|
|
11
|
-
export let value = "1";
|
|
12
11
|
let klass = "";
|
|
13
12
|
export { klass as class };
|
|
14
13
|
export let maxWidth = "32rem";
|
|
15
14
|
export let classHeader = "";
|
|
16
15
|
export let classBody = "";
|
|
17
|
-
export function open() {
|
|
18
|
-
goto($urlParam.with({ [key]: value }), {
|
|
16
|
+
export function open(value = 1, options = {}) {
|
|
17
|
+
return goto($urlParam.with({ [key]: value }), {
|
|
18
|
+
...options,
|
|
19
|
+
replaceState: true,
|
|
20
|
+
noScroll: true
|
|
21
|
+
});
|
|
19
22
|
}
|
|
20
|
-
export function close() {
|
|
21
|
-
goto($urlParam.without(key), { replaceState: true, noScroll: true });
|
|
23
|
+
export function close(options = {}) {
|
|
24
|
+
return goto($urlParam.without(key), { ...options, replaceState: true, noScroll: true });
|
|
22
25
|
}
|
|
23
|
-
const { offset, destroy, isActive } = subscibeDrawerLayers(key
|
|
26
|
+
const { offset, index, destroy, isActive } = subscibeDrawerLayers(key);
|
|
24
27
|
onDestroy(destroy);
|
|
25
28
|
contextContainer.set("drawer");
|
|
26
29
|
</script>
|
|
@@ -28,15 +31,20 @@ contextContainer.set("drawer");
|
|
|
28
31
|
{#if $isActive}
|
|
29
32
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
30
33
|
<div
|
|
31
|
-
on:click={close}
|
|
32
|
-
on:keyup={close}
|
|
34
|
+
on:click={() => close()}
|
|
35
|
+
on:keyup={() => close()}
|
|
33
36
|
transition:fade={{ duration: 200 }}
|
|
34
|
-
|
|
37
|
+
style="z-index: {10 + $index};"
|
|
38
|
+
class="fixed inset-0 bg-black/15 backdrop-blur-[1.5px] dark:bg-white/15"
|
|
35
39
|
/>
|
|
36
40
|
|
|
37
41
|
<aside
|
|
38
42
|
transition:fly|local={{ x: 500, duration: 200, opacity: 1 }}
|
|
39
|
-
style="
|
|
43
|
+
style="
|
|
44
|
+
z-index: {10 + $index};
|
|
45
|
+
max-width: min(100%, {maxWidth});
|
|
46
|
+
transform: translateX({-$offset * 4}rem);
|
|
47
|
+
"
|
|
40
48
|
class="{klass}
|
|
41
49
|
fixed bottom-0 right-0 top-0 z-10 flex
|
|
42
50
|
w-full flex-col overflow-y-scroll bg-base-100
|
|
@@ -50,7 +58,7 @@ contextContainer.set("drawer");
|
|
|
50
58
|
"
|
|
51
59
|
>
|
|
52
60
|
<h2 class="title">{title}</h2>
|
|
53
|
-
<button on:click={close} class="btn btn-square btn-sm">
|
|
61
|
+
<button on:click={() => close()} class="btn btn-square btn-sm">
|
|
54
62
|
<Icon path={mdiClose} title="annuler" />
|
|
55
63
|
</button>
|
|
56
64
|
</div>
|
|
@@ -3,21 +3,44 @@ declare const __propDef: {
|
|
|
3
3
|
props: {
|
|
4
4
|
title?: string | undefined;
|
|
5
5
|
/** Key used in url query params */ key: string;
|
|
6
|
-
/** Value need to match in url query params*/ value?: string | undefined;
|
|
7
6
|
class?: string | undefined;
|
|
8
7
|
maxWidth?: string | undefined;
|
|
9
8
|
classHeader?: string | undefined;
|
|
10
9
|
classBody?: string | undefined;
|
|
11
|
-
open?: ((
|
|
12
|
-
|
|
10
|
+
open?: ((value?: number, options?: {
|
|
11
|
+
replaceState?: boolean | undefined;
|
|
12
|
+
noScroll?: boolean | undefined;
|
|
13
|
+
keepFocus?: boolean | undefined;
|
|
14
|
+
invalidateAll?: boolean | undefined;
|
|
15
|
+
state?: App.PageState | undefined;
|
|
16
|
+
} | undefined) => Promise<void>) | undefined;
|
|
17
|
+
close?: ((options?: {
|
|
18
|
+
replaceState?: boolean | undefined;
|
|
19
|
+
noScroll?: boolean | undefined;
|
|
20
|
+
keepFocus?: boolean | undefined;
|
|
21
|
+
invalidateAll?: boolean | undefined;
|
|
22
|
+
state?: App.PageState | undefined;
|
|
23
|
+
} | undefined) => Promise<void>) | undefined;
|
|
13
24
|
};
|
|
14
25
|
events: {
|
|
15
26
|
[evt: string]: CustomEvent<any>;
|
|
16
27
|
};
|
|
17
28
|
slots: {
|
|
18
29
|
default: {
|
|
19
|
-
open: (
|
|
20
|
-
|
|
30
|
+
open: (value?: number, options?: {
|
|
31
|
+
replaceState?: boolean | undefined;
|
|
32
|
+
noScroll?: boolean | undefined;
|
|
33
|
+
keepFocus?: boolean | undefined;
|
|
34
|
+
invalidateAll?: boolean | undefined;
|
|
35
|
+
state?: App.PageState | undefined;
|
|
36
|
+
} | undefined) => Promise<void>;
|
|
37
|
+
close: (options?: {
|
|
38
|
+
replaceState?: boolean | undefined;
|
|
39
|
+
noScroll?: boolean | undefined;
|
|
40
|
+
keepFocus?: boolean | undefined;
|
|
41
|
+
invalidateAll?: boolean | undefined;
|
|
42
|
+
state?: App.PageState | undefined;
|
|
43
|
+
} | undefined) => Promise<void>;
|
|
21
44
|
};
|
|
22
45
|
};
|
|
23
46
|
};
|
|
@@ -25,7 +48,19 @@ export type DrawerProps = typeof __propDef.props;
|
|
|
25
48
|
export type DrawerEvents = typeof __propDef.events;
|
|
26
49
|
export type DrawerSlots = typeof __propDef.slots;
|
|
27
50
|
export default class Drawer extends SvelteComponent<DrawerProps, DrawerEvents, DrawerSlots> {
|
|
28
|
-
get open(): (
|
|
29
|
-
|
|
51
|
+
get open(): (value?: number, options?: {
|
|
52
|
+
replaceState?: boolean | undefined;
|
|
53
|
+
noScroll?: boolean | undefined;
|
|
54
|
+
keepFocus?: boolean | undefined;
|
|
55
|
+
invalidateAll?: boolean | undefined;
|
|
56
|
+
state?: App.PageState | undefined;
|
|
57
|
+
} | undefined) => Promise<void>;
|
|
58
|
+
get close(): (options?: {
|
|
59
|
+
replaceState?: boolean | undefined;
|
|
60
|
+
noScroll?: boolean | undefined;
|
|
61
|
+
keepFocus?: boolean | undefined;
|
|
62
|
+
invalidateAll?: boolean | undefined;
|
|
63
|
+
state?: App.PageState | undefined;
|
|
64
|
+
} | undefined) => Promise<void>;
|
|
30
65
|
}
|
|
31
66
|
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="svelte" />
|
|
2
2
|
import { type Readable } from 'svelte/store';
|
|
3
|
-
export declare function subscibeDrawerLayers(key: string
|
|
3
|
+
export declare function subscibeDrawerLayers(key: string): {
|
|
4
4
|
isActive: Readable<boolean>;
|
|
5
|
+
index: Readable<number>;
|
|
5
6
|
offset: Readable<number>;
|
|
6
7
|
destroy(): void;
|
|
7
8
|
};
|
package/dist/ui/drawer/layers.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { derived,
|
|
1
|
+
import { derived, writable } from 'svelte/store';
|
|
2
2
|
import { page } from '$app/stores';
|
|
3
3
|
import { browser } from '$app/environment';
|
|
4
4
|
const layers = writable([]);
|
|
@@ -9,10 +9,10 @@ const layersOffset = derived(layers, ($layers) => {
|
|
|
9
9
|
return { ...acc, [layer]: drawerOffset };
|
|
10
10
|
}, {});
|
|
11
11
|
});
|
|
12
|
-
export function subscibeDrawerLayers(key
|
|
12
|
+
export function subscibeDrawerLayers(key) {
|
|
13
13
|
const layerId = Math.random().toString().slice(2, 12);
|
|
14
14
|
let isInitialized = false;
|
|
15
|
-
const isActive = derived(page, ({ url }) => url.searchParams.
|
|
15
|
+
const isActive = derived(page, ({ url }) => url.searchParams.has(key), false);
|
|
16
16
|
const isActiveUnsubscribe = isActive.subscribe(($isActive) => {
|
|
17
17
|
if ($isActive)
|
|
18
18
|
addLayer();
|
|
@@ -41,7 +41,8 @@ export function subscibeDrawerLayers(key, value) {
|
|
|
41
41
|
}
|
|
42
42
|
return {
|
|
43
43
|
isActive,
|
|
44
|
-
|
|
44
|
+
index: derived(layers, ($layers) => $layers.indexOf(layerId)),
|
|
45
|
+
offset: derived(layersOffset, (offsets) => offsets[layerId]),
|
|
45
46
|
destroy() {
|
|
46
47
|
removeLayer();
|
|
47
48
|
isActiveUnsubscribe();
|