@3sln/deck 0.0.5

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.
package/vite-plugin.js ADDED
@@ -0,0 +1,147 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { sha256, loadDeckConfig, getProjectFiles, getHtmlTemplate } from './src/config.js';
4
+
5
+ export default function deckPlugin() {
6
+ let resolvedConfig;
7
+
8
+ return {
9
+ name: 'vite-plugin-deck',
10
+
11
+ resolveId(id) {
12
+ if (id.startsWith('/@deck-dev-hmr/')) {
13
+ return id;
14
+ }
15
+ return null;
16
+ },
17
+
18
+ async handleHotUpdate({read, modules, server}) {
19
+ const rawUrls = modules.map(m => m.url).filter(u => u.endsWith('?raw'));
20
+ if (rawUrls.length === 0) {
21
+ return;
22
+ }
23
+
24
+ server.ws.send({
25
+ type: 'custom',
26
+ event: 'deck-raw-update',
27
+ data: {urls: rawUrls, text: await read()},
28
+ });
29
+ },
30
+
31
+ load(id) {
32
+ if (id.startsWith('/@deck-dev-hmr/')) {
33
+ const realPath = decodeURIComponent(id.slice('/@deck-dev-hmr/'.length));
34
+ const rawPath = realPath + '?raw';
35
+ return `
36
+ import realDefault from '${realPath}';
37
+ import moduleText from '${rawPath}';
38
+
39
+ let lastArgs;
40
+ let abortController = new AbortController();
41
+
42
+ if (import.meta.hot?.data.lastArgs) {
43
+ lastArgs = import.meta.hot.data.lastArgs;
44
+ }
45
+
46
+ const textObservers = import.meta.hot?.data.textObservers ?? [];
47
+ export const moduleText$ = {
48
+ subscribe: observer => {
49
+ const observerObj = typeof observer === 'function' ? {next: observer} : observer;
50
+ observerObj?.next(moduleText);
51
+ textObservers.push(observerObj);
52
+
53
+ return {
54
+ unsubscribe: () => {
55
+ textObservers = textObservers.filter(x => x !== observerObj);
56
+ }
57
+ };
58
+ }
59
+ };
60
+
61
+ export default (...args) => {
62
+ lastArgs = args;
63
+ const thisContext = { signal: abortController.signal };
64
+ realDefault.call(thisContext, ...args);
65
+ };
66
+
67
+ if (import.meta.hot) {
68
+ import.meta.hot.dispose(data => {
69
+ data.lastArgs = lastArgs;
70
+ data.textObservers = textObservers;
71
+ abortController.abort();
72
+ });
73
+
74
+ import.meta.hot.accept(newModule => {
75
+ if (newModule && newModule.default && lastArgs) {
76
+ newModule.default(...lastArgs);
77
+ }
78
+ });
79
+ import.meta.hot.on('deck-raw-update', ({urls, text}) => {
80
+ if (!urls.includes('${rawPath}')) {
81
+ return;
82
+ }
83
+
84
+ for (const observer of textObservers) {
85
+ observer?.next(text);
86
+ }
87
+ });
88
+ }
89
+ `;
90
+ }
91
+ return null;
92
+ },
93
+
94
+ config(config, {command}) {
95
+ return {optimizeDeps: {include: config.optimizeDeps?.include ?? []}};
96
+ },
97
+
98
+ configResolved(config) {
99
+ resolvedConfig = config;
100
+ },
101
+
102
+ async configureServer(server) {
103
+ const config = await loadDeckConfig(resolvedConfig.root);
104
+ const devConfig = config.dev;
105
+
106
+ server.watcher.on('all', (eventName, eventPath) => {
107
+ const projPath = path.relative(resolvedConfig.root, eventPath);
108
+ const webPath = '/' + projPath.replace(/\\/g, '/');
109
+ const files = getProjectFiles(resolvedConfig.root, devConfig).map(p => `/${p}`);
110
+ if (!files.includes(webPath)) return;
111
+
112
+ switch (eventName) {
113
+ case 'add':
114
+ case 'change':
115
+ server.ws.send({type: 'custom', event: 'deck:card-changed', data: {path: webPath}});
116
+ break;
117
+ case 'unlink':
118
+ server.ws.send({type: 'custom', event: 'deck:card-removed', data: {path: webPath}});
119
+ break;
120
+ }
121
+ });
122
+
123
+ server.middlewares.use(async (req, res, next) => {
124
+ if (req.url.endsWith('/')) {
125
+ const cardPaths = getProjectFiles(resolvedConfig.root, devConfig).map(p => `/${p}`);
126
+ const initialCardsData = await Promise.all(cardPaths.map(async (p) => {
127
+ const content = await fs.readFile(path.join(resolvedConfig.root, p), 'utf-8');
128
+ const hash = await sha256(content);
129
+ return { path: p, hash };
130
+ }));
131
+
132
+ const template = getHtmlTemplate({
133
+ title: devConfig.title,
134
+ importMap: devConfig.importMap,
135
+ initialCardsData,
136
+ pinnedCardPaths: devConfig.pinned,
137
+ entryFile: '@3sln/deck'
138
+ });
139
+ const html = await server.transformIndexHtml(req.url, template);
140
+ res.end(html);
141
+ return;
142
+ }
143
+ next();
144
+ });
145
+ },
146
+ };
147
+ }