@typed/vite-plugin 0.0.19 → 0.0.21

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.
@@ -0,0 +1,6 @@
1
+ import type { ModuleTreeJsonWithFallback } from '@typed/compiler';
2
+ import type { ClientManifest, HtmlEntryFile } from './vite-plugin.js';
3
+ export declare function collectModuleTrees(clientManifest: ClientManifest): Map<HtmlEntryFile, import("@typed/compiler").SourceFileToJson<import("@typed/compiler").ModuleTreeWithFallback>[]>;
4
+ export declare function collectStaticPaths(htmlEntryFile: HtmlEntryFile, moduleTrees: ModuleTreeJsonWithFallback[]): Promise<ReadonlyArray<string>>;
5
+ export declare function collectStaticPathsFromTree(htmlEntryFile: HtmlEntryFile, moduleTree: ModuleTreeJsonWithFallback): Promise<Set<string>>;
6
+ //# sourceMappingURL=prerender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../src/prerender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAGjE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErE,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,cAAc,sHA2BhE;AAED,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,0BAA0B,EAAE,GACxC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAUhC;AAED,wBAAsB,0BAA0B,CAC9C,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,0BAA0B,GACrC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAatB"}
@@ -0,0 +1,44 @@
1
+ import { join } from 'path';
2
+ import { pathCardinality } from '@typed/framework';
3
+ export function collectModuleTrees(clientManifest) {
4
+ const entryFileToModuleTrees = new Map();
5
+ // Retrieve all module trees from the client manifest
6
+ for (const htmlEntryFile of clientManifest.entryFiles) {
7
+ for (const i of htmlEntryFile.imports) {
8
+ const manifestEntries = clientManifest.modules[i];
9
+ if (!manifestEntries) {
10
+ continue;
11
+ }
12
+ for (const key in manifestEntries) {
13
+ const manifestEntry = manifestEntries[key];
14
+ if (manifestEntry.type === 'runtime' || manifestEntry.type === 'browser') {
15
+ if (entryFileToModuleTrees.get(htmlEntryFile)?.push(manifestEntry)) {
16
+ continue;
17
+ }
18
+ entryFileToModuleTrees.set(htmlEntryFile, [manifestEntry]);
19
+ }
20
+ }
21
+ }
22
+ }
23
+ return entryFileToModuleTrees;
24
+ }
25
+ export async function collectStaticPaths(htmlEntryFile, moduleTrees) {
26
+ const staticPaths = new Set();
27
+ for (const moduleTree of moduleTrees) {
28
+ const paths = await collectStaticPathsFromTree(htmlEntryFile, moduleTree);
29
+ paths.forEach((p) => staticPaths.add(p));
30
+ }
31
+ return Array.from(staticPaths).sort((a, b) => pathCardinality(a, b));
32
+ }
33
+ export async function collectStaticPathsFromTree(htmlEntryFile, moduleTree) {
34
+ const staticPaths = new Set();
35
+ // Collect all static paths
36
+ for (const mod of moduleTree.modules) {
37
+ staticPaths.add(join(htmlEntryFile.basePath, mod.route));
38
+ }
39
+ for (const child of moduleTree.children) {
40
+ await collectStaticPathsFromTree(htmlEntryFile, child);
41
+ }
42
+ return staticPaths;
43
+ }
44
+ //# sourceMappingURL=prerender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prerender.js","sourceRoot":"","sources":["../src/prerender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIlD,MAAM,UAAU,kBAAkB,CAAC,cAA8B;IAC/D,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA+C,CAAA;IAErF,qDAAqD;IACrD,KAAK,MAAM,aAAa,IAAI,cAAc,CAAC,UAAU,EAAE;QACrD,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE;YACrC,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YAEjD,IAAI,CAAC,eAAe,EAAE;gBACpB,SAAQ;aACT;YAED,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE;gBACjC,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;gBAE1C,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE;oBACxE,IAAI,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE;wBAClE,SAAQ;qBACT;oBAED,sBAAsB,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;iBAC3D;aACF;SACF;KACF;IAED,OAAO,sBAAsB,CAAA;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,aAA4B,EAC5B,WAAyC;IAEzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAErC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;QACpC,MAAM,KAAK,GAAG,MAAM,0BAA0B,CAAC,aAAa,EAAE,UAAU,CAAC,CAAA;QAEzE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;KACzC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,aAA4B,EAC5B,UAAsC;IAEtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAErC,2BAA2B;IAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE;QACpC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;KACzD;IAED,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,EAAE;QACvC,MAAM,0BAA0B,CAAC,aAAa,EAAE,KAAK,CAAC,CAAA;KACvD;IAED,OAAO,WAAW,CAAA;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function staticHtmlPlugin(): void;
2
+ //# sourceMappingURL=staticHtmlPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staticHtmlPlugin.d.ts","sourceRoot":"","sources":["../src/staticHtmlPlugin.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,SAAM"}
@@ -0,0 +1,2 @@
1
+ export function staticHtmlPlugin() { }
2
+ //# sourceMappingURL=staticHtmlPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staticHtmlPlugin.js","sourceRoot":"","sources":["../src/staticHtmlPlugin.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,KAAK,CAAC"}
@@ -1,4 +1,5 @@
1
- import type { PluginOption } from 'vite';
1
+ import { type ApiModuleTreeJson, type ModuleTreeJsonWithFallback } from '@typed/compiler';
2
+ import type { Plugin, PluginOption } from 'vite';
2
3
  /**
3
4
  * The Configuration for the Typed Plugin. All file paths can be relative to sourceDirectory or
4
5
  * can be absolute, path.resolve is used to stitch things together.
@@ -38,6 +39,66 @@ export interface PluginOptions {
38
39
  * If true, will configure the plugin to save all the generated files to disk
39
40
  */
40
41
  readonly saveGeneratedModules?: boolean;
42
+ /**
43
+ * If true, will configure the plugin to operate in a static build mode.
44
+ */
45
+ readonly isStaticBuild?: boolean;
46
+ }
47
+ export declare const PLUGIN_NAME = "@typed/vite-plugin";
48
+ export interface TypedVitePlugin extends Plugin {
49
+ readonly name: typeof PLUGIN_NAME;
50
+ readonly resolvedOptions: ResolvedOptions;
51
+ }
52
+ export interface Manifest {
53
+ readonly entryFiles: EntryFile[];
54
+ readonly modules: {
55
+ [importer: string]: Record<string, ManifestEntry>;
56
+ };
57
+ }
58
+ export interface ClientManifest extends Manifest {
59
+ readonly entryFiles: HtmlEntryFile[];
60
+ readonly modules: {
61
+ [importer: string]: Record<string, ManifestEntry>;
62
+ };
63
+ }
64
+ export type EntryFile = HtmlEntryFile | TsEntryFile;
65
+ export interface HtmlEntryFile {
66
+ readonly type: 'html';
67
+ readonly filePath: string;
68
+ readonly imports: string[];
69
+ readonly basePath: string;
70
+ }
71
+ export interface TsEntryFile {
72
+ readonly type: 'ts';
73
+ readonly filePath: string;
74
+ }
75
+ export type ManifestEntry = ApiManifestEntry | ExpressManifestEntry | HtmlManifestEntry | RuntimeManifestEntry | BrowserManifestEntry;
76
+ export interface ApiManifestEntry extends ApiModuleTreeJson {
77
+ readonly type: 'api';
78
+ }
79
+ export interface ExpressManifestEntry extends ApiModuleTreeJson {
80
+ readonly type: 'express';
81
+ }
82
+ export interface HtmlManifestEntry {
83
+ readonly type: 'html';
84
+ readonly filePath: string;
85
+ }
86
+ export interface BrowserManifestEntry extends ModuleTreeJsonWithFallback {
87
+ readonly type: 'browser';
88
+ }
89
+ export interface RuntimeManifestEntry extends ModuleTreeJsonWithFallback {
90
+ readonly type: 'runtime';
91
+ }
92
+ export interface ResolvedOptions {
93
+ readonly sourceDirectory: string;
94
+ readonly tsConfig: string;
95
+ readonly serverFilePath: string;
96
+ readonly clientOutputDirectory: string;
97
+ readonly serverOutputDirectory: string;
98
+ readonly htmlFiles: readonly string[];
99
+ readonly debug: boolean;
100
+ readonly saveGeneratedModules: boolean;
101
+ readonly isStaticBuild: boolean;
41
102
  }
42
- export default function makePlugin({ sourceDirectory: directory, tsConfig, serverFilePath, clientOutputDirectory, serverOutputDirectory, htmlFileGlobs, debug, saveGeneratedModules, }: PluginOptions): PluginOption[];
103
+ export default function makePlugin({ sourceDirectory: directory, tsConfig, serverFilePath, clientOutputDirectory, serverOutputDirectory, htmlFileGlobs, debug, saveGeneratedModules, isStaticBuild, }: PluginOptions): PluginOption[];
43
104
  //# sourceMappingURL=vite-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAqB,YAAY,EAA6B,MAAM,MAAM,CAAA;AAItF;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAEvC;;OAEG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAEvC;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAE1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IAExB;;OAEG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CACxC;AAsBD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,eAAe,EAAE,SAAS,EAC1B,QAAQ,EACR,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,EACb,KAAa,EACb,oBAA4B,GAC7B,EAAE,aAAa,GAAG,YAAY,EAAE,CAoXhC"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import { existsSync } from 'fs';
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { readFile } from 'fs/promises';
3
- import { basename, dirname, relative, resolve } from 'path';
3
+ import { EOL } from 'os';
4
+ import { basename, dirname, join, relative, resolve } from 'path';
4
5
  import effectTransformer from '@effect/language-service/transformer';
5
- import { setupTsProject, makeHtmlModule, makeRuntimeModule, readDirectory, readModules, readApiModules, makeApiModule, } from '@typed/compiler';
6
+ import { setupTsProject, makeHtmlModule, makeRuntimeModule, readDirectory, readModules, readApiModules, makeApiModule, moduleTreeToJson, apiModuleTreeToJson, } from '@typed/compiler';
6
7
  import glob from 'fast-glob';
7
8
  import { Project, SourceFile, ts } from 'ts-morph';
8
9
  // @ts-expect-error Unable to resolve types w/ NodeNext
@@ -10,12 +11,13 @@ import vavite from 'vavite';
10
11
  import compression from 'vite-plugin-compression';
11
12
  import tsconfigPaths from 'vite-tsconfig-paths';
12
13
  const cwd = process.cwd();
13
- const PLUGIN_NAME = '@typed/vite-plugin';
14
+ export const PLUGIN_NAME = '@typed/vite-plugin';
14
15
  const RUNTIME_VIRTUAL_ENTRYPOINT_PREFIX = 'runtime';
15
16
  const BROWSER_VIRTUAL_ENTRYPOINT_PREFIX = 'browser';
16
17
  const HTML_VIRTUAL_ENTRYPOINT_PREFIX = 'html';
17
18
  const API_VIRTUAL_ENTRYPOINT_PREFIX = 'api';
18
19
  const EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX = 'express';
20
+ const TYPED_CONFIG_IMPORT = 'typed:config';
19
21
  const PREFIXES = [
20
22
  RUNTIME_VIRTUAL_ENTRYPOINT_PREFIX,
21
23
  BROWSER_VIRTUAL_ENTRYPOINT_PREFIX,
@@ -24,7 +26,7 @@ const PREFIXES = [
24
26
  EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX,
25
27
  ];
26
28
  const VIRTUAL_ID_PREFIX = '\0';
27
- export default function makePlugin({ sourceDirectory: directory, tsConfig, serverFilePath, clientOutputDirectory, serverOutputDirectory, htmlFileGlobs, debug = false, saveGeneratedModules = false, }) {
29
+ export default function makePlugin({ sourceDirectory: directory, tsConfig, serverFilePath, clientOutputDirectory, serverOutputDirectory, htmlFileGlobs, debug = false, saveGeneratedModules = false, isStaticBuild = false, }) {
28
30
  // Resolved options
29
31
  const sourceDirectory = resolve(cwd, directory);
30
32
  const tsConfigFilePath = resolve(sourceDirectory, tsConfig ?? 'tsconfig.json');
@@ -40,9 +42,32 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
40
42
  optimize: defaultIncludeExcludeTs,
41
43
  debug: debug ? defaultIncludeExcludeTs : {},
42
44
  };
45
+ const resolvedOptions = {
46
+ sourceDirectory,
47
+ tsConfig: tsConfigFilePath,
48
+ serverFilePath: resolvedServerFilePath,
49
+ serverOutputDirectory: resolvedServerOutputDirectory,
50
+ clientOutputDirectory: resolvedClientOutputDirectory,
51
+ htmlFiles: findHtmlFiles(sourceDirectory, htmlFileGlobs).map((p) => resolve(sourceDirectory, p)),
52
+ debug,
53
+ saveGeneratedModules,
54
+ isStaticBuild,
55
+ };
43
56
  const dependentsMap = new Map();
44
57
  const filePathToModule = new Map();
58
+ const manifest = {
59
+ entryFiles: [],
60
+ modules: {},
61
+ };
62
+ const addManifestEntry = (entry, importer, id) => {
63
+ if (!manifest.modules[importer]) {
64
+ manifest.modules[importer] = {};
65
+ }
66
+ manifest.modules[importer][id] = entry;
67
+ };
45
68
  let devServer;
69
+ let logger;
70
+ let isSsr = false;
46
71
  let project;
47
72
  let transformers;
48
73
  const serverExists = existsSync(resolvedServerFilePath);
@@ -50,22 +75,14 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
50
75
  tsconfigPaths({
51
76
  projects: [tsConfigFilePath],
52
77
  }),
53
- ...(serverExists
54
- ? [
55
- vavite({
56
- serverEntry: resolvedServerFilePath,
57
- serveClientAssetsInDev: true,
58
- }),
59
- ]
60
- : []),
61
78
  ];
62
79
  const setupProject = () => {
63
80
  if (project) {
64
81
  return;
65
82
  }
66
- info(`Setting up TypeScript project...`);
83
+ info(`Setting up TypeScript project...`, logger);
67
84
  project = setupTsProject(tsConfigFilePath);
68
- info(`Setup TypeScript project.`);
85
+ info(`Setup TypeScript project.`, logger);
69
86
  // Setup transformer for virtual modules.
70
87
  transformers = {
71
88
  before: [
@@ -78,7 +95,9 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
78
95
  setupProject();
79
96
  return {
80
97
  ...project.getCompilerOptions(),
81
- allowJs: true,
98
+ inlineSourceMap: false,
99
+ inlineSources: saveGeneratedModules,
100
+ sourceMap: true,
82
101
  };
83
102
  };
84
103
  const handleFileChange = async (path, event) => {
@@ -101,7 +120,7 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
101
120
  for (const dependent of dependents ?? []) {
102
121
  const mod = devServer.moduleGraph.getModuleById(dependent);
103
122
  if (mod) {
104
- info(`reloading ${dependent}`);
123
+ info(`reloading ${dependent}`, logger);
105
124
  await devServer.reloadModule(mod);
106
125
  }
107
126
  }
@@ -115,19 +134,23 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
115
134
  }
116
135
  }
117
136
  };
118
- const buildRenderModule = async (importer, id) => {
137
+ const buildRuntimeModule = async (importer, id) => {
119
138
  const moduleDirectory = resolve(dirname(importer), parseModulesFromId(id, importer));
120
139
  const relativeDirectory = relative(sourceDirectory, moduleDirectory);
121
140
  const isBrowser = id.startsWith(BROWSER_VIRTUAL_ENTRYPOINT_PREFIX);
122
141
  const moduleType = isBrowser ? 'browser' : 'runtime';
123
142
  const filePath = `${moduleDirectory}.${moduleType}.__generated__.ts`;
124
- info(`Building ${moduleType} module for ${relativeDirectory}...`);
125
143
  const directory = await readDirectory(moduleDirectory);
126
144
  const moduleTree = readModules(project, directory);
145
+ addManifestEntry({
146
+ type: moduleType,
147
+ ...moduleTreeToJson(sourceDirectory, moduleTree),
148
+ }, relative(sourceDirectory, importer), id);
127
149
  // Setup the TypeScript project if it hasn't been already
128
150
  setupProject();
129
151
  const sourceFile = makeRuntimeModule(project, moduleTree, importer, filePath, isBrowser);
130
- info(`Built ${moduleType} module for ${relativeDirectory}.`);
152
+ addDependents(sourceFile);
153
+ info(`Built ${moduleType} module for ${relativeDirectory}.`, logger);
131
154
  filePathToModule.set(filePath, sourceFile);
132
155
  if (saveGeneratedModules) {
133
156
  await sourceFile.save();
@@ -139,9 +162,8 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
139
162
  const htmlFilePath = resolve(dirname(importer), htmlFileName + '.html');
140
163
  const relativeHtmlFilePath = relative(sourceDirectory, htmlFilePath);
141
164
  let html = '';
142
- info(`Building html module for ${relativeHtmlFilePath}...`);
143
165
  // If there's a dev server, use it to transform the HTML for development
144
- if (devServer) {
166
+ if (!isStaticBuild && devServer) {
145
167
  html = (await readFile(htmlFilePath, 'utf-8')).toString();
146
168
  html = await devServer.transformIndexHtml(getRelativePath(sourceDirectory, htmlFilePath), html);
147
169
  }
@@ -157,8 +179,14 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
157
179
  serverOutputDirectory: resolvedServerOutputDirectory,
158
180
  clientOutputDirectory: resolvedClientOutputDirectory,
159
181
  devServer,
182
+ isStaticBuild,
160
183
  });
161
- info(`Built html module for ${relativeHtmlFilePath}.`);
184
+ addManifestEntry({
185
+ type: 'html',
186
+ filePath: relativeHtmlFilePath,
187
+ }, relative(sourceDirectory, importer), id);
188
+ addDependents(sourceFile);
189
+ info(`Built html module for ${relativeHtmlFilePath}.`, logger);
162
190
  const filePath = sourceFile.getFilePath();
163
191
  filePathToModule.set(filePath, sourceFile);
164
192
  if (saveGeneratedModules) {
@@ -171,35 +199,54 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
171
199
  const moduleName = parseModulesFromId(id, importer);
172
200
  const moduleDirectory = resolve(importDirectory, moduleName);
173
201
  const relativeDirectory = relative(sourceDirectory, moduleDirectory);
174
- const moduleType = id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX) ? 'express' : 'API';
175
- info(`Building ${moduleType} module for ${relativeDirectory}...`);
202
+ const moduleType = id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX) ? 'express' : 'api';
176
203
  const directory = await readDirectory(moduleDirectory);
177
204
  const moduleTree = readApiModules(project, directory);
178
205
  const filePath = `${importDirectory}/${basename(moduleName)}.${moduleType.toLowerCase()}.__generated__.ts`;
179
206
  const sourceFile = makeApiModule(project, moduleTree, filePath, importer, id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX));
180
- info(`Built ${moduleType} module for ${relativeDirectory}.`);
207
+ addManifestEntry({
208
+ type: moduleType,
209
+ ...apiModuleTreeToJson(sourceDirectory, moduleTree),
210
+ }, relative(sourceDirectory, importer), id);
211
+ addDependents(sourceFile);
212
+ info(`Built ${moduleType} module for ${relativeDirectory}.`, logger);
181
213
  filePathToModule.set(filePath, sourceFile);
182
214
  if (saveGeneratedModules) {
183
215
  await sourceFile.save();
184
216
  }
185
217
  return filePath;
186
218
  };
219
+ const addDependents = (sourceFile) => {
220
+ const importer = sourceFile.getFilePath();
221
+ const imports = sourceFile
222
+ .getLiteralsReferencingOtherSourceFiles()
223
+ .map((i) => i.getLiteralValue());
224
+ for (const i of imports) {
225
+ const dependents = dependentsMap.get(i) ?? new Set();
226
+ dependents.add(importer);
227
+ dependentsMap.set(i, dependents);
228
+ }
229
+ };
187
230
  const virtualModulePlugin = {
188
231
  name: PLUGIN_NAME,
232
+ resolvedOptions,
189
233
  config(config, env) {
234
+ isSsr = env.ssrBuild ?? false;
190
235
  // Configure Build steps when running with vavite
191
236
  if (env.mode === 'multibuild') {
192
237
  const clientBuild = {
193
238
  outDir: resolvedClientOutputDirectory,
194
239
  rollupOptions: {
195
- input: buildClientInput(findHtmlFiles(sourceDirectory, htmlFileGlobs).map((p) => resolve(sourceDirectory, p))),
240
+ input: buildClientInput(resolvedOptions.htmlFiles),
196
241
  },
197
242
  };
198
243
  const serverBuild = {
199
244
  ssr: true,
200
245
  outDir: resolvedServerOutputDirectory,
201
246
  rollupOptions: {
202
- input: resolvedServerFilePath,
247
+ input: {
248
+ index: resolvedServerFilePath,
249
+ },
203
250
  },
204
251
  };
205
252
  config.buildSteps = [
@@ -219,6 +266,30 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
219
266
  ];
220
267
  return;
221
268
  }
269
+ if (serverExists) {
270
+ config.plugins?.push(vavite({
271
+ serverEntry: resolvedServerFilePath,
272
+ serveClientAssetsInDev: true,
273
+ }));
274
+ }
275
+ else {
276
+ // TODO: Add vavite plugins without reloader
277
+ }
278
+ },
279
+ configResolved(resolvedConfig) {
280
+ logger = resolvedConfig.logger;
281
+ const input = resolvedConfig.build.rollupOptions.input;
282
+ if (!input)
283
+ return;
284
+ if (typeof input === 'string') {
285
+ manifest.entryFiles.push(parseEntryFile(sourceDirectory, input));
286
+ }
287
+ else if (Array.isArray(input)) {
288
+ manifest.entryFiles.push(...input.map((i) => parseEntryFile(sourceDirectory, i)));
289
+ }
290
+ else {
291
+ manifest.entryFiles.push(...Object.values(input).map((i) => parseEntryFile(sourceDirectory, i)));
292
+ }
222
293
  },
223
294
  configureServer(server) {
224
295
  devServer = server;
@@ -237,13 +308,16 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
237
308
  async watchChange(path, { event }) {
238
309
  handleFileChange(path, event);
239
310
  },
240
- closeBundle() {
311
+ async closeBundle() {
241
312
  if (project) {
242
313
  const diagnostics = project.getPreEmitDiagnostics();
243
314
  if (diagnostics.length > 0) {
244
315
  this.error(project.formatDiagnosticsWithColorAndContext(diagnostics));
245
316
  }
246
317
  }
318
+ if (Object.keys(manifest).length > 0) {
319
+ writeFileSync(resolve(isSsr ? resolvedServerOutputDirectory : resolvedClientOutputDirectory, 'typed-manifest.json'), JSON.stringify(manifest, null, 2) + EOL);
320
+ }
247
321
  },
248
322
  async resolveId(id, importer) {
249
323
  if (!importer) {
@@ -252,16 +326,22 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
252
326
  if (id.startsWith(RUNTIME_VIRTUAL_ENTRYPOINT_PREFIX) ||
253
327
  id.startsWith(BROWSER_VIRTUAL_ENTRYPOINT_PREFIX)) {
254
328
  setupProject();
255
- return VIRTUAL_ID_PREFIX + (await buildRenderModule(importer, id));
329
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildRuntimeModule(importer, id));
330
+ return virtualId;
256
331
  }
257
332
  if (id.startsWith(HTML_VIRTUAL_ENTRYPOINT_PREFIX)) {
258
333
  setupProject();
259
- return VIRTUAL_ID_PREFIX + (await buildHtmlModule(importer, id));
334
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildHtmlModule(importer, id));
335
+ return virtualId;
260
336
  }
261
337
  if (id.startsWith(API_VIRTUAL_ENTRYPOINT_PREFIX) ||
262
338
  id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX)) {
263
339
  setupProject();
264
- return VIRTUAL_ID_PREFIX + (await buildApiModule(importer, id));
340
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildApiModule(importer, id));
341
+ return virtualId;
342
+ }
343
+ if (id === TYPED_CONFIG_IMPORT) {
344
+ return VIRTUAL_ID_PREFIX + TYPED_CONFIG_IMPORT;
265
345
  }
266
346
  importer = importer.replace(VIRTUAL_ID_PREFIX, '');
267
347
  // Virtual modules have problems with resolving relative paths due to not
@@ -274,21 +354,21 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
274
354
  id = id.replace(VIRTUAL_ID_PREFIX, '');
275
355
  const sourceFile = filePathToModule.get(id) ?? project?.getSourceFile(id);
276
356
  if (sourceFile) {
277
- logDiagnostics(project, sourceFile, sourceDirectory, id);
278
- const text = sourceFile.getFullText();
279
- const output = ts.transpileModule(text, {
280
- fileName: id,
281
- compilerOptions: transpilerCompilerOptions(),
282
- transformers,
283
- });
357
+ logDiagnostics(project, sourceFile, sourceDirectory, id, logger);
284
358
  return {
285
- code: output.outputText,
286
- map: output.sourceMapText,
359
+ code: sourceFile.getFullText(),
360
+ };
361
+ }
362
+ if (id === TYPED_CONFIG_IMPORT) {
363
+ return {
364
+ code: Object.entries(resolvedOptions)
365
+ .map(([key, value]) => `export const ${key} = ${JSON.stringify(value)}`)
366
+ .join(EOL),
287
367
  };
288
368
  }
289
369
  },
290
370
  transform(text, id) {
291
- if (/.tsx?$/.test(id) || /.m?jsx?$/.test(id)) {
371
+ if (/.[c|m]?tsx?$/.test(id)) {
292
372
  const output = ts.transpileModule(text, {
293
373
  fileName: id,
294
374
  compilerOptions: transpilerCompilerOptions(),
@@ -304,20 +384,18 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
304
384
  plugins.push(virtualModulePlugin);
305
385
  return plugins;
306
386
  }
307
- function logDiagnostics(project, sourceFile, sourceDirectory, filePath) {
387
+ function logDiagnostics(project, sourceFile, sourceDirectory, filePath, logger) {
308
388
  const diagnostics = sourceFile.getPreEmitDiagnostics();
309
389
  const relativeFilePath = relative(sourceDirectory, filePath);
310
390
  if (diagnostics.length > 0) {
311
- info(sourceFile.getFullText());
312
- info(project.formatDiagnosticsWithColorAndContext(diagnostics));
313
- }
314
- else {
315
- info(`${relativeFilePath} module successfuly typed-checked.`);
391
+ info(`Type-checking errors found at ${relativeFilePath}`, logger);
392
+ info(`Source:` + EOL + sourceFile.getFullText(), logger);
393
+ info(project.formatDiagnosticsWithColorAndContext(diagnostics), logger);
316
394
  }
317
395
  }
318
396
  function findRelativeFile(importer, id) {
319
397
  const dir = dirname(importer);
320
- const tsPath = resolve(dir, id.replace(/.js(x)?$/, '.ts$1'));
398
+ const tsPath = resolve(dir, id.replace(/.([c|m])?js(x)?$/, '.$1ts$2'));
321
399
  if (existsSync(tsPath)) {
322
400
  return tsPath;
323
401
  }
@@ -347,12 +425,7 @@ function findHtmlFiles(directory, htmlFileGlobs) {
347
425
  });
348
426
  }
349
427
  function buildClientInput(htmlFilePaths) {
350
- const input = {};
351
- for (const htmlFilePath of htmlFilePaths) {
352
- const htmlFile = basename(htmlFilePath, '.html');
353
- input[htmlFile] = htmlFilePath;
354
- }
355
- return input;
428
+ return htmlFilePaths.reduce((acc, htmlFilePath) => ({ ...acc, [basename(htmlFilePath, '.html')]: htmlFilePath }), {});
356
429
  }
357
430
  function getRelativePath(from, to) {
358
431
  const path = relative(from, to);
@@ -361,8 +434,62 @@ function getRelativePath(from, to) {
361
434
  }
362
435
  return path;
363
436
  }
364
- function info(message) {
365
- const date = new Date();
366
- console.info(`[${PLUGIN_NAME}] ${date.toISOString()};`, `${message}`);
437
+ function info(message, logger) {
438
+ if (logger) {
439
+ logger.info(`[${PLUGIN_NAME}]: ${message}`);
440
+ }
441
+ else {
442
+ console.info(`[${PLUGIN_NAME}]:`, `${message}`);
443
+ }
444
+ }
445
+ function parseEntryFile(sourceDirectory, filePath) {
446
+ if (filePath.endsWith('.html')) {
447
+ return parseHtmlEntryFile(sourceDirectory, filePath);
448
+ }
449
+ return parseTsEntryFile(sourceDirectory, filePath);
450
+ }
451
+ function parseHtmlEntryFile(sourceDirectory, filePath) {
452
+ const content = readFileSync(filePath, 'utf-8').toString();
453
+ return {
454
+ type: 'html',
455
+ filePath: relative(sourceDirectory, filePath),
456
+ imports: parseHtmlImports(sourceDirectory, content),
457
+ basePath: parseBasePath(content),
458
+ };
459
+ }
460
+ function parseHtmlImports(sourceDirectory, content) {
461
+ const imports = [];
462
+ const matches = content.match(/<script[^>]*src="([^"]*)"[^>]*>/g);
463
+ if (matches) {
464
+ for (const match of matches) {
465
+ // If script is not type=module then skip
466
+ if (!match.includes('type="module"')) {
467
+ continue;
468
+ }
469
+ const src = match.match(/src="([^"]*)"/)?.[1];
470
+ if (src) {
471
+ const fullPath = join(sourceDirectory, src);
472
+ const relativePath = relative(sourceDirectory, fullPath);
473
+ imports.push(relativePath);
474
+ }
475
+ }
476
+ }
477
+ return imports;
478
+ }
479
+ function parseBasePath(content) {
480
+ const baseTag = content.match(/<base[^>]*>/)?.[0];
481
+ if (baseTag) {
482
+ const href = baseTag.match(/href="([^"]*)"/)?.[1];
483
+ if (href) {
484
+ return href;
485
+ }
486
+ }
487
+ return '/';
488
+ }
489
+ function parseTsEntryFile(sourceDirectory, filePath) {
490
+ return {
491
+ type: 'ts',
492
+ filePath: relative(sourceDirectory, filePath),
493
+ };
367
494
  }
368
495
  //# sourceMappingURL=vite-plugin.js.map