@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.20
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/package.json +58 -36
- package/src/cli.js +14 -11
- package/src/constants.js +6 -1
- package/src/core/adapt/builder.js +54 -60
- package/src/core/adapt/index.js +2 -5
- package/src/core/config/index.js +141 -76
- package/src/core/config/options.js +260 -260
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +143 -13
- package/src/core/generate_manifest/index.js +18 -15
- package/src/core/postbuild/analyse.js +7 -19
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +4 -2
- package/src/core/postbuild/prerender.js +193 -69
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +72 -52
- package/src/core/sync/sync.js +35 -26
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/utils.js +22 -2
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +105 -56
- package/src/core/sync/write_client_manifest.js +13 -28
- package/src/core/sync/write_env.js +7 -5
- package/src/core/sync/write_server.js +25 -33
- package/src/core/sync/write_tsconfig/index.js +274 -0
- package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
- package/src/core/sync/write_tsconfig/utils.js +77 -0
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +119 -116
- package/src/core/utils.js +30 -5
- package/src/exports/env/index.js +77 -0
- package/src/exports/env/public.d.ts +55 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/public.d.ts +194 -0
- package/src/exports/hooks/sequence.js +9 -6
- package/src/exports/index.js +53 -20
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +8 -5
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +37 -0
- package/src/exports/internal/server/telemetry.js +95 -0
- package/src/exports/internal/shared.js +90 -0
- package/src/exports/node/index.js +64 -22
- package/src/exports/params/index.js +70 -0
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +219 -1118
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +53 -64
- package/src/exports/vite/build/remote.js +24 -19
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +199 -125
- package/src/exports/vite/index.js +1514 -833
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +32 -24
- package/src/exports/vite/utils.js +83 -45
- package/src/pathname.js +55 -0
- package/src/runner.js +15 -0
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +3 -3
- package/src/runtime/app/{forms.js → forms/index.js} +73 -42
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +37 -37
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +34 -2
- package/src/runtime/app/paths/internal/server.js +6 -23
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -29
- package/src/runtime/app/paths/server.js +36 -17
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +2 -2
- package/src/runtime/app/server/public.d.ts +519 -0
- package/src/runtime/app/server/remote/command.js +13 -11
- package/src/runtime/app/server/remote/form.js +61 -39
- package/src/runtime/app/server/remote/prerender.js +45 -45
- package/src/runtime/app/server/remote/query.js +106 -108
- package/src/runtime/app/server/remote/requested.js +27 -19
- package/src/runtime/app/server/remote/shared.js +75 -75
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/client.js +4 -2
- package/src/runtime/app/state/index.js +7 -5
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/state/server.js +3 -0
- package/src/runtime/app/stores.js +15 -78
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +1336 -648
- package/src/runtime/client/constants.js +3 -6
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +25 -25
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +37 -61
- package/src/runtime/client/remote-functions/form.svelte.js +267 -178
- package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
- package/src/runtime/client/remote-functions/query/index.js +10 -17
- package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
- package/src/runtime/client/remote-functions/query/proxy.js +5 -5
- package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
- package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
- package/src/runtime/client/snapshots.js +147 -0
- package/src/runtime/client/state.svelte.js +94 -55
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/client/types.d.ts +13 -9
- package/src/runtime/client/utils.js +22 -110
- package/src/runtime/components/root.svelte +56 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +172 -61
- package/src/runtime/pathname.js +20 -32
- package/src/runtime/props.svelte.js +72 -0
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/cookie.js +70 -53
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +48 -52
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +3 -4
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +160 -0
- package/src/runtime/server/fetch.js +31 -38
- package/src/runtime/server/index.js +90 -64
- package/src/runtime/server/internal.js +71 -0
- package/src/runtime/server/page/actions.js +84 -64
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +88 -104
- package/src/runtime/server/page/data_serializer.js +22 -23
- package/src/runtime/server/page/index.js +35 -53
- package/src/runtime/server/page/load_data.js +47 -54
- package/src/runtime/server/page/render.js +172 -238
- package/src/runtime/server/page/respond_with_error.js +16 -30
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +85 -26
- package/src/runtime/server/remote-functions.js +639 -0
- package/src/runtime/server/respond.js +188 -129
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/state.js +53 -0
- package/src/runtime/server/utils.js +12 -154
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +11 -1
- package/src/types/ambient.d.ts +87 -36
- package/src/types/global-private.d.ts +25 -25
- package/src/types/internal.d.ts +160 -150
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +28 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/filesystem.js +1 -23
- package/src/utils/fork.js +7 -2
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +9 -2
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +6 -7
- package/src/utils/params.js +67 -0
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +145 -73
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +33 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +2291 -2135
- package/types/index.d.ts.map +116 -108
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_root.js +0 -148
- package/src/core/sync/write_tsconfig.js +0 -250
- package/src/exports/internal/server.js +0 -22
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/runtime/telemetry/otel.js +0 -21
- package/src/runtime/telemetry/record_span.js +0 -65
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** @import { RemoteFormInput, RemoteForm, InvalidField } from '
|
|
2
|
-
/** @import { InternalRemoteFormIssue, MaybePromise, RemoteFormInternals } from 'types' */
|
|
1
|
+
/** @import { RemoteFormInput, RemoteForm, InvalidField } from '$app/server' */
|
|
2
|
+
/** @import { InternalRemoteFormIssue, MaybePromise, HasNonOptionalBoolean, RemoteFormInternals } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
4
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
5
5
|
import {
|
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
set_nested_value,
|
|
8
8
|
deep_set,
|
|
9
9
|
normalize_issue,
|
|
10
|
-
flatten_issues
|
|
10
|
+
flatten_issues,
|
|
11
|
+
parse_form_key
|
|
11
12
|
} from '../../../form-utils.js';
|
|
12
|
-
import { get_cache, run_remote_function } from './shared.js';
|
|
13
|
+
import { get_cache, get_implicit_lookup, run_remote_function } from './shared.js';
|
|
13
14
|
import { ValidationError } from '@sveltejs/kit/internal';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -44,7 +45,7 @@ import { ValidationError } from '@sveltejs/kit/internal';
|
|
|
44
45
|
* @template {StandardSchemaV1<RemoteFormInput, Record<string, any>>} Schema
|
|
45
46
|
* @template Output
|
|
46
47
|
* @overload
|
|
47
|
-
* @param {Schema} validate
|
|
48
|
+
* @param {true extends HasNonOptionalBoolean<StandardSchemaV1.InferInput<Schema>> ? 'Error: All booleans in form schemas must be optional (e.g. `v.optional(v.boolean(), false)`) because checkbox inputs do not send a false value when unchecked.' : Schema} validate
|
|
48
49
|
* @param {(data: StandardSchemaV1.InferOutput<Schema>, issue: InvalidField<StandardSchemaV1.InferInput<Schema>>) => MaybePromise<Output>} fn
|
|
49
50
|
* @returns {RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>}
|
|
50
51
|
* @since 2.27
|
|
@@ -71,8 +72,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
71
72
|
* @param {string | number | boolean} [key]
|
|
72
73
|
*/
|
|
73
74
|
function create_instance(key) {
|
|
74
|
-
/** @type {RemoteForm<Input, Output>} */
|
|
75
|
-
const instance = {};
|
|
75
|
+
const instance = /** @type {RemoteForm<Input, Output>} */ ({});
|
|
76
76
|
|
|
77
77
|
instance.method = 'POST';
|
|
78
78
|
|
|
@@ -88,8 +88,8 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
88
88
|
name: '',
|
|
89
89
|
id: '',
|
|
90
90
|
fn: async (data, meta, form_data) => {
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const output =
|
|
92
|
+
/** @type {{ submission: true, input?: Record<string, any>, issues?: InternalRemoteFormIssue[], result: Output }} */ ({});
|
|
93
93
|
|
|
94
94
|
// make it possible to differentiate between user submission and programmatic `field.set(...)` updates
|
|
95
95
|
output.submission = true;
|
|
@@ -102,15 +102,12 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
if (validated?.issues !== undefined) {
|
|
105
|
-
handle_issues(output, validated.issues, form_data);
|
|
105
|
+
handle_issues(output, validated.issues, form_data, __.id);
|
|
106
106
|
} else {
|
|
107
107
|
if (validated !== undefined) {
|
|
108
108
|
data = validated.value;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
state.remote.refreshes ??= new Map();
|
|
112
|
-
state.remote.reconnects ??= new Map();
|
|
113
|
-
|
|
114
111
|
const issue = create_issues();
|
|
115
112
|
|
|
116
113
|
try {
|
|
@@ -123,7 +120,7 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
123
120
|
);
|
|
124
121
|
} catch (e) {
|
|
125
122
|
if (e instanceof ValidationError) {
|
|
126
|
-
handle_issues(output, e.issues, form_data);
|
|
123
|
+
handle_issues(output, e.issues, form_data, __.id);
|
|
127
124
|
} else {
|
|
128
125
|
throw e;
|
|
129
126
|
}
|
|
@@ -133,7 +130,12 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
133
130
|
// We don't need to care about args or deduplicating calls, because uneval results are only relevant in full page reloads
|
|
134
131
|
// where only one form submission is active at the same time
|
|
135
132
|
if (!event.isRemoteRequest) {
|
|
136
|
-
get_cache(__, state)
|
|
133
|
+
const cache = get_cache(__, state);
|
|
134
|
+
cache[''] ??= output;
|
|
135
|
+
|
|
136
|
+
// register under the client-side action id so the output is serialized
|
|
137
|
+
// into the page, allowing the hydrated client to restore `result`/`issues`/`input`
|
|
138
|
+
get_implicit_lookup(__, state)[__.key ? `${__.id}/${__.key}` : __.id] = () => cache[''];
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
return output;
|
|
@@ -143,42 +145,55 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
143
145
|
Object.defineProperty(instance, '__', { value: __ });
|
|
144
146
|
|
|
145
147
|
Object.defineProperty(instance, 'action', {
|
|
146
|
-
get: () =>
|
|
148
|
+
get: () => {
|
|
149
|
+
const search = new URLSearchParams(get_request_store().event.url.search);
|
|
150
|
+
search.delete('/remote');
|
|
151
|
+
|
|
152
|
+
const query = search.toString();
|
|
153
|
+
const action_id = __.key ? `${__.id}/${encodeURIComponent(__.key)}` : __.id;
|
|
154
|
+
|
|
155
|
+
return `?${query ? `${query}&` : ''}/remote=${action_id}`;
|
|
156
|
+
},
|
|
147
157
|
enumerable: true
|
|
148
158
|
});
|
|
149
159
|
|
|
150
160
|
Object.defineProperty(instance, 'fields', {
|
|
151
161
|
get() {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
// the form instance is created once per module and shared across requests,
|
|
163
|
+
// so the current request's state has to be resolved at access time
|
|
164
|
+
return create_field_proxy({
|
|
165
|
+
form_id: __.id,
|
|
166
|
+
get: () => get_cache(__, get_request_store().state)?.['']?.input ?? {},
|
|
167
|
+
set: (path, value) => {
|
|
168
|
+
const cache = get_cache(__, get_request_store().state);
|
|
157
169
|
const entry = cache[''];
|
|
158
170
|
|
|
159
|
-
if (entry?.
|
|
171
|
+
if (entry?.submission) {
|
|
160
172
|
// don't override a submission
|
|
161
173
|
return;
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
if (path.length === 0) {
|
|
165
|
-
(cache[''] ??= {
|
|
177
|
+
(cache[''] ??= {}).input = value;
|
|
166
178
|
return;
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
const input = entry?.
|
|
181
|
+
const input = entry?.input ?? {};
|
|
170
182
|
deep_set(input, path.map(String), value);
|
|
171
|
-
(cache[''] ??= {
|
|
183
|
+
(cache[''] ??= {}).input = input;
|
|
172
184
|
},
|
|
173
|
-
() =>
|
|
174
|
-
|
|
185
|
+
get_issues: () =>
|
|
186
|
+
flatten_issues(get_cache(__, get_request_store().state)?.['']?.issues ?? []),
|
|
187
|
+
get_touched: () => ({}),
|
|
188
|
+
get_dirty: () => ({})
|
|
189
|
+
});
|
|
175
190
|
}
|
|
176
191
|
});
|
|
177
192
|
|
|
178
193
|
Object.defineProperty(instance, 'result', {
|
|
179
194
|
get() {
|
|
180
195
|
try {
|
|
181
|
-
return get_cache(__)?.['']?.
|
|
196
|
+
return get_cache(__, get_request_store().state)?.['']?.result;
|
|
182
197
|
} catch {
|
|
183
198
|
return undefined;
|
|
184
199
|
}
|
|
@@ -190,6 +205,10 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
190
205
|
get: () => 0
|
|
191
206
|
});
|
|
192
207
|
|
|
208
|
+
Object.defineProperty(instance, 'submitted', {
|
|
209
|
+
get: () => false
|
|
210
|
+
});
|
|
211
|
+
|
|
193
212
|
Object.defineProperty(instance, 'preflight', {
|
|
194
213
|
// preflight is a noop on the server
|
|
195
214
|
value: () => instance
|
|
@@ -217,11 +236,15 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
217
236
|
value: (key) => {
|
|
218
237
|
const { state } = get_request_store();
|
|
219
238
|
const cache_key = __.id + '|' + JSON.stringify(key);
|
|
239
|
+
/** @type {RemoteForm<Input, Output> & { __: RemoteFormInternals }} */
|
|
220
240
|
let instance = (state.remote.forms ??= new Map()).get(cache_key);
|
|
221
241
|
|
|
222
242
|
if (!instance) {
|
|
223
|
-
instance =
|
|
224
|
-
|
|
243
|
+
instance = /** @type {RemoteForm<Input, Output> & { __: RemoteFormInternals }} */ (
|
|
244
|
+
create_instance(key)
|
|
245
|
+
);
|
|
246
|
+
instance.__.id = __.id;
|
|
247
|
+
instance.__.key = JSON.stringify(key);
|
|
225
248
|
instance.__.name = __.name;
|
|
226
249
|
|
|
227
250
|
state.remote.forms.set(cache_key, instance);
|
|
@@ -242,8 +265,9 @@ export function form(validate_or_fn, maybe_fn) {
|
|
|
242
265
|
* @param {{ issues?: InternalRemoteFormIssue[], input?: Record<string, any>, result: any }} output
|
|
243
266
|
* @param {readonly StandardSchemaV1.Issue[]} issues
|
|
244
267
|
* @param {FormData | null} form_data - null if the form is progressively enhanced
|
|
268
|
+
* @param {string} form_id - hash/name of the form
|
|
245
269
|
*/
|
|
246
|
-
function handle_issues(output, issues, form_data) {
|
|
270
|
+
function handle_issues(output, issues, form_data, form_id) {
|
|
247
271
|
output.issues = issues.map((issue) => normalize_issue(issue, true));
|
|
248
272
|
|
|
249
273
|
// if it was a progressively-enhanced submission, we don't need
|
|
@@ -251,19 +275,17 @@ function handle_issues(output, issues, form_data) {
|
|
|
251
275
|
if (form_data) {
|
|
252
276
|
output.input = {};
|
|
253
277
|
|
|
254
|
-
for (
|
|
278
|
+
for (const field_name of form_data.keys()) {
|
|
255
279
|
// redact sensitive fields
|
|
256
|
-
if (/^[.\]]?_/.test(
|
|
257
|
-
|
|
258
|
-
const is_array = key.endsWith('[]');
|
|
259
|
-
const values = form_data.getAll(key).filter((value) => typeof value === 'string');
|
|
280
|
+
if (/^[.\]]?_/.test(field_name)) continue;
|
|
260
281
|
|
|
261
|
-
|
|
282
|
+
const values = form_data.getAll(field_name).filter((value) => typeof value === 'string');
|
|
283
|
+
const field = parse_form_key(form_id, field_name);
|
|
262
284
|
|
|
263
285
|
set_nested_value(
|
|
264
286
|
/** @type {Record<string, any>} */ (output.input),
|
|
265
|
-
|
|
266
|
-
is_array ? values : values[0]
|
|
287
|
+
field,
|
|
288
|
+
field.is_array ? values : values[0]
|
|
267
289
|
);
|
|
268
290
|
}
|
|
269
291
|
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
/** @import { RemoteResource, RemotePrerenderFunction } from '
|
|
2
|
-
/** @import { RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
|
|
1
|
+
/** @import { RemoteResource, RemotePrerenderFunction } from '$app/server' */
|
|
2
|
+
/** @import { RemoteFunctionResponse, RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
|
|
3
3
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { json } from '@sveltejs/kit';
|
|
5
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
6
6
|
import { get_request_store } from '@sveltejs/kit/internal/server';
|
|
7
|
-
import {
|
|
7
|
+
import { stringify_remote_arg } from '../../../shared.js';
|
|
8
|
+
import { parse, stringify } from '#app/internal/transport';
|
|
8
9
|
import { noop } from '../../../../utils/functions.js';
|
|
9
|
-
import { app_dir, base } from '
|
|
10
|
-
import {
|
|
11
|
-
create_validator,
|
|
12
|
-
get_cache,
|
|
13
|
-
get_response,
|
|
14
|
-
parse_remote_response,
|
|
15
|
-
run_remote_function
|
|
16
|
-
} from './shared.js';
|
|
10
|
+
import { app_dir, base } from '#app/paths';
|
|
11
|
+
import { create_validator, get_response, run_remote_function } from './shared.js';
|
|
17
12
|
|
|
18
13
|
/**
|
|
19
14
|
* Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call.
|
|
@@ -89,50 +84,55 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
89
84
|
|
|
90
85
|
/** @type {RemotePrerenderFunction<Input, Output> & { __: RemotePrerenderInternals }} */
|
|
91
86
|
const wrapper = (arg) => {
|
|
87
|
+
const { event, state } = get_request_store();
|
|
88
|
+
const payload = stringify_remote_arg(arg);
|
|
89
|
+
|
|
90
|
+
// `get_response` (as opposed to bare `get_cache`) also registers the call in the
|
|
91
|
+
// implicit lookup, so that the result is inlined into the page payload (`data.p`)
|
|
92
|
+
// and the client doesn't need to fetch it again upon hydration
|
|
92
93
|
/** @type {Promise<Output> & Partial<RemoteResource<Output>>} */
|
|
93
|
-
const promise = (async () => {
|
|
94
|
-
const { event, state } = get_request_store();
|
|
95
|
-
const payload = stringify_remote_arg(arg, state.transport);
|
|
94
|
+
const promise = get_response(__, payload, state, async () => {
|
|
96
95
|
const id = __.id;
|
|
97
96
|
const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`;
|
|
98
97
|
|
|
99
|
-
if (!state.prerendering && !
|
|
98
|
+
if (!state.prerendering && !__SVELTEKIT_DEV__ && !event.isRemoteRequest) {
|
|
99
|
+
/** @type {RemoteFunctionResponse | undefined} */
|
|
100
|
+
let prerendered;
|
|
101
|
+
|
|
100
102
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (!response.ok) {
|
|
110
|
-
throw new Error('Prerendered response not found');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const prerendered = await response.json();
|
|
114
|
-
|
|
115
|
-
if (prerendered.type === 'error') {
|
|
116
|
-
error(prerendered.status, prerendered.error);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return prerendered.result;
|
|
120
|
-
})
|
|
121
|
-
}).data;
|
|
122
|
-
|
|
123
|
-
return parse_remote_response(await promise, state.transport);
|
|
124
|
-
});
|
|
103
|
+
// TODO adapters can provide prerendered data more efficiently than
|
|
104
|
+
// fetching from the public internet
|
|
105
|
+
// `request.url` rather than `event.url`, which throws inside queries
|
|
106
|
+
const response = await fetch(new URL(url, event.request.url).href);
|
|
107
|
+
|
|
108
|
+
if (response.ok) {
|
|
109
|
+
prerendered = /** @type {RemoteFunctionResponse} */ (await response.json());
|
|
110
|
+
}
|
|
125
111
|
} catch {
|
|
126
112
|
// not available prerendered, fallback to normal function
|
|
127
113
|
}
|
|
114
|
+
|
|
115
|
+
if (prerendered) {
|
|
116
|
+
if (prerendered.type === 'error') {
|
|
117
|
+
throw new HandledHttpError(prerendered.error);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return parse(prerendered.data)._;
|
|
121
|
+
}
|
|
128
122
|
}
|
|
129
123
|
|
|
124
|
+
// during a prerender run, the same function might be invoked while rendering
|
|
125
|
+
// multiple pages — share the result across the entire run
|
|
130
126
|
if (state.prerendering?.remote_responses.has(url)) {
|
|
131
127
|
return /** @type {Promise<any>} */ (state.prerendering.remote_responses.get(url));
|
|
132
128
|
}
|
|
133
129
|
|
|
134
|
-
const promise =
|
|
135
|
-
|
|
130
|
+
const promise = run_remote_function(
|
|
131
|
+
event,
|
|
132
|
+
{ ...state, is_in_remote_prerender: true },
|
|
133
|
+
false,
|
|
134
|
+
() => validate(arg),
|
|
135
|
+
fn
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
if (state.prerendering) {
|
|
@@ -142,7 +142,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
142
142
|
const result = await promise;
|
|
143
143
|
|
|
144
144
|
if (state.prerendering) {
|
|
145
|
-
const body = { type: 'result',
|
|
145
|
+
const body = { type: 'result', data: stringify({ _: result }) };
|
|
146
146
|
state.prerendering.dependencies.set(url, {
|
|
147
147
|
body: JSON.stringify(body),
|
|
148
148
|
response: json(body)
|
|
@@ -151,7 +151,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
|
|
|
151
151
|
|
|
152
152
|
// TODO this is missing error/loading/current/status
|
|
153
153
|
return result;
|
|
154
|
-
})
|
|
154
|
+
});
|
|
155
155
|
|
|
156
156
|
promise.catch(noop);
|
|
157
157
|
|