@svadmin/core 0.50.0 → 0.53.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.
Files changed (98) hide show
  1. package/package.json +21 -4
  2. package/src/access-control-contract.ts +250 -0
  3. package/src/adapters/casbin.ts +20 -14
  4. package/src/adapters/casl.ts +22 -19
  5. package/src/admin-tool.ts +7 -7
  6. package/src/audit-contract.ts +105 -0
  7. package/src/audit.ts +88 -128
  8. package/src/auth-hooks.svelte.ts +593 -261
  9. package/src/auth-mutation-contract.ts +143 -0
  10. package/src/auth-query-contract.ts +97 -0
  11. package/src/captured-mutation.svelte.ts +45 -0
  12. package/src/chatProvider.svelte.ts +1 -1
  13. package/src/command-contract.ts +195 -0
  14. package/src/context.svelte.ts +217 -205
  15. package/src/contract-context.svelte.ts +37 -0
  16. package/src/contract-form.svelte.ts +566 -0
  17. package/src/create-contract.ts +56 -0
  18. package/src/create-hooks.svelte.ts +347 -0
  19. package/src/create-many-contract.ts +90 -0
  20. package/src/create-many-hooks.svelte.ts +396 -0
  21. package/src/data-transfer.svelte.ts +1 -215
  22. package/src/defined-options.ts +50 -0
  23. package/src/delete-contract.ts +50 -0
  24. package/src/delete-hooks.svelte.ts +403 -0
  25. package/src/delete-many-contract.ts +60 -0
  26. package/src/delete-many-hooks.svelte.ts +402 -0
  27. package/src/enterprise.ts +4 -4
  28. package/src/export-format.ts +16 -14
  29. package/src/export-hooks.svelte.ts +191 -0
  30. package/src/feature-gate-contract.ts +53 -0
  31. package/src/hook-utils.svelte.ts +53 -105
  32. package/src/hooks.svelte.ts +19 -776
  33. package/src/http.ts +88 -87
  34. package/src/i18n.svelte.ts +64 -2
  35. package/src/import-contract.ts +106 -0
  36. package/src/import-hooks.svelte.ts +310 -0
  37. package/src/index.ts +77 -30
  38. package/src/inferencer-graphql.ts +7 -6
  39. package/src/inferencer.ts +9 -0
  40. package/src/infinite-query.svelte.ts +228 -0
  41. package/src/invalidation-contract.ts +26 -0
  42. package/src/live-sse.ts +91 -127
  43. package/src/live-subscription.svelte.ts +130 -0
  44. package/src/live-transport.ts +127 -0
  45. package/src/live-websocket.ts +85 -118
  46. package/src/live.svelte.ts +66 -68
  47. package/src/notification.svelte.ts +17 -15
  48. package/src/permission-catalog.ts +121 -0
  49. package/src/permission-hints-contract.ts +48 -0
  50. package/src/permissions.svelte.ts +112 -59
  51. package/src/plain-data.ts +61 -0
  52. package/src/provider-bundle.ts +85 -79
  53. package/src/provider-response.ts +35 -0
  54. package/src/query-hooks.svelte.ts +241 -288
  55. package/src/query-invalidation.ts +172 -0
  56. package/src/query-keys.ts +221 -110
  57. package/src/query-session.svelte.ts +220 -0
  58. package/src/query-snapshot.ts +144 -0
  59. package/src/reactive-projection.ts +53 -0
  60. package/src/record-decoder.ts +63 -0
  61. package/src/resource-binding.svelte.ts +19 -0
  62. package/src/resource-contract.ts +595 -0
  63. package/src/resource-mutation-types.ts +30 -0
  64. package/src/resource-schemas.ts +371 -0
  65. package/src/resource-transport-config.ts +156 -0
  66. package/src/route-parsing.ts +11 -11
  67. package/src/router-provider.ts +64 -59
  68. package/src/router.ts +8 -3
  69. package/src/routing-hooks.svelte.ts +90 -62
  70. package/src/schema-validation.ts +92 -0
  71. package/src/schema.ts +13 -0
  72. package/src/select-options.ts +95 -0
  73. package/src/select-query.svelte.ts +191 -0
  74. package/src/session-query.svelte.ts +103 -0
  75. package/src/strict-command-hooks.svelte.ts +333 -0
  76. package/src/strict-hooks.svelte.ts +198 -0
  77. package/src/table-hooks.svelte.ts +180 -174
  78. package/src/table-state.svelte.ts +117 -117
  79. package/src/task-contract.ts +87 -0
  80. package/src/task-hooks.svelte.ts +190 -180
  81. package/src/task-provider.ts +115 -0
  82. package/src/task-subscription.ts +132 -0
  83. package/src/theme.svelte.ts +155 -154
  84. package/src/toast.svelte.ts +38 -37
  85. package/src/types.ts +68 -110
  86. package/src/unsafe.ts +7 -0
  87. package/src/update-contract.ts +65 -0
  88. package/src/update-hooks.svelte.ts +347 -0
  89. package/src/update-many-contract.ts +79 -0
  90. package/src/update-many-hooks.svelte.ts +373 -0
  91. package/src/url-sync.ts +11 -10
  92. package/src/useCan.ts +96 -31
  93. package/src/useParsed.svelte.ts +18 -14
  94. package/src/useStepsForm.svelte.ts +123 -63
  95. package/src/utility-hooks.svelte.ts +101 -158
  96. package/src/form-hooks.svelte.ts +0 -889
  97. package/src/mutation-hooks.svelte.ts +0 -561
  98. package/src/schema-form.ts +0 -31
@@ -0,0 +1,198 @@
1
+ import { definedOptions } from './defined-options';
2
+ import * as query from './query-hooks.svelte';
3
+ import * as bulk from './hooks.svelte';
4
+ import { createTableQuery,type UseTableOptions } from './table-hooks.svelte';
5
+ import type { ContractOptions } from './contract-context.svelte';
6
+ import { captureAdminContext } from './context.svelte';
7
+ import { contractKey,validateContractId,parseContractId,parseContractRecord,type ResourceContract,type ContractSchemas,type ContractRecord,type ContractId,type ContractFormAction } from './resource-contract';
8
+ import type { RecordDecoder } from './record-decoder';
9
+ import type { KnownResources,Filter } from './types';
10
+ import { useQueryClient } from '@tanstack/svelte-query';
11
+ import { replaceReactiveMembers } from './reactive-projection';
12
+ import { snapshotInvalidationParams } from './invalidation-contract';
13
+ import { captureQueryProvider } from './query-snapshot';
14
+ import { captureAuthLiveScope } from './auth-hooks.svelte';
15
+ import { invalidateOwnedQueries, refreshSuperseded, type RefreshScope } from './query-invalidation';
16
+ import { useContractDelete, type ContractDeleteOptions } from './delete-hooks.svelte';
17
+ import { useContractUpdate, type ContractUpdateOptions } from './update-hooks.svelte';
18
+ import { useContractForm, type ContractFormOptions } from './contract-form.svelte';
19
+ import { useContractDeleteMany, type ContractDeleteManyOptions } from './delete-many-hooks.svelte';
20
+ import { useContractUpdateMany, type ContractUpdateManyOptions } from './update-many-hooks.svelte';
21
+ import type { ContractUpdateManyParams } from './update-many-contract';
22
+ import type { ContractDeleteManyParams } from './delete-many-contract';
23
+ import { useContractCreateMany, type ContractCreateManyOptions } from './create-many-hooks.svelte';
24
+ import { useContractCreate, type ContractCreateOptions } from './create-hooks.svelte';
25
+
26
+ type Field<T>=Extract<keyof T,string>;
27
+ type ValueField<T>={ [K in Field<T>]-?: T[K] extends string|number? K:never }[Field<T>];
28
+ type FieldPredicate<T>=
29
+ |{ operator: 'eq'|'ne'; value: Exclude<T,undefined> }
30
+ |{ operator: 'in'|'nin'; value: Exclude<T,undefined>[] }
31
+ |{ operator: 'null'|'nnull'; value: null }
32
+ |(NonNullable<T> extends string? { operator: 'contains'|'ncontains'|'startswith'|'endswith'; value: NonNullable<T> }:never)
33
+ |(NonNullable<T> extends string|number? (
34
+ |{ operator: 'lt'|'lte'|'gt'|'gte'; value: NonNullable<T> }
35
+ |{ operator: 'between'|'nbetween'; value: [NonNullable<T>,NonNullable<T>] }
36
+ ):never);
37
+ export type ContractFilter<T>=string extends keyof T ? Filter : Filter&(
38
+ |{ [K in Field<T>]: { field: K }&FieldPredicate<T[K]> }[Field<T>]
39
+ |{ operator: 'and'|'or'; value: ContractFilter<T>[] });
40
+ export type ContractSort<T>={ field: Field<T>; order: 'asc'|'desc' };
41
+ type Bound<S extends ContractSchemas>={ resource: ResourceContract<S> };
42
+ type QueryOptions<O,S extends ContractSchemas>=
43
+ Omit<O,'resource'|'contract'|'id'|'ids'|'filters'|'sorters'>&Bound<S>;
44
+ type ListOptions<O,S extends ContractSchemas>=QueryOptions<O,S>&{
45
+ filters?: ContractFilter<NoInfer<ContractRecord<S>>>[];
46
+ sorters?: ContractSort<NoInfer<ContractRecord<S>>>[];
47
+ };
48
+ type Id<S extends ContractSchemas>=NoInfer<ContractId<S>>;
49
+ type Row<S extends ContractSchemas>=ContractRecord<S>;
50
+
51
+ function bind<O extends Bound<ContractSchemas>>(options: O): Omit<O,'resource'|'contract'>&{ resource: KnownResources }&ContractOptions {
52
+ contractKey(options.resource);
53
+ return replaceReactiveMembers(options,{
54
+ get resource() {
55
+ contractKey(options.resource);
56
+ return options.resource.name;
57
+ },
58
+ get contract() {
59
+ contractKey(options.resource);
60
+ return options.resource;
61
+ },
62
+ });
63
+ }
64
+ function getter<O extends Bound<ContractSchemas>>(options: query.MaybeGetter<O>) {
65
+ return () => bind(typeof options==='function'? options():options);
66
+ }
67
+
68
+ function recordDecoder<S extends ContractSchemas>(options: query.MaybeGetter<Bound<S>>): () => RecordDecoder<Row<S>> {
69
+ return () => {
70
+ const contract=(typeof options==='function'? options():options).resource;
71
+ return value => parseContractRecord(contract,value);
72
+ };
73
+ }
74
+
75
+ export function useList<S extends ContractSchemas>(options: query.MaybeGetter<ListOptions<query.UseListOptions,S>>) {
76
+ return query.createListQuery(getter(options),recordDecoder(options));
77
+ }
78
+ export function useOne<S extends ContractSchemas>(options: query.MaybeGetter<QueryOptions<query.UseOneOptions,S>&{ id: Id<S> }>) {
79
+ return query.createOneQuery(getter(options),recordDecoder(options));
80
+ }
81
+ export function useMany<S extends ContractSchemas>(options: query.MaybeGetter<QueryOptions<query.UseManyOptions,S>&{ ids: Id<S>[] }>) {
82
+ return query.createManyQuery(getter(options),recordDecoder(options));
83
+ }
84
+ export function useShow<S extends ContractSchemas>(options: query.MaybeGetter<QueryOptions<query.UseOneOptions,S>&{ id: Id<S> }>) {
85
+ const result=query.createShowQuery(getter(options),recordDecoder(options));
86
+ return replaceReactiveMembers(result,{
87
+ get showId(): Id<S> {
88
+ return parseContractId((typeof options==='function'? options():options).resource,result.showId);
89
+ },
90
+ setShowId(id: Id<S>) {
91
+ validateContractId((typeof options==='function'? options():options).resource,id);
92
+ result.setShowId(id);
93
+ },
94
+ });
95
+ }
96
+ export function useInfiniteList<S extends ContractSchemas>(options: ListOptions<bulk.UseInfiniteListOptions,S>) {
97
+ return bulk.createInfiniteListQuery(bind(options),recordDecoder(options));
98
+ }
99
+ export function useSelect<S extends ContractSchemas>(
100
+ options: ListOptions<Omit<bulk.UseSelectOptions<Row<S>>,'optionLabel'|'optionValue'|'defaultValue'|'onSearch'>,S>&{
101
+ optionLabel: Field<NoInfer<Row<S>>>|((row: NoInfer<Row<S>>) => string);
102
+ optionValue: ValueField<NoInfer<Row<S>>>|((row: NoInfer<Row<S>>) => string|number);
103
+ defaultValue?: Id<S>[];
104
+ onSearch?: (value: string) => ContractFilter<NoInfer<Row<S>>>[];
105
+ },
106
+ ) {
107
+ return bulk.createSelectQuery(bind(options),recordDecoder(options));
108
+ }
109
+ export function useTable<S extends ContractSchemas>(
110
+ options: query.MaybeGetter<QueryOptions<UseTableOptions,S>&{
111
+ sorters?: { initial?: ContractSort<NoInfer<Row<S>>>[]; permanent?: ContractSort<NoInfer<Row<S>>>[]; mode?: 'off'|'server' };
112
+ filters?: { initial?: ContractFilter<NoInfer<Row<S>>>[]; permanent?: ContractFilter<NoInfer<Row<S>>>[]; mode?: 'off'|'server'; defaultBehavior?: 'merge'|'replace' };
113
+ }>,
114
+ ) {
115
+ const result=createTableQuery(getter(options),recordDecoder(options));
116
+ return replaceReactiveMembers(result,{
117
+ setSorters(value: ContractSort<Row<S>>[]) { result.setSorters(value); },
118
+ setFilters(value: ContractFilter<Row<S>>[],mode?: 'merge'|'replace') { result.setFilters(value,mode); },
119
+ });
120
+ }
121
+
122
+ export function useCreate<S extends ContractSchemas>(options: ContractCreateOptions<S>) {
123
+ return useContractCreate(options);
124
+ }
125
+ export function useUpdate<S extends ContractSchemas>(options: ContractUpdateOptions<S>) {
126
+ return useContractUpdate(options);
127
+ }
128
+ export function useDelete<S extends ContractSchemas>(options: ContractDeleteOptions<S>) {
129
+ return useContractDelete(options);
130
+ }
131
+ export function useCreateMany<S extends ContractSchemas>(options: ContractCreateManyOptions<S>) {
132
+ return useContractCreateMany(options);
133
+ }
134
+ export function useUpdateMany<S extends ContractSchemas>(options: ContractUpdateManyOptions<S>) {
135
+ return useContractUpdateMany(options);
136
+ }
137
+ export function useDeleteMany<S extends ContractSchemas>(options: ContractDeleteManyOptions<S>) {
138
+ return useContractDeleteMany(options);
139
+ }
140
+
141
+ export function useInvalidate<S extends ContractSchemas>(options: Bound<S>&{ dataProviderName?: string }) {
142
+ contractKey(options.resource);
143
+ const context=captureAdminContext();
144
+ const client=useQueryClient();
145
+ let disposed=false;
146
+ $effect(() => () => { disposed=true; });
147
+ return async (params: { id?: Id<S>; invalidates?: ('list'|'many'|'detail'|'resourceAll')[]|'all'|false }={}): Promise<void> => {
148
+ const input=snapshotInvalidationParams(params);
149
+ const contract=options.resource;
150
+ const key=contractKey(contract);
151
+ if(input.id!==undefined) validateContractId(contract,input.id);
152
+ if(input.invalidates===false||(Array.isArray(input.invalidates)&&input.invalidates.length===0)) return;
153
+ const auth=context.authProvider;
154
+ const authScope=captureAuthLiveScope(auth);
155
+ if(disposed || !authScope.isCurrent()) throw refreshSuperseded();
156
+ const resource=contract.name;
157
+ const providerName=options.dataProviderName;
158
+ // Validate the selected route before context's legacy provider fallback can run.
159
+ const captured=captureQueryProvider(context,{
160
+ resource,contract,...definedOptions({ dataProviderName: providerName }),
161
+ });
162
+ const matcher={ ...context.queryKeyMatcher(resource,providerName),contract: key };
163
+ const tenant=context.tenantCacheKey?.__svadminTenant;
164
+ const current=() => {
165
+ try {
166
+ return !disposed && auth===context.authProvider && authScope.isCurrent() &&
167
+ tenant===context.tenantCacheKey?.__svadminTenant && key===contractKey(options.resource) &&
168
+ matcher.provider===context.queryKeyMatcher(resource,providerName).provider &&
169
+ providerName===options.dataProviderName && captured.source===captureQueryProvider(context,{
170
+ resource,contract: options.resource,...definedOptions({ dataProviderName: providerName }),
171
+ }).source;
172
+ } catch { return false; }
173
+ };
174
+ const scopes: readonly RefreshScope[]=input.invalidates===undefined || input.invalidates==='all'
175
+ ? ['resourceAll'] : input.invalidates;
176
+ await invalidateOwnedQueries({
177
+ client, matcher: { ...matcher,resource }, owner: { source: captured.source,authSession: authScope.cacheKey },
178
+ scopes, current, ...definedOptions({ id: input.id }),
179
+ });
180
+ };
181
+ }
182
+
183
+ export function useForm<S extends ContractSchemas,A extends ContractFormAction>(options: ContractFormOptions<S,A>) {
184
+ return useContractForm(options);
185
+ }
186
+
187
+ export type StrictUseListOptions<S extends ContractSchemas>=ListOptions<query.UseListOptions,S>;
188
+ export type StrictUseOneOptions<S extends ContractSchemas>=QueryOptions<query.UseOneOptions,S>&{ id: Id<S> };
189
+ export type StrictUseManyOptions<S extends ContractSchemas>=QueryOptions<query.UseManyOptions,S>&{ ids: Id<S>[] };
190
+ export type StrictUseInfiniteListOptions<S extends ContractSchemas>=Parameters<typeof useInfiniteList<S>>[0];
191
+ export type StrictUseSelectOptions<S extends ContractSchemas>=Parameters<typeof useSelect<S>>[0];
192
+ export type StrictUseDeleteManyOptions<S extends ContractSchemas>=ContractDeleteManyOptions<S>;
193
+ export type StrictUseDeleteManyMutateParams<S extends ContractSchemas>=ContractDeleteManyParams<S>;
194
+ export type StrictUseUpdateManyMutateParams<S extends ContractSchemas>=ContractUpdateManyParams<S>;
195
+ export type StrictUseCreateManyMutateParams<S extends ContractSchemas>=
196
+ Parameters<ReturnType<typeof useCreateMany<S>>['mutation']['mutateAsync']>[0];
197
+ export type StrictUseFormOptions<S extends ContractSchemas,A extends ContractFormAction>=Parameters<typeof useForm<S,A>>[0];
198
+ export type StrictUseFormReturn<S extends ContractSchemas,A extends ContractFormAction>=ReturnType<typeof useForm<S,A>>;