@typed/vite-plugin 0.0.20 → 0.0.22

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,20 @@ 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
- : []),
78
+ serverExists &&
79
+ !isStaticBuild &&
80
+ vavite({
81
+ serverEntry: resolvedServerFilePath,
82
+ serveClientAssetsInDev: true,
83
+ }),
61
84
  ];
62
85
  const setupProject = () => {
63
86
  if (project) {
64
87
  return;
65
88
  }
66
- info(`Setting up TypeScript project...`);
89
+ info(`Setting up TypeScript project...`, logger);
67
90
  project = setupTsProject(tsConfigFilePath);
68
- info(`Setup TypeScript project.`);
91
+ info(`Setup TypeScript project.`, logger);
69
92
  // Setup transformer for virtual modules.
70
93
  transformers = {
71
94
  before: [
@@ -78,7 +101,9 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
78
101
  setupProject();
79
102
  return {
80
103
  ...project.getCompilerOptions(),
81
- allowJs: true,
104
+ inlineSourceMap: false,
105
+ inlineSources: saveGeneratedModules,
106
+ sourceMap: true,
82
107
  };
83
108
  };
84
109
  const handleFileChange = async (path, event) => {
@@ -101,7 +126,7 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
101
126
  for (const dependent of dependents ?? []) {
102
127
  const mod = devServer.moduleGraph.getModuleById(dependent);
103
128
  if (mod) {
104
- info(`reloading ${dependent}`);
129
+ info(`reloading ${dependent}`, logger);
105
130
  await devServer.reloadModule(mod);
106
131
  }
107
132
  }
@@ -115,19 +140,23 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
115
140
  }
116
141
  }
117
142
  };
118
- const buildRenderModule = async (importer, id) => {
143
+ const buildRuntimeModule = async (importer, id) => {
119
144
  const moduleDirectory = resolve(dirname(importer), parseModulesFromId(id, importer));
120
145
  const relativeDirectory = relative(sourceDirectory, moduleDirectory);
121
146
  const isBrowser = id.startsWith(BROWSER_VIRTUAL_ENTRYPOINT_PREFIX);
122
147
  const moduleType = isBrowser ? 'browser' : 'runtime';
123
148
  const filePath = `${moduleDirectory}.${moduleType}.__generated__.ts`;
124
- info(`Building ${moduleType} module for ${relativeDirectory}...`);
125
149
  const directory = await readDirectory(moduleDirectory);
126
150
  const moduleTree = readModules(project, directory);
151
+ addManifestEntry({
152
+ type: moduleType,
153
+ ...moduleTreeToJson(sourceDirectory, moduleTree),
154
+ }, relative(sourceDirectory, importer), id);
127
155
  // Setup the TypeScript project if it hasn't been already
128
156
  setupProject();
129
157
  const sourceFile = makeRuntimeModule(project, moduleTree, importer, filePath, isBrowser);
130
- info(`Built ${moduleType} module for ${relativeDirectory}.`);
158
+ addDependents(sourceFile);
159
+ info(`Built ${moduleType} module for ${relativeDirectory}.`, logger);
131
160
  filePathToModule.set(filePath, sourceFile);
132
161
  if (saveGeneratedModules) {
133
162
  await sourceFile.save();
@@ -139,9 +168,8 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
139
168
  const htmlFilePath = resolve(dirname(importer), htmlFileName + '.html');
140
169
  const relativeHtmlFilePath = relative(sourceDirectory, htmlFilePath);
141
170
  let html = '';
142
- info(`Building html module for ${relativeHtmlFilePath}...`);
143
171
  // If there's a dev server, use it to transform the HTML for development
144
- if (devServer) {
172
+ if (!isStaticBuild && devServer) {
145
173
  html = (await readFile(htmlFilePath, 'utf-8')).toString();
146
174
  html = await devServer.transformIndexHtml(getRelativePath(sourceDirectory, htmlFilePath), html);
147
175
  }
@@ -157,8 +185,14 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
157
185
  serverOutputDirectory: resolvedServerOutputDirectory,
158
186
  clientOutputDirectory: resolvedClientOutputDirectory,
159
187
  devServer,
188
+ isStaticBuild,
160
189
  });
161
- info(`Built html module for ${relativeHtmlFilePath}.`);
190
+ addManifestEntry({
191
+ type: 'html',
192
+ filePath: relativeHtmlFilePath,
193
+ }, relative(sourceDirectory, importer), id);
194
+ addDependents(sourceFile);
195
+ info(`Built html module for ${relativeHtmlFilePath}.`, logger);
162
196
  const filePath = sourceFile.getFilePath();
163
197
  filePathToModule.set(filePath, sourceFile);
164
198
  if (saveGeneratedModules) {
@@ -171,35 +205,54 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
171
205
  const moduleName = parseModulesFromId(id, importer);
172
206
  const moduleDirectory = resolve(importDirectory, moduleName);
173
207
  const relativeDirectory = relative(sourceDirectory, moduleDirectory);
174
- const moduleType = id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX) ? 'express' : 'API';
175
- info(`Building ${moduleType} module for ${relativeDirectory}...`);
208
+ const moduleType = id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX) ? 'express' : 'api';
176
209
  const directory = await readDirectory(moduleDirectory);
177
210
  const moduleTree = readApiModules(project, directory);
178
211
  const filePath = `${importDirectory}/${basename(moduleName)}.${moduleType.toLowerCase()}.__generated__.ts`;
179
212
  const sourceFile = makeApiModule(project, moduleTree, filePath, importer, id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX));
180
- info(`Built ${moduleType} module for ${relativeDirectory}.`);
213
+ addManifestEntry({
214
+ type: moduleType,
215
+ ...apiModuleTreeToJson(sourceDirectory, moduleTree),
216
+ }, relative(sourceDirectory, importer), id);
217
+ addDependents(sourceFile);
218
+ info(`Built ${moduleType} module for ${relativeDirectory}.`, logger);
181
219
  filePathToModule.set(filePath, sourceFile);
182
220
  if (saveGeneratedModules) {
183
221
  await sourceFile.save();
184
222
  }
185
223
  return filePath;
186
224
  };
225
+ const addDependents = (sourceFile) => {
226
+ const importer = sourceFile.getFilePath();
227
+ const imports = sourceFile
228
+ .getLiteralsReferencingOtherSourceFiles()
229
+ .map((i) => i.getLiteralValue());
230
+ for (const i of imports) {
231
+ const dependents = dependentsMap.get(i) ?? new Set();
232
+ dependents.add(importer);
233
+ dependentsMap.set(i, dependents);
234
+ }
235
+ };
187
236
  const virtualModulePlugin = {
188
237
  name: PLUGIN_NAME,
238
+ resolvedOptions,
189
239
  config(config, env) {
240
+ isSsr = env.ssrBuild ?? false;
190
241
  // Configure Build steps when running with vavite
191
242
  if (env.mode === 'multibuild') {
192
243
  const clientBuild = {
193
244
  outDir: resolvedClientOutputDirectory,
194
245
  rollupOptions: {
195
- input: buildClientInput(findHtmlFiles(sourceDirectory, htmlFileGlobs).map((p) => resolve(sourceDirectory, p))),
246
+ input: buildClientInput(resolvedOptions.htmlFiles),
196
247
  },
197
248
  };
198
249
  const serverBuild = {
199
250
  ssr: true,
200
251
  outDir: resolvedServerOutputDirectory,
201
252
  rollupOptions: {
202
- input: resolvedServerFilePath,
253
+ input: {
254
+ index: resolvedServerFilePath,
255
+ },
203
256
  },
204
257
  };
205
258
  config.buildSteps = [
@@ -220,6 +273,21 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
220
273
  return;
221
274
  }
222
275
  },
276
+ configResolved(resolvedConfig) {
277
+ logger = resolvedConfig.logger;
278
+ const input = resolvedConfig.build.rollupOptions.input;
279
+ if (!input)
280
+ return;
281
+ if (typeof input === 'string') {
282
+ manifest.entryFiles.push(parseEntryFile(sourceDirectory, input));
283
+ }
284
+ else if (Array.isArray(input)) {
285
+ manifest.entryFiles.push(...input.map((i) => parseEntryFile(sourceDirectory, i)));
286
+ }
287
+ else {
288
+ manifest.entryFiles.push(...Object.values(input).map((i) => parseEntryFile(sourceDirectory, i)));
289
+ }
290
+ },
223
291
  configureServer(server) {
224
292
  devServer = server;
225
293
  server.watcher.on('all', (event, path) => {
@@ -237,13 +305,16 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
237
305
  async watchChange(path, { event }) {
238
306
  handleFileChange(path, event);
239
307
  },
240
- closeBundle() {
308
+ async closeBundle() {
241
309
  if (project) {
242
310
  const diagnostics = project.getPreEmitDiagnostics();
243
311
  if (diagnostics.length > 0) {
244
312
  this.error(project.formatDiagnosticsWithColorAndContext(diagnostics));
245
313
  }
246
314
  }
315
+ if (Object.keys(manifest).length > 0) {
316
+ writeFileSync(resolve(isSsr ? resolvedServerOutputDirectory : resolvedClientOutputDirectory, 'typed-manifest.json'), JSON.stringify(manifest, null, 2) + EOL);
317
+ }
247
318
  },
248
319
  async resolveId(id, importer) {
249
320
  if (!importer) {
@@ -252,16 +323,22 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
252
323
  if (id.startsWith(RUNTIME_VIRTUAL_ENTRYPOINT_PREFIX) ||
253
324
  id.startsWith(BROWSER_VIRTUAL_ENTRYPOINT_PREFIX)) {
254
325
  setupProject();
255
- return VIRTUAL_ID_PREFIX + (await buildRenderModule(importer, id));
326
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildRuntimeModule(importer, id));
327
+ return virtualId;
256
328
  }
257
329
  if (id.startsWith(HTML_VIRTUAL_ENTRYPOINT_PREFIX)) {
258
330
  setupProject();
259
- return VIRTUAL_ID_PREFIX + (await buildHtmlModule(importer, id));
331
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildHtmlModule(importer, id));
332
+ return virtualId;
260
333
  }
261
334
  if (id.startsWith(API_VIRTUAL_ENTRYPOINT_PREFIX) ||
262
335
  id.startsWith(EXPRESS_VIRTUAL_ENTRYPOINT_PREFIX)) {
263
336
  setupProject();
264
- return VIRTUAL_ID_PREFIX + (await buildApiModule(importer, id));
337
+ const virtualId = VIRTUAL_ID_PREFIX + (await buildApiModule(importer, id));
338
+ return virtualId;
339
+ }
340
+ if (id === TYPED_CONFIG_IMPORT) {
341
+ return VIRTUAL_ID_PREFIX + TYPED_CONFIG_IMPORT;
265
342
  }
266
343
  importer = importer.replace(VIRTUAL_ID_PREFIX, '');
267
344
  // Virtual modules have problems with resolving relative paths due to not
@@ -274,21 +351,21 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
274
351
  id = id.replace(VIRTUAL_ID_PREFIX, '');
275
352
  const sourceFile = filePathToModule.get(id) ?? project?.getSourceFile(id);
276
353
  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
- });
354
+ logDiagnostics(project, sourceFile, sourceDirectory, id, logger);
284
355
  return {
285
- code: output.outputText,
286
- map: output.sourceMapText,
356
+ code: sourceFile.getFullText(),
357
+ };
358
+ }
359
+ if (id === TYPED_CONFIG_IMPORT) {
360
+ return {
361
+ code: Object.entries(resolvedOptions)
362
+ .map(([key, value]) => `export const ${key} = ${JSON.stringify(value)}`)
363
+ .join(EOL),
287
364
  };
288
365
  }
289
366
  },
290
367
  transform(text, id) {
291
- if (/.tsx?$/.test(id) || /.m?jsx?$/.test(id)) {
368
+ if (/.[c|m]?tsx?$/.test(id)) {
292
369
  const output = ts.transpileModule(text, {
293
370
  fileName: id,
294
371
  compilerOptions: transpilerCompilerOptions(),
@@ -304,20 +381,18 @@ export default function makePlugin({ sourceDirectory: directory, tsConfig, serve
304
381
  plugins.push(virtualModulePlugin);
305
382
  return plugins;
306
383
  }
307
- function logDiagnostics(project, sourceFile, sourceDirectory, filePath) {
384
+ function logDiagnostics(project, sourceFile, sourceDirectory, filePath, logger) {
308
385
  const diagnostics = sourceFile.getPreEmitDiagnostics();
309
386
  const relativeFilePath = relative(sourceDirectory, filePath);
310
387
  if (diagnostics.length > 0) {
311
- info(sourceFile.getFullText());
312
- info(project.formatDiagnosticsWithColorAndContext(diagnostics));
313
- }
314
- else {
315
- info(`${relativeFilePath} module successfuly typed-checked.`);
388
+ info(`Type-checking errors found at ${relativeFilePath}`, logger);
389
+ info(`Source:` + EOL + sourceFile.getFullText(), logger);
390
+ info(project.formatDiagnosticsWithColorAndContext(diagnostics), logger);
316
391
  }
317
392
  }
318
393
  function findRelativeFile(importer, id) {
319
394
  const dir = dirname(importer);
320
- const tsPath = resolve(dir, id.replace(/.js(x)?$/, '.ts$1'));
395
+ const tsPath = resolve(dir, id.replace(/.([c|m])?js(x)?$/, '.$1ts$2'));
321
396
  if (existsSync(tsPath)) {
322
397
  return tsPath;
323
398
  }
@@ -347,12 +422,7 @@ function findHtmlFiles(directory, htmlFileGlobs) {
347
422
  });
348
423
  }
349
424
  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;
425
+ return htmlFilePaths.reduce((acc, htmlFilePath) => ({ ...acc, [basename(htmlFilePath, '.html')]: htmlFilePath }), {});
356
426
  }
357
427
  function getRelativePath(from, to) {
358
428
  const path = relative(from, to);
@@ -361,8 +431,62 @@ function getRelativePath(from, to) {
361
431
  }
362
432
  return path;
363
433
  }
364
- function info(message) {
365
- const date = new Date();
366
- console.info(`[${PLUGIN_NAME}] ${date.toISOString()};`, `${message}`);
434
+ function info(message, logger) {
435
+ if (logger) {
436
+ logger.info(`[${PLUGIN_NAME}]: ${message}`);
437
+ }
438
+ else {
439
+ console.info(`[${PLUGIN_NAME}]:`, `${message}`);
440
+ }
441
+ }
442
+ function parseEntryFile(sourceDirectory, filePath) {
443
+ if (filePath.endsWith('.html')) {
444
+ return parseHtmlEntryFile(sourceDirectory, filePath);
445
+ }
446
+ return parseTsEntryFile(sourceDirectory, filePath);
447
+ }
448
+ function parseHtmlEntryFile(sourceDirectory, filePath) {
449
+ const content = readFileSync(filePath, 'utf-8').toString();
450
+ return {
451
+ type: 'html',
452
+ filePath: relative(sourceDirectory, filePath),
453
+ imports: parseHtmlImports(sourceDirectory, content),
454
+ basePath: parseBasePath(content),
455
+ };
456
+ }
457
+ function parseHtmlImports(sourceDirectory, content) {
458
+ const imports = [];
459
+ const matches = content.match(/<script[^>]*src="([^"]*)"[^>]*>/g);
460
+ if (matches) {
461
+ for (const match of matches) {
462
+ // If script is not type=module then skip
463
+ if (!match.includes('type="module"')) {
464
+ continue;
465
+ }
466
+ const src = match.match(/src="([^"]*)"/)?.[1];
467
+ if (src) {
468
+ const fullPath = join(sourceDirectory, src);
469
+ const relativePath = relative(sourceDirectory, fullPath);
470
+ imports.push(relativePath);
471
+ }
472
+ }
473
+ }
474
+ return imports;
475
+ }
476
+ function parseBasePath(content) {
477
+ const baseTag = content.match(/<base[^>]*>/)?.[0];
478
+ if (baseTag) {
479
+ const href = baseTag.match(/href="([^"]*)"/)?.[1];
480
+ if (href) {
481
+ return href;
482
+ }
483
+ }
484
+ return '/';
485
+ }
486
+ function parseTsEntryFile(sourceDirectory, filePath) {
487
+ return {
488
+ type: 'ts',
489
+ filePath: relative(sourceDirectory, filePath),
490
+ };
367
491
  }
368
492
  //# sourceMappingURL=vite-plugin.js.map