Skip to content

Commit

Permalink
Ensure public types don't reference internal types
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Feb 20, 2022
1 parent 4476ccb commit ddea796
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 113 deletions.
2 changes: 1 addition & 1 deletion packages/kit/src/core/dev/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function create_plugin(config, cwd) {
configureServer(vite) {
__fetch_polyfill();

/** @type {import('types').SSRManifest} */
/** @type {import('types').SSRManifestInternal} */
let manifest;

function update_manifest() {
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
106 changes: 77 additions & 29 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,6 @@
/// <reference types="vite/client" />

import { CompileOptions } from 'svelte/types/compiler/interfaces';
import {
Logger,
PrerenderOnErrorValue,
SSRNodeLoader,
SSRRoute,
TrailingSlash,
Either,
MaybePromise,
RecursiveRequired,
RouteDefinition,
AdapterEntry,
ResponseHeaders,
Fallthrough,
RequiredResolveOptions,
Body
} from './internal';
import './ambient';

export class App {
Expand All @@ -34,6 +18,32 @@ export interface Adapter {
adapt(builder: Builder): Promise<void>;
}

export interface AdapterEntry {
/**
* A string that uniquely identifies an HTTP service (e.g. serverless function) and is used for deduplication.
* For example, `/foo/a-[b]` and `/foo/[c]` are different routes, but would both
* be represented in a Netlify _redirects file as `/foo/:param`, so they share an ID
*/
id: string;

/**
* A function that compares the candidate route with the current route to determine
* if it should be treated as a fallback for the current route. For example, `/foo/[c]`
* is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes
*/
filter: (route: RouteDefinition) => boolean;

/**
* A function that is invoked once the entry has been created. This is where you
* should write the function to the filesystem and generate redirect manifests.
*/
complete: (entry: {
generateManifest: (opts: { relativePath: string; format?: 'esm' | 'cjs' }) => string;
}) => void;
}

export type Body = JSONValue | Uint8Array | ReadableStream | import('stream').Readable;

export interface Builder {
log: Logger;
rimraf(dir: string): void;
Expand Down Expand Up @@ -269,6 +279,8 @@ export type CspDirectives = {
>;
};

export type Either<T, U> = Only<T, U> | Only<U, T>;

export interface EndpointOutput<Output extends Body = Body> {
status?: number;
headers?: Headers | Partial<ResponseHeaders>;
Expand All @@ -288,6 +300,10 @@ export interface ExternalFetch {
(req: Request): Promise<Response>;
}

export interface Fallthrough {
fallthrough: true;
}

export interface GetSession {
(event: RequestEvent): MaybePromise<App.Session>;
}
Expand All @@ -303,6 +319,12 @@ export interface HandleError {
(input: { error: Error & { frame?: string }; event: RequestEvent }): void;
}

export type HttpMethod = 'get' | 'head' | 'post' | 'put' | 'delete' | 'patch';

export type JSONObject = { [key: string]: JSONValue };

export type JSONValue = string | number | boolean | null | ToJSON | JSONValue[] | JSONObject;

export interface Load<Params = Record<string, string>, Props = Record<string, any>> {
(input: LoadInput<Params>): MaybePromise<Either<Fallthrough, LoadOutput<Props>>>;
}
Expand All @@ -325,6 +347,19 @@ export interface LoadOutput<Props = Record<string, any>> {
maxage?: number;
}

export interface Logger {
(msg: string): void;
success(msg: string): void;
error(msg: string): void;
warn(msg: string): void;
minor(msg: string): void;
info(msg: string): void;
}

export type MaybePromise<T> = T | Promise<T>;

type Only<T, U> = { [P in keyof T]: T[P] } & { [P in Exclude<keyof U, keyof T>]?: never };

export interface Prerendered {
pages: Map<
string,
Expand Down Expand Up @@ -360,6 +395,11 @@ export interface PrerenderErrorHandler {
}): void;
}

export type PrerenderOnErrorValue = 'fail' | 'continue' | PrerenderErrorHandler;

/** `string[]` is only for set-cookie, everything else must be type of `string` */
export type ResponseHeaders = Record<string, string | number | string[]>;

export interface RequestEvent {
request: Request;
url: URL;
Expand All @@ -378,23 +418,31 @@ export interface RequestOptions {
platform?: App.Platform;
}

export interface RequiredResolveOptions {
ssr: boolean;
transformPage: ({ html }: { html: string }) => string;
}

export type ResolveOptions = Partial<RequiredResolveOptions>;

export interface RouteDefinition {
type: 'page' | 'endpoint';
pattern: RegExp;
segments: RouteSegment[];
methods: HttpMethod[];
}

export interface RouteSegment {
content: string;
dynamic: boolean;
rest: boolean;
}

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>;
type ToJSON = { toJSON(...args: any[]): Exclude<JSONValue, ToJSON> };

export type TrailingSlash = 'never' | 'always' | 'ignore';
109 changes: 27 additions & 82 deletions packages/kit/types/internal.d.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
import { OutputAsset, OutputChunk } from 'rollup';
import {
SSRManifest,
ValidatedConfig,
RequestHandler,
Load,
App,
Config,
Either,
ExternalFetch,
Fallthrough,
GetSession,
Handle,
HandleError,
HttpMethod,
JSONObject,
Load,
MaybePromise,
RequestEvent,
App,
RequestHandler,
RequestOptions,
PrerenderErrorHandler
ResponseHeaders,
RouteSegment,
SSRManifest,
TrailingSlash
} from './index';

export interface AdapterEntry {
/**
* A string that uniquely identifies an HTTP service (e.g. serverless function) and is used for deduplication.
* For example, `/foo/a-[b]` and `/foo/[c]` are different routes, but would both
* be represented in a Netlify _redirects file as `/foo/:param`, so they share an ID
*/
id: string;

/**
* A function that compares the candidate route with the current route to determine
* if it should be treated as a fallback for the current route. For example, `/foo/[c]`
* is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes
*/
filter: (route: RouteDefinition) => boolean;

/**
* A function that is invoked once the entry has been created. This is where you
* should write the function to the filesystem and generate redirect manifests.
*/
complete: (entry: {
generateManifest: (opts: { relativePath: string; format?: 'esm' | 'cjs' }) => string;
}) => void;
export interface SSRManifestInternal extends SSRManifest {
/** private fields */
_: {
mime: Record<string, string>;
entry: {
file: string;
js: string[];
css: string[];
};
nodes: SSRNodeLoader[];
routes: SSRRoute[];
};
}

export interface AppModule {
Expand All @@ -58,8 +55,6 @@ export interface Asset {
type: string | null;
}

export type Body = JSONValue | Uint8Array | ReadableStream | import('stream').Readable;

export interface BuildData {
app_dir: string;
manifest_data: ManifestData;
Expand Down Expand Up @@ -89,8 +84,6 @@ export type CSRComponentLoader = () => Promise<CSRComponent>;

export type CSRRoute = [RegExp, CSRComponentLoader[], CSRComponentLoader[], GetParams?, HasShadow?];

export type Either<T, U> = Only<T, U> | Only<U, T>;

export interface EndpointData {
type: 'endpoint';
key: string;
Expand All @@ -100,10 +93,6 @@ export interface EndpointData {
file: string;
}

export interface Fallthrough {
fallthrough: true;
}

export type GetParams = (match: RegExpExecArray) => Record<string, string>;

type HasShadow = 1;
Expand All @@ -115,8 +104,6 @@ export interface Hooks {
handleError: HandleError;
}

export type HttpMethod = 'get' | 'head' | 'post' | 'put' | 'delete' | 'patch';

export class InternalApp extends App {
render(
request: Request,
Expand All @@ -126,19 +113,6 @@ export class InternalApp extends App {
): Promise<Response>;
}

export type JSONObject = { [key: string]: JSONValue };

export type JSONValue = string | number | boolean | null | ToJSON | JSONValue[] | JSONObject;

export interface Logger {
(msg: string): void;
success(msg: string): void;
error(msg: string): void;
warn(msg: string): void;
minor(msg: string): void;
info(msg: string): void;
}

export interface ManifestData {
assets: Asset[];
layout: string;
Expand All @@ -147,8 +121,6 @@ export interface ManifestData {
routes: RouteData[];
}

export type MaybePromise<T> = T | Promise<T>;

export interface MethodOverride {
parameter: string;
allowed: string[];
Expand All @@ -166,8 +138,6 @@ export type NormalizedLoadOutput = Either<
Fallthrough
>;

type Only<T, U> = { [P in keyof T]: T[P] } & { [P in Exclude<keyof U, keyof T>]?: never };

export interface PageData {
type: 'page';
key: string;
Expand All @@ -185,8 +155,6 @@ export interface PrerenderDependency {
body: null | string | Uint8Array;
}

export type PrerenderOnErrorValue = 'fail' | 'continue' | PrerenderErrorHandler;

export interface PrerenderOptions {
fallback?: string;
all: boolean;
Expand All @@ -204,33 +172,12 @@ export type RecursiveRequired<T> = {
: T[K]; // Use the exact type for everything else
};

export interface RequiredResolveOptions {
ssr: boolean;
transformPage: ({ html }: { html: string }) => string;
}

export interface Respond {
(request: Request, options: SSROptions, state?: SSRState): Promise<Response>;
}

/** `string[]` is only for set-cookie, everything else must be type of `string` */
export type ResponseHeaders = Record<string, string | number | string[]>;

export type RouteData = PageData | EndpointData;

export interface RouteDefinition {
type: 'page' | 'endpoint';
pattern: RegExp;
segments: RouteSegment[];
methods: HttpMethod[];
}

export interface RouteSegment {
content: string;
dynamic: boolean;
rest: boolean;
}

export interface ShadowEndpointOutput<Output extends JSONObject = JSONObject> {
status?: number;
headers?: Partial<ResponseHeaders>;
Expand Down Expand Up @@ -301,7 +248,7 @@ export interface SSROptions {
handle_error(error: Error & { frame?: string }, event: RequestEvent): void;
hooks: Hooks;
hydrate: boolean;
manifest: SSRManifest;
manifest: SSRManifestInternal;
method_override: MethodOverride;
paths: {
base: string;
Expand Down Expand Up @@ -365,8 +312,6 @@ export interface SSRState {

export type StrictBody = string | Uint8Array;

type ToJSON = { toJSON(...args: any[]): Exclude<JSONValue, ToJSON> };

export type TrailingSlash = 'never' | 'always' | 'ignore';
export type ValidatedConfig = RecursiveRequired<Config>;

export * from './index';

0 comments on commit ddea796

Please sign in to comment.