@sveltejs/kit 1.0.0-next.415 → 1.0.0-next.418

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.415",
3
+ "version": "1.0.0-next.418",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -37,14 +37,14 @@
37
37
  "rollup": "^2.75.7",
38
38
  "svelte": "^3.48.0",
39
39
  "svelte-preprocess": "^4.10.6",
40
- "svelte2tsx": "~0.5.10",
40
+ "tiny-glob": "^0.2.9",
41
41
  "typescript": "^4.7.4",
42
42
  "uvu": "^0.5.3",
43
- "vite": "^3.0.0"
43
+ "vite": "3.0.2"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "svelte": "^3.44.0",
47
- "vite": "^3.0.0"
47
+ "vite": "3.0.2"
48
48
  },
49
49
  "bin": {
50
50
  "svelte-kit": "svelte-kit.js"
@@ -88,10 +88,9 @@
88
88
  "check": "tsc",
89
89
  "check:all": "tsc && pnpm -r --filter=\"./**\" check",
90
90
  "format": "npm run lint -- --write",
91
- "test": "npm run test:unit && npm run test:packaging && npm run test:integration",
91
+ "test": "npm run test:unit && npm run test:integration",
92
92
  "test:integration": "pnpm run -r --workspace-concurrency 1 --filter=\"./test/**\" test",
93
93
  "test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\" -i packaging",
94
- "test:packaging": "uvu src/packaging \"(spec\\.js|test[\\\\/]index\\.js)\"",
95
94
  "types": "node scripts/extract-types.js",
96
95
  "postinstall": "node svelte-kit.js sync"
97
96
  }
package/src/cli.js CHANGED
@@ -22,21 +22,6 @@ function handle_error(e) {
22
22
  const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
23
23
  const prog = sade('svelte-kit').version(pkg.version);
24
24
 
25
- prog
26
- .command('package')
27
- .describe('Create a package')
28
- .option('-w, --watch', 'Rerun when files change', false)
29
- .action(async ({ watch }) => {
30
- try {
31
- const config = await load_config();
32
- const packaging = await import('./packaging/index.js');
33
-
34
- await (watch ? packaging.watch(config) : packaging.build(config));
35
- } catch (error) {
36
- handle_error(error);
37
- }
38
- });
39
-
40
25
  prog
41
26
  .command('sync')
42
27
  .describe('Synchronise generated files')
@@ -78,6 +63,14 @@ prog
78
63
  replace('dev');
79
64
  replace('build');
80
65
  replace('preview');
66
+ prog
67
+ .command('package')
68
+ .describe('No longer available - use @sveltejs/package instead')
69
+ .action(() => {
70
+ console.error(
71
+ 'svelte-kit package has been removed. It now lives in its own npm package. See the PR on how to migrate: https://github.com/sveltejs/kit/pull/5730'
72
+ );
73
+ });
81
74
 
82
75
  prog.parse(process.argv, { unknown: (arg) => `Unknown option: ${arg}` });
83
76
 
@@ -173,13 +173,7 @@ const options = object(
173
173
 
174
174
  outDir: string('.svelte-kit'),
175
175
 
176
- package: object({
177
- dir: string('package'),
178
- // excludes all .d.ts and filename starting with _
179
- exports: fun((filepath) => !/^_|\/_|\.d\.ts$/.test(filepath)),
180
- files: fun(() => true),
181
- emitTypes: boolean(true)
182
- }),
176
+ package: error((keypath) => `${keypath} has been removed — use @sveltejs/package instead`),
183
177
 
184
178
  paths: object({
185
179
  base: validate('', (input, keypath) => {
@@ -172,12 +172,22 @@ export default function create_manifest_data({
172
172
  if (item.is_page) {
173
173
  const route = /** @type {import('types').PageData} */ (route_map.get(id));
174
174
 
175
- if (item.kind === 'component') {
176
- route.leaf.component = project_relative;
177
-
178
- const { layouts, errors } = trace(tree, id, item.uses_layout, project_relative);
175
+ // This ensures that layouts and errors are set for pages that have no Svelte file
176
+ // and only redirect or throw an error, but are set to the Svelte file definition if it exists.
177
+ // This ensures the proper error page is used and rendered in the proper layout.
178
+ if (item.kind === 'component' || route.layouts.length === 0) {
179
+ const { layouts, errors } = trace(
180
+ tree,
181
+ id,
182
+ item.kind === 'component' ? item.uses_layout : undefined,
183
+ project_relative
184
+ );
179
185
  route.layouts = layouts;
180
186
  route.errors = errors;
187
+ }
188
+
189
+ if (item.kind === 'component') {
190
+ route.leaf.component = project_relative;
181
191
  } else if (item.kind === 'server') {
182
192
  route.leaf.server = project_relative;
183
193
  } else {
@@ -246,12 +246,18 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
246
246
 
247
247
  exports.push(`export type PageData = ${data};`);
248
248
  if (load) {
249
- exports.push(`export type PageLoad = ${load};`);
249
+ exports.push(
250
+ `export type PageLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
251
+ );
252
+ exports.push('export type PageLoadEvent = Parameters<PageLoad>[0];');
250
253
  }
251
254
 
252
255
  exports.push(`export type PageServerData = ${server_data};`);
253
256
  if (server_load) {
254
- exports.push(`export type PageServerLoad = ${server_load};`);
257
+ exports.push(
258
+ `export type PageServerLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
259
+ );
260
+ exports.push('export type PageServerLoadEvent = Parameters<PageServerLoad>[0];');
255
261
  }
256
262
 
257
263
  if (group.leaf.server) {
@@ -292,12 +298,18 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
292
298
 
293
299
  exports.push(`export type LayoutData = ${data};`);
294
300
  if (load) {
295
- exports.push(`export type LayoutLoad = ${load};`);
301
+ exports.push(
302
+ `export type LayoutLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
303
+ );
304
+ exports.push('export type LayoutLoadEvent = Parameters<LayoutLoad>[0];');
296
305
  }
297
306
 
298
307
  exports.push(`export type LayoutServerData = ${server_data};`);
299
308
  if (server_load) {
300
- exports.push(`export type LayoutServerLoad = ${server_load};`);
309
+ exports.push(
310
+ `export type LayoutServerLoad<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
311
+ );
312
+ exports.push('export type LayoutServerLoadEvent = Parameters<LayoutServerLoad>[0];');
301
313
  }
302
314
  }
303
315
 
@@ -311,9 +323,15 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
311
323
  /** @type {string[]} */
312
324
  const load_exports = [];
313
325
 
326
+ /** @type {string[]} */
327
+ const load_event_exports = [];
328
+
314
329
  /** @type {string[]} */
315
330
  const server_load_exports = [];
316
331
 
332
+ /** @type {string[]} */
333
+ const server_load_event_exports = [];
334
+
317
335
  for (const [name, node] of group.named_layouts) {
318
336
  const { data, server_data, load, server_load, written_proxies } = process_node(
319
337
  ts,
@@ -326,26 +344,39 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
326
344
  data_exports.push(`export type ${name} = ${data};`);
327
345
  server_data_exports.push(`export type ${name} = ${server_data};`);
328
346
  if (load) {
329
- load_exports.push(`export type ${name} = ${load};`);
347
+ load_exports.push(
348
+ `export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
349
+ );
350
+ load_event_exports.push(`export type ${name} = Parameters<LayoutLoad.${name}>[0];`);
330
351
  }
331
352
  if (server_load) {
332
- server_load_exports.push(`export type ${name} = ${load};`);
353
+ server_load_exports.push(
354
+ `export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
355
+ );
356
+ server_load_event_exports.push(
357
+ `export type ${name} = Parameters<LayoutServerLoad.${name}>[0];`
358
+ );
333
359
  }
334
360
  }
335
361
 
336
362
  exports.push(`\nexport namespace LayoutData {\n\t${data_exports.join('\n\t')}\n}`);
337
363
  exports.push(`\nexport namespace LayoutLoad {\n\t${load_exports.join('\n\t')}\n}`);
364
+ exports.push(`\nexport namespace LayoutLoadEvent {\n\t${load_event_exports.join('\n\t')}\n}`);
338
365
  exports.push(
339
366
  `\nexport namespace LayoutServerData {\n\t${server_data_exports.join('\n\t')}\n}`
340
367
  );
341
368
  exports.push(
342
369
  `\nexport namespace LayoutServerLoad {\n\t${server_load_exports.join('\n\t')}\n}`
343
370
  );
371
+ exports.push(
372
+ `\nexport namespace LayoutServerLoadEvent {\n\t${server_load_event_exports.join('\n\t')}\n}`
373
+ );
344
374
  }
345
375
  }
346
376
 
347
377
  if (group.endpoint) {
348
378
  exports.push(`export type RequestHandler = Kit.RequestHandler<RouteParams>;`);
379
+ exports.push(`export type RequestEvent = Kit.RequestEvent<RouteParams>;`);
349
380
  }
350
381
 
351
382
  const output = [imports.join('\n'), declarations.join('\n'), exports.join('\n')]
@@ -384,7 +415,7 @@ function process_node(ts, node, outdir, params, groups) {
384
415
  }
385
416
 
386
417
  server_data = get_data_type(node.server, 'load', 'null', proxy);
387
- server_load = `Kit.ServerLoad<${params}, ${get_parent_type('LayoutServerData')}>`;
418
+ server_load = `Kit.ServerLoad<${params}, ${get_parent_type('LayoutServerData')}, OutputData>`;
388
419
 
389
420
  if (proxy) {
390
421
  const types = [];
@@ -415,7 +446,7 @@ function process_node(ts, node, outdir, params, groups) {
415
446
  }
416
447
 
417
448
  data = get_data_type(node.shared, 'load', server_data, proxy);
418
- load = `Kit.Load<${params}, ${server_data}, ${get_parent_type('LayoutData')}>`;
449
+ load = `Kit.Load<${params}, ${server_data}, ${get_parent_type('LayoutData')}, OutputData>`;
419
450
  } else {
420
451
  data = server_data;
421
452
  }
@@ -468,7 +499,7 @@ function process_node(ts, node, outdir, params, groups) {
468
499
  parent = parent_layout.parent;
469
500
  }
470
501
 
471
- let parent_str = parent_imports[0] || 'null';
502
+ let parent_str = parent_imports[0] || 'Record<never, never>';
472
503
  for (let i = 1; i < parent_imports.length; i++) {
473
504
  // Omit is necessary because a parent could have a property with the same key which would
474
505
  // cause a type conflict. At runtime the child overwrites the parent property in this case,
@@ -448,7 +448,7 @@ export function create_client({ target, base, trailing_slash }) {
448
448
  * url: URL;
449
449
  * params: Record<string, string>;
450
450
  * routeId: string | null;
451
- * server_data: import('types').JSONObject | null;
451
+ * server_data: Record<string, any> | null;
452
452
  * }} options
453
453
  * @returns {Promise<import('./types').BranchNode>}
454
454
  */
@@ -6,7 +6,7 @@ import {
6
6
  prefetch,
7
7
  prefetchRoutes
8
8
  } from '$app/navigation';
9
- import { CSRPageNode, CSRRoute, JSONObject } from 'types';
9
+ import { CSRPageNode, CSRRoute } from 'types';
10
10
  import { HttpError } from '../../index/private.js';
11
11
  import { SerializedHttpError } from '../server/page/types.js';
12
12
 
@@ -92,7 +92,7 @@ export interface ServerDataRedirected {
92
92
  export interface ServerDataLoaded {
93
93
  type: 'data';
94
94
  nodes: Array<{
95
- data?: JSONObject | null; // TODO or `-1` to indicate 'reuse cached data'?
95
+ data?: Record<string, any> | null; // TODO or `-1` to indicate 'reuse cached data'?
96
96
  status?: number;
97
97
  message?: string;
98
98
  error?: {
@@ -29,7 +29,9 @@ export async function render_endpoint(event, route) {
29
29
  return method_not_allowed(mod, method);
30
30
  }
31
31
 
32
- const response = await handler(event);
32
+ const response = await handler(
33
+ /** @type {import('types').RequestEvent<Record<string, any>>} */ (event)
34
+ );
33
35
 
34
36
  if (!(response instanceof Response)) {
35
37
  return new Response(
@@ -257,7 +257,7 @@ export async function respond(request, options, state) {
257
257
  event,
258
258
  node,
259
259
  parent: async () => {
260
- /** @type {import('types').JSONObject} */
260
+ /** @type {Record<string, any>} */
261
261
  const data = {};
262
262
  for (let j = 0; j < i; j += 1) {
263
263
  const parent = await promises[j];
@@ -137,7 +137,7 @@ export async function render_page(event, route, options, state, resolve_opts) {
137
137
  /** @type {Error | null} */
138
138
  let load_error = null;
139
139
 
140
- /** @type {Array<Promise<import('types').JSONObject | null>>} */
140
+ /** @type {Array<Promise<Record<string, any> | null>>} */
141
141
  const server_promises = nodes.map((node, i) => {
142
142
  if (load_error) {
143
143
  // if an error happens immediately, don't bother with the rest of the nodes
@@ -156,7 +156,7 @@ export async function render_page(event, route, options, state, resolve_opts) {
156
156
  event,
157
157
  node,
158
158
  parent: async () => {
159
- /** @type {import('types').JSONObject} */
159
+ /** @type {Record<string, any>} */
160
160
  const data = {};
161
161
  for (let j = 0; j < i; j += 1) {
162
162
  Object.assign(data, await server_promises[j]);
@@ -5,7 +5,7 @@ import { LoadURL, PrerenderingURL } from '../../../utils/url.js';
5
5
  * @param {{
6
6
  * event: import('types').RequestEvent;
7
7
  * node: import('types').SSRNode | undefined;
8
- * parent: () => Promise<import('types').JSONObject | null>;
8
+ * parent: () => Promise<Record<string, any>>;
9
9
  * }} opts
10
10
  */
11
11
  export async function load_server_data({ event, node, parent }) {
@@ -37,7 +37,7 @@ export async function load_server_data({ event, node, parent }) {
37
37
  * fetcher: typeof fetch;
38
38
  * node: import('types').SSRNode | undefined;
39
39
  * parent: () => Promise<Record<string, any>>;
40
- * server_data_promise: Promise<import('types').JSONObject | null>;
40
+ * server_data_promise: Promise<Record<string, any> | null>;
41
41
  * state: import('types').SSRState;
42
42
  * }} opts
43
43
  */
@@ -70,7 +70,7 @@ export async function load_data({ event, fetcher, node, parent, server_data_prom
70
70
 
71
71
  /** @param {Record<string, any>} object */
72
72
  async function unwrap_promises(object) {
73
- /** @type {import('types').JSONObject} */
73
+ /** @type {Record<string, any>} */
74
74
  const unwrapped = {};
75
75
 
76
76
  for (const key in object) {
@@ -86,7 +86,7 @@ export async function render_response({
86
86
  /** @type {import('types').Page} */
87
87
  page: {
88
88
  error,
89
- params: event.params,
89
+ params: /** @type {Record<string, any>} */ (event.params),
90
90
  routeId: event.routeId,
91
91
  status,
92
92
  url: state.prerendering ? new PrerenderingURL(event.url) : event.url,
@@ -1,4 +1,4 @@
1
- import { JSONValue, ResponseHeaders, SSRNode, CspDirectives } from 'types';
1
+ import { ResponseHeaders, SSRNode, CspDirectives } from 'types';
2
2
  import { HttpError } from '../../../index/private';
3
3
 
4
4
  export interface Fetched {
@@ -21,7 +21,7 @@ export interface FetchState {
21
21
  export type Loaded = {
22
22
  node: SSRNode;
23
23
  data: Record<string, any> | null;
24
- server_data: JSONValue;
24
+ server_data: any;
25
25
  };
26
26
 
27
27
  type CspMode = 'hash' | 'nonce' | 'auto';
@@ -37,7 +37,7 @@ const render_json_payload_script_regex = new RegExp(
37
37
  * Attribute names must be type-checked so we don't need to escape them.
38
38
  *
39
39
  * @param {import('types').PayloadScriptAttributes} attrs A list of attributes to be added to the element.
40
- * @param {import('types').JSONValue} payload The data to be carried by the element. Must be serializable to JSON.
40
+ * @param {any} payload The data to be carried by the element. Must be serializable to JSON.
41
41
  * @returns {string} The raw HTML of a script element carrying the JSON payload.
42
42
  * @example const html = render_json_payload_script({ type: 'data', url: '/data.json' }, { foo: 'bar' });
43
43
  */
@@ -286,6 +286,20 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) {
286
286
  }
287
287
  });
288
288
 
289
+ const runtime_base = runtime_directory.startsWith(process.cwd())
290
+ ? `/${path.relative('.', runtime_directory)}`
291
+ : `/@fs${
292
+ // Windows/Linux separation - Windows starts with a drive letter, we need a / in front there
293
+ runtime_directory.startsWith('/') ? '' : '/'
294
+ }${runtime_directory}`;
295
+
296
+ const { set_private_env } = await vite.ssrLoadModule(`${runtime_base}/env-private.js`);
297
+ const { set_public_env } = await vite.ssrLoadModule(`${runtime_base}/env-public.js`);
298
+
299
+ const env = get_env(vite_config.mode, svelte_config.kit.env.publicPrefix);
300
+ set_private_env(env.private);
301
+ set_public_env(env.public);
302
+
289
303
  return () => {
290
304
  const serve_static_middleware = vite.middlewares.stack.find(
291
305
  (middleware) =>
@@ -320,20 +334,6 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) {
320
334
  );
321
335
  }
322
336
 
323
- // For some reason using runtime_prefix here is buggy, since Vite will later load the modules
324
- // again with a slightly different url (with the drive letter) on windows
325
- const runtime_base = `/@fs${
326
- // Windows/Linux separation - Windows starts with a drive letter, we need a / in front there
327
- runtime_directory.startsWith('/') ? '' : '/'
328
- }${runtime_directory}`;
329
-
330
- const { set_private_env } = await vite.ssrLoadModule(`${runtime_base}/env-private.js`);
331
- const { set_public_env } = await vite.ssrLoadModule(`${runtime_base}/env-public.js`);
332
-
333
- const env = get_env(vite_config.mode, svelte_config.kit.env.publicPrefix);
334
- set_private_env(env.private);
335
- set_public_env(env.public);
336
-
337
337
  /** @type {Partial<import('types').Hooks>} */
338
338
  const user_hooks = resolve_entry(svelte_config.kit.files.hooks)
339
339
  ? await vite.ssrLoadModule(`/${svelte_config.kit.files.hooks}`)
package/types/index.d.ts CHANGED
@@ -7,8 +7,6 @@ import { CompileOptions } from 'svelte/types/compiler/interfaces';
7
7
  import {
8
8
  AdapterEntry,
9
9
  CspDirectives,
10
- JSONObject,
11
- JSONValue,
12
10
  Logger,
13
11
  MaybePromise,
14
12
  Prerendered,
@@ -109,6 +107,14 @@ export interface Config {
109
107
  extensions?: string[];
110
108
  kit?: KitConfig;
111
109
  preprocess?: any;
110
+ package?: {
111
+ source?: string;
112
+ dir?: string;
113
+ emitTypes?: boolean;
114
+ exports?: (filepath: string) => boolean;
115
+ files?: (filepath: string) => boolean;
116
+ };
117
+ [key: string]: any;
112
118
  }
113
119
 
114
120
  export interface KitConfig {
@@ -143,12 +149,6 @@ export interface KitConfig {
143
149
  allowed?: string[];
144
150
  };
145
151
  outDir?: string;
146
- package?: {
147
- dir?: string;
148
- emitTypes?: boolean;
149
- exports?(filepath: string): boolean;
150
- files?(filepath: string): boolean;
151
- };
152
152
  paths?: {
153
153
  assets?: string;
154
154
  base?: string;
@@ -193,18 +193,18 @@ export interface HandleError {
193
193
  * rather than using `Load` directly.
194
194
  */
195
195
  export interface Load<
196
- Params extends Record<string, string> = Record<string, string>,
197
- InputData extends JSONObject | null = JSONObject | null,
198
- ParentData extends Record<string, any> | null = Record<string, any> | null,
199
- OutputData extends Record<string, any> = Record<string, any>
196
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
197
+ InputData extends Record<string, any> | null = Record<string, any> | null,
198
+ ParentData extends Record<string, any> = Record<string, any>,
199
+ OutputData extends Record<string, any> | void = Record<string, any> | void
200
200
  > {
201
- (event: LoadEvent<Params, InputData, ParentData>): MaybePromise<OutputData | void>;
201
+ (event: LoadEvent<Params, InputData, ParentData>): MaybePromise<OutputData>;
202
202
  }
203
203
 
204
204
  export interface LoadEvent<
205
- Params extends Record<string, string> = Record<string, string>,
206
- Data extends JSONObject | null = JSONObject | null,
207
- ParentData extends Record<string, any> | null = Record<string, any> | null
205
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
206
+ Data extends Record<string, any> | null = Record<string, any> | null,
207
+ ParentData extends Record<string, any> = Record<string, any>
208
208
  > {
209
209
  fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
210
210
  params: Params;
@@ -234,7 +234,9 @@ export interface ParamMatcher {
234
234
  (param: string): boolean;
235
235
  }
236
236
 
237
- export interface RequestEvent<Params extends Record<string, string> = Record<string, string>> {
237
+ export interface RequestEvent<
238
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>
239
+ > {
238
240
  clientAddress: string;
239
241
  locals: App.Locals;
240
242
  params: Params;
@@ -259,8 +261,6 @@ export interface ResolveOptions {
259
261
  transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise<string | undefined>;
260
262
  }
261
263
 
262
- export type ResponseBody = JSONValue | Uint8Array | ReadableStream | Error;
263
-
264
264
  export class Server {
265
265
  constructor(manifest: SSRManifest);
266
266
  init(options: ServerInitOptions): void;
@@ -294,21 +294,23 @@ export interface SSRManifest {
294
294
  * rather than using `ServerLoad` directly.
295
295
  */
296
296
  export interface ServerLoad<
297
- Params extends Record<string, string> = Record<string, string>,
298
- ParentData extends JSONObject | null = JSONObject | null,
299
- OutputData extends JSONObject | void = JSONObject | void
297
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
298
+ ParentData extends Record<string, any> = Record<string, any>,
299
+ OutputData extends Record<string, any> | void = Record<string, any> | void
300
300
  > {
301
- (event: ServerLoadEvent<Params, ParentData>): MaybePromise<OutputData | void>;
301
+ (event: ServerLoadEvent<Params, ParentData>): MaybePromise<OutputData>;
302
302
  }
303
303
 
304
304
  export interface ServerLoadEvent<
305
- Params extends Record<string, string> = Record<string, string>,
306
- ParentData extends JSONObject | null = JSONObject | null
305
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
306
+ ParentData extends Record<string, any> = Record<string, any>
307
307
  > extends RequestEvent<Params> {
308
308
  parent: () => Promise<ParentData>;
309
309
  }
310
310
 
311
- export interface Action<Params extends Record<string, string> = Record<string, string>> {
311
+ export interface Action<
312
+ Params extends Partial<Record<string, string>> = Partial<Record<string, string>>
313
+ > {
312
314
  (event: RequestEvent<Params>): MaybePromise<
313
315
  | { status?: number; errors: Record<string, string>; location?: never }
314
316
  | { status?: never; errors?: never; location: string }
@@ -26,15 +26,6 @@ export interface AdapterEntry {
26
26
  }) => MaybePromise<void>;
27
27
  }
28
28
 
29
- // TODO is this still used?
30
- export type BodyValidator<T> = {
31
- [P in keyof T]: T[P] extends { [k: string]: unknown }
32
- ? BodyValidator<T[P]> // recurse when T[P] is an object
33
- : T[P] extends BigInt | Function | Symbol
34
- ? never
35
- : T[P];
36
- };
37
-
38
29
  // Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts
39
30
  //
40
31
  // MIT License
@@ -145,20 +136,6 @@ export interface CspDirectives {
145
136
 
146
137
  export type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
147
138
 
148
- export interface JSONObject {
149
- [key: string]: JSONValue;
150
- }
151
-
152
- export type JSONValue =
153
- | string
154
- | number
155
- | boolean
156
- | null
157
- | undefined
158
- | ToJSON
159
- | JSONValue[]
160
- | JSONObject;
161
-
162
139
  export interface Logger {
163
140
  (msg: string): void;
164
141
  success(msg: string): void;
@@ -229,8 +206,4 @@ export interface RouteSegment {
229
206
  rest: boolean;
230
207
  }
231
208
 
232
- export interface ToJSON {
233
- toJSON(...args: any[]): Exclude<JSONValue, ToJSON>;
234
- }
235
-
236
209
  export type TrailingSlash = 'never' | 'always' | 'ignore';
@@ -1,218 +0,0 @@
1
- import * as fs from 'fs';
2
- import { dirname, join, relative } from 'path';
3
- import colors from 'kleur';
4
- import chokidar from 'chokidar';
5
- import { preprocess } from 'svelte/compiler';
6
- import { copy, mkdirp, rimraf } from '../utils/filesystem.js';
7
- import { analyze, generate_pkg, resolve_lib_alias, scan, strip_lang_tags, write } from './utils.js';
8
- import { emit_dts, transpile_ts } from './typescript.js';
9
- import { write_tsconfig } from '../core/sync/write_tsconfig.js';
10
-
11
- const essential_files = ['README', 'LICENSE', 'CHANGELOG', '.gitignore', '.npmignore'];
12
-
13
- /**
14
- * @param {import('types').ValidatedConfig} config
15
- * @param {string} cwd
16
- */
17
- export async function build(config, cwd = process.cwd()) {
18
- const { lib } = config.kit.files;
19
- const { dir } = config.kit.package;
20
-
21
- if (!fs.existsSync(lib)) {
22
- throw new Error(`${lib} does not exist`);
23
- }
24
-
25
- rimraf(dir);
26
- mkdirp(dir);
27
-
28
- // Make sure generated tsconfig is up-to-date
29
- write_tsconfig(config.kit, cwd);
30
-
31
- const files = scan(config);
32
-
33
- if (config.kit.package.emitTypes) {
34
- await emit_dts(config, cwd, files);
35
- }
36
-
37
- const pkg = generate_pkg(cwd, files);
38
-
39
- if (!pkg.svelte && files.some((file) => file.is_svelte)) {
40
- // Several heuristics in Kit/vite-plugin-svelte to tell Vite to mark Svelte packages
41
- // rely on the "svelte" property. Vite/Rollup/Webpack plugin can all deal with it.
42
- // See https://github.com/sveltejs/kit/issues/1959 for more info and related threads.
43
- if (pkg.exports['.']) {
44
- const svelte_export =
45
- typeof pkg.exports['.'] === 'string'
46
- ? pkg.exports['.']
47
- : pkg.exports['.'].import || pkg.exports['.'].default;
48
- if (svelte_export) {
49
- pkg.svelte = svelte_export;
50
- } else {
51
- console.warn(
52
- 'Cannot generate a "svelte" entry point because the "." entry in "exports" is not a string. If you set it by hand, please also set one of the options as a "svelte" entry point\n'
53
- );
54
- }
55
- } else {
56
- console.warn(
57
- 'Cannot generate a "svelte" entry point because the "." entry in "exports" is missing. Please specify one or set a "svelte" entry point yourself\n'
58
- );
59
- }
60
- }
61
-
62
- write(join(dir, 'package.json'), JSON.stringify(pkg, null, 2));
63
-
64
- for (const file of files) {
65
- await process_file(config, file);
66
- }
67
-
68
- const whitelist = fs.readdirSync(cwd).filter((file) => {
69
- const lowercased = file.toLowerCase();
70
- return essential_files.some((name) => lowercased.startsWith(name.toLowerCase()));
71
- });
72
-
73
- for (const pathname of whitelist) {
74
- const full_path = join(cwd, pathname);
75
- if (fs.lstatSync(full_path).isDirectory()) continue; // just to be sure
76
-
77
- const package_path = join(dir, pathname);
78
- if (!fs.existsSync(package_path)) fs.copyFileSync(full_path, package_path);
79
- }
80
-
81
- const from = relative(cwd, lib);
82
- const to = relative(cwd, dir);
83
- console.log(colors.bold().green(`${from} -> ${to}`));
84
- console.log(`Successfully built '${pkg.name}' package. To publish it to npm:`);
85
- console.log(colors.bold().cyan(` cd ${to}`));
86
- console.log(colors.bold().cyan(' npm publish\n'));
87
- }
88
-
89
- /**
90
- * @param {import('types').ValidatedConfig} config
91
- */
92
- export async function watch(config, cwd = process.cwd()) {
93
- await build(config, cwd);
94
-
95
- const message = `\nWatching ${relative(cwd, config.kit.files.lib)} for changes...\n`;
96
-
97
- console.log(message);
98
-
99
- const { lib } = config.kit.files;
100
- const { dir } = config.kit.package;
101
-
102
- /** @type {Array<{ file: import('./types').File, type: string }>} */
103
- const pending = [];
104
-
105
- /** @type {Array<(value?: any) => void>} */
106
- const fulfillers = [];
107
-
108
- /** @type {NodeJS.Timeout} */
109
- let timeout;
110
-
111
- const watcher = chokidar.watch(lib, { ignoreInitial: true });
112
- const ready = new Promise((resolve) => watcher.on('ready', resolve));
113
-
114
- watcher.on('all', async (type, path) => {
115
- const file = analyze(config, relative(lib, path));
116
- if (!file.is_included) return;
117
-
118
- pending.push({ file, type });
119
-
120
- clearTimeout(timeout);
121
- timeout = setTimeout(async () => {
122
- const files = scan(config);
123
-
124
- let should_update_pkg = false;
125
-
126
- const events = pending.slice();
127
- pending.length = 0;
128
-
129
- for (const { file, type } of events) {
130
- if ((type === 'unlink' || type === 'add') && file.is_exported) {
131
- should_update_pkg = true;
132
- }
133
-
134
- if (type === 'unlink') {
135
- for (const candidate of [
136
- file.name,
137
- `${file.base}.d.ts`,
138
- `${file.base}.d.mts`,
139
- `${file.base}.d.cts`
140
- ]) {
141
- const resolved = join(dir, candidate);
142
-
143
- if (fs.existsSync(resolved)) {
144
- fs.unlinkSync(resolved);
145
-
146
- const parent = dirname(resolved);
147
- if (parent !== dir && fs.readdirSync(parent).length === 0) {
148
- fs.rmdirSync(parent);
149
- }
150
- }
151
- }
152
- console.log(`Removed ${file.dest}`);
153
- }
154
-
155
- if (type === 'add' || type === 'change') {
156
- await process_file(config, file);
157
- console.log(`Processing ${file.name}`);
158
- }
159
- }
160
-
161
- if (should_update_pkg) {
162
- const pkg = generate_pkg(cwd, files);
163
- write(join(dir, 'package.json'), JSON.stringify(pkg, null, 2));
164
- console.log('Updated package.json');
165
- }
166
-
167
- if (config.kit.package.emitTypes) {
168
- await emit_dts(config, cwd, scan(config));
169
- console.log('Updated .d.ts files');
170
- }
171
-
172
- console.log(message);
173
-
174
- fulfillers.forEach((fn) => fn());
175
- }, 100);
176
- });
177
-
178
- return {
179
- watcher,
180
- ready,
181
- settled: () =>
182
- new Promise((fulfil, reject) => {
183
- fulfillers.push(fulfil);
184
- setTimeout(() => reject(new Error('Timed out')), 1000);
185
- })
186
- };
187
- }
188
-
189
- /**
190
- * @param {import('types').ValidatedConfig} config
191
- * @param {import('./types').File} file
192
- */
193
- async function process_file(config, file) {
194
- if (!file.is_included) return;
195
-
196
- const filename = join(config.kit.files.lib, file.name);
197
- const dest = join(config.kit.package.dir, file.dest);
198
-
199
- if (file.is_svelte || file.name.endsWith('.ts')) {
200
- let contents = fs.readFileSync(filename, 'utf-8');
201
-
202
- if (file.is_svelte) {
203
- if (config.preprocess) {
204
- const preprocessed = (await preprocess(contents, config.preprocess, { filename })).code;
205
- contents = strip_lang_tags(preprocessed);
206
- }
207
- }
208
-
209
- if (file.name.endsWith('.ts') && !file.name.endsWith('.d.ts')) {
210
- contents = await transpile_ts(filename, contents);
211
- }
212
-
213
- contents = resolve_lib_alias(file.name, contents, config);
214
- write(dest, contents);
215
- } else {
216
- copy(filename, dest);
217
- }
218
- }
@@ -1,8 +0,0 @@
1
- export type File = {
2
- name: string;
3
- dest: string;
4
- base: string;
5
- is_included: boolean;
6
- is_exported: boolean;
7
- is_svelte: boolean;
8
- };
@@ -1,150 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { createRequire } from 'module';
4
- import { posixify, mkdirp, rimraf, walk } from '../utils/filesystem.js';
5
- import { resolve_lib_alias, write } from './utils.js';
6
-
7
- /**
8
- * @param {import('types').ValidatedConfig} config
9
- * @param {string} cwd
10
- * @param {import('./types').File[]} files
11
- */
12
- export async function emit_dts(config, cwd, files) {
13
- const tmp = `${config.kit.outDir}/package/types`;
14
- rimraf(tmp);
15
- mkdirp(tmp);
16
-
17
- const require = createRequire(import.meta.url);
18
- const emit = await try_load_svelte2tsx();
19
- await emit({
20
- libRoot: config.kit.files.lib,
21
- svelteShimsPath: require.resolve('svelte2tsx/svelte-shims.d.ts'),
22
- declarationDir: path.relative(cwd, tmp)
23
- });
24
-
25
- const handwritten = new Set();
26
- const excluded = new Set();
27
-
28
- // remove excluded files, and files that conflict with hand-written .d.ts
29
- for (const file of files) {
30
- if (file.name.endsWith('.d.ts')) {
31
- handwritten.add(file.name);
32
- }
33
-
34
- if (!file.is_included) {
35
- excluded.add(file.base + '.d.ts');
36
- excluded.add(file.base + '.d.mts');
37
- excluded.add(file.base + '.d.cts');
38
- }
39
- }
40
-
41
- // resolve $lib alias (TODO others), copy into package dir
42
- for (const file of walk(tmp)) {
43
- const normalized = posixify(file);
44
-
45
- if (handwritten.has(normalized)) {
46
- console.warn(`Using $lib/${normalized} instead of generated .d.ts file`);
47
- }
48
-
49
- // don't overwrite hand-written .d.ts files
50
- if (excluded.has(normalized)) continue;
51
-
52
- const source = fs.readFileSync(path.join(tmp, normalized), 'utf8');
53
- write(
54
- path.join(config.kit.package.dir, normalized),
55
- resolve_lib_alias(normalized, source, config)
56
- );
57
- }
58
- }
59
-
60
- async function try_load_svelte2tsx() {
61
- const svelte2tsx = await load();
62
- const emit_dts = svelte2tsx.emitDts;
63
- if (!emit_dts) {
64
- throw new Error(
65
- 'You need to install svelte2tsx >=0.4.1 if you want to generate type definitions'
66
- );
67
- }
68
- return emit_dts;
69
-
70
- async function load() {
71
- try {
72
- return await import('svelte2tsx');
73
- } catch (e) {
74
- throw new Error(
75
- 'You need svelte2tsx and typescript if you want to generate type definitions. Install it through your package manager, or disable generation which is highly discouraged. See https://kit.svelte.dev/docs/packaging'
76
- );
77
- }
78
- }
79
- }
80
-
81
- /**
82
- * @param {string} filename
83
- * @param {string} source
84
- */
85
- export async function transpile_ts(filename, source) {
86
- const ts = await try_load_ts();
87
- return ts.transpileModule(source, {
88
- compilerOptions: load_tsconfig(filename, ts),
89
- fileName: filename
90
- }).outputText;
91
- }
92
-
93
- async function try_load_ts() {
94
- try {
95
- return (await import('typescript')).default;
96
- } catch (e) {
97
- throw new Error(
98
- 'You need to install TypeScript if you want to transpile TypeScript files and/or generate type definitions'
99
- );
100
- }
101
- }
102
-
103
- /**
104
- * @param {string} filename
105
- * @param {import('typescript')} ts
106
- */
107
- function load_tsconfig(filename, ts) {
108
- let config_filename;
109
-
110
- // ts.findConfigFile is broken (it will favour a distant tsconfig
111
- // over a near jsconfig, and then only when you call it twice)
112
- // so we implement it ourselves
113
- let dir = filename;
114
- while (dir !== (dir = path.dirname(dir))) {
115
- const tsconfig = path.join(dir, 'tsconfig.json');
116
- const jsconfig = path.join(dir, 'jsconfig.json');
117
-
118
- if (fs.existsSync(tsconfig)) {
119
- config_filename = tsconfig;
120
- break;
121
- }
122
-
123
- if (fs.existsSync(jsconfig)) {
124
- config_filename = jsconfig;
125
- break;
126
- }
127
- }
128
-
129
- if (!config_filename) {
130
- throw new Error('Failed to locate tsconfig or jsconfig');
131
- }
132
-
133
- const { error, config } = ts.readConfigFile(config_filename, ts.sys.readFile);
134
-
135
- if (error) {
136
- throw new Error('Malformed tsconfig\n' + JSON.stringify(error, null, 2));
137
- }
138
-
139
- // Do this so TS will not search for initial files which might take a while
140
- config.include = [];
141
- config.files = [];
142
- const { options } = ts.parseJsonConfigFileContent(
143
- config,
144
- ts.sys,
145
- path.dirname(config_filename),
146
- { sourceMap: false },
147
- config_filename
148
- );
149
- return options;
150
- }
@@ -1,143 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { posixify, mkdirp, walk } from '../utils/filesystem.js';
4
-
5
- /**
6
- * Resolves the `$lib` alias.
7
- *
8
- * TODO: make this more generic to also handle other aliases the user could have defined via
9
- * `kit.alias`. Also investigate how to do this in a more robust way (right now regex string
10
- * replacement is used).
11
- * For more discussion see https://github.com/sveltejs/kit/pull/2453
12
- *
13
- * @param {string} file Relative to the lib root
14
- * @param {string} content
15
- * @param {import('types').ValidatedConfig} config
16
- * @returns {string}
17
- */
18
- export function resolve_lib_alias(file, content, config) {
19
- /**
20
- * @param {string} match
21
- * @param {string} _
22
- * @param {string} import_path
23
- */
24
- const replace_import_path = (match, _, import_path) => {
25
- if (!import_path.startsWith('$lib/')) {
26
- return match;
27
- }
28
-
29
- const full_path = path.join(config.kit.files.lib, file);
30
- const full_import_path = path.join(config.kit.files.lib, import_path.slice('$lib/'.length));
31
- let resolved = posixify(path.relative(path.dirname(full_path), full_import_path));
32
- resolved = resolved.startsWith('.') ? resolved : './' + resolved;
33
- return match.replace(import_path, resolved);
34
- };
35
- content = content.replace(/from\s+('|")([^"';,]+?)\1/g, replace_import_path);
36
- content = content.replace(/import\s*\(\s*('|")([^"';,]+?)\1\s*\)/g, replace_import_path);
37
- return content;
38
- }
39
-
40
- /**
41
- * Strip out lang="X" or type="text/X" tags. Doing it here is only a temporary solution.
42
- * See https://github.com/sveltejs/kit/issues/2450 for ideas for places where it's handled better.
43
- *
44
- * @param {string} content
45
- */
46
- export function strip_lang_tags(content) {
47
- return content
48
- .replace(/(<!--[^]*?-->)|(<script[^>]*?)\s(?:type|lang)=(["']).*?\3/g, '$1$2')
49
- .replace(/(<!--[^]*?-->)|(<style[^>]*?)\s(?:type|lang)=(["']).*?\3/g, '$1$2');
50
- }
51
-
52
- /**
53
- * @param {string} file
54
- * @param {Parameters<typeof fs.writeFileSync>[1]} contents
55
- */
56
- export function write(file, contents) {
57
- mkdirp(path.dirname(file));
58
- fs.writeFileSync(file, contents);
59
- }
60
-
61
- /**
62
- * @param {import('types').ValidatedConfig} config
63
- * @returns {import('./types').File[]}
64
- */
65
- export function scan(config) {
66
- return walk(config.kit.files.lib).map((file) => analyze(config, file));
67
- }
68
-
69
- /**
70
- * @param {import('types').ValidatedConfig} config
71
- * @param {string} file
72
- * @returns {import('./types').File}
73
- */
74
- export function analyze(config, file) {
75
- const name = posixify(file);
76
-
77
- const svelte_extension = config.extensions.find((ext) => name.endsWith(ext));
78
-
79
- const base = svelte_extension ? name : name.slice(0, -path.extname(name).length);
80
-
81
- const dest = svelte_extension
82
- ? name.slice(0, -svelte_extension.length) + '.svelte'
83
- : name.endsWith('.d.ts')
84
- ? name
85
- : name.endsWith('.ts')
86
- ? name.slice(0, -3) + '.js'
87
- : name;
88
-
89
- return {
90
- name,
91
- dest,
92
- base,
93
- is_included: config.kit.package.files(name),
94
- is_exported: config.kit.package.exports(name),
95
- is_svelte: !!svelte_extension
96
- };
97
- }
98
-
99
- /**
100
- * @param {string} cwd
101
- * @param {import('./types').File[]} files
102
- */
103
- export function generate_pkg(cwd, files) {
104
- const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
105
-
106
- // Remove fields that are specific to the original package.json
107
- // See: https://pnpm.io/package_json#publishconfigdirectory
108
- delete pkg.publishConfig?.directory;
109
- delete pkg.linkDirectory?.directory;
110
- delete pkg.scripts;
111
-
112
- pkg.type = 'module';
113
-
114
- pkg.exports = {
115
- './package.json': './package.json',
116
- ...pkg.exports
117
- };
118
-
119
- /** @type {Record<string, string>} */
120
- const clashes = {};
121
-
122
- for (const file of files) {
123
- if (file.is_included && file.is_exported) {
124
- const original = `$lib/${file.name}`;
125
- const entry = `./${file.dest}`;
126
- const key = entry.replace(/\/index\.js$|(\/[^/]+)\.js$/, '$1');
127
-
128
- if (clashes[key]) {
129
- throw new Error(
130
- `Duplicate "${key}" export. Please remove or rename either ${clashes[key]} or ${original}`
131
- );
132
- }
133
-
134
- if (!pkg.exports[key]) {
135
- pkg.exports[key] = entry;
136
- }
137
-
138
- clashes[key] = original;
139
- }
140
- }
141
-
142
- return pkg;
143
- }