@sveltejs/kit 1.0.0-next.50 → 1.0.0-next.500
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/README.md +12 -9
- package/package.json +94 -67
- package/postinstall.js +38 -0
- package/scripts/special-types/$env+dynamic+private.md +10 -0
- package/scripts/special-types/$env+dynamic+public.md +8 -0
- package/scripts/special-types/$env+static+private.md +19 -0
- package/scripts/special-types/$env+static+public.md +7 -0
- package/scripts/special-types/$lib.md +5 -0
- package/src/cli.js +108 -0
- package/src/constants.js +7 -0
- package/src/core/adapt/builder.js +206 -0
- package/src/core/adapt/index.js +31 -0
- package/src/core/config/default-error.html +56 -0
- package/src/core/config/index.js +110 -0
- package/src/core/config/options.js +504 -0
- package/src/core/config/types.d.ts +1 -0
- package/src/core/env.js +121 -0
- package/src/core/generate_manifest/index.js +93 -0
- package/src/core/prerender/crawl.js +198 -0
- package/src/core/prerender/entities.js +2252 -0
- package/src/core/prerender/prerender.js +431 -0
- package/src/core/prerender/queue.js +80 -0
- package/src/core/sync/create_manifest_data/index.js +488 -0
- package/src/core/sync/create_manifest_data/types.d.ts +37 -0
- package/src/core/sync/sync.js +70 -0
- package/src/core/sync/utils.js +33 -0
- package/src/core/sync/write_ambient.js +53 -0
- package/src/core/sync/write_client_manifest.js +106 -0
- package/src/core/sync/write_matchers.js +25 -0
- package/src/core/sync/write_root.js +91 -0
- package/src/core/sync/write_tsconfig.js +195 -0
- package/src/core/sync/write_types/index.js +678 -0
- package/src/core/utils.js +70 -0
- package/src/exports/hooks/index.js +1 -0
- package/src/exports/hooks/sequence.js +44 -0
- package/src/exports/index.js +45 -0
- package/src/exports/node/index.js +173 -0
- package/src/exports/node/polyfills.js +41 -0
- package/src/exports/vite/build/build_server.js +378 -0
- package/src/exports/vite/build/build_service_worker.js +90 -0
- package/src/exports/vite/build/utils.js +180 -0
- package/src/exports/vite/dev/index.js +577 -0
- package/src/exports/vite/graph_analysis/index.js +277 -0
- package/src/exports/vite/graph_analysis/types.d.ts +5 -0
- package/src/exports/vite/graph_analysis/utils.js +30 -0
- package/src/exports/vite/index.js +598 -0
- package/src/exports/vite/preview/index.js +189 -0
- package/src/exports/vite/types.d.ts +3 -0
- package/src/exports/vite/utils.js +157 -0
- package/src/runtime/app/env.js +1 -0
- package/src/runtime/app/environment.js +11 -0
- package/src/runtime/app/forms.js +114 -0
- package/src/runtime/app/navigation.js +23 -0
- package/src/runtime/app/paths.js +1 -0
- package/src/runtime/app/stores.js +102 -0
- package/src/runtime/client/ambient.d.ts +26 -0
- package/src/runtime/client/client.js +1583 -0
- package/src/runtime/client/fetcher.js +107 -0
- package/src/runtime/client/parse.js +60 -0
- package/src/runtime/client/singletons.js +21 -0
- package/src/runtime/client/start.js +37 -0
- package/src/runtime/client/types.d.ts +84 -0
- package/src/runtime/client/utils.js +159 -0
- package/src/runtime/components/error.svelte +16 -0
- package/{assets → src/runtime}/components/layout.svelte +0 -0
- package/src/runtime/control.js +98 -0
- package/src/runtime/env/dynamic/private.js +1 -0
- package/src/runtime/env/dynamic/public.js +1 -0
- package/src/runtime/env-private.js +6 -0
- package/src/runtime/env-public.js +6 -0
- package/src/runtime/env.js +6 -0
- package/src/runtime/hash.js +16 -0
- package/src/runtime/paths.js +11 -0
- package/src/runtime/server/cookie.js +127 -0
- package/src/runtime/server/data/index.js +136 -0
- package/src/runtime/server/endpoint.js +90 -0
- package/src/runtime/server/index.js +340 -0
- package/src/runtime/server/page/actions.js +243 -0
- package/src/runtime/server/page/crypto.js +239 -0
- package/src/runtime/server/page/csp.js +250 -0
- package/src/runtime/server/page/fetch.js +301 -0
- package/src/runtime/server/page/index.js +304 -0
- package/src/runtime/server/page/load_data.js +124 -0
- package/src/runtime/server/page/render.js +342 -0
- package/src/runtime/server/page/respond_with_error.js +104 -0
- package/src/runtime/server/page/serialize_data.js +87 -0
- package/src/runtime/server/page/types.d.ts +41 -0
- package/src/runtime/server/utils.js +179 -0
- package/src/utils/array.js +9 -0
- package/src/utils/error.js +22 -0
- package/src/utils/escape.js +46 -0
- package/src/utils/filesystem.js +137 -0
- package/src/utils/functions.js +16 -0
- package/src/utils/http.js +55 -0
- package/src/utils/misc.js +1 -0
- package/src/utils/routing.js +117 -0
- package/src/utils/unit_test.js +11 -0
- package/src/utils/url.js +142 -0
- package/svelte-kit.js +1 -1
- package/types/ambient.d.ts +426 -0
- package/types/index.d.ts +444 -0
- package/types/internal.d.ts +378 -0
- package/types/private.d.ts +224 -0
- package/CHANGELOG.md +0 -484
- package/assets/components/error.svelte +0 -13
- package/assets/runtime/app/env.js +0 -5
- package/assets/runtime/app/navigation.js +0 -44
- package/assets/runtime/app/paths.js +0 -1
- package/assets/runtime/app/stores.js +0 -93
- package/assets/runtime/chunks/utils.js +0 -22
- package/assets/runtime/internal/singletons.js +0 -23
- package/assets/runtime/internal/start.js +0 -779
- package/assets/runtime/paths.js +0 -12
- package/dist/chunks/index.js +0 -3516
- package/dist/chunks/index2.js +0 -587
- package/dist/chunks/index3.js +0 -246
- package/dist/chunks/index4.js +0 -528
- package/dist/chunks/index5.js +0 -763
- package/dist/chunks/index6.js +0 -322
- package/dist/chunks/standard.js +0 -99
- package/dist/chunks/utils.js +0 -83
- package/dist/cli.js +0 -550
- package/dist/ssr.js +0 -2588
- package/types.d.ts +0 -89
- package/types.internal.d.ts +0 -191
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import mime from 'mime';
|
|
4
|
+
import { runtime_directory } from '../../utils.js';
|
|
5
|
+
import { posixify } from '../../../utils/filesystem.js';
|
|
6
|
+
import { parse_route_id, affects_path } from '../../../utils/routing.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {{
|
|
10
|
+
* config: import('types').ValidatedConfig;
|
|
11
|
+
* fallback?: string;
|
|
12
|
+
* cwd?: string;
|
|
13
|
+
* }} opts
|
|
14
|
+
* @returns {import('types').ManifestData}
|
|
15
|
+
*/
|
|
16
|
+
export default function create_manifest_data({
|
|
17
|
+
config,
|
|
18
|
+
fallback = `${runtime_directory}/components`,
|
|
19
|
+
cwd = process.cwd()
|
|
20
|
+
}) {
|
|
21
|
+
const assets = create_assets(config);
|
|
22
|
+
const matchers = create_matchers(config, cwd);
|
|
23
|
+
const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
assets,
|
|
27
|
+
matchers,
|
|
28
|
+
nodes,
|
|
29
|
+
routes
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {import('types').ValidatedConfig} config
|
|
35
|
+
*/
|
|
36
|
+
function create_assets(config) {
|
|
37
|
+
return list_files(config.kit.files.assets).map((file) => ({
|
|
38
|
+
file,
|
|
39
|
+
size: fs.statSync(path.resolve(config.kit.files.assets, file)).size,
|
|
40
|
+
type: mime.getType(file)
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('types').ValidatedConfig} config
|
|
46
|
+
* @param {string} cwd
|
|
47
|
+
*/
|
|
48
|
+
function create_matchers(config, cwd) {
|
|
49
|
+
const params_base = path.relative(cwd, config.kit.files.params);
|
|
50
|
+
|
|
51
|
+
/** @type {Record<string, string>} */
|
|
52
|
+
const matchers = {};
|
|
53
|
+
if (fs.existsSync(config.kit.files.params)) {
|
|
54
|
+
for (const file of fs.readdirSync(config.kit.files.params)) {
|
|
55
|
+
const ext = path.extname(file);
|
|
56
|
+
if (!config.kit.moduleExtensions.includes(ext)) continue;
|
|
57
|
+
const type = file.slice(0, -ext.length);
|
|
58
|
+
|
|
59
|
+
if (/^\w+$/.test(type)) {
|
|
60
|
+
const matcher_file = path.join(params_base, file);
|
|
61
|
+
|
|
62
|
+
// Disallow same matcher with different extensions
|
|
63
|
+
if (matchers[type]) {
|
|
64
|
+
throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`);
|
|
65
|
+
} else {
|
|
66
|
+
matchers[type] = matcher_file;
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return matchers;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {import('types').ValidatedConfig} config
|
|
81
|
+
* @param {string} cwd
|
|
82
|
+
* @param {string} fallback
|
|
83
|
+
*/
|
|
84
|
+
function create_routes_and_nodes(cwd, config, fallback) {
|
|
85
|
+
/** @type {Map<string, import('types').RouteData>} */
|
|
86
|
+
const route_map = new Map();
|
|
87
|
+
|
|
88
|
+
/** @type {Map<string, import('./types').Part[][]>} */
|
|
89
|
+
const segment_map = new Map();
|
|
90
|
+
|
|
91
|
+
const routes_base = posixify(path.relative(cwd, config.kit.files.routes));
|
|
92
|
+
|
|
93
|
+
const valid_extensions = [...config.extensions, ...config.kit.moduleExtensions];
|
|
94
|
+
|
|
95
|
+
/** @type {import('types').PageNode[]} */
|
|
96
|
+
const nodes = [];
|
|
97
|
+
|
|
98
|
+
if (fs.existsSync(config.kit.files.routes)) {
|
|
99
|
+
/**
|
|
100
|
+
* @param {number} depth
|
|
101
|
+
* @param {string} id
|
|
102
|
+
* @param {string} segment
|
|
103
|
+
* @param {import('types').RouteData | null} parent
|
|
104
|
+
*/
|
|
105
|
+
const walk = (depth, id, segment, parent) => {
|
|
106
|
+
if (/\]\[/.test(id)) {
|
|
107
|
+
throw new Error(`Invalid route ${id} — parameters must be separated`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (count_occurrences('[', id) !== count_occurrences(']', id)) {
|
|
111
|
+
throw new Error(`Invalid route ${id} — brackets are unbalanced`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const { pattern, names, types } = parse_route_id(id);
|
|
115
|
+
|
|
116
|
+
const segments = id.split('/');
|
|
117
|
+
|
|
118
|
+
segment_map.set(
|
|
119
|
+
id,
|
|
120
|
+
segments
|
|
121
|
+
.filter((segment) => segment !== '' && affects_path(segment))
|
|
122
|
+
.map((segment) => {
|
|
123
|
+
/** @type {import('./types').Part[]} */
|
|
124
|
+
const parts = [];
|
|
125
|
+
segment.split(/\[(.+?)\]/).map((content, i) => {
|
|
126
|
+
const dynamic = !!(i % 2);
|
|
127
|
+
|
|
128
|
+
if (!content) return;
|
|
129
|
+
|
|
130
|
+
parts.push({
|
|
131
|
+
content,
|
|
132
|
+
dynamic,
|
|
133
|
+
rest: dynamic && content.startsWith('...'),
|
|
134
|
+
type: (dynamic && content.split('=')[1]) || null
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
return parts;
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
/** @type {import('types').RouteData} */
|
|
142
|
+
const route = {
|
|
143
|
+
id,
|
|
144
|
+
parent,
|
|
145
|
+
|
|
146
|
+
segment,
|
|
147
|
+
pattern,
|
|
148
|
+
names,
|
|
149
|
+
types,
|
|
150
|
+
|
|
151
|
+
layout: null,
|
|
152
|
+
error: null,
|
|
153
|
+
leaf: null,
|
|
154
|
+
page: null,
|
|
155
|
+
endpoint: null
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// important to do this before walking children, so that child
|
|
159
|
+
// routes appear later
|
|
160
|
+
route_map.set(id, route);
|
|
161
|
+
|
|
162
|
+
// if we don't do this, the route map becomes unwieldy to console.log
|
|
163
|
+
Object.defineProperty(route, 'parent', { enumerable: false });
|
|
164
|
+
|
|
165
|
+
const dir = path.join(cwd, routes_base, id);
|
|
166
|
+
|
|
167
|
+
// We can't use withFileTypes because of a NodeJs bug which returns wrong results
|
|
168
|
+
// with isDirectory() in case of symlinks: https://github.com/nodejs/node/issues/30646
|
|
169
|
+
const files = fs.readdirSync(dir).map((name) => ({
|
|
170
|
+
is_dir: fs.statSync(path.join(dir, name)).isDirectory(),
|
|
171
|
+
name
|
|
172
|
+
}));
|
|
173
|
+
|
|
174
|
+
// process files first
|
|
175
|
+
for (const file of files) {
|
|
176
|
+
if (file.is_dir) continue;
|
|
177
|
+
if (!file.name.startsWith('+')) continue;
|
|
178
|
+
if (!valid_extensions.find((ext) => file.name.endsWith(ext))) continue;
|
|
179
|
+
|
|
180
|
+
const project_relative = posixify(path.relative(cwd, path.join(dir, file.name)));
|
|
181
|
+
|
|
182
|
+
const item = analyze(
|
|
183
|
+
project_relative,
|
|
184
|
+
file.name,
|
|
185
|
+
config.extensions,
|
|
186
|
+
config.kit.moduleExtensions
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
if (item.kind === 'component') {
|
|
190
|
+
if (item.is_error) {
|
|
191
|
+
route.error = {
|
|
192
|
+
depth,
|
|
193
|
+
component: project_relative
|
|
194
|
+
};
|
|
195
|
+
} else if (item.is_layout) {
|
|
196
|
+
if (!route.layout) route.layout = { depth, child_pages: [] };
|
|
197
|
+
route.layout.component = project_relative;
|
|
198
|
+
if (item.uses_layout !== undefined) route.layout.parent_id = item.uses_layout;
|
|
199
|
+
} else {
|
|
200
|
+
if (!route.leaf) route.leaf = { depth };
|
|
201
|
+
route.leaf.component = project_relative;
|
|
202
|
+
if (item.uses_layout !== undefined) route.leaf.parent_id = item.uses_layout;
|
|
203
|
+
}
|
|
204
|
+
} else if (item.is_layout) {
|
|
205
|
+
if (!route.layout) route.layout = { depth, child_pages: [] };
|
|
206
|
+
route.layout[item.kind] = project_relative;
|
|
207
|
+
} else if (item.is_page) {
|
|
208
|
+
if (!route.leaf) route.leaf = { depth };
|
|
209
|
+
route.leaf[item.kind] = project_relative;
|
|
210
|
+
} else {
|
|
211
|
+
route.endpoint = {
|
|
212
|
+
file: project_relative
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// then handle children
|
|
218
|
+
for (const file of files) {
|
|
219
|
+
if (file.is_dir) {
|
|
220
|
+
walk(depth + 1, path.posix.join(id, file.name), file.name, route);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
walk(0, '', '', null);
|
|
226
|
+
|
|
227
|
+
const root = /** @type {import('types').RouteData} */ (route_map.get(''));
|
|
228
|
+
if (route_map.size === 1) {
|
|
229
|
+
if (!root.leaf && !root.error && !root.layout && !root.endpoint) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
// TODO adjust this error message for 1.0
|
|
232
|
+
// 'No routes found. If you are using a custom src/routes directory, make sure it is specified in svelte.config.js'
|
|
233
|
+
'The filesystem router API has changed, see https://github.com/sveltejs/kit/discussions/5774 for details'
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
// If there's no routes directory, we'll just create a single empty route. This ensures the root layout and
|
|
239
|
+
// error components are included in the manifest, which is needed for subsequent build/dev commands to work
|
|
240
|
+
route_map.set('', {
|
|
241
|
+
id: '',
|
|
242
|
+
segment: '',
|
|
243
|
+
pattern: /^$/,
|
|
244
|
+
names: [],
|
|
245
|
+
types: [],
|
|
246
|
+
parent: null,
|
|
247
|
+
layout: null,
|
|
248
|
+
error: null,
|
|
249
|
+
leaf: null,
|
|
250
|
+
page: null,
|
|
251
|
+
endpoint: null
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const root = /** @type {import('types').RouteData} */ (route_map.get(''));
|
|
256
|
+
|
|
257
|
+
if (!root.layout?.component) {
|
|
258
|
+
if (!root.layout) root.layout = { depth: 0, child_pages: [] };
|
|
259
|
+
root.layout.component = posixify(path.relative(cwd, `${fallback}/layout.svelte`));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (!root.error?.component) {
|
|
263
|
+
if (!root.error) root.error = { depth: 0 };
|
|
264
|
+
root.error.component = posixify(path.relative(cwd, `${fallback}/error.svelte`));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// we do layouts/errors first as they are more likely to be reused,
|
|
268
|
+
// and smaller indexes take fewer bytes. also, this guarantees that
|
|
269
|
+
// the default error/layout are 0/1
|
|
270
|
+
route_map.forEach((route) => {
|
|
271
|
+
if (route.layout) nodes.push(route.layout);
|
|
272
|
+
if (route.error) nodes.push(route.error);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
/** @type {Map<string, string>} */
|
|
276
|
+
const conflicts = new Map();
|
|
277
|
+
|
|
278
|
+
route_map.forEach((route) => {
|
|
279
|
+
if (!route.leaf) return;
|
|
280
|
+
|
|
281
|
+
nodes.push(route.leaf);
|
|
282
|
+
|
|
283
|
+
const normalized = route.id.split('/').filter(affects_path).join('/');
|
|
284
|
+
|
|
285
|
+
if (conflicts.has(normalized)) {
|
|
286
|
+
throw new Error(`${conflicts.get(normalized)} and ${route.id} occupy the same route`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
conflicts.set(normalized, route.id);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
const indexes = new Map(nodes.map((node, i) => [node, i]));
|
|
293
|
+
|
|
294
|
+
route_map.forEach((route) => {
|
|
295
|
+
if (!route.leaf) return;
|
|
296
|
+
|
|
297
|
+
route.page = {
|
|
298
|
+
layouts: [],
|
|
299
|
+
errors: [],
|
|
300
|
+
leaf: /** @type {number} */ (indexes.get(route.leaf))
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
/** @type {import('types').RouteData | null} */
|
|
304
|
+
let current_route = route;
|
|
305
|
+
let current_node = route.leaf;
|
|
306
|
+
let parent_id = route.leaf.parent_id;
|
|
307
|
+
|
|
308
|
+
while (current_route) {
|
|
309
|
+
if (parent_id === undefined || current_route.segment === parent_id) {
|
|
310
|
+
if (current_route.layout || current_route.error) {
|
|
311
|
+
route.page.layouts.unshift(
|
|
312
|
+
current_route.layout ? indexes.get(current_route.layout) : undefined
|
|
313
|
+
);
|
|
314
|
+
route.page.errors.unshift(
|
|
315
|
+
current_route.error ? indexes.get(current_route.error) : undefined
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (current_route.layout) {
|
|
320
|
+
/** @type {import('types').PageNode[]} */ (current_route.layout.child_pages).push(
|
|
321
|
+
route.leaf
|
|
322
|
+
);
|
|
323
|
+
current_node.parent = current_node = current_route.layout;
|
|
324
|
+
parent_id = current_node.parent_id;
|
|
325
|
+
} else {
|
|
326
|
+
parent_id = undefined;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
current_route = current_route.parent;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (parent_id !== undefined) {
|
|
334
|
+
throw new Error(`${current_node.component} references missing segment "${parent_id}"`);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const routes = Array.from(route_map.values()).sort((a, b) => compare(a, b, segment_map));
|
|
339
|
+
|
|
340
|
+
return { nodes, routes };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* @param {string} project_relative
|
|
345
|
+
* @param {string} file
|
|
346
|
+
* @param {string[]} component_extensions
|
|
347
|
+
* @param {string[]} module_extensions
|
|
348
|
+
* @returns {import('./types').RouteFile}
|
|
349
|
+
*/
|
|
350
|
+
function analyze(project_relative, file, component_extensions, module_extensions) {
|
|
351
|
+
const component_extension = component_extensions.find((ext) => file.endsWith(ext));
|
|
352
|
+
if (component_extension) {
|
|
353
|
+
const name = file.slice(0, -component_extension.length);
|
|
354
|
+
const pattern = /^\+(?:(page(?:@(.*))?)|(layout(?:@(.*))?)|(error))$/;
|
|
355
|
+
const match = pattern.exec(name);
|
|
356
|
+
if (!match) {
|
|
357
|
+
// TODO remove for 1.0
|
|
358
|
+
if (/^\+layout-/.test(name)) {
|
|
359
|
+
throw new Error(
|
|
360
|
+
`${project_relative} should be reimplemented with layout groups: https://kit.svelte.dev/docs/advanced-routing#advanced-layouts`
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
kind: 'component',
|
|
369
|
+
is_page: !!match[1],
|
|
370
|
+
is_layout: !!match[3],
|
|
371
|
+
is_error: !!match[5],
|
|
372
|
+
uses_layout: match[2] ?? match[4]
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const module_extension = module_extensions.find((ext) => file.endsWith(ext));
|
|
377
|
+
if (module_extension) {
|
|
378
|
+
const name = file.slice(0, -module_extension.length);
|
|
379
|
+
const pattern =
|
|
380
|
+
/^\+(?:(server)|(page(?:(@[a-zA-Z0-9_-]*))?(\.server)?)|(layout(?:(@[a-zA-Z0-9_-]*))?(\.server)?))$/;
|
|
381
|
+
const match = pattern.exec(name);
|
|
382
|
+
if (!match) {
|
|
383
|
+
throw new Error(`Files prefixed with + are reserved (saw ${project_relative})`);
|
|
384
|
+
} else if (match[3] || match[6]) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
// prettier-ignore
|
|
387
|
+
`Only Svelte files can reference named layouts. Remove '${match[3] || match[6]}' from ${file} (at ${project_relative})`
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const kind = !!(match[1] || match[4] || match[7]) ? 'server' : 'shared';
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
kind,
|
|
395
|
+
is_page: !!match[2],
|
|
396
|
+
is_layout: !!match[5]
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
throw new Error(`Files and directories prefixed with + are reserved (saw ${project_relative})`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @param {import('types').RouteData} a
|
|
405
|
+
* @param {import('types').RouteData} b
|
|
406
|
+
* @param {Map<string, import('./types').Part[][]>} segment_map
|
|
407
|
+
*/
|
|
408
|
+
function compare(a, b, segment_map) {
|
|
409
|
+
const a_segments = /** @type {import('./types').Part[][]} */ (segment_map.get(a.id));
|
|
410
|
+
const b_segments = /** @type {import('./types').Part[][]} */ (segment_map.get(b.id));
|
|
411
|
+
|
|
412
|
+
const max_segments = Math.max(a_segments.length, b_segments.length);
|
|
413
|
+
for (let i = 0; i < max_segments; i += 1) {
|
|
414
|
+
const sa = a_segments[i];
|
|
415
|
+
const sb = b_segments[i];
|
|
416
|
+
|
|
417
|
+
// /x < /x/y, but /[...x]/y < /[...x]
|
|
418
|
+
if (!sa) return a.id.includes('[...') ? +1 : -1;
|
|
419
|
+
if (!sb) return b.id.includes('[...') ? -1 : +1;
|
|
420
|
+
|
|
421
|
+
const max_parts = Math.max(sa.length, sb.length);
|
|
422
|
+
for (let i = 0; i < max_parts; i += 1) {
|
|
423
|
+
const pa = sa[i];
|
|
424
|
+
const pb = sb[i];
|
|
425
|
+
|
|
426
|
+
// xy < x[y], but [x].json < [x]
|
|
427
|
+
if (pa === undefined) return pb.dynamic ? -1 : +1;
|
|
428
|
+
if (pb === undefined) return pa.dynamic ? +1 : -1;
|
|
429
|
+
|
|
430
|
+
// x < [x]
|
|
431
|
+
if (pa.dynamic !== pb.dynamic) {
|
|
432
|
+
return pa.dynamic ? +1 : -1;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (pa.dynamic) {
|
|
436
|
+
// [x] < [...x]
|
|
437
|
+
if (pa.rest !== pb.rest) {
|
|
438
|
+
return pa.rest ? +1 : -1;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// [x=type] < [x]
|
|
442
|
+
if (!!pa.type !== !!pb.type) {
|
|
443
|
+
return pa.type ? -1 : +1;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (!!a.endpoint !== !!b.endpoint) {
|
|
450
|
+
return a.endpoint ? -1 : +1;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return a < b ? -1 : 1;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** @param {string} dir */
|
|
457
|
+
function list_files(dir) {
|
|
458
|
+
/** @type {string[]} */
|
|
459
|
+
const files = [];
|
|
460
|
+
|
|
461
|
+
/** @param {string} current */
|
|
462
|
+
function walk(current) {
|
|
463
|
+
for (const file of fs.readdirSync(path.resolve(dir, current))) {
|
|
464
|
+
const child = path.posix.join(current, file);
|
|
465
|
+
if (fs.statSync(path.resolve(dir, child)).isDirectory()) {
|
|
466
|
+
walk(child);
|
|
467
|
+
} else {
|
|
468
|
+
files.push(child);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (fs.existsSync(dir)) walk('');
|
|
474
|
+
|
|
475
|
+
return files;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* @param {string} needle
|
|
480
|
+
* @param {string} haystack
|
|
481
|
+
*/
|
|
482
|
+
function count_occurrences(needle, haystack) {
|
|
483
|
+
let count = 0;
|
|
484
|
+
for (let i = 0; i < haystack.length; i += 1) {
|
|
485
|
+
if (haystack[i] === needle) count += 1;
|
|
486
|
+
}
|
|
487
|
+
return count;
|
|
488
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PageNode } from 'types';
|
|
2
|
+
|
|
3
|
+
interface Part {
|
|
4
|
+
content: string;
|
|
5
|
+
dynamic: boolean;
|
|
6
|
+
rest: boolean;
|
|
7
|
+
type: string | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface RouteTreeNode {
|
|
11
|
+
error: PageNode | undefined;
|
|
12
|
+
layout: PageNode | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type RouteTree = Map<string, RouteTreeNode>;
|
|
16
|
+
|
|
17
|
+
interface RouteComponent {
|
|
18
|
+
kind: 'component';
|
|
19
|
+
is_page: boolean;
|
|
20
|
+
is_layout: boolean;
|
|
21
|
+
is_error: boolean;
|
|
22
|
+
uses_layout: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface RouteSharedModule {
|
|
26
|
+
kind: 'shared';
|
|
27
|
+
is_page: boolean;
|
|
28
|
+
is_layout: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface RouteServerModule {
|
|
32
|
+
kind: 'server';
|
|
33
|
+
is_page: boolean;
|
|
34
|
+
is_layout: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type RouteFile = RouteComponent | RouteSharedModule | RouteServerModule;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import create_manifest_data from './create_manifest_data/index.js';
|
|
4
|
+
import { write_client_manifest } from './write_client_manifest.js';
|
|
5
|
+
import { write_matchers } from './write_matchers.js';
|
|
6
|
+
import { write_root } from './write_root.js';
|
|
7
|
+
import { write_tsconfig } from './write_tsconfig.js';
|
|
8
|
+
import { write_types, write_all_types } from './write_types/index.js';
|
|
9
|
+
import { write_ambient } from './write_ambient.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Initialize SvelteKit's generated files.
|
|
13
|
+
* @param {import('types').ValidatedConfig} config
|
|
14
|
+
* @param {string} mode
|
|
15
|
+
*/
|
|
16
|
+
export function init(config, mode) {
|
|
17
|
+
// TODO remove for 1.0
|
|
18
|
+
if (fs.existsSync('src/app.d.ts')) {
|
|
19
|
+
const content = fs.readFileSync('src/app.d.ts', 'utf-8');
|
|
20
|
+
if (content.includes('PageError')) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
'App.PageError has been renamed to App.Error — please update your src/app.d.ts'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
write_tsconfig(config.kit);
|
|
28
|
+
write_ambient(config.kit, mode);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Update SvelteKit's generated files
|
|
33
|
+
* @param {import('types').ValidatedConfig} config
|
|
34
|
+
*/
|
|
35
|
+
export async function create(config) {
|
|
36
|
+
const manifest_data = create_manifest_data({ config });
|
|
37
|
+
|
|
38
|
+
const output = path.join(config.kit.outDir, 'generated');
|
|
39
|
+
|
|
40
|
+
write_client_manifest(config, manifest_data, output);
|
|
41
|
+
write_root(manifest_data, output);
|
|
42
|
+
write_matchers(manifest_data, output);
|
|
43
|
+
await write_all_types(config, manifest_data);
|
|
44
|
+
|
|
45
|
+
return { manifest_data };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Update SvelteKit's generated files in response to a single file content update.
|
|
50
|
+
* Do not call this when the file in question was created/deleted.
|
|
51
|
+
*
|
|
52
|
+
* @param {import('types').ValidatedConfig} config
|
|
53
|
+
* @param {import('types').ManifestData} manifest_data
|
|
54
|
+
* @param {string} file
|
|
55
|
+
*/
|
|
56
|
+
export async function update(config, manifest_data, file) {
|
|
57
|
+
await write_types(config, manifest_data, file);
|
|
58
|
+
|
|
59
|
+
return { manifest_data };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Run sync.init and sync.update in series, returning the result from sync.update.
|
|
64
|
+
* @param {import('types').ValidatedConfig} config
|
|
65
|
+
* @param {string} mode The Vite mode
|
|
66
|
+
*/
|
|
67
|
+
export async function all(config, mode) {
|
|
68
|
+
init(config, mode);
|
|
69
|
+
return await create(config);
|
|
70
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { mkdirp } from '../../utils/filesystem.js';
|
|
4
|
+
|
|
5
|
+
/** @type {Map<string, string>} */
|
|
6
|
+
const previous_contents = new Map();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} file
|
|
10
|
+
* @param {string} code
|
|
11
|
+
*/
|
|
12
|
+
export function write_if_changed(file, code) {
|
|
13
|
+
if (code !== previous_contents.get(file)) {
|
|
14
|
+
write(file, code);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} file
|
|
20
|
+
* @param {string} code
|
|
21
|
+
*/
|
|
22
|
+
export function write(file, code) {
|
|
23
|
+
previous_contents.set(file, code);
|
|
24
|
+
mkdirp(path.dirname(file));
|
|
25
|
+
fs.writeFileSync(file, code);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** @param {string} str */
|
|
29
|
+
export function trim(str) {
|
|
30
|
+
const indentation = /** @type {RegExpExecArray} */ (/\n?(\s*)/.exec(str))[1];
|
|
31
|
+
const pattern = new RegExp(`^${indentation}`, 'gm');
|
|
32
|
+
return str.replace(pattern, '').trim();
|
|
33
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { get_env } from '../../exports/vite/utils.js';
|
|
4
|
+
import { GENERATED_COMMENT } from '../../constants.js';
|
|
5
|
+
import { create_dynamic_types, create_static_types } from '../env.js';
|
|
6
|
+
import { write_if_changed } from './utils.js';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
const descriptions_dir = fileURLToPath(new URL('../../../scripts/special-types', import.meta.url));
|
|
10
|
+
|
|
11
|
+
/** @param {string} filename */
|
|
12
|
+
function read_description(filename) {
|
|
13
|
+
const content = fs.readFileSync(`${descriptions_dir}/${filename}`, 'utf8');
|
|
14
|
+
return `/**\n${content
|
|
15
|
+
.trim()
|
|
16
|
+
.split('\n')
|
|
17
|
+
.map((line) => ` * ${line}`)
|
|
18
|
+
.join('\n')}\n */`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {{ public: Record<string, string>, private: Record<string, string> }} env
|
|
23
|
+
*/
|
|
24
|
+
const template = (env) => `
|
|
25
|
+
${GENERATED_COMMENT}
|
|
26
|
+
|
|
27
|
+
/// <reference types="@sveltejs/kit" />
|
|
28
|
+
|
|
29
|
+
${read_description('$env+static+private.md')}
|
|
30
|
+
${create_static_types('$env/static/private', env.private)}
|
|
31
|
+
|
|
32
|
+
${read_description('$env+static+public.md')}
|
|
33
|
+
${create_static_types('$env/static/public', env.public)}
|
|
34
|
+
|
|
35
|
+
${read_description('$env+dynamic+private.md')}
|
|
36
|
+
${create_dynamic_types('$env/dynamic/private', env.private)}
|
|
37
|
+
|
|
38
|
+
${read_description('$env+dynamic+public.md')}
|
|
39
|
+
${create_dynamic_types('$env/dynamic/public', env.public)}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Writes ambient declarations including types reference to @sveltejs/kit,
|
|
44
|
+
* and the existing environment variables in process.env to
|
|
45
|
+
* $env/static/private and $env/static/public
|
|
46
|
+
* @param {import('types').ValidatedKitConfig} config
|
|
47
|
+
* @param {string} mode The Vite mode
|
|
48
|
+
*/
|
|
49
|
+
export function write_ambient(config, mode) {
|
|
50
|
+
const env = get_env(config.env, mode);
|
|
51
|
+
|
|
52
|
+
write_if_changed(path.join(config.outDir, 'ambient.d.ts'), template(env));
|
|
53
|
+
}
|