@fougere/svelte 0.9.3-alpha.0 → 0.11.0-alpha.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.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/useFormFor.d.ts +1 -1
- package/dist/useFormFor.d.ts.map +1 -1
- package/dist/useFormFor.js +6 -4
- package/dist/useFormFor.js.map +1 -1
- package/dist/useFougereData/CommandStore.d.ts +13 -0
- package/dist/useFougereData/CommandStore.d.ts.map +1 -0
- package/dist/useFougereData/CommandStore.js +27 -0
- package/dist/useFougereData/CommandStore.js.map +1 -0
- package/dist/useFougereData/QueryState.d.ts +11 -0
- package/dist/useFougereData/QueryState.d.ts.map +1 -0
- package/dist/useFougereData/QueryState.js +2 -0
- package/dist/useFougereData/QueryState.js.map +1 -0
- package/dist/useFougereData/QueryStore.d.ts +12 -0
- package/dist/useFougereData/QueryStore.d.ts.map +1 -0
- package/dist/useFougereData/QueryStore.js +37 -0
- package/dist/useFougereData/QueryStore.js.map +1 -0
- package/package.json +6 -5
- package/src/index.ts +4 -1
- package/src/useFormFor.ts +6 -4
- package/src/useFougereData/CommandStore.ts +38 -0
- package/src/useFougereData/QueryState.ts +11 -0
- package/src/useFougereData/QueryStore.ts +55 -0
- package/template/package.json +25 -0
- package/template/src/routes/+page.svelte +19 -0
- package/template/tsconfig.json +7 -0
- package/template/vite.config.ts +12 -0
- package/dist/useFougereData.d.ts +0 -30
- package/dist/useFougereData.d.ts.map +0 -1
- package/dist/useFougereData.js +0 -62
- package/dist/useFougereData.js.map +0 -1
- package/src/useFougereData.ts +0 -107
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** `@fougere/svelte` — the four primitives, in Svelte, for any host that renders it. */
|
|
2
|
-
export {
|
|
2
|
+
export { useCommand } from './useFougereData/CommandStore.js';
|
|
3
|
+
export { useQuery } from './useFougereData/QueryStore.js';
|
|
4
|
+
export { facade, facadeOf } from '@fougere/app/client';
|
|
3
5
|
export { useFormFor, type FormOptions } from './useFormFor.js';
|
|
4
6
|
export { useCurrentUser } from './useCurrentUser.js';
|
|
5
7
|
export { fetcher, CALL_ENDPOINT } from '@fougere/app/client';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE7D,YAAY,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** `@fougere/svelte` — the four primitives, in Svelte, for any host that renders it. */
|
|
2
|
-
export {
|
|
2
|
+
export { useCommand } from './useFougereData/CommandStore.js';
|
|
3
|
+
export { useQuery } from './useFougereData/QueryStore.js';
|
|
4
|
+
// The facade a page names, and the one an entity class names for a form.
|
|
5
|
+
export { facade, facadeOf } from '@fougere/app/client';
|
|
3
6
|
export { useFormFor } from './useFormFor.js';
|
|
4
7
|
export { useCurrentUser } from './useCurrentUser.js';
|
|
5
8
|
export { fetcher, CALL_ENDPOINT } from '@fougere/app/client';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,yEAAyE;AACzE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/useFormFor.d.ts
CHANGED
|
@@ -20,6 +20,6 @@ export declare function useFormFor<T = Record<string, unknown>>(entity: FormEnti
|
|
|
20
20
|
validator: () => boolean;
|
|
21
21
|
valid: Readable<boolean>;
|
|
22
22
|
/** `{ loading, error }` of the underlying command. */
|
|
23
|
-
command: import("./useFougereData.js").CommandStore<
|
|
23
|
+
command: import("./useFougereData/CommandStore.js").CommandStore<unknown, import("@fougere/core/contract").ErrorCode>;
|
|
24
24
|
};
|
|
25
25
|
//# sourceMappingURL=useFormFor.d.ts.map
|
package/dist/useFormFor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFor.d.ts","sourceRoot":"","sources":["../src/useFormFor.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAA0B,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEpF,OAAO,EAML,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,WAAgB;;
|
|
1
|
+
{"version":3,"file":"useFormFor.d.ts","sourceRoot":"","sources":["../src/useFormFor.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAA0B,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEpF,OAAO,EAML,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,WAAgB;;IAuCjG;kDAC8C;kBACkC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;;;kBApBlF,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;qBANpB,OAAO;;IAgC3B,sDAAsD;;EAGzD"}
|
package/dist/useFormFor.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** The form contract — state, validation, submission, error mapping. */
|
|
2
2
|
import { writable, derived, get } from 'svelte/store';
|
|
3
3
|
import { validationErrorsOf } from '@fougere/core/contract';
|
|
4
|
-
import { entityKeyOf, errorsByField, formFieldsOf, payloadOf, } from '@fougere/app/client';
|
|
5
|
-
import { useCommand } from './useFougereData.js';
|
|
4
|
+
import { entityKeyOf, facadeOf, errorsByField, formFieldsOf, payloadOf, } from '@fougere/app/client';
|
|
5
|
+
import { useCommand } from './useFougereData/CommandStore.js';
|
|
6
6
|
export function useFormFor(entity, options = {}) {
|
|
7
7
|
const entityKey = entityKeyOf(entity);
|
|
8
8
|
const fields = formFieldsOf(entity, entityKey);
|
|
@@ -10,7 +10,9 @@ export function useFormFor(entity, options = {}) {
|
|
|
10
10
|
// create form there is none, so the field opens on what is about to be written.
|
|
11
11
|
const values = writable(Object.fromEntries(fields.map((field) => [field.name, options.initial?.[field.name] ?? field.default])));
|
|
12
12
|
const errors = writable({});
|
|
13
|
-
|
|
13
|
+
// A form is designated by its ENTITY — it is a set of fields — so the facade it submits to is
|
|
14
|
+
// an address with no handler type behind it, and `T` stays the caller's to state.
|
|
15
|
+
const command = useCommand(facadeOf(entity), options.op ?? 'create');
|
|
14
16
|
/** Local pre-verdict — same rules as the handler, saves a lost round-trip. */
|
|
15
17
|
function validator() {
|
|
16
18
|
const result = entity.validate(payloadOf(get(values)));
|
|
@@ -21,7 +23,7 @@ export function useFormFor(entity, options = {}) {
|
|
|
21
23
|
if (!validator())
|
|
22
24
|
return null;
|
|
23
25
|
try {
|
|
24
|
-
return await command.execute({ params: options.params, input: payloadOf(get(values)) });
|
|
26
|
+
return (await command.execute({ params: options.params, input: payloadOf(get(values)) }));
|
|
25
27
|
}
|
|
26
28
|
catch (err) {
|
|
27
29
|
const refusals = validationErrorsOf(err);
|
package/dist/useFormFor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFor.js","sourceRoot":"","sources":["../src/useFormFor.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAgC,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"useFormFor.js","sourceRoot":"","sources":["../src/useFormFor.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAgC,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,SAAS,GAGV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAW9D,MAAM,UAAU,UAAU,CAA8B,MAAkB,EAAE,OAAO,GAAgB,EAAE;IACnG,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,MAAM,GAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE5D,8EAA8E;IAC9E,gFAAgF;IAChF,MAAM,MAAM,GAAsC,QAAQ,CACxD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACxG,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAyB,EAAE,CAAC,CAAC;IACpD,8FAA8F;IAC9F,kFAAkF;IAClF,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,QAAQ,CAAC,CAAC;IAErE,8EAA8E;IAC9E,SAAS,SAAS;QAChB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/D,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAM,CAAC;QACjG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAEjG,OAAO;QACL,MAAM;QACN;sDAC8C;QAC9C,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAA8B;QACzG,MAAM;QACN,MAAM;QACN,MAAM;QACN,SAAS;QACT,KAAK;QACL,sDAAsD;QACtD,OAAO;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { get, type Readable } from 'svelte/store';
|
|
2
|
+
import type { ErrorCode, FougereError } from '@fougere/core/contract';
|
|
3
|
+
import { type CallInput, type Answer, type Refused, type FacadeName } from '@fougere/app/client';
|
|
4
|
+
export interface CommandStore<T, Refused extends ErrorCode = ErrorCode> extends Readable<{
|
|
5
|
+
loading: boolean;
|
|
6
|
+
error: FougereError<Refused> | null;
|
|
7
|
+
}> {
|
|
8
|
+
execute(input?: CallInput): Promise<T>;
|
|
9
|
+
}
|
|
10
|
+
export declare function useCommand<Handler, Address extends string, Op extends keyof Handler & string>(facade: FacadeName<Handler, Address>, op: Op): CommandStore<Answer<Handler, Op>, Refused<Address, Op>>;
|
|
11
|
+
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
12
|
+
export { get };
|
|
13
|
+
//# sourceMappingURL=CommandStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandStore.d.ts","sourceRoot":"","sources":["../../src/useFougereData/CommandStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAA+F,KAAK,SAAS,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE9L,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,OAAO,SAAS,SAAS,GAAG,SAAS,CACpE,SAAQ,QAAQ,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxC;AAED,wBAAgB,UAAU,CACxB,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EACjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAqBvG;AAED,+EAA+E;AAC/E,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { writable, get } from 'svelte/store';
|
|
2
|
+
import { asFougereError, callOf, addressOf, fetcher, invocationOf, mountedKeys, revalidate, sendCall } from '@fougere/app/client';
|
|
3
|
+
export function useCommand(facade, op) {
|
|
4
|
+
const entityKey = addressOf(facade);
|
|
5
|
+
const store = writable({ loading: false, error: null });
|
|
6
|
+
return {
|
|
7
|
+
subscribe: store.subscribe,
|
|
8
|
+
async execute(input) {
|
|
9
|
+
store.set({ loading: true, error: null });
|
|
10
|
+
try {
|
|
11
|
+
const result = (await sendCall(fetcher, callOf(facade, op), invocationOf(input)));
|
|
12
|
+
// The link: same entity designated on both sides → revalidate its queries.
|
|
13
|
+
revalidate(mountedKeys(entityKey));
|
|
14
|
+
store.set({ loading: false, error: null });
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const failure = asFougereError(err, entityKey, op);
|
|
19
|
+
store.set({ loading: false, error: failure });
|
|
20
|
+
throw failure;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
26
|
+
export { get };
|
|
27
|
+
//# sourceMappingURL=CommandStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandStore.js","sourceRoot":"","sources":["../../src/useFougereData/CommandStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAiB,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAA8D,MAAM,qBAAqB,CAAC;AAO9L,MAAM,UAAU,UAAU,CAIxB,MAAoC,EAAE,EAAM;IAC5C,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAmD,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1G,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK,CAAC,OAAO,CAAC,KAAiB;YAC7B,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAwB,CAAC;gBACzG,2EAA2E;gBAC3E,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;gBACnC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3C,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;gBACnD,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9C,MAAM,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FougereError } from '@fougere/core/contract';
|
|
2
|
+
import { type Rows } from '@fougere/app/client';
|
|
3
|
+
export interface QueryState<Answered> {
|
|
4
|
+
data: Answered | null;
|
|
5
|
+
items: Rows<Answered>[];
|
|
6
|
+
total?: number;
|
|
7
|
+
hasMore?: boolean;
|
|
8
|
+
loading: boolean;
|
|
9
|
+
error: FougereError | null;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=QueryState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryState.d.ts","sourceRoot":"","sources":["../../src/useFougereData/QueryState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,WAAW,UAAU,CAAC,QAAQ;IAClC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryState.js","sourceRoot":"","sources":["../../src/useFougereData/QueryState.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Readable } from 'svelte/store';
|
|
2
|
+
import { type CallInput, type Answer, type FacadeName } from '@fougere/app/client';
|
|
3
|
+
import type { QueryState } from './QueryState.js';
|
|
4
|
+
export interface QueryStore<T> extends Readable<QueryState<T>> {
|
|
5
|
+
refresh(): Promise<void>;
|
|
6
|
+
/** Unregister from the link. Call it from `onDestroy` when a component unmounts. */
|
|
7
|
+
dispose(): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function useQuery<Handler, Address extends string, Op extends keyof Handler & string>(facade: FacadeName<Handler, Address>, op: Op, input?: CallInput, opts?: {
|
|
10
|
+
immediate?: boolean;
|
|
11
|
+
}): QueryStore<Answer<Handler, Op>>;
|
|
12
|
+
//# sourceMappingURL=QueryStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryStore.d.ts","sourceRoot":"","sources":["../../src/useFougereData/QueryStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAA0H,KAAK,SAAS,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAa,MAAM,qBAAqB,CAAC;AACtN,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,UAAU,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,oFAAoF;IACpF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,QAAQ,CACtB,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EAEjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EACpC,EAAE,EAAE,EAAE,EACN,KAAK,CAAC,EAAE,SAAS,EACjB,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAmCjC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { asFougereError, callOf, addressOf, fetcher, invocationOf, itemsOf, onRefetch, pageOf, queryKeyOf, sendCall, trackQuery } from '@fougere/app/client';
|
|
3
|
+
export function useQuery(facade, op, input, opts) {
|
|
4
|
+
const entityKey = addressOf(facade);
|
|
5
|
+
const key = queryKeyOf(entityKey, op, input);
|
|
6
|
+
const immediate = opts?.immediate !== false;
|
|
7
|
+
const store = writable({
|
|
8
|
+
data: null,
|
|
9
|
+
items: [],
|
|
10
|
+
loading: immediate,
|
|
11
|
+
error: null,
|
|
12
|
+
});
|
|
13
|
+
async function refresh() {
|
|
14
|
+
store.update((state) => ({ ...state, loading: true, error: null }));
|
|
15
|
+
try {
|
|
16
|
+
const data = (await sendCall(fetcher, callOf(facade, op), invocationOf(input)));
|
|
17
|
+
const page = pageOf(data);
|
|
18
|
+
store.set({ data, items: itemsOf(data), total: page.total, hasMore: page.hasMore, loading: false, error: null });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
store.update((state) => ({ ...state, loading: false, error: asFougereError(err, entityKey, op) }));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const untrack = trackQuery(entityKey, key);
|
|
25
|
+
const off = onRefetch(key, () => void refresh());
|
|
26
|
+
if (immediate)
|
|
27
|
+
void refresh();
|
|
28
|
+
return {
|
|
29
|
+
subscribe: store.subscribe,
|
|
30
|
+
refresh,
|
|
31
|
+
dispose() {
|
|
32
|
+
untrack();
|
|
33
|
+
off();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=QueryStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryStore.js","sourceRoot":"","sources":["../../src/useFougereData/QueryStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAiB,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAA2D,MAAM,qBAAqB,CAAC;AAStN,MAAM,UAAU,QAAQ,CAKtB,MAAoC,EACpC,EAAM,EACN,KAAiB,EACjB,IAA8B;IAE9B,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,KAAK,KAAK,CAAC;IAE5C,MAAM,KAAK,GAAG,QAAQ,CAAkC;QACtD,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,KAAK,UAAU,OAAO;QACpB,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAwB,CAAC;YACvG,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAA4B,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9I,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IACjD,IAAI,SAAS;QAAE,KAAK,OAAO,EAAE,CAAC;IAE9B,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO;QACP,OAAO;YACL,OAAO,EAAE,CAAC;YACV,GAAG,EAAE,CAAC;QACR,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0-alpha.0",
|
|
4
4
|
"description": "Fougere's four primitives as Svelte stores — host-independent.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -27,16 +27,17 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
-
"src"
|
|
30
|
+
"src",
|
|
31
|
+
"template"
|
|
31
32
|
],
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@fougere/app": "0.
|
|
34
|
-
"@fougere/core": "0.
|
|
34
|
+
"@fougere/app": "0.11.0-alpha.0",
|
|
35
|
+
"@fougere/core": "0.11.0-alpha.0"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"svelte": "^5.53.4",
|
|
38
39
|
"vitest": "^4.1.0",
|
|
39
|
-
"@fougere/schema": "0.
|
|
40
|
+
"@fougere/schema": "0.11.0-alpha.0"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"svelte": "^5.0.0"
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** `@fougere/svelte` — the four primitives, in Svelte, for any host that renders it. */
|
|
2
|
-
export {
|
|
2
|
+
export { useCommand } from './useFougereData/CommandStore.js';
|
|
3
|
+
export { useQuery } from './useFougereData/QueryStore.js';
|
|
4
|
+
// The facade a page names, and the one an entity class names for a form.
|
|
5
|
+
export { facade, facadeOf } from '@fougere/app/client';
|
|
3
6
|
export { useFormFor, type FormOptions } from './useFormFor.js';
|
|
4
7
|
export { useCurrentUser } from './useCurrentUser.js';
|
|
5
8
|
export { fetcher, CALL_ENDPOINT } from '@fougere/app/client';
|
package/src/useFormFor.ts
CHANGED
|
@@ -3,14 +3,14 @@ import { writable, derived, get, type Readable, type Writable } from 'svelte/sto
|
|
|
3
3
|
import { validationErrorsOf } from '@fougere/core/contract';
|
|
4
4
|
import {
|
|
5
5
|
entityKeyOf,
|
|
6
|
+
facadeOf,
|
|
6
7
|
errorsByField,
|
|
7
8
|
formFieldsOf,
|
|
8
9
|
payloadOf,
|
|
9
|
-
type EntityClass,
|
|
10
10
|
type FormEntity,
|
|
11
11
|
type FormField,
|
|
12
12
|
} from '@fougere/app/client';
|
|
13
|
-
import { useCommand } from './useFougereData.js';
|
|
13
|
+
import { useCommand } from './useFougereData/CommandStore.js';
|
|
14
14
|
|
|
15
15
|
export interface FormOptions {
|
|
16
16
|
/** Command the submit rides. Default: 'create'. */
|
|
@@ -31,7 +31,9 @@ export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, opti
|
|
|
31
31
|
Object.fromEntries(fields.map((field) => [field.name, options.initial?.[field.name] ?? field.default])),
|
|
32
32
|
);
|
|
33
33
|
const errors = writable<Record<string, string>>({});
|
|
34
|
-
|
|
34
|
+
// A form is designated by its ENTITY — it is a set of fields — so the facade it submits to is
|
|
35
|
+
// an address with no handler type behind it, and `T` stays the caller's to state.
|
|
36
|
+
const command = useCommand(facadeOf(entity), options.op ?? 'create');
|
|
35
37
|
|
|
36
38
|
/** Local pre-verdict — same rules as the handler, saves a lost round-trip. */
|
|
37
39
|
function validator(): boolean {
|
|
@@ -43,7 +45,7 @@ export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, opti
|
|
|
43
45
|
async function submit(): Promise<T | null> {
|
|
44
46
|
if (!validator()) return null;
|
|
45
47
|
try {
|
|
46
|
-
return await command.execute({ params: options.params, input: payloadOf(get(values)) });
|
|
48
|
+
return (await command.execute({ params: options.params, input: payloadOf(get(values)) })) as T;
|
|
47
49
|
} catch (err) {
|
|
48
50
|
const refusals = validationErrorsOf(err);
|
|
49
51
|
if (refusals) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { writable, get, type Readable } from 'svelte/store';
|
|
2
|
+
import type { ErrorCode, FougereError } from '@fougere/core/contract';
|
|
3
|
+
import { asFougereError, callOf, addressOf, fetcher, invocationOf, mountedKeys, revalidate, sendCall, type CallInput, type Answer, type Refused, type FacadeName } from '@fougere/app/client';
|
|
4
|
+
|
|
5
|
+
export interface CommandStore<T, Refused extends ErrorCode = ErrorCode>
|
|
6
|
+
extends Readable<{ loading: boolean; error: FougereError<Refused> | null }> {
|
|
7
|
+
execute(input?: CallInput): Promise<T>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function useCommand<
|
|
11
|
+
Handler,
|
|
12
|
+
Address extends string,
|
|
13
|
+
Op extends keyof Handler & string,
|
|
14
|
+
>(facade: FacadeName<Handler, Address>, op: Op): CommandStore<Answer<Handler, Op>, Refused<Address, Op>> {
|
|
15
|
+
const entityKey = addressOf(facade);
|
|
16
|
+
const store = writable<{ loading: boolean; error: FougereError | null }>({ loading: false, error: null });
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
subscribe: store.subscribe,
|
|
20
|
+
async execute(input?: CallInput): Promise<Answer<Handler, Op>> {
|
|
21
|
+
store.set({ loading: true, error: null });
|
|
22
|
+
try {
|
|
23
|
+
const result = (await sendCall(fetcher, callOf(facade, op), invocationOf(input))) as Answer<Handler, Op>;
|
|
24
|
+
// The link: same entity designated on both sides → revalidate its queries.
|
|
25
|
+
revalidate(mountedKeys(entityKey));
|
|
26
|
+
store.set({ loading: false, error: null });
|
|
27
|
+
return result;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
const failure = asFougereError(err, entityKey, op);
|
|
30
|
+
store.set({ loading: false, error: failure });
|
|
31
|
+
throw failure;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
38
|
+
export { get };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FougereError } from '@fougere/core/contract';
|
|
2
|
+
import { type Rows } from '@fougere/app/client';
|
|
3
|
+
|
|
4
|
+
export interface QueryState<Answered> {
|
|
5
|
+
data: Answered | null;
|
|
6
|
+
items: Rows<Answered>[];
|
|
7
|
+
total?: number;
|
|
8
|
+
hasMore?: boolean;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
error: FougereError | null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { writable, type Readable } from 'svelte/store';
|
|
2
|
+
import { asFougereError, callOf, addressOf, fetcher, invocationOf, itemsOf, onRefetch, pageOf, queryKeyOf, sendCall, trackQuery, type CallInput, type Answer, type FacadeName, type Rows } from '@fougere/app/client';
|
|
3
|
+
import type { QueryState } from './QueryState.js';
|
|
4
|
+
|
|
5
|
+
export interface QueryStore<T> extends Readable<QueryState<T>> {
|
|
6
|
+
refresh(): Promise<void>;
|
|
7
|
+
/** Unregister from the link. Call it from `onDestroy` when a component unmounts. */
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useQuery<
|
|
12
|
+
Handler,
|
|
13
|
+
Address extends string,
|
|
14
|
+
Op extends keyof Handler & string,
|
|
15
|
+
>(
|
|
16
|
+
facade: FacadeName<Handler, Address>,
|
|
17
|
+
op: Op,
|
|
18
|
+
input?: CallInput,
|
|
19
|
+
opts?: { immediate?: boolean },
|
|
20
|
+
): QueryStore<Answer<Handler, Op>> {
|
|
21
|
+
const entityKey = addressOf(facade);
|
|
22
|
+
const key = queryKeyOf(entityKey, op, input);
|
|
23
|
+
const immediate = opts?.immediate !== false;
|
|
24
|
+
|
|
25
|
+
const store = writable<QueryState<Answer<Handler, Op>>>({
|
|
26
|
+
data: null,
|
|
27
|
+
items: [],
|
|
28
|
+
loading: immediate,
|
|
29
|
+
error: null,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
async function refresh(): Promise<void> {
|
|
33
|
+
store.update((state) => ({ ...state, loading: true, error: null }));
|
|
34
|
+
try {
|
|
35
|
+
const data = (await sendCall(fetcher, callOf(facade, op), invocationOf(input))) as Answer<Handler, Op>;
|
|
36
|
+
const page = pageOf(data);
|
|
37
|
+
store.set({ data, items: itemsOf<Rows<Answer<Handler, Op>>>(data), total: page.total, hasMore: page.hasMore, loading: false, error: null });
|
|
38
|
+
} catch (err) {
|
|
39
|
+
store.update((state) => ({ ...state, loading: false, error: asFougereError(err, entityKey, op) }));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const untrack = trackQuery(entityKey, key);
|
|
44
|
+
const off = onRefetch(key, () => void refresh());
|
|
45
|
+
if (immediate) void refresh();
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
subscribe: store.subscribe,
|
|
49
|
+
refresh,
|
|
50
|
+
dispose() {
|
|
51
|
+
untrack();
|
|
52
|
+
off();
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fougere-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite dev",
|
|
7
|
+
"build": "vite build"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@fougere/core": "latest",
|
|
11
|
+
"@fougere/schema": "latest",
|
|
12
|
+
"@fougere/svelte": "latest",
|
|
13
|
+
"@fougere/defaults": "latest",
|
|
14
|
+
"@fougere/container": "latest",
|
|
15
|
+
"better-sqlite3": "^13.0.3",
|
|
16
|
+
"kysely": "^0.28.17"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@fougere/vite": "latest",
|
|
20
|
+
"@sveltejs/kit": "^2.0.0",
|
|
21
|
+
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
|
22
|
+
"svelte": "^5.0.0",
|
|
23
|
+
"vite": "^8.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy } from 'svelte';
|
|
3
|
+
import { useQuery } from '@fougere/svelte';
|
|
4
|
+
// Written by the scan: one export per address, carrying the handler that answers there.
|
|
5
|
+
// Replace `post` with a facade your own frond serves.
|
|
6
|
+
import { post } from '@fronds/facade';
|
|
7
|
+
|
|
8
|
+
const rows = useQuery(post, 'list');
|
|
9
|
+
onDestroy(() => rows.dispose());
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<main>
|
|
13
|
+
<h1>Fougere</h1>
|
|
14
|
+
{#if $rows.loading}<p>Loading…</p>{/if}
|
|
15
|
+
{#if $rows.error}<p style="color:#b00">{$rows.error.message}</p>{/if}
|
|
16
|
+
{#each $rows.items as row (row.id)}
|
|
17
|
+
<pre>{JSON.stringify(row, null, 2)}</pre>
|
|
18
|
+
{/each}
|
|
19
|
+
</main>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { fougere } from '@fougere/vite';
|
|
3
|
+
import { sveltekit } from '@sveltejs/kit/vite';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The same `fougere()` the React and TanStack starters use — it knows nothing about which
|
|
7
|
+
* host renders. It states the packages a boot loads at runtime, keeps class names through
|
|
8
|
+
* minification, and writes `@fronds/facade`.
|
|
9
|
+
*/
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
plugins: [fougere(), sveltekit()],
|
|
12
|
+
});
|
package/dist/useFougereData.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/** The couple — useQuery (reads) and useCommand (writes), in Svelte. */
|
|
2
|
-
import { get, type Readable } from 'svelte/store';
|
|
3
|
-
import type { FougereError } from '@fougere/core/contract';
|
|
4
|
-
import { type CallInput, type EntityClass } from '@fougere/app/client';
|
|
5
|
-
export interface QueryState<T> {
|
|
6
|
-
data: T | null;
|
|
7
|
-
items: T[];
|
|
8
|
-
total?: number;
|
|
9
|
-
hasMore?: boolean;
|
|
10
|
-
loading: boolean;
|
|
11
|
-
error: FougereError | null;
|
|
12
|
-
}
|
|
13
|
-
export interface QueryStore<T> extends Readable<QueryState<T>> {
|
|
14
|
-
refresh(): Promise<void>;
|
|
15
|
-
/** Unregister from the link. Call it from `onDestroy` when a component unmounts. */
|
|
16
|
-
dispose(): void;
|
|
17
|
-
}
|
|
18
|
-
export declare function useQuery<T = Record<string, unknown>>(entity: EntityClass, op: string, input?: CallInput, opts?: {
|
|
19
|
-
immediate?: boolean;
|
|
20
|
-
}): QueryStore<T>;
|
|
21
|
-
export interface CommandStore<T> extends Readable<{
|
|
22
|
-
loading: boolean;
|
|
23
|
-
error: FougereError | null;
|
|
24
|
-
}> {
|
|
25
|
-
execute(input?: CallInput): Promise<T>;
|
|
26
|
-
}
|
|
27
|
-
export declare function useCommand<T = unknown>(entity: EntityClass, op: string): CommandStore<T>;
|
|
28
|
-
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
29
|
-
export { get };
|
|
30
|
-
//# sourceMappingURL=useFougereData.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useFougereData.d.ts","sourceRoot":"","sources":["../src/useFougereData.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAY,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAcL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,oFAAoF;IACpF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClD,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,CAAC,EAAE,SAAS,EACjB,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,UAAU,CAAC,CAAC,CAAC,CAmCf;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,CAAC;IACjG,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxC;AAED,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAqBxF;AAED,+EAA+E;AAC/E,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/useFougereData.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/** The couple — useQuery (reads) and useCommand (writes), in Svelte. */
|
|
2
|
-
import { writable, get } from 'svelte/store';
|
|
3
|
-
import { asFougereError, callOf, entityKeyOf, fetcher, invocationOf, itemsOf, mountedKeys, onRefetch, pageOf, queryKeyOf, revalidate, sendCall, trackQuery, } from '@fougere/app/client';
|
|
4
|
-
export function useQuery(entity, op, input, opts) {
|
|
5
|
-
const entityKey = entityKeyOf(entity);
|
|
6
|
-
const key = queryKeyOf(entityKey, op, input);
|
|
7
|
-
const immediate = opts?.immediate !== false;
|
|
8
|
-
const store = writable({
|
|
9
|
-
data: null,
|
|
10
|
-
items: [],
|
|
11
|
-
loading: immediate,
|
|
12
|
-
error: null,
|
|
13
|
-
});
|
|
14
|
-
async function refresh() {
|
|
15
|
-
store.update((state) => ({ ...state, loading: true, error: null }));
|
|
16
|
-
try {
|
|
17
|
-
const data = (await sendCall(fetcher, callOf(entity, op), invocationOf(input)));
|
|
18
|
-
const page = pageOf(data);
|
|
19
|
-
store.set({ data, items: itemsOf(data), total: page.total, hasMore: page.hasMore, loading: false, error: null });
|
|
20
|
-
}
|
|
21
|
-
catch (err) {
|
|
22
|
-
store.update((state) => ({ ...state, loading: false, error: asFougereError(err, entityKey, op) }));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const untrack = trackQuery(entityKey, key);
|
|
26
|
-
const off = onRefetch(key, () => void refresh());
|
|
27
|
-
if (immediate)
|
|
28
|
-
void refresh();
|
|
29
|
-
return {
|
|
30
|
-
subscribe: store.subscribe,
|
|
31
|
-
refresh,
|
|
32
|
-
dispose() {
|
|
33
|
-
untrack();
|
|
34
|
-
off();
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
export function useCommand(entity, op) {
|
|
39
|
-
const entityKey = entityKeyOf(entity);
|
|
40
|
-
const store = writable({ loading: false, error: null });
|
|
41
|
-
return {
|
|
42
|
-
subscribe: store.subscribe,
|
|
43
|
-
async execute(input) {
|
|
44
|
-
store.set({ loading: true, error: null });
|
|
45
|
-
try {
|
|
46
|
-
const result = (await sendCall(fetcher, callOf(entity, op), invocationOf(input)));
|
|
47
|
-
// The link: same entity designated on both sides → revalidate its queries.
|
|
48
|
-
revalidate(mountedKeys(entityKey));
|
|
49
|
-
store.set({ loading: false, error: null });
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
const failure = asFougereError(err, entityKey, op);
|
|
54
|
-
store.set({ loading: false, error: failure });
|
|
55
|
-
throw failure;
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
61
|
-
export { get };
|
|
62
|
-
//# sourceMappingURL=useFougereData.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useFougereData.js","sourceRoot":"","sources":["../src/useFougereData.ts"],"names":[],"mappings":"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"}
|
package/src/useFougereData.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/** The couple — useQuery (reads) and useCommand (writes), in Svelte. */
|
|
2
|
-
import { writable, get, type Readable } from 'svelte/store';
|
|
3
|
-
import type { FougereError } from '@fougere/core/contract';
|
|
4
|
-
import {
|
|
5
|
-
asFougereError,
|
|
6
|
-
callOf,
|
|
7
|
-
entityKeyOf,
|
|
8
|
-
fetcher,
|
|
9
|
-
invocationOf,
|
|
10
|
-
itemsOf,
|
|
11
|
-
mountedKeys,
|
|
12
|
-
onRefetch,
|
|
13
|
-
pageOf,
|
|
14
|
-
queryKeyOf,
|
|
15
|
-
revalidate,
|
|
16
|
-
sendCall,
|
|
17
|
-
trackQuery,
|
|
18
|
-
type CallInput,
|
|
19
|
-
type EntityClass,
|
|
20
|
-
} from '@fougere/app/client';
|
|
21
|
-
|
|
22
|
-
export interface QueryState<T> {
|
|
23
|
-
data: T | null;
|
|
24
|
-
items: T[];
|
|
25
|
-
total?: number;
|
|
26
|
-
hasMore?: boolean;
|
|
27
|
-
loading: boolean;
|
|
28
|
-
error: FougereError | null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface QueryStore<T> extends Readable<QueryState<T>> {
|
|
32
|
-
refresh(): Promise<void>;
|
|
33
|
-
/** Unregister from the link. Call it from `onDestroy` when a component unmounts. */
|
|
34
|
-
dispose(): void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function useQuery<T = Record<string, unknown>>(
|
|
38
|
-
entity: EntityClass,
|
|
39
|
-
op: string,
|
|
40
|
-
input?: CallInput,
|
|
41
|
-
opts?: { immediate?: boolean },
|
|
42
|
-
): QueryStore<T> {
|
|
43
|
-
const entityKey = entityKeyOf(entity);
|
|
44
|
-
const key = queryKeyOf(entityKey, op, input);
|
|
45
|
-
const immediate = opts?.immediate !== false;
|
|
46
|
-
|
|
47
|
-
const store = writable<QueryState<T>>({
|
|
48
|
-
data: null,
|
|
49
|
-
items: [],
|
|
50
|
-
loading: immediate,
|
|
51
|
-
error: null,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
async function refresh(): Promise<void> {
|
|
55
|
-
store.update((state) => ({ ...state, loading: true, error: null }));
|
|
56
|
-
try {
|
|
57
|
-
const data = (await sendCall(fetcher, callOf(entity, op), invocationOf(input))) as T;
|
|
58
|
-
const page = pageOf(data);
|
|
59
|
-
store.set({ data, items: itemsOf<T>(data), total: page.total, hasMore: page.hasMore, loading: false, error: null });
|
|
60
|
-
} catch (err) {
|
|
61
|
-
store.update((state) => ({ ...state, loading: false, error: asFougereError(err, entityKey, op) }));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const untrack = trackQuery(entityKey, key);
|
|
66
|
-
const off = onRefetch(key, () => void refresh());
|
|
67
|
-
if (immediate) void refresh();
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
subscribe: store.subscribe,
|
|
71
|
-
refresh,
|
|
72
|
-
dispose() {
|
|
73
|
-
untrack();
|
|
74
|
-
off();
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface CommandStore<T> extends Readable<{ loading: boolean; error: FougereError | null }> {
|
|
80
|
-
execute(input?: CallInput): Promise<T>;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function useCommand<T = unknown>(entity: EntityClass, op: string): CommandStore<T> {
|
|
84
|
-
const entityKey = entityKeyOf(entity);
|
|
85
|
-
const store = writable<{ loading: boolean; error: FougereError | null }>({ loading: false, error: null });
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
subscribe: store.subscribe,
|
|
89
|
-
async execute(input?: CallInput): Promise<T> {
|
|
90
|
-
store.set({ loading: true, error: null });
|
|
91
|
-
try {
|
|
92
|
-
const result = (await sendCall(fetcher, callOf(entity, op), invocationOf(input))) as T;
|
|
93
|
-
// The link: same entity designated on both sides → revalidate its queries.
|
|
94
|
-
revalidate(mountedKeys(entityKey));
|
|
95
|
-
store.set({ loading: false, error: null });
|
|
96
|
-
return result;
|
|
97
|
-
} catch (err) {
|
|
98
|
-
const failure = asFougereError(err, entityKey, op);
|
|
99
|
-
store.set({ loading: false, error: failure });
|
|
100
|
-
throw failure;
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** Read a store's current value without subscribing — used by `useFormFor`. */
|
|
107
|
-
export { get };
|