@azure-net/kit 5.1.1 → 5.3.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/infra/datasource/BaseDatasource.js +2 -4
- package/dist/infra/query/QueryBuilder.js +37 -17
- package/dist/infra/response/BaseResponse.js +1 -1
- package/dist/plugin/AzureNetPlugin.js +52 -11
- package/dist/shared/app/App.d.ts +25 -2
- package/dist/shared/app/App.js +42 -1
- package/dist/shared/app/index.d.ts +1 -1
- package/dist/shared/background-task/BackgroundTask.d.ts +16 -0
- package/dist/shared/background-task/BackgroundTask.js +34 -0
- package/dist/shared/background-task/index.d.ts +1 -0
- package/dist/shared/background-task/index.js +1 -0
- package/dist/shared/boundary-provider/Provider.d.ts +1 -1
- package/dist/shared/boundary-provider/Provider.js +12 -8
- package/dist/shared/class-mirror/ClassMirror.js +0 -6
- package/dist/shared/cookie/UniversalCookie.d.ts +30 -0
- package/dist/shared/cookie/UniversalCookie.js +115 -30
- package/dist/shared/event-bus/EventBus.d.ts +11 -1
- package/dist/shared/event-bus/EventBus.js +1 -4
- package/dist/shared/index.d.ts +3 -2
- package/dist/shared/index.js +3 -2
- package/dist/shared/logger/index.d.ts +2 -1
- package/dist/shared/logger/index.js +15 -10
- package/dist/svelte/active-form/ActiveForm.svelte.js +10 -9
- package/dist/svelte/async-signal/AsyncSignal.svelte.js +4 -1
- package/dist/svelte/query/Query.svelte.js +43 -12
- package/dist/svelte/shared/cloneStateValue.d.ts +2 -0
- package/dist/svelte/shared/cloneStateValue.js +100 -0
- package/package.json +8 -7
|
@@ -7,10 +7,8 @@ export class BaseHttpDatasource {
|
|
|
7
7
|
this.httpClient = params.http ?? createHttpServiceInstance();
|
|
8
8
|
this.query = params.query ?? createQueryInstance();
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
throw err;
|
|
13
|
-
});
|
|
10
|
+
_createRawRequest(callback) {
|
|
11
|
+
return callback({ http: this.httpClient, query: this.query });
|
|
14
12
|
}
|
|
15
13
|
createRawRequest = this._createRawRequest.bind(this);
|
|
16
14
|
}
|
|
@@ -8,8 +8,19 @@ const normalizeSettings = (base, override) => {
|
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
10
|
const encodeQuery = (entries) => entries.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&');
|
|
11
|
+
const stringifyQueryValue = (value) => {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.stringify(value);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
const circular = error instanceof TypeError && /circular|cyclic/i.test(error.message);
|
|
17
|
+
throw new AzureNetKitInternalError(`[QueryInstance] Query value could not be serialized${circular ? ': circular reference detected' : ''}`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
11
20
|
const encodeArrayEntries = (key, values, arrayFormat) => {
|
|
12
|
-
const cleanValues = values
|
|
21
|
+
const cleanValues = values
|
|
22
|
+
.filter((value) => value !== null && value !== undefined)
|
|
23
|
+
.map((value) => (typeof value === 'object' && !(value instanceof Date) ? stringifyQueryValue(value) : String(value)));
|
|
13
24
|
switch (arrayFormat) {
|
|
14
25
|
case 'repeat':
|
|
15
26
|
return cleanValues.map((v) => [key, v]);
|
|
@@ -23,26 +34,35 @@ const encodeArrayEntries = (key, values, arrayFormat) => {
|
|
|
23
34
|
throw new AzureNetKitInternalError(`[QueryInstance] Unsupported array format: ${arrayFormat}`);
|
|
24
35
|
}
|
|
25
36
|
};
|
|
26
|
-
const serializeEntries = (obj, arrayFormat, objectFormat, prefix = '') => {
|
|
37
|
+
const serializeEntries = (obj, arrayFormat, objectFormat, prefix = '', ancestors = new WeakSet()) => {
|
|
38
|
+
if (ancestors.has(obj)) {
|
|
39
|
+
throw new AzureNetKitInternalError('[QueryInstance] Query value could not be serialized: circular reference detected');
|
|
40
|
+
}
|
|
41
|
+
ancestors.add(obj);
|
|
27
42
|
const entries = [];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (typeof value === 'object' && !(value instanceof Date)) {
|
|
37
|
-
if (objectFormat === 'nested-brackets') {
|
|
38
|
-
entries.push(...serializeEntries(value, arrayFormat, objectFormat, fullKey));
|
|
43
|
+
try {
|
|
44
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
45
|
+
if (value === null || value === undefined)
|
|
46
|
+
continue;
|
|
47
|
+
const fullKey = prefix ? (objectFormat === 'nested-brackets' ? `${prefix}[${key}]` : `${prefix}.${key}`) : key;
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
entries.push(...encodeArrayEntries(fullKey, value, arrayFormat));
|
|
50
|
+
continue;
|
|
39
51
|
}
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
if (typeof value === 'object' && !(value instanceof Date)) {
|
|
53
|
+
if (objectFormat === 'nested-brackets') {
|
|
54
|
+
entries.push(...serializeEntries(value, arrayFormat, objectFormat, fullKey, ancestors));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
entries.push([fullKey, stringifyQueryValue(value)]);
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
42
60
|
}
|
|
43
|
-
|
|
61
|
+
entries.push([fullKey, String(value)]);
|
|
44
62
|
}
|
|
45
|
-
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
ancestors.delete(obj);
|
|
46
66
|
}
|
|
47
67
|
return entries;
|
|
48
68
|
};
|
|
@@ -37,7 +37,7 @@ export class ResponseBuilder {
|
|
|
37
37
|
const keys = path.split('.');
|
|
38
38
|
let result = this.state.data;
|
|
39
39
|
for (const key of keys) {
|
|
40
|
-
if (result && typeof result === 'object' && key
|
|
40
|
+
if (result && typeof result === 'object' && Object.hasOwn(result, key)) {
|
|
41
41
|
result = result[key];
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
@@ -20,10 +20,28 @@ const findStaticImportInsertPosition = (sourceCode) => {
|
|
|
20
20
|
};
|
|
21
21
|
const createVirtualServerHooks = (silentChromeDevtools) => `// ${GENERATED_MARKER}
|
|
22
22
|
import { edgesHandle, edgesHandleRaw } from '${VIRTUAL_SERVER_UTILS_ID}';
|
|
23
|
+
import { RequestContext } from '@azure-net/kit/server-context';
|
|
23
24
|
|
|
24
25
|
const getRegister = async () => (await import('${VIRTUAL_PROGRAM_ID}')).register;
|
|
25
26
|
|
|
27
|
+
const withRequestContext = (event, callback) => {
|
|
28
|
+
try {
|
|
29
|
+
RequestContext.current();
|
|
30
|
+
} catch {
|
|
31
|
+
return edgesHandleRaw(event, callback);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return callback();
|
|
35
|
+
};
|
|
36
|
+
|
|
26
37
|
export const init = async () => (await getRegister()).serverInit();
|
|
38
|
+
export const handleFetch = (input) => withRequestContext(input.event, async () => (await getRegister()).serverFetch(input));
|
|
39
|
+
export const handleValidationError = (input) => withRequestContext(
|
|
40
|
+
input.event,
|
|
41
|
+
async () => (await getRegister()).serverValidationError(input)
|
|
42
|
+
);
|
|
43
|
+
export const reroute = async (input) => (await getRegister()).reroute(input);
|
|
44
|
+
export const getTransport = async () => (await getRegister()).transport;
|
|
27
45
|
|
|
28
46
|
export const handle = edgesHandle(async ({ serialize, edgesEvent, resolve }) => {
|
|
29
47
|
const register = await getRegister();
|
|
@@ -59,8 +77,26 @@ const createVirtualServerUtils = () => "export { edgesHandle, edgesHandleRaw } f
|
|
|
59
77
|
const createVirtualClientHooks = () => `// ${GENERATED_MARKER}
|
|
60
78
|
const getRegister = async () => (await import('${VIRTUAL_PROGRAM_ID}')).register;
|
|
61
79
|
|
|
62
|
-
export const
|
|
80
|
+
export const transport = {};
|
|
81
|
+
|
|
82
|
+
const createCodecView = (method) => new Proxy({}, {
|
|
83
|
+
get: (_, key) => transport[key]?.[method],
|
|
84
|
+
ownKeys: () => Reflect.ownKeys(transport),
|
|
85
|
+
getOwnPropertyDescriptor: (_, key) => key in transport
|
|
86
|
+
? { configurable: true, enumerable: true, value: transport[key][method] }
|
|
87
|
+
: undefined
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const decoders = createCodecView('decode');
|
|
91
|
+
export const encoders = createCodecView('encode');
|
|
92
|
+
|
|
93
|
+
export const init = async () => {
|
|
94
|
+
const register = await getRegister();
|
|
95
|
+
Object.assign(transport, register.transport);
|
|
96
|
+
return register.clientInit();
|
|
97
|
+
};
|
|
63
98
|
export const handleError = async (input) => (await getRegister()).clientError(input);
|
|
99
|
+
export const reroute = async (input) => (await getRegister()).reroute(input);
|
|
64
100
|
`;
|
|
65
101
|
const createVirtualProgram = (root) => {
|
|
66
102
|
const tsProgram = path.join(root, 'src', 'program.ts');
|
|
@@ -90,7 +126,8 @@ const hasUserHook = (root, hookName) => {
|
|
|
90
126
|
const assertNoUserHooks = (root) => {
|
|
91
127
|
const serverHook = hasUserHook(root, 'hooks.server');
|
|
92
128
|
const clientHook = hasUserHook(root, 'hooks.client');
|
|
93
|
-
const
|
|
129
|
+
const universalHook = hasUserHook(root, 'hooks');
|
|
130
|
+
const hook = serverHook ?? clientHook ?? universalHook;
|
|
94
131
|
if (!hook)
|
|
95
132
|
return;
|
|
96
133
|
throw new Error(`[AzureNetPlugin] ${path.relative(root, hook)} is not allowed when AzureNetPlugin is enabled. ` +
|
|
@@ -112,21 +149,16 @@ const transformGeneratedServerInternal = (sourceCode) => {
|
|
|
112
149
|
if (!getHooksPattern.test(sourceCode)) {
|
|
113
150
|
throw new Error('[AzureNetPlugin] Unsupported SvelteKit generated server internals: get_hooks() was not found.');
|
|
114
151
|
}
|
|
115
|
-
const universalImportMatch = sourceCode.match(/\(\{\s*reroute,\s*transport\s*\}\s*=\s*await\s*import\([^)]+\)\);/);
|
|
116
|
-
const universalImport = universalImportMatch?.[0] ? `\n\t${universalImportMatch[0]}` : '';
|
|
117
152
|
const importLine = `import * as __azureNetServerHooks from '${VIRTUAL_SERVER_HOOKS_ID}';`;
|
|
118
153
|
const getHooksReplacement = `export async function get_hooks() {
|
|
119
|
-
\tlet reroute;
|
|
120
|
-
\tlet transport;${universalImport}
|
|
121
|
-
|
|
122
154
|
\treturn {
|
|
123
155
|
\t\thandle: __azureNetServerHooks.handle,
|
|
124
|
-
\t\thandleFetch:
|
|
156
|
+
\t\thandleFetch: __azureNetServerHooks.handleFetch,
|
|
125
157
|
\t\thandleError: __azureNetServerHooks.handleError,
|
|
126
|
-
\t\thandleValidationError:
|
|
158
|
+
\t\thandleValidationError: __azureNetServerHooks.handleValidationError,
|
|
127
159
|
\t\tinit: __azureNetServerHooks.init,
|
|
128
|
-
\t\treroute,
|
|
129
|
-
\t\ttransport
|
|
160
|
+
\t\treroute: __azureNetServerHooks.reroute,
|
|
161
|
+
\t\ttransport: await __azureNetServerHooks.getTransport()
|
|
130
162
|
\t};
|
|
131
163
|
}`;
|
|
132
164
|
const transformed = ensureVirtualImport(sourceCode, `// ${GENERATED_MARKER}\n${importLine}`).replace(getHooksPattern, getHooksReplacement);
|
|
@@ -142,6 +174,11 @@ const transformGeneratedClientApp = (sourceCode) => {
|
|
|
142
174
|
if (!handleErrorPattern.test(sourceCode)) {
|
|
143
175
|
throw new Error('[AzureNetPlugin] Unsupported SvelteKit generated client app: default handleError was not found.');
|
|
144
176
|
}
|
|
177
|
+
const decodersPattern = /export const decoders = Object\.fromEntries\(Object\.entries\(hooks\.transport\)\.map\(\(\[k, v\]\) => \[k, v\.decode\]\)\);/;
|
|
178
|
+
const encodersPattern = /export const encoders = Object\.fromEntries\(Object\.entries\(hooks\.transport\)\.map\(\(\[k, v\]\) => \[k, v\.encode\]\)\);/;
|
|
179
|
+
if (!decodersPattern.test(sourceCode) || !encodersPattern.test(sourceCode)) {
|
|
180
|
+
throw new Error('[AzureNetPlugin] Unsupported SvelteKit generated client app: transport codecs were not found.');
|
|
181
|
+
}
|
|
145
182
|
let transformed = ensureVirtualImport(sourceCode, `// ${GENERATED_MARKER}\nimport * as __azureNetClientHooks from '${VIRTUAL_CLIENT_HOOKS_ID}';`);
|
|
146
183
|
transformed = transformed.replace(handleErrorPattern, 'handleError: __azureNetClientHooks.handleError');
|
|
147
184
|
if (/^\s*init:\s*[^,\n]+,?/m.test(transformed)) {
|
|
@@ -150,6 +187,10 @@ const transformGeneratedClientApp = (sourceCode) => {
|
|
|
150
187
|
else {
|
|
151
188
|
transformed = transformed.replace(/handleError:\s*__azureNetClientHooks\.handleError,?/m, 'handleError: __azureNetClientHooks.handleError,\n\tinit: __azureNetClientHooks.init,');
|
|
152
189
|
}
|
|
190
|
+
transformed = transformed.replace(/^\s*reroute:\s*[^,\n]+,?/m, '\treroute: __azureNetClientHooks.reroute,');
|
|
191
|
+
transformed = transformed.replace(/^\s*transport:\s*[^,\n]+,?/m, '\ttransport: __azureNetClientHooks.transport');
|
|
192
|
+
transformed = transformed.replace(decodersPattern, 'export const decoders = __azureNetClientHooks.decoders;');
|
|
193
|
+
transformed = transformed.replace(encodersPattern, 'export const encoders = __azureNetClientHooks.encoders;');
|
|
153
194
|
return transformed;
|
|
154
195
|
};
|
|
155
196
|
export const AzureNetPlugin = (options) => {
|
package/dist/shared/app/App.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ContextData } from '../../external/edges/ServerContext.js';
|
|
2
2
|
import { type IServerMiddleware } from './middleware/ServerMiddleware.js';
|
|
3
|
-
import type { Handle, HandleClientError, HandleServerError, RequestEvent, ServerInit } from '@sveltejs/kit';
|
|
3
|
+
import type { Handle, HandleClientError, HandleFetch, HandleServerError, HandleValidationError, RequestEvent, Reroute, ServerInit, Transport } from '@sveltejs/kit';
|
|
4
4
|
import { type IClientMiddleware } from './middleware/ClientMiddleware.js';
|
|
5
5
|
import { useLogger } from '../logger/index.js';
|
|
6
6
|
type MaybePromise<T> = T | Promise<T>;
|
|
@@ -11,7 +11,7 @@ type AppDependencyFactories<TApp> = Record<string, AppDependencyFactory<TApp>>;
|
|
|
11
11
|
type ResolvedDependencies<T> = {
|
|
12
12
|
[K in keyof T]: T[K] extends (...args: never[]) => infer TReturn ? TReturn : never;
|
|
13
13
|
};
|
|
14
|
-
type BuilderFlags = Partial<Record<'use' | 'useClient' | 'useClientInit' | 'useClientError' | 'useServerInit' | 'useServer' | 'useServerError', true>>;
|
|
14
|
+
type BuilderFlags = Partial<Record<'use' | 'useClient' | 'useClientInit' | 'useClientError' | 'useServerInit' | 'useServer' | 'useServerError' | 'useServerFetch' | 'useServerValidationError' | 'useReroute' | 'useTransport', true>>;
|
|
15
15
|
type WithFlag<TFlags extends BuilderFlags, TKey extends keyof BuilderFlags> = TFlags & Record<TKey, true>;
|
|
16
16
|
type BuilderDependencies<TBuilder> = TBuilder extends {
|
|
17
17
|
readonly __types__?: infer TDependencies;
|
|
@@ -55,6 +55,14 @@ export interface AppServerErrorContext<TDependencies extends Record<string, unkn
|
|
|
55
55
|
message: string;
|
|
56
56
|
useLogger: typeof useLogger;
|
|
57
57
|
}
|
|
58
|
+
export type AppServerFetchContext<TDependencies extends Record<string, unknown>> = Parameters<HandleFetch>[0] & {
|
|
59
|
+
Container: AppContainer<TDependencies>;
|
|
60
|
+
requestContext: ContextData;
|
|
61
|
+
};
|
|
62
|
+
export type AppServerValidationErrorContext<TDependencies extends Record<string, unknown>> = Parameters<HandleValidationError>[0] & {
|
|
63
|
+
Container: AppContainer<TDependencies>;
|
|
64
|
+
requestContext: ContextData;
|
|
65
|
+
};
|
|
58
66
|
export type AppUniversalLifecycleCallback<TDependencies extends Record<string, unknown>> = (context: AppUniversalLifecycleContext<TDependencies>) => MaybePromise<void>;
|
|
59
67
|
export type AppClientLifecycleCallback<TDependencies extends Record<string, unknown>> = (context: AppClientLifecycleContext<TDependencies>) => MaybePromise<void>;
|
|
60
68
|
export type AppClientInitLifecycleCallback<TDependencies extends Record<string, unknown>> = (context: AppClientInitLifecycleContext<TDependencies>) => MaybePromise<void>;
|
|
@@ -62,6 +70,9 @@ export type AppClientErrorCallback<TDependencies extends Record<string, unknown>
|
|
|
62
70
|
export type AppServerInitLifecycleCallback = ServerInit;
|
|
63
71
|
export type AppServerLifecycleCallback<TDependencies extends Record<string, unknown>> = (context: AppServerLifecycleContext<TDependencies>) => MaybePromise<Response | void>;
|
|
64
72
|
export type AppServerErrorCallback<TDependencies extends Record<string, unknown>> = (context: AppServerErrorContext<TDependencies>) => ReturnType<HandleServerError>;
|
|
73
|
+
export type AppServerFetchCallback<TDependencies extends Record<string, unknown>> = (context: AppServerFetchContext<TDependencies>) => ReturnType<HandleFetch>;
|
|
74
|
+
export type AppServerValidationErrorCallback<TDependencies extends Record<string, unknown>> = (context: AppServerValidationErrorContext<TDependencies>) => ReturnType<HandleValidationError>;
|
|
75
|
+
export type AppRerouteCallback = Reroute;
|
|
65
76
|
export type CreateAppBuilder<TDependencies extends Record<string, unknown>, TFlags extends BuilderFlags = object> = {
|
|
66
77
|
readonly __types__?: TDependencies;
|
|
67
78
|
dependencies<TNext extends AppDependencyFactories<AppContainer<TDependencies>>>(dependencies: TNext): CreateAppBuilder<TDependencies & ResolvedDependencies<TNext>, TFlags>;
|
|
@@ -79,6 +90,14 @@ export type CreateAppBuilder<TDependencies extends Record<string, unknown>, TFla
|
|
|
79
90
|
useServer(callback: AppServerLifecycleCallback<TDependencies>): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useServer'>>;
|
|
80
91
|
}> & OnceMethod<TFlags, 'useServerError', {
|
|
81
92
|
useServerError(callback: AppServerErrorCallback<TDependencies>): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useServerError'>>;
|
|
93
|
+
}> & OnceMethod<TFlags, 'useServerFetch', {
|
|
94
|
+
useServerFetch(callback: AppServerFetchCallback<TDependencies>): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useServerFetch'>>;
|
|
95
|
+
}> & OnceMethod<TFlags, 'useServerValidationError', {
|
|
96
|
+
useServerValidationError(callback: AppServerValidationErrorCallback<TDependencies>): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useServerValidationError'>>;
|
|
97
|
+
}> & OnceMethod<TFlags, 'useReroute', {
|
|
98
|
+
useReroute(callback: AppRerouteCallback): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useReroute'>>;
|
|
99
|
+
}> & OnceMethod<TFlags, 'useTransport', {
|
|
100
|
+
useTransport(transport: Transport): CreateAppBuilder<TDependencies, WithFlag<TFlags, 'useTransport'>>;
|
|
82
101
|
}>;
|
|
83
102
|
export interface AppRegistrar {
|
|
84
103
|
(): MaybePromise<void>;
|
|
@@ -86,7 +105,11 @@ export interface AppRegistrar {
|
|
|
86
105
|
clientError: HandleClientError;
|
|
87
106
|
serverInit: ServerInit;
|
|
88
107
|
serverError: HandleServerError;
|
|
108
|
+
serverFetch: HandleFetch;
|
|
109
|
+
serverValidationError: HandleValidationError;
|
|
89
110
|
handle: Handle;
|
|
111
|
+
reroute: Reroute;
|
|
112
|
+
transport: Transport;
|
|
90
113
|
}
|
|
91
114
|
export interface CreateAppInstance<TDependencies extends Record<string, unknown>> {
|
|
92
115
|
Container: AppContainer<TDependencies>;
|
package/dist/shared/app/App.js
CHANGED
|
@@ -79,6 +79,22 @@ const createBuilder = (dependencies, callbacks) => {
|
|
|
79
79
|
setCallback(callbacks, 'useServerError', callback);
|
|
80
80
|
return builder;
|
|
81
81
|
},
|
|
82
|
+
useServerFetch(callback) {
|
|
83
|
+
setCallback(callbacks, 'useServerFetch', callback);
|
|
84
|
+
return builder;
|
|
85
|
+
},
|
|
86
|
+
useServerValidationError(callback) {
|
|
87
|
+
setCallback(callbacks, 'useServerValidationError', callback);
|
|
88
|
+
return builder;
|
|
89
|
+
},
|
|
90
|
+
useReroute(callback) {
|
|
91
|
+
setCallback(callbacks, 'useReroute', callback);
|
|
92
|
+
return builder;
|
|
93
|
+
},
|
|
94
|
+
useTransport(transport) {
|
|
95
|
+
setCallback(callbacks, 'useTransport', transport);
|
|
96
|
+
return builder;
|
|
97
|
+
},
|
|
82
98
|
dependencies(nextDependencies) {
|
|
83
99
|
for (const [key, factory] of Object.entries(nextDependencies)) {
|
|
84
100
|
dependencies.set(key, factory);
|
|
@@ -195,6 +211,27 @@ export const createApp = (callback, name = DEFAULT_APP_NAME) => {
|
|
|
195
211
|
message
|
|
196
212
|
});
|
|
197
213
|
};
|
|
214
|
+
const runServerFetch = (input) => {
|
|
215
|
+
if (!callbacks.useServerFetch)
|
|
216
|
+
return input.fetch(input.request);
|
|
217
|
+
return callbacks.useServerFetch({
|
|
218
|
+
...input,
|
|
219
|
+
Container,
|
|
220
|
+
requestContext: getServerRequestContext()
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
const runServerValidationError = (input) => {
|
|
224
|
+
if (!callbacks.useServerValidationError) {
|
|
225
|
+
console.error('Remote function schema validation failed:', input.issues);
|
|
226
|
+
return { message: 'Bad Request' };
|
|
227
|
+
}
|
|
228
|
+
return callbacks.useServerValidationError({
|
|
229
|
+
...input,
|
|
230
|
+
Container,
|
|
231
|
+
requestContext: getServerRequestContext()
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
const reroute = (input) => callbacks.useReroute?.(input);
|
|
198
235
|
const handle = async ({ event, resolve }) => {
|
|
199
236
|
const requestContext = getServerRequestContext();
|
|
200
237
|
const flags = getLifecycleFlags(appKey, requestContext);
|
|
@@ -227,7 +264,11 @@ export const createApp = (callback, name = DEFAULT_APP_NAME) => {
|
|
|
227
264
|
clientError: runClientError,
|
|
228
265
|
serverInit: runServerInit,
|
|
229
266
|
serverError: runServerError,
|
|
230
|
-
|
|
267
|
+
serverFetch: runServerFetch,
|
|
268
|
+
serverValidationError: runServerValidationError,
|
|
269
|
+
handle,
|
|
270
|
+
reroute,
|
|
271
|
+
transport: callbacks.useTransport ?? {}
|
|
231
272
|
});
|
|
232
273
|
return {
|
|
233
274
|
Container,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createApp, type AppClientErrorCallback, type AppClientErrorContext, type AppClientInitLifecycleCallback, type AppClientInitLifecycleContext, type AppClientLifecycleCallback, type AppClientLifecycleContext, type AppContainer, type AppRegistrar, type AppServerErrorCallback, type AppServerErrorContext, type AppServerInitLifecycleCallback, type AppServerInitLifecycleContext, type AppServerLifecycleCallback, type AppServerLifecycleContext, type AppUniversalLifecycleCallback, type AppUniversalLifecycleContext, type CreateAppInstance } from './App.js';
|
|
1
|
+
export { createApp, type AppClientErrorCallback, type AppClientErrorContext, type AppClientInitLifecycleCallback, type AppClientInitLifecycleContext, type AppClientLifecycleCallback, type AppClientLifecycleContext, type AppContainer, type AppRegistrar, type AppServerErrorCallback, type AppServerErrorContext, type AppServerFetchCallback, type AppServerFetchContext, type AppServerInitLifecycleCallback, type AppServerInitLifecycleContext, type AppServerLifecycleCallback, type AppServerLifecycleContext, type AppServerValidationErrorCallback, type AppServerValidationErrorContext, type AppRerouteCallback, type AppUniversalLifecycleCallback, type AppUniversalLifecycleContext, type CreateAppInstance } from './App.js';
|
|
2
2
|
export type { IClientMiddleware } from './middleware/ClientMiddleware.js';
|
|
3
3
|
export type { IServerMiddleware } from './middleware/ServerMiddleware.js';
|
|
4
4
|
export type { EnsureRoute, EnsureRouteSource, EnsureRouteTarget } from './middleware/Shared.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type MaybePromise<T> = T | PromiseLike<T>;
|
|
2
|
+
type WaitUntil = (promise: Promise<unknown>) => void;
|
|
3
|
+
type WaitUntilTarget = WaitUntil | {
|
|
4
|
+
waitUntil: WaitUntil;
|
|
5
|
+
};
|
|
6
|
+
export declare class BackgroundTask<T = void> implements Promise<T> {
|
|
7
|
+
#private;
|
|
8
|
+
readonly [Symbol.toStringTag] = "Promise";
|
|
9
|
+
private constructor();
|
|
10
|
+
static run<T = void>(task: () => MaybePromise<T>): BackgroundTask<T>;
|
|
11
|
+
waitUntil(target: WaitUntilTarget): this;
|
|
12
|
+
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
13
|
+
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult>;
|
|
14
|
+
finally(onfinally?: (() => void) | null): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class BackgroundTask {
|
|
2
|
+
[Symbol.toStringTag] = 'Promise';
|
|
3
|
+
#promise;
|
|
4
|
+
constructor(task) {
|
|
5
|
+
try {
|
|
6
|
+
this.#promise = Promise.resolve(task());
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
this.#promise = Promise.reject(error);
|
|
10
|
+
}
|
|
11
|
+
void this.#promise.catch(() => undefined);
|
|
12
|
+
}
|
|
13
|
+
static run(task) {
|
|
14
|
+
return new BackgroundTask(task);
|
|
15
|
+
}
|
|
16
|
+
waitUntil(target) {
|
|
17
|
+
if (typeof target === 'function') {
|
|
18
|
+
target(this.#promise);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
target.waitUntil(this.#promise);
|
|
22
|
+
}
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
then(onfulfilled, onrejected) {
|
|
26
|
+
return this.#promise.then(onfulfilled, onrejected);
|
|
27
|
+
}
|
|
28
|
+
catch(onrejected) {
|
|
29
|
+
return this.#promise.catch(onrejected);
|
|
30
|
+
}
|
|
31
|
+
finally(onfinally) {
|
|
32
|
+
return this.#promise.finally(onfinally);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BackgroundTask } from './BackgroundTask.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BackgroundTask } from './BackgroundTask.js';
|
|
@@ -17,5 +17,5 @@ export interface ProviderSettings<T extends ServiceMap, D extends Record<string,
|
|
|
17
17
|
register: ProviderFactory<T, D>;
|
|
18
18
|
}
|
|
19
19
|
export declare const createBoundaryProvider: <T extends ServiceMap, D extends Record<string, ProviderWithType<ServiceMap>>>(name: string, settings: ProviderSettings<T, D>) => ProviderWithType<T>;
|
|
20
|
-
export declare function cleanupProvider(name: string): void
|
|
20
|
+
export declare function cleanupProvider(name: string): Promise<void>;
|
|
21
21
|
export {};
|
|
@@ -152,14 +152,17 @@ export const createBoundaryProvider = (name, settings) => {
|
|
|
152
152
|
};
|
|
153
153
|
return providerFn;
|
|
154
154
|
};
|
|
155
|
-
export function cleanupProvider(name) {
|
|
155
|
+
export async function cleanupProvider(name) {
|
|
156
156
|
const cleanupCache = async (cache) => {
|
|
157
157
|
const promises = [];
|
|
158
158
|
for (const [key, service] of cache.entries()) {
|
|
159
159
|
if (service && typeof service === 'object' && 'dispose' in service) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
promises.push(disposeResult.catch((err) => console.error(`Error disposing ${name}.${key}:`, err)));
|
|
160
|
+
try {
|
|
161
|
+
const disposeResult = service.dispose();
|
|
162
|
+
promises.push(Promise.resolve(disposeResult).catch((err) => console.error(`Error disposing ${name}.${key}:`, err)));
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
console.error(`Error disposing ${name}.${key}:`, err);
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
168
|
}
|
|
@@ -168,18 +171,19 @@ export function cleanupProvider(name) {
|
|
|
168
171
|
};
|
|
169
172
|
if (BROWSER) {
|
|
170
173
|
const cache = clientCache.get(name);
|
|
171
|
-
|
|
172
|
-
void cleanupCache(cache);
|
|
173
|
-
}
|
|
174
|
+
clientCache.delete(name);
|
|
174
175
|
providerProxyCache.delete(name);
|
|
175
176
|
clientBootFlags.delete(name);
|
|
177
|
+
if (cache)
|
|
178
|
+
await cleanupCache(cache);
|
|
176
179
|
}
|
|
177
180
|
else {
|
|
178
181
|
const context = RequestContext.current();
|
|
179
182
|
const providers = context.data.providers;
|
|
180
183
|
if (providers?.has(name)) {
|
|
181
184
|
const cache = providers.get(name);
|
|
182
|
-
|
|
185
|
+
providers.delete(name);
|
|
186
|
+
await cleanupCache(cache);
|
|
183
187
|
}
|
|
184
188
|
}
|
|
185
189
|
}
|
|
@@ -26,12 +26,6 @@ export class ClassMirror {
|
|
|
26
26
|
},
|
|
27
27
|
has(proxyTarget, prop) {
|
|
28
28
|
return Reflect.has(proxyTarget, prop) || Reflect.has(proxyTarget[MIRROR_TARGET], prop);
|
|
29
|
-
},
|
|
30
|
-
ownKeys(proxyTarget) {
|
|
31
|
-
return [...new Set([...Reflect.ownKeys(proxyTarget), ...Reflect.ownKeys(proxyTarget[MIRROR_TARGET])])];
|
|
32
|
-
},
|
|
33
|
-
getOwnPropertyDescriptor(proxyTarget, prop) {
|
|
34
|
-
return Reflect.getOwnPropertyDescriptor(proxyTarget, prop) ?? Reflect.getOwnPropertyDescriptor(proxyTarget[MIRROR_TARGET], prop);
|
|
35
29
|
}
|
|
36
30
|
});
|
|
37
31
|
}
|
|
@@ -9,12 +9,42 @@ export type CookieOptions = {
|
|
|
9
9
|
priority?: 'low' | 'medium' | 'high' | undefined;
|
|
10
10
|
partitioned?: boolean | undefined;
|
|
11
11
|
};
|
|
12
|
+
/** Cookie operations with shared defaults and request-local resolution at call time. */
|
|
13
|
+
export declare class UniversalCookieInstance {
|
|
14
|
+
private readonly defaults;
|
|
15
|
+
constructor(options?: CookieOptions);
|
|
16
|
+
set<T>(name: string, value: T, options?: CookieOptions): void;
|
|
17
|
+
get<T = string>(name: string): T | undefined;
|
|
18
|
+
getAll<T = Record<string, unknown>>(): T | undefined;
|
|
19
|
+
has(name: string): boolean;
|
|
20
|
+
delete(name: string, options?: CookieOptions): void;
|
|
21
|
+
clear(options?: CookieOptions): void;
|
|
22
|
+
toCredentials(): string;
|
|
23
|
+
createNamedInstance<T = string>(name: string): UniversalNamedCookieInstance<T>;
|
|
24
|
+
}
|
|
25
|
+
/** Type-safe operations for one cookie name. */
|
|
26
|
+
export declare class UniversalNamedCookieInstance<T = string> {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
private readonly cookies;
|
|
29
|
+
constructor(name: string, cookies: UniversalCookieInstance);
|
|
30
|
+
set(value: T, options?: CookieOptions): void;
|
|
31
|
+
get(): T | undefined;
|
|
32
|
+
has(): boolean;
|
|
33
|
+
delete(options?: CookieOptions): void;
|
|
34
|
+
clear(options?: CookieOptions): void;
|
|
35
|
+
}
|
|
12
36
|
/**
|
|
13
37
|
* Utility class for managing cookies in svelte ssr (browser and server).
|
|
14
38
|
* Supports setting, getting, deleting, checking, and clearing cookies.
|
|
15
39
|
* All methods are static and operate without creating instances.
|
|
16
40
|
*/
|
|
17
41
|
export declare class UniversalCookie {
|
|
42
|
+
/** Creates reusable cookie operations with shared defaults. */
|
|
43
|
+
static createInstance(options?: CookieOptions): UniversalCookieInstance;
|
|
44
|
+
/** Creates reusable operations bound to one cookie name. */
|
|
45
|
+
static createNamedInstance<T = string>(name: string, options?: CookieOptions): UniversalNamedCookieInstance<T>;
|
|
46
|
+
private static serialize;
|
|
47
|
+
private static deserialize;
|
|
18
48
|
/**
|
|
19
49
|
* Sets a cookie with the specified key, value, and options.
|
|
20
50
|
* Serializes non-string values as JSON.
|
|
@@ -1,11 +1,111 @@
|
|
|
1
1
|
import { BROWSER, Cookies } from '../../external/tools/index.js';
|
|
2
2
|
import { RequestContext } from '../../external/edges/ServerContext.js';
|
|
3
|
+
const cloneCookieOptions = (options) => ({
|
|
4
|
+
...options,
|
|
5
|
+
expires: options.expires instanceof Date ? new Date(options.expires) : options.expires
|
|
6
|
+
});
|
|
7
|
+
const mergeCookieOptions = (defaults, overrides) => overrides ? { ...defaults, ...overrides } : defaults;
|
|
8
|
+
/** Cookie operations with shared defaults and request-local resolution at call time. */
|
|
9
|
+
export class UniversalCookieInstance {
|
|
10
|
+
defaults;
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.defaults = cloneCookieOptions(options);
|
|
13
|
+
}
|
|
14
|
+
set(name, value, options) {
|
|
15
|
+
UniversalCookie.set(name, value, mergeCookieOptions(this.defaults, options));
|
|
16
|
+
}
|
|
17
|
+
get(name) {
|
|
18
|
+
return UniversalCookie.get(name);
|
|
19
|
+
}
|
|
20
|
+
getAll() {
|
|
21
|
+
return UniversalCookie.getAll();
|
|
22
|
+
}
|
|
23
|
+
has(name) {
|
|
24
|
+
return UniversalCookie.has(name);
|
|
25
|
+
}
|
|
26
|
+
delete(name, options) {
|
|
27
|
+
UniversalCookie.delete(name, mergeCookieOptions(this.defaults, options));
|
|
28
|
+
}
|
|
29
|
+
clear(options) {
|
|
30
|
+
UniversalCookie.clear(mergeCookieOptions(this.defaults, options));
|
|
31
|
+
}
|
|
32
|
+
toCredentials() {
|
|
33
|
+
return UniversalCookie.toCredentials();
|
|
34
|
+
}
|
|
35
|
+
createNamedInstance(name) {
|
|
36
|
+
return new UniversalNamedCookieInstance(name, this);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Type-safe operations for one cookie name. */
|
|
40
|
+
export class UniversalNamedCookieInstance {
|
|
41
|
+
name;
|
|
42
|
+
cookies;
|
|
43
|
+
constructor(name, cookies) {
|
|
44
|
+
if (!name)
|
|
45
|
+
throw new TypeError('Cookie name must not be empty.');
|
|
46
|
+
this.name = name;
|
|
47
|
+
this.cookies = cookies;
|
|
48
|
+
}
|
|
49
|
+
set(value, options) {
|
|
50
|
+
this.cookies.set(this.name, value, options);
|
|
51
|
+
}
|
|
52
|
+
get() {
|
|
53
|
+
return this.cookies.get(this.name);
|
|
54
|
+
}
|
|
55
|
+
has() {
|
|
56
|
+
return this.cookies.has(this.name);
|
|
57
|
+
}
|
|
58
|
+
delete(options) {
|
|
59
|
+
this.cookies.delete(this.name, options);
|
|
60
|
+
}
|
|
61
|
+
clear(options) {
|
|
62
|
+
this.delete(options);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
3
65
|
/**
|
|
4
66
|
* Utility class for managing cookies in svelte ssr (browser and server).
|
|
5
67
|
* Supports setting, getting, deleting, checking, and clearing cookies.
|
|
6
68
|
* All methods are static and operate without creating instances.
|
|
7
69
|
*/
|
|
8
70
|
export class UniversalCookie {
|
|
71
|
+
/** Creates reusable cookie operations with shared defaults. */
|
|
72
|
+
static createInstance(options = {}) {
|
|
73
|
+
return new UniversalCookieInstance(options);
|
|
74
|
+
}
|
|
75
|
+
/** Creates reusable operations bound to one cookie name. */
|
|
76
|
+
static createNamedInstance(name, options = {}) {
|
|
77
|
+
return this.createInstance(options).createNamedInstance(name);
|
|
78
|
+
}
|
|
79
|
+
static serialize(value) {
|
|
80
|
+
if (typeof value === 'string')
|
|
81
|
+
return value;
|
|
82
|
+
const serialized = JSON.stringify(value);
|
|
83
|
+
if (serialized === undefined)
|
|
84
|
+
throw new TypeError('Cookie value is not JSON-serializable.');
|
|
85
|
+
return serialized;
|
|
86
|
+
}
|
|
87
|
+
static deserialize(value, decodeLegacy = false) {
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(value);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
if (!decodeLegacy)
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
let decodedValue;
|
|
96
|
+
try {
|
|
97
|
+
decodedValue = decodeURIComponent(value);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(decodedValue);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return decodedValue;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
9
109
|
/**
|
|
10
110
|
* Sets a cookie with the specified key, value, and options.
|
|
11
111
|
* Serializes non-string values as JSON.
|
|
@@ -17,21 +117,14 @@ export class UniversalCookie {
|
|
|
17
117
|
* @returns {void}
|
|
18
118
|
*/
|
|
19
119
|
static set(name, value, options) {
|
|
120
|
+
const serializedValue = this.serialize(value);
|
|
20
121
|
if (BROWSER) {
|
|
21
|
-
Cookies.set(name,
|
|
122
|
+
Cookies.set(name, serializedValue, options);
|
|
22
123
|
return;
|
|
23
124
|
}
|
|
24
125
|
else {
|
|
25
126
|
const event = RequestContext.current().event;
|
|
26
127
|
if (event) {
|
|
27
|
-
const encodedKey = encodeURIComponent(name);
|
|
28
|
-
let serializedValue;
|
|
29
|
-
if (typeof value === 'string') {
|
|
30
|
-
serializedValue = encodeURIComponent(value);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
serializedValue = encodeURIComponent(JSON.stringify(value));
|
|
34
|
-
}
|
|
35
128
|
let expires;
|
|
36
129
|
if (options?.expires !== undefined) {
|
|
37
130
|
if (typeof options.expires === 'number') {
|
|
@@ -43,7 +136,7 @@ export class UniversalCookie {
|
|
|
43
136
|
expires = options.expires;
|
|
44
137
|
}
|
|
45
138
|
}
|
|
46
|
-
event.cookies.set(
|
|
139
|
+
event.cookies.set(name, serializedValue, {
|
|
47
140
|
...options,
|
|
48
141
|
path: options?.path ?? '/',
|
|
49
142
|
httpOnly: options?.httpOnly ?? false,
|
|
@@ -64,22 +157,15 @@ export class UniversalCookie {
|
|
|
64
157
|
*/
|
|
65
158
|
static get(name) {
|
|
66
159
|
if (BROWSER) {
|
|
67
|
-
|
|
160
|
+
const value = Cookies.get(name, { parse: false });
|
|
161
|
+
return value === null ? undefined : this.deserialize(value);
|
|
68
162
|
}
|
|
69
163
|
else {
|
|
70
164
|
const event = RequestContext.current().event;
|
|
71
165
|
if (event) {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const decodedValue = decodeURIComponent(cookieValue);
|
|
76
|
-
try {
|
|
77
|
-
return JSON.parse(decodedValue);
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
return decodedValue;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
166
|
+
const cookieValue = event.cookies.get(name) ?? event.cookies.get(encodeURIComponent(name));
|
|
167
|
+
if (cookieValue !== undefined)
|
|
168
|
+
return this.deserialize(cookieValue, true);
|
|
83
169
|
return undefined;
|
|
84
170
|
}
|
|
85
171
|
return undefined;
|
|
@@ -94,7 +180,8 @@ export class UniversalCookie {
|
|
|
94
180
|
*/
|
|
95
181
|
static getAll() {
|
|
96
182
|
if (BROWSER) {
|
|
97
|
-
|
|
183
|
+
const allCookies = Cookies.getAll({ parse: false });
|
|
184
|
+
return Object.fromEntries(Object.entries(allCookies).map(([name, value]) => [name, this.deserialize(String(value))]));
|
|
98
185
|
}
|
|
99
186
|
else {
|
|
100
187
|
const event = RequestContext.current().event;
|
|
@@ -102,12 +189,7 @@ export class UniversalCookie {
|
|
|
102
189
|
if (event) {
|
|
103
190
|
const allCookies = event.cookies.getAll();
|
|
104
191
|
for (const singleCookie of allCookies) {
|
|
105
|
-
|
|
106
|
-
result[singleCookie.name] = JSON.parse(singleCookie.value);
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
result[singleCookie.name] = singleCookie.value;
|
|
110
|
-
}
|
|
192
|
+
result[singleCookie.name] = this.deserialize(singleCookie.value, true);
|
|
111
193
|
}
|
|
112
194
|
}
|
|
113
195
|
return result;
|
|
@@ -154,7 +236,10 @@ export class UniversalCookie {
|
|
|
154
236
|
static toCredentials() {
|
|
155
237
|
const all = this.getAll() ?? {};
|
|
156
238
|
return Object.entries(all)
|
|
157
|
-
.map(([
|
|
239
|
+
.map(([key, value]) => {
|
|
240
|
+
const serialized = typeof value === 'string' ? value : JSON.stringify(value);
|
|
241
|
+
return `${encodeURIComponent(key)}=${encodeURIComponent(serialized)}`;
|
|
242
|
+
})
|
|
158
243
|
.join('; ');
|
|
159
244
|
}
|
|
160
245
|
}
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import { EventBus } from '../../external/tools/index.js';
|
|
2
|
-
|
|
2
|
+
declare global {
|
|
3
|
+
namespace App {
|
|
4
|
+
interface CustomEvents {
|
|
5
|
+
readonly __azureNetEvents__?: never;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export type AppEventsList = App.CustomEvents extends {
|
|
10
|
+
list: infer TEvents extends object;
|
|
11
|
+
} ? TEvents : Record<never, never>;
|
|
12
|
+
export declare const AppEvents: () => EventBus<AppEventsList>;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
import { EventBus } from '../../external/tools/index.js';
|
|
2
2
|
import { createPresenter } from '../../external/edges/Edges.js';
|
|
3
|
-
export const AppEvents = createPresenter(() => {
|
|
4
|
-
const appEventBus = new EventBus({});
|
|
5
|
-
return appEventBus;
|
|
6
|
-
});
|
|
3
|
+
export const AppEvents = createPresenter(() => new EventBus({}));
|
package/dist/shared/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { UniversalCookie, type CookieOptions } from './cookie/index.js';
|
|
1
|
+
export { UniversalCookie, UniversalCookieInstance, UniversalNamedCookieInstance, type CookieOptions } from './cookie/index.js';
|
|
2
|
+
export { BackgroundTask } from './background-task/index.js';
|
|
2
3
|
export { AppEvents } from './event-bus/index.js';
|
|
3
4
|
export { ClassMirror } from './class-mirror/index.js';
|
|
4
5
|
export { createBoundaryProvider, cleanupProvider, type ProviderSettings } from './boundary-provider/index.js';
|
|
5
|
-
export
|
|
6
|
+
export * from './app/index.js';
|
|
6
7
|
export { useLogger, LoggerErrors, type ILoggerError, type ILoggerSettings } from './logger/index.js';
|
|
7
8
|
export { useRedirect, type IRedirectSettings, type RedirectStatus } from './redirect/index.js';
|
package/dist/shared/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { UniversalCookie } from './cookie/index.js';
|
|
1
|
+
export { UniversalCookie, UniversalCookieInstance, UniversalNamedCookieInstance } from './cookie/index.js';
|
|
2
|
+
export { BackgroundTask } from './background-task/index.js';
|
|
2
3
|
export { AppEvents } from './event-bus/index.js';
|
|
3
4
|
export { ClassMirror } from './class-mirror/index.js';
|
|
4
5
|
export { createBoundaryProvider, cleanupProvider } from './boundary-provider/index.js';
|
|
5
|
-
export
|
|
6
|
+
export * from './app/index.js';
|
|
6
7
|
export { useLogger, LoggerErrors } from './logger/index.js';
|
|
7
8
|
export { useRedirect } from './redirect/index.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppError, type IAppError } from '../app-error/index.js';
|
|
2
|
+
import { BackgroundTask } from '../background-task/index.js';
|
|
2
3
|
export declare enum LoggerErrors {
|
|
3
4
|
AzureNetKitInternal = 0,
|
|
4
5
|
AzureNetAppError = 1,
|
|
@@ -20,4 +21,4 @@ export interface ILoggerSettings {
|
|
|
20
21
|
filterLog?: (error: ILoggerError) => boolean;
|
|
21
22
|
includeOnly?: LoggerErrors[];
|
|
22
23
|
}
|
|
23
|
-
export declare const useLogger: (error: unknown, settings: ILoggerSettings) => void
|
|
24
|
+
export declare const useLogger: (error: unknown, settings: ILoggerSettings) => BackgroundTask<void>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AppError, AzureNetKitInternalError } from '../app-error/index.js';
|
|
2
2
|
import { BROWSER } from '../../external/tools/index.js';
|
|
3
3
|
import { RequestContext } from '../../external/edges/ServerContext.js';
|
|
4
|
+
import { BackgroundTask } from '../background-task/index.js';
|
|
4
5
|
export var LoggerErrors;
|
|
5
6
|
(function (LoggerErrors) {
|
|
6
7
|
LoggerErrors[LoggerErrors["AzureNetKitInternal"] = 0] = "AzureNetKitInternal";
|
|
@@ -50,24 +51,28 @@ const getFetcher = () => {
|
|
|
50
51
|
export const useLogger = (error, settings) => {
|
|
51
52
|
const preparedError = prepareError(error);
|
|
52
53
|
if (settings.filterLog && settings.filterLog(preparedError)) {
|
|
53
|
-
return;
|
|
54
|
+
return BackgroundTask.run(() => undefined);
|
|
54
55
|
}
|
|
55
56
|
if (settings.includeOnly && !settings.includeOnly.includes(preparedError.type)) {
|
|
56
|
-
return;
|
|
57
|
+
return BackgroundTask.run(() => undefined);
|
|
57
58
|
}
|
|
58
59
|
const prefix = settings?.prefix ?? '[Logger]';
|
|
59
60
|
const errorMessage = prefix + preparedError.message + (settings?.joinToLog ? settings.joinToLog(preparedError) : '');
|
|
60
61
|
console.log(errorMessage);
|
|
61
|
-
if (settings.collector)
|
|
62
|
-
|
|
62
|
+
if (!settings.collector)
|
|
63
|
+
return BackgroundTask.run(() => undefined);
|
|
64
|
+
const { collector } = settings;
|
|
65
|
+
return BackgroundTask.run(async () => {
|
|
63
66
|
try {
|
|
64
|
-
|
|
65
|
-
settings.collector?.onError?.(err);
|
|
66
|
-
return;
|
|
67
|
-
});
|
|
67
|
+
await getFetcher()(collector.request(preparedError));
|
|
68
68
|
}
|
|
69
69
|
catch (err) {
|
|
70
|
-
|
|
70
|
+
try {
|
|
71
|
+
collector.onError?.(err);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
71
76
|
}
|
|
72
|
-
}
|
|
77
|
+
});
|
|
73
78
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ObjectUtil } from '../../external/tools/index.js';
|
|
2
|
+
import { cloneStateValue } from '../shared/cloneStateValue.js';
|
|
2
3
|
export const createActiveForm = (onSubmit, config) => {
|
|
3
4
|
const isPromise = (value) => {
|
|
4
5
|
return typeof value?.then === 'function';
|
|
5
6
|
};
|
|
6
7
|
let initial = {};
|
|
7
|
-
let formData = $state(
|
|
8
|
+
let formData = $state(cloneStateValue(initial));
|
|
8
9
|
let formErrors = $state({});
|
|
9
10
|
let pending = $state(false);
|
|
10
11
|
let submitRunId = 0;
|
|
@@ -15,18 +16,18 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
15
16
|
const source = config?.initialData;
|
|
16
17
|
if (!source) {
|
|
17
18
|
initial = {};
|
|
18
|
-
formData =
|
|
19
|
+
formData = cloneStateValue(initial);
|
|
19
20
|
formErrors = {};
|
|
20
|
-
return initial;
|
|
21
|
+
return cloneStateValue(initial);
|
|
21
22
|
}
|
|
22
23
|
const value = source();
|
|
23
24
|
const nextInitial = isPromise(value) ? await value : value;
|
|
24
25
|
if (runId !== initialLoadRunId)
|
|
25
|
-
return initial;
|
|
26
|
-
initial = (nextInitial ?? {});
|
|
27
|
-
formData =
|
|
26
|
+
return cloneStateValue(initial);
|
|
27
|
+
initial = cloneStateValue((nextInitial ?? {}));
|
|
28
|
+
formData = cloneStateValue(initial);
|
|
28
29
|
formErrors = {};
|
|
29
|
-
return initial;
|
|
30
|
+
return cloneStateValue(initial);
|
|
30
31
|
};
|
|
31
32
|
const ready = loadInitialData();
|
|
32
33
|
const abortedResponse = () => ({
|
|
@@ -45,7 +46,7 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
45
46
|
formData = {};
|
|
46
47
|
break;
|
|
47
48
|
case 'initial':
|
|
48
|
-
formData =
|
|
49
|
+
formData = cloneStateValue(initial);
|
|
49
50
|
break;
|
|
50
51
|
case 'reloadInitial':
|
|
51
52
|
await loadInitialData();
|
|
@@ -70,7 +71,7 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
70
71
|
if (aborted || runId !== submitRunId)
|
|
71
72
|
return abortedResponse();
|
|
72
73
|
}
|
|
73
|
-
const result = await onSubmit(
|
|
74
|
+
const result = await onSubmit(cloneStateValue(formData));
|
|
74
75
|
if (runId !== submitRunId)
|
|
75
76
|
return result;
|
|
76
77
|
if (result.success) {
|
|
@@ -124,6 +124,9 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
124
124
|
}
|
|
125
125
|
await start('manual');
|
|
126
126
|
};
|
|
127
|
+
const refresh = async () => {
|
|
128
|
+
await start('manual');
|
|
129
|
+
};
|
|
127
130
|
if (BROWSER) {
|
|
128
131
|
const signalKey = key ?? asyncSignalManager.generateKey();
|
|
129
132
|
const callback = (source) => start(source);
|
|
@@ -163,7 +166,7 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
163
166
|
return start('auto');
|
|
164
167
|
},
|
|
165
168
|
execute,
|
|
166
|
-
refresh
|
|
169
|
+
refresh,
|
|
167
170
|
reset: () => {
|
|
168
171
|
currentRunId += 1;
|
|
169
172
|
abortController?.abort();
|
|
@@ -1,24 +1,55 @@
|
|
|
1
|
-
import { ObjectUtil } from '../../external/tools/index.js';
|
|
2
1
|
import { untrack } from 'svelte';
|
|
2
|
+
import { ObjectUtil } from '../../external/tools/index.js';
|
|
3
|
+
import { cloneStateValue } from '../shared/cloneStateValue.js';
|
|
4
|
+
const trackDeep = (value, seen = new WeakSet()) => {
|
|
5
|
+
if (value === null || typeof value !== 'object' || seen.has(value))
|
|
6
|
+
return;
|
|
7
|
+
seen.add(value);
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
for (const item of value)
|
|
10
|
+
trackDeep(item, seen);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (value instanceof Map) {
|
|
14
|
+
for (const [key, item] of value) {
|
|
15
|
+
trackDeep(key, seen);
|
|
16
|
+
trackDeep(item, seen);
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (value instanceof Set) {
|
|
21
|
+
for (const item of value)
|
|
22
|
+
trackDeep(item, seen);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const prototype = Object.getPrototypeOf(value);
|
|
26
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
27
|
+
return;
|
|
28
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
29
|
+
trackDeep(Reflect.get(value, key), seen);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
3
32
|
export const createQuery = (initialValue, options) => {
|
|
4
|
-
const baseInitial =
|
|
5
|
-
let data = $state(
|
|
6
|
-
const includeKeys = options?.onChange?.include ?? [];
|
|
33
|
+
const baseInitial = cloneStateValue(initialValue);
|
|
34
|
+
let data = $state(cloneStateValue(baseInitial));
|
|
35
|
+
const includeKeys = [...new Set(options?.onChange?.include ?? [])];
|
|
7
36
|
const hasWatch = Boolean(options?.onChange?.handler) && includeKeys.length > 0;
|
|
8
|
-
const
|
|
37
|
+
const lastSnapshots = new Map();
|
|
9
38
|
let onChangeController = null;
|
|
10
39
|
let onChangeRunId = 0;
|
|
11
40
|
if (hasWatch) {
|
|
12
41
|
includeKeys.forEach((key) => {
|
|
13
|
-
|
|
42
|
+
lastSnapshots.set(key, cloneStateValue(data[key]));
|
|
14
43
|
});
|
|
15
44
|
$effect(() => {
|
|
16
45
|
const changedKeys = [];
|
|
17
46
|
includeKeys.forEach((key) => {
|
|
18
47
|
const nextValue = data[key];
|
|
19
|
-
|
|
48
|
+
trackDeep(nextValue);
|
|
49
|
+
const nextSnapshot = cloneStateValue(nextValue);
|
|
50
|
+
if (!ObjectUtil.equals(lastSnapshots.get(key), nextSnapshot)) {
|
|
20
51
|
changedKeys.push(key);
|
|
21
|
-
|
|
52
|
+
lastSnapshots.set(key, nextSnapshot);
|
|
22
53
|
}
|
|
23
54
|
});
|
|
24
55
|
if (!changedKeys.length)
|
|
@@ -33,7 +64,7 @@ export const createQuery = (initialValue, options) => {
|
|
|
33
64
|
await options.onChange.handler({
|
|
34
65
|
changedKeys,
|
|
35
66
|
signal: localController.signal,
|
|
36
|
-
snapshot:
|
|
67
|
+
snapshot: cloneStateValue(data)
|
|
37
68
|
});
|
|
38
69
|
};
|
|
39
70
|
untrack(() => {
|
|
@@ -54,13 +85,13 @@ export const createQuery = (initialValue, options) => {
|
|
|
54
85
|
});
|
|
55
86
|
}
|
|
56
87
|
const reset = () => {
|
|
57
|
-
data =
|
|
88
|
+
data = cloneStateValue(baseInitial);
|
|
58
89
|
};
|
|
59
90
|
const patch = (value) => {
|
|
60
91
|
data = { ...data, ...value };
|
|
61
92
|
};
|
|
62
|
-
const snapshot = () =>
|
|
63
|
-
const initial = () =>
|
|
93
|
+
const snapshot = () => cloneStateValue(data);
|
|
94
|
+
const initial = () => cloneStateValue(baseInitial);
|
|
64
95
|
return {
|
|
65
96
|
get data() {
|
|
66
97
|
return data;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const preserveExtensibility = (source, target) => {
|
|
2
|
+
if (!Object.isExtensible(source))
|
|
3
|
+
Object.preventExtensions(target);
|
|
4
|
+
};
|
|
5
|
+
const cloneProperties = (source, target, seen, excluded) => {
|
|
6
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
7
|
+
if (key === excluded)
|
|
8
|
+
continue;
|
|
9
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(source, key);
|
|
10
|
+
if (!descriptor)
|
|
11
|
+
continue;
|
|
12
|
+
if ('value' in descriptor)
|
|
13
|
+
descriptor.value = cloneValue(descriptor.value, seen);
|
|
14
|
+
Reflect.defineProperty(target, key, descriptor);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const cloneValue = (value, seen) => {
|
|
18
|
+
if (value === null || typeof value !== 'object')
|
|
19
|
+
return value;
|
|
20
|
+
const cached = seen.get(value);
|
|
21
|
+
if (cached !== undefined)
|
|
22
|
+
return cached;
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
const result = new Array(value.length);
|
|
25
|
+
seen.set(value, result);
|
|
26
|
+
cloneProperties(value, result, seen, 'length');
|
|
27
|
+
const lengthDescriptor = Reflect.getOwnPropertyDescriptor(value, 'length');
|
|
28
|
+
if (lengthDescriptor)
|
|
29
|
+
Reflect.defineProperty(result, 'length', lengthDescriptor);
|
|
30
|
+
preserveExtensibility(value, result);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
if (value instanceof Date) {
|
|
34
|
+
const result = new Date(value.getTime());
|
|
35
|
+
seen.set(value, result);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Map) {
|
|
39
|
+
const result = new Map();
|
|
40
|
+
seen.set(value, result);
|
|
41
|
+
for (const [key, entryValue] of value) {
|
|
42
|
+
result.set(cloneValue(key, seen), cloneValue(entryValue, seen));
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
if (value instanceof Set) {
|
|
47
|
+
const result = new Set();
|
|
48
|
+
seen.set(value, result);
|
|
49
|
+
for (const entryValue of value)
|
|
50
|
+
result.add(cloneValue(entryValue, seen));
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
if (value instanceof RegExp) {
|
|
54
|
+
const result = new RegExp(value.source, value.flags);
|
|
55
|
+
result.lastIndex = value.lastIndex;
|
|
56
|
+
seen.set(value, result);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
if (typeof URL !== 'undefined' && value instanceof URL) {
|
|
60
|
+
const result = new URL(value.href);
|
|
61
|
+
seen.set(value, result);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
|
|
65
|
+
const result = new URLSearchParams(value);
|
|
66
|
+
seen.set(value, result);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
if (value instanceof ArrayBuffer) {
|
|
70
|
+
const result = value.slice(0);
|
|
71
|
+
seen.set(value, result);
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
if (typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer) {
|
|
75
|
+
const result = value.slice(0);
|
|
76
|
+
seen.set(value, result);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
if (ArrayBuffer.isView(value)) {
|
|
80
|
+
const buffer = cloneValue(value.buffer, seen);
|
|
81
|
+
const result = value instanceof DataView
|
|
82
|
+
? new DataView(buffer, value.byteOffset, value.byteLength)
|
|
83
|
+
: new value.constructor(buffer, value.byteOffset, value.length);
|
|
84
|
+
seen.set(value, result);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
const prototype = Object.getPrototypeOf(value);
|
|
88
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
89
|
+
// File, Blob, Promise and class instances cannot be cloned generically without
|
|
90
|
+
// losing internal slots or behavior. Keeping them is lossless and preserves DX.
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
const result = Object.create(prototype);
|
|
94
|
+
seen.set(value, result);
|
|
95
|
+
cloneProperties(value, result, seen);
|
|
96
|
+
preserveExtensibility(value, result);
|
|
97
|
+
return result;
|
|
98
|
+
};
|
|
99
|
+
/** Creates a detached graph from plain state while preserving opaque values. */
|
|
100
|
+
export const cloneStateValue = (value) => cloneValue(value, new WeakMap());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-net/kit",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Pixel1917",
|
|
6
6
|
"description": "Universal toolkit and library collection, developed as part of the Azure-net ecosystem",
|
|
@@ -73,15 +73,15 @@
|
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@sveltejs/kit": ">=2.
|
|
77
|
-
"svelte": ">=5.
|
|
76
|
+
"@sveltejs/kit": ">=2.57.1",
|
|
77
|
+
"svelte": ">=5.55.4"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@eslint/compat": "^2.0.5",
|
|
81
81
|
"@eslint/js": "^10.0.1",
|
|
82
82
|
"@playwright/test": "^1.59.1",
|
|
83
83
|
"@sveltejs/adapter-auto": "^7.0.1",
|
|
84
|
-
"@sveltejs/kit": "^2.
|
|
84
|
+
"@sveltejs/kit": "^2.70.2",
|
|
85
85
|
"@sveltejs/package": "^2.5.7",
|
|
86
86
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
87
87
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"prettier": "^3.8.3",
|
|
96
96
|
"prettier-plugin-svelte": "^3.5.1",
|
|
97
97
|
"publint": "^0.3.18",
|
|
98
|
-
"svelte": "^5.
|
|
98
|
+
"svelte": "^5.56.9",
|
|
99
99
|
"svelte-check": "^4.4.6",
|
|
100
100
|
"typescript": "^5.0.0",
|
|
101
101
|
"typescript-eslint": "^8.58.2",
|
|
@@ -126,9 +126,10 @@
|
|
|
126
126
|
"format": "prettier --write .",
|
|
127
127
|
"lint": "prettier --check . && eslint .",
|
|
128
128
|
"test:unit": "vitest --config vitest.config.ts",
|
|
129
|
+
"test:client": "vitest --config vitest.client.config.ts",
|
|
129
130
|
"test:integration": "vitest --config vitest.integration.config.ts --run",
|
|
130
|
-
"test": "
|
|
131
|
-
"test:e2e": "playwright test
|
|
131
|
+
"test": "pnpm test:unit -- --run && pnpm test:client -- --run && pnpm test:integration && pnpm test:e2e",
|
|
132
|
+
"test:e2e": "playwright test",
|
|
132
133
|
"commit": "pnpm format && git add ."
|
|
133
134
|
}
|
|
134
135
|
}
|