UNPKG

5.93 kBTypeScriptView Raw
1/**
2 * Types for google-closure-deps
3 */
4export namespace parser {
5 export class ParseResult {
6 /** @const */
7 dependencies: depGraph.Dependency[];
8 /** @const */
9 errors: ParseError[];
10 /** @const */
11 hasFatalError: boolean;
12 /** @const */
13 source: ParseResult.Source;
14 /** @const */
15 isFromDepsFile: boolean;
16 constructor(
17 dependencies: depGraph.Dependency[],
18 errors: ParseError[],
19 source: ParseResult.Source
20 );
21 }
22
23 namespace ParseResult {
24 // TODO: workaround for a bug of @typescript-eslint
25 // eslint-disable-next-line @typescript-eslint/no-unused-vars
26 enum Source {
27 /**
28 * Scanned from an actual source file.
29 */
30 SOURCE_FILE = "f",
31
32 /**
33 * A goog.addDependency statement.
34 */
35 GOOG_ADD_DEPENDENCY = "d",
36 }
37 }
38
39 export class ParseError {
40 /** @const */
41 fatal: boolean;
42 /** @const */
43 message: string;
44 /** @const */
45 sourceName: string;
46 /** @const */
47 line: number;
48 /** @const */
49 lineOffset: number;
50
51 constructor(
52 fatal: boolean,
53 message: string,
54 sourceName: string,
55 line: number,
56 lineOffset: number
57 );
58 }
59
60 export function parseFile(path: string): ParseResult;
61
62 export function parseFileAsync(path: string): Promise<ParseResult>;
63
64 /**
65 * Parses a file that contains only goog.addDependency statements. This is regex
66 * based to be lightweight and avoid addtional dependencies.
67 */
68 export function parseDependencyFile(
69 text: string,
70 filePath: string
71 ): ParseResult;
72}
73
74export namespace depGraph {
75 export enum DependencyType {
76 /** A file containing goog.provide statements. */
77 CLOSURE_PROVIDE = "closure provide",
78 /** A file containing a goog.module statement. */
79 CLOSURE_MODULE = "closure module",
80 /** An ES6 module file. */
81 ES6_MODULE = "es6 module",
82 /** A JavaScript file that has no goog.provide/module and is not an ES6 module. */
83 SCRIPT = "script",
84 }
85
86 /**
87 * A Dependency in the dependency graph (a vertex).
88 */
89 export class Dependency {
90 /** @const */
91 type: DependencyType;
92 /**
93 * Full path of this file on disc.
94 * @const
95 */
96 path: string;
97 /**
98 * Array of Closure symbols this file provides.
99 * @const
100 */
101 closureSymbols: string[];
102 /**
103 * Array of imports in this file.
104 * @const
105 */
106 imports: Import[];
107 /**
108 * The language level of this file; e.g. "es3", "es6", etc.
109 * @const
110 */
111 language: string | null;
112
113 constructor(
114 type: DependencyType,
115 filepath: string,
116 closureSymbols: string[],
117 imports: Import[],
118 language?: string
119 );
120
121 /**
122 * Updates the path to Closure Library for this file. This is useful for
123 * ParsedDependency, which cannot know the full path of a file on until it
124 * knows the path to Closure Library, as the path in the goog.addDependency
125 * call is relative from Closure Library.
126 */
127 setClosurePath(path: string): void;
128
129 isParsedFromDepsFile(): boolean;
130 }
131
132 /**
133 * Generic super class for all types of imports. This acts as an edge in the
134 * dependency graph between two dependencies.
135 */
136 export abstract class Import {
137 /**
138 * Dependency this import is contained in.
139 */
140 from: Dependency;
141 /**
142 * The Closure symbol or path that is required.
143 * @const
144 */
145 symOrPath: string;
146
147 constructor(symOrPath: string);
148
149 /**
150 * Asserts that this import edge is valid.
151 */
152 abstract validate(to: Dependency): void;
153 abstract isGoogRequire(): boolean;
154 abstract isEs6Import(): boolean;
155 }
156
157 export class GoogRequire extends Import {
158 validate(to: Dependency): void;
159 isGoogRequire(): true;
160 isEs6Import(): false;
161 }
162
163 export class Es6Import extends Import {
164 validate(to: Dependency): void;
165 isGoogRequire(): true;
166 isEs6Import(): false;
167 }
168
169 /**
170 * Interface for resolving module specifiers.
171 */
172 export interface ModuleResolver {
173 /**
174 * @param fromPath The path of the module that is doing the
175 * importing.
176 * @param importSpec The raw text of the import.
177 * @return The resolved path of the referenced module.
178 */
179 resolve(fromPath: string, importSpec: string): string;
180 }
181
182 /**
183 * Dependency graph that provides validation along with a topological sorting
184 * of dependencies given an entrypoint.
185 *
186 * A dependency graph is not validated by default, you must call validate() if
187 * you wish to perform validation.
188 */
189 export class Graph {
190 /** @const */
191 depsBySymbol: Map<string, Dependency>;
192 /** @const */
193 depsByPath: Map<string, Dependency>;
194 /** @const */
195 moduleResolver: ModuleResolver;
196
197 constructor(
198 dependencies: readonly Dependency[],
199 moduleResolver?: ModuleResolver
200 );
201
202 /**
203 * Validates the dependency graph. Throws an error if the graph is invalid.
204 *
205 * This method uses Tarjan's algorithm to ensure Closure files are not part
206 * of any cycle. Check it out:
207 * https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
208 */
209 validate(): void;
210
211 private resolve_(i: Import): Dependency;
212
213 /**
214 * Provides a topological sorting of dependencies given the entrypoints.
215 */
216 order(...entrypoints: Dependency[]): Dependency[];
217 }
218}
219
220export namespace depFile {
221 /**
222 * Gets the text of a dependency file for the given dependencies.
223 *
224 * @param pathToClosure The path to Closure Library. Required as paths
225 * in goog.addDependency statements are relative to Closure's base.js.
226 * @param dependencies
227 * @param moduleResolver
228 * @return
229 */
230 export function getDepFileText(
231 pathToClosure: string,
232 dependencies: depGraph.Dependency[],
233 moduleResolver?: depGraph.ModuleResolver
234 ): string;
235}