Skip to content

Commit

Permalink
semi public types (#4104)
Browse files Browse the repository at this point in the history
* semi public types

* move types around

* add exports

* make more types private

* fix docs

* changeset

* remove TODO
  • Loading branch information
Rich-Harris committed Feb 24, 2022
1 parent 77590cb commit ae6121e
Show file tree
Hide file tree
Showing 8 changed files with 414 additions and 371 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-moles-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[breaking] separate public from private-but-documented types
13 changes: 6 additions & 7 deletions documentation/docs/13-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,17 @@ See [Prerendering](/docs/page-options#prerender). An object containing zero or m
```js
import adapter from '@sveltejs/adapter-static';

/** @type {import('@sveltejs/kit').PrerenderErrorHandler} */
const handleError = ({ status, path, referrer, referenceType }) => {
if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
console.warn(`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`);
};

/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
prerender: {
onError: handleError
onError: ({ status, path, referrer, referenceType }) => {
if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
console.warn(
`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`
);
}
}
}
};
Expand Down
12 changes: 12 additions & 0 deletions packages/kit/scripts/extract-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ function get_types(code, statements) {
});
}

{
const code = fs.readFileSync('types/private.d.ts', 'utf-8');
const node = ts.createSourceFile('private.d.ts', code, ts.ScriptTarget.Latest);

modules.push({
name: 'Additional types',
comment:
'The following are referenced by the public types documented above, but cannot be imported directly:',
...get_types(code, node.statements)
});
}

{
const code = fs.readFileSync('types/ambient.d.ts', 'utf-8');
const node = ts.createSourceFile('ambient.d.ts', code, ts.ScriptTarget.Latest);
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function get_mime_lookup(manifest_data) {
return mime;
}

/** @param {import('@sveltejs/kit').ValidatedConfig} config */
/** @param {import('types').ValidatedConfig} config */
export function get_aliases(config) {
const alias = {
__GENERATED__: path.posix.resolve(`${SVELTE_KIT}/generated`),
Expand Down
289 changes: 12 additions & 277 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,82 +5,27 @@ import './ambient';

import { CompileOptions } from 'svelte/types/compiler/interfaces';
import {
AdapterEntry,
Body,
Builder,
CspDirectives,
Either,
EndpointOutput,
ErrorLoadInput,
Fallthrough,
Logger,
LoadInput,
LoadOutput,
MaybePromise,
PrerenderOnErrorValue,
RecursiveRequired,
RequiredResolveOptions,
ResponseHeaders,
RouteDefinition,
SSRNodeLoader,
SSRRoute,
RequestEvent,
ResolveOptions,
TrailingSlash
} from './internal';
} from './private';

export interface Adapter {
name: string;
adapt(builder: Builder): Promise<void>;
}

export interface Builder {
log: Logger;
rimraf(dir: string): void;
mkdirp(dir: string): void;

appDir: string;
trailingSlash: TrailingSlash;

/**
* Create entry points that map to individual functions
* @param fn A function that groups a set of routes into an entry point
*/
createEntries(fn: (route: RouteDefinition) => AdapterEntry): void;

generateManifest: (opts: { relativePath: string; format?: 'esm' | 'cjs' }) => string;

getBuildDirectory(name: string): string;
getClientDirectory(): string;
getServerDirectory(): string;
getStaticDirectory(): string;

/**
* @param dest the destination folder to which files should be copied
* @returns an array of paths corresponding to the files that have been created by the copy
*/
writeClient(dest: string): string[];
/**
* @param dest the destination folder to which files should be copied
* @returns an array of paths corresponding to the files that have been created by the copy
*/
writeServer(dest: string): string[];
/**
* @param dest the destination folder to which files should be copied
* @returns an array of paths corresponding to the files that have been created by the copy
*/
writeStatic(dest: string): string[];
/**
* @param from the source file or folder
* @param to the destination file or folder
* @param opts.filter a function to determine whether a file or folder should be copied
* @param opts.replace a map of strings to replace
* @returns an array of paths corresponding to the files that have been created by the copy
*/
copy(
from: string,
to: string,
opts?: {
filter?: (basename: string) => boolean;
replace?: Record<string, string>;
}
): string[];

prerender(options: { all?: boolean; dest: string; fallback?: string }): Promise<Prerendered>;
}

export interface Config {
compilerOptions?: CompileOptions;
extensions?: string[];
Expand Down Expand Up @@ -142,129 +87,10 @@ export interface Config {
preprocess?: any;
}

// Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts
//
// MIT License
//
// Copyright (c) 2021-present, Joshua Hemphill
// Copyright (c) 2021, Tecnico Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

export namespace Csp {
type ActionSource = 'strict-dynamic' | 'report-sample';
type BaseSource = 'self' | 'unsafe-eval' | 'unsafe-hashes' | 'unsafe-inline' | 'none';
type CryptoSource = `${'nonce' | 'sha256' | 'sha384' | 'sha512'}-${string}`;
type FrameSource = HostSource | SchemeSource | 'self' | 'none';
type HostNameScheme = `${string}.${string}` | 'localhost';
type HostSource = `${HostProtocolSchemes}${HostNameScheme}${PortScheme}`;
type HostProtocolSchemes = `${string}://` | '';
type HttpDelineator = '/' | '?' | '#' | '\\';
type PortScheme = `:${number}` | '' | ':*';
type SchemeSource = 'http:' | 'https:' | 'data:' | 'mediastream:' | 'blob:' | 'filesystem:';
type Source = HostSource | SchemeSource | CryptoSource | BaseSource;
type Sources = Source[];
type UriPath = `${HttpDelineator}${string}`;
}

export type CspDirectives = {
'child-src'?: Csp.Sources;
'default-src'?: Array<Csp.Source | Csp.ActionSource>;
'frame-src'?: Csp.Sources;
'worker-src'?: Csp.Sources;
'connect-src'?: Csp.Sources;
'font-src'?: Csp.Sources;
'img-src'?: Csp.Sources;
'manifest-src'?: Csp.Sources;
'media-src'?: Csp.Sources;
'object-src'?: Csp.Sources;
'prefetch-src'?: Csp.Sources;
'script-src'?: Array<Csp.Source | Csp.ActionSource>;
'script-src-elem'?: Csp.Sources;
'script-src-attr'?: Csp.Sources;
'style-src'?: Array<Csp.Source | Csp.ActionSource>;
'style-src-elem'?: Csp.Sources;
'style-src-attr'?: Csp.Sources;
'base-uri'?: Array<Csp.Source | Csp.ActionSource>;
sandbox?: Array<
| 'allow-downloads-without-user-activation'
| 'allow-forms'
| 'allow-modals'
| 'allow-orientation-lock'
| 'allow-pointer-lock'
| 'allow-popups'
| 'allow-popups-to-escape-sandbox'
| 'allow-presentation'
| 'allow-same-origin'
| 'allow-scripts'
| 'allow-storage-access-by-user-activation'
| 'allow-top-navigation'
| 'allow-top-navigation-by-user-activation'
>;
'form-action'?: Array<Csp.Source | Csp.ActionSource>;
'frame-ancestors'?: Array<Csp.HostSource | Csp.SchemeSource | Csp.FrameSource>;
'navigate-to'?: Array<Csp.Source | Csp.ActionSource>;
'report-uri'?: Csp.UriPath[];
'report-to'?: string[];

'require-trusted-types-for'?: Array<'script'>;
'trusted-types'?: Array<'none' | 'allow-duplicates' | '*' | string>;
'upgrade-insecure-requests'?: boolean;

/** @deprecated */
'require-sri-for'?: Array<'script' | 'style' | 'script style'>;

/** @deprecated */
'block-all-mixed-content'?: boolean;

/** @deprecated */
'plugin-types'?: Array<`${string}/${string}` | 'none'>;

/** @deprecated */
referrer?: Array<
| 'no-referrer'
| 'no-referrer-when-downgrade'
| 'origin'
| 'origin-when-cross-origin'
| 'same-origin'
| 'strict-origin'
| 'strict-origin-when-cross-origin'
| 'unsafe-url'
| 'none'
>;
};

export interface EndpointOutput<Output extends Body = Body> {
status?: number;
headers?: Headers | Partial<ResponseHeaders>;
body?: Output;
}

export interface ErrorLoad<Params = Record<string, string>, Props = Record<string, any>> {
(input: ErrorLoadInput<Params>): MaybePromise<LoadOutput<Props>>;
}

export interface ErrorLoadInput<Params = Record<string, string>> extends LoadInput<Params> {
status?: number;
error?: Error;
}

export interface ExternalFetch {
(req: Request): Promise<Response>;
}
Expand All @@ -288,29 +114,6 @@ export interface Load<Params = Record<string, string>, Props = Record<string, an
(input: LoadInput<Params>): MaybePromise<Either<Fallthrough, LoadOutput<Props>>>;
}

export interface LoadInput<Params = Record<string, string>> {
url: URL;
params: Params;
props: Record<string, any>;
fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
session: App.Session;
stuff: Partial<App.Stuff>;
}

export interface LoadOutput<Props = Record<string, any>> {
status?: number;
error?: string | Error;
redirect?: string;
props?: Props;
stuff?: Partial<App.Stuff>;
maxage?: number;
}

export interface Navigation {
from: URL;
to: URL;
}

export interface Page<Params extends Record<string, string> = Record<string, string>> {
url: URL;
params: Params;
Expand All @@ -319,47 +122,9 @@ export interface Page<Params extends Record<string, string> = Record<string, str
error: Error | null;
}

export interface Prerendered {
pages: Map<
string,
{
/** The location of the .html file relative to the output directory */
file: string;
}
>;
assets: Map<
string,
{
/** The MIME type of the asset */
type: string;
}
>;
redirects: Map<
string,
{
status: number;
location: string;
}
>;
/** An array of prerendered paths (without trailing slashes, regardless of the trailingSlash config) */
paths: string[];
}

export interface PrerenderErrorHandler {
(details: {
status: number;
path: string;
referrer: string | null;
referenceType: 'linked' | 'fetched';
}): void;
}

export interface RequestEvent<Params = Record<string, string>> {
request: Request;
url: URL;
params: Params;
locals: App.Locals;
platform: Readonly<App.Platform>;
export interface Navigation {
from: URL;
to: URL;
}

/**
Expand All @@ -373,33 +138,3 @@ export interface RequestHandler<Params = Record<string, string>, Output extends
Either<Output extends Response ? Response : EndpointOutput<Output>, Fallthrough>
>;
}

export interface RequestOptions {
platform?: App.Platform;
}

export type ResolveOptions = Partial<RequiredResolveOptions>;

export class Server {
constructor(manifest: SSRManifest);
respond(request: Request, options?: RequestOptions): Promise<Response>;
}

export interface SSRManifest {
appDir: string;
assets: Set<string>;
/** private fields */
_: {
mime: Record<string, string>;
entry: {
file: string;
js: string[];
css: string[];
};
nodes: SSRNodeLoader[];
routes: SSRRoute[];
};
}

// TODO should this be public?
export type ValidatedConfig = RecursiveRequired<Config>;
Loading

0 comments on commit ae6121e

Please sign in to comment.