xpine 0.0.4 → 0.0.6

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.
@@ -1,114 +1,102 @@
1
- // Enables SPA like behavior for links
2
-
1
+ // src/static/spa.mjs
3
2
  async function replaceDocumentContentsWithLinkResponse() {
4
- const links = [...document.querySelectorAll('[data-spa]')];
3
+ const links = [...document.querySelectorAll("[data-spa]")];
5
4
  for (const link of links) {
6
- link.addEventListener('click', updatePageOnLinkClick);
5
+ link.addEventListener("click", updatePageOnLinkClick);
7
6
  }
8
-
9
7
  }
10
-
11
8
  async function updatePageOnLinkClick(e) {
12
- const targetHref = e?.target?.getAttribute('href');
9
+ const targetHref = e?.target?.getAttribute("href");
13
10
  if (!targetHref) return;
14
- if (isExternalURL(targetHref) && !e?.target?.getAttribute('data-spa-crossorigin')) return;
11
+ if (isExternalURL(targetHref) && !e?.target?.getAttribute("data-spa-crossorigin")) return;
15
12
  e.preventDefault();
16
13
  try {
17
14
  await getNewPageContent(targetHref);
18
15
  if (targetHref === window.location.pathname) return;
19
16
  window.history.pushState(
20
17
  {
21
- type: 'link-click',
22
- targetHref,
18
+ type: "link-click",
19
+ targetHref
23
20
  },
24
- '',
21
+ "",
25
22
  targetHref
26
23
  );
27
- const event = new CustomEvent('spa:updatePageURL', {
24
+ const event = new CustomEvent("spa:updatePageURL", {
28
25
  detail: {
29
- href: targetHref,
30
- },
26
+ href: targetHref
27
+ }
31
28
  });
32
29
  window.dispatchEvent(event);
33
30
  } catch (err) {
34
31
  console.error(err);
35
32
  }
36
33
  }
37
-
38
34
  async function getNewPageContent(href) {
39
35
  try {
40
36
  const res = await fetch(href);
41
37
  const text = await res.text();
42
38
  const parser = new DOMParser();
43
- const dom = parser.parseFromString(text, 'text/html');
39
+ const dom = parser.parseFromString(text, "text/html");
44
40
  diffHead(dom);
45
41
  const newScripts = removeBodyScripts(dom);
46
42
  const clonedPersistentNodes = getPersistentNodesFromDocument(dom);
47
43
  const body = dom.body.innerHTML;
48
44
  document.body.innerHTML = body;
49
45
  for (const clonedNode of clonedPersistentNodes) {
50
- // @ts-ignore
51
- const newNode = document.body.querySelector(`[data-persistent="${clonedNode?.getAttribute('data-persistent')}"]`);
46
+ const newNode = document.body.querySelector(`[data-persistent="${clonedNode?.getAttribute("data-persistent")}"]`);
52
47
  newNode.replaceWith(clonedNode);
53
48
  }
54
49
  replaceAttributesOnDocumentBody(dom);
55
50
  replaceDocumentContentsWithLinkResponse();
56
51
  for (const script of newScripts) document.body.appendChild(script);
57
- // Send an event
58
- const event = new CustomEvent('spa:updatePageContent', {
52
+ const event = new CustomEvent("spa:updatePageContent", {
59
53
  detail: {
60
- href,
61
- },
54
+ href
55
+ }
62
56
  });
63
57
  window.dispatchEvent(event);
64
58
  } catch (err) {
65
59
  console.error(err);
66
- console.error('Error getting link', href);
60
+ console.error("Error getting link", href);
67
61
  }
68
62
  }
69
-
70
63
  function diffHead(dom) {
71
64
  const domHeadChildren = [...dom.head.children];
72
65
  const currentHeadChildren = [...document.head.children];
73
66
  const result = {
74
67
  childrenToAdd: [],
75
- childrenToRemove: [],
68
+ childrenToRemove: []
76
69
  };
77
70
  for (const domChild of domHeadChildren) {
78
- const foundInCurrentChildren = currentHeadChildren.find(child => child.outerHTML === domChild.outerHTML);
71
+ const foundInCurrentChildren = currentHeadChildren.find((child) => child.outerHTML === domChild.outerHTML);
79
72
  if (!foundInCurrentChildren) result.childrenToAdd.push(domChild);
80
73
  }
81
74
  for (const currentChild of currentHeadChildren) {
82
- const foundInDomChildren = domHeadChildren.find(child => child.outerHTML === currentChild.outerHTML);
75
+ const foundInDomChildren = domHeadChildren.find((child) => child.outerHTML === currentChild.outerHTML);
83
76
  if (!foundInDomChildren) result.childrenToRemove.push(currentChild);
84
77
  }
85
78
  applyHeadDiffsToDocument(result);
86
79
  }
87
-
88
80
  function applyHeadDiffsToDocument(diff) {
89
81
  for (const child of diff.childrenToRemove) {
90
- // Remove from head
91
82
  document.head.removeChild(child);
92
83
  }
93
84
  for (const child of diff.childrenToAdd) {
94
- // Handle script tags
95
- if (child?.nodeName?.toLowerCase() == 'script') {
96
- const scriptElement = document.createElement('script');
85
+ if (child?.nodeName?.toLowerCase() == "script") {
86
+ const scriptElement = document.createElement("script");
97
87
  portAttributesToElement(child, scriptElement);
98
88
  scriptElement.innerHTML = child.innerHTML;
99
89
  document.head.appendChild(scriptElement);
100
90
  continue;
101
91
  }
102
- // Add to the head
103
92
  document.head.appendChild(child);
104
93
  }
105
94
  }
106
-
107
95
  function removeBodyScripts(dom) {
108
- const scripts = [...dom.body.querySelectorAll('script')];
96
+ const scripts = [...dom.body.querySelectorAll("script")];
109
97
  const newElements = [];
110
98
  for (const script of scripts) {
111
- const element = document.createElement('script');
99
+ const element = document.createElement("script");
112
100
  portAttributesToElement(script, element);
113
101
  element.innerHTML = script.innerHTML;
114
102
  dom.body.removeChild(script);
@@ -116,60 +104,48 @@ function removeBodyScripts(dom) {
116
104
  }
117
105
  return newElements;
118
106
  }
119
-
120
107
  function portAttributesToElement(oldEl, newEl) {
121
108
  for (const attribute of oldEl.attributes) {
122
109
  newEl.setAttribute(attribute.name, attribute.nodeValue);
123
110
  }
124
111
  }
125
-
126
112
  function getPersistentNodesFromDocument(dom) {
127
- // Find persistent nodes
128
- const persistentNodesFromDom = [...dom.querySelectorAll('[data-persistent]')].map(el => el.getAttribute('data-persistent'));
129
- const persistentNodesFromBody = [...document.body.querySelectorAll('[data-persistent]')];
130
- // Cross match the persistent nodes between current page and new page to find valid ones
131
- const validPersistentNodes = persistentNodesFromBody.filter(el => {
132
- return persistentNodesFromDom.includes(el.getAttribute('data-persistent'));
113
+ const persistentNodesFromDom = [...dom.querySelectorAll("[data-persistent]")].map((el) => el.getAttribute("data-persistent"));
114
+ const persistentNodesFromBody = [...document.body.querySelectorAll("[data-persistent]")];
115
+ const validPersistentNodes = persistentNodesFromBody.filter((el) => {
116
+ return persistentNodesFromDom.includes(el.getAttribute("data-persistent"));
133
117
  });
134
- // Clone
135
- return validPersistentNodes.map(el => el.cloneNode(true));
118
+ return validPersistentNodes.map((el) => el.cloneNode(true));
136
119
  }
137
-
138
120
  function replaceAttributesOnDocumentBody(dom) {
139
121
  while (document.body.attributes.length > 0) {
140
122
  document.body.removeAttribute(document.body.attributes[0].name);
141
123
  }
142
- // Set attributes on the body
143
124
  for (const attribute of dom.body.attributes) {
144
125
  document.body.setAttribute(attribute.name, attribute.nodeValue);
145
126
  }
146
127
  }
147
-
148
128
  async function handleBackButton() {
149
129
  await getNewPageContent(window.history.state?.targetHref || window.location.href);
150
130
  }
151
-
152
131
  function isRelativeURL(url) {
153
- if (typeof url !== 'string') return false;
132
+ if (typeof url !== "string") return false;
154
133
  try {
155
134
  new URL(url);
156
135
  return false;
157
136
  } catch (err) {
158
- if (url?.startsWith('//')) return false;
137
+ if (url?.startsWith("//")) return false;
159
138
  return true;
160
139
  }
161
140
  }
162
-
163
141
  function isExternalURL(url) {
164
142
  if (isRelativeURL(url)) return false;
165
143
  try {
166
144
  const computedURL = new URL(url);
167
145
  return computedURL?.origin !== window.location?.origin;
168
146
  } catch {
169
- return false; // Not a URL
147
+ return false;
170
148
  }
171
149
  }
172
-
173
- window.addEventListener('DOMContentLoaded', replaceDocumentContentsWithLinkResponse);
174
- window.addEventListener('popstate', handleBackButton);
175
-
150
+ window.addEventListener("DOMContentLoaded", replaceDocumentContentsWithLinkResponse);
151
+ window.addEventListener("popstate", handleBackButton);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xpine",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "main": "dist/index.js",
5
5
  "dependencies": {
6
6
  "@tailwindcss/postcss": "^4.0.8",
package/src/auth.ts DELETED
@@ -1,40 +0,0 @@
1
- import jsonwebtoken from 'jsonwebtoken';
2
- import { ServerRequest } from '../types';
3
- const { verify, sign, } = jsonwebtoken;
4
-
5
- export async function signUser(email: string, username: string) {
6
- return new Promise((resolve, reject) => {
7
- sign(
8
- {
9
- user: {
10
- email,
11
- username,
12
- },
13
- },
14
- // @ts-ignore
15
- process.env.JWT_PRIVATE_KEY,
16
- { expiresIn: '30d', },
17
- (err, token) => {
18
- if (err) reject(err);
19
- resolve(token);
20
- });
21
- });
22
- }
23
-
24
- export async function verifyUser(token: string): Promise<any> {
25
- return new Promise((resolve, reject) => {
26
- // @ts-ignore
27
- verify(token, process.env.JWT_PRIVATE_KEY, (err, authorizedData) => {
28
- if (err) reject(err);
29
- resolve(authorizedData);
30
- });
31
- });
32
- }
33
-
34
- export function getTokenFromRequest(req: ServerRequest) {
35
- // @ts-ignore
36
- const { authorization, } = req.headers;
37
- if (!authorization) return null;
38
- const token = authorization.split(' ').pop() || '';
39
- return token || null;
40
- }
@@ -1,180 +0,0 @@
1
- import ts from 'typescript';
2
- import fs from 'fs-extra';
3
- import path from 'path';
4
-
5
- type ImportDeclaration = {
6
- node: ts.Node;
7
- importPath: string;
8
- }
9
-
10
- // node arg should initially be the source node
11
- export function getImportDeclarationNodes(node: ts.Node, sourceFile: ts.SourceFile, importDeclarations: ImportDeclaration[] = []) {
12
- if (node.kind === ts.SyntaxKind.ImportDeclaration) {
13
- let importPath = null;
14
- node.forEachChild(child => {
15
- if (child.kind === ts.SyntaxKind.StringLiteral) {
16
- importPath = child.getText(sourceFile).replace(/[\"\']/g, '');
17
- }
18
- });
19
- importDeclarations.push({
20
- node,
21
- importPath,
22
- });
23
- }
24
- node.forEachChild(child => {
25
- getImportDeclarationNodes(child, sourceFile, importDeclarations);
26
- });
27
- return importDeclarations;
28
- }
29
-
30
- export function stripImportsNodesFromFile(importsToStrip: string[], content: string, importDeclarations: ImportDeclaration[]) {
31
- let outputContent = content;
32
- const filteredImports = importDeclarations.filter(item => importsToStrip.includes(item.importPath));
33
- for (const importItem of filteredImports) {
34
- outputContent = outputContent.slice(0, importItem.node.pos) + outputContent.slice(importItem.node.end);
35
- }
36
- return outputContent;
37
- }
38
-
39
- type FoundAlpineFunction = {
40
- name: string;
41
- isDefaultExport: boolean;
42
- hasExport: boolean;
43
- }
44
-
45
- export function findDataAttributesAndFunctions(
46
- node: ts.Node,
47
- sourceFile: ts.SourceFile,
48
- foundDataAttributes: string[] = [],
49
- foundFunctions: FoundAlpineFunction[] = []
50
- ) {
51
- if (node.kind === ts.SyntaxKind.JsxAttribute) {
52
- const attribute = getAttributeValuePair(node, sourceFile);
53
- if (attribute?.[0] === 'x-data' && attribute?.[1]) {
54
- // We found a data attribute,
55
- // so now we have to search throughout the file for a function declaration of the same name
56
- foundDataAttributes.push(attribute[1].replace(/[^a-zA-Z0-9]/g, ''));
57
- }
58
- }
59
- if (node.kind === ts.SyntaxKind.SourceFile) {
60
- node.forEachChild(child => {
61
- if ([ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration].includes(child.kind)) {
62
- const functions = getFunctionDeclarationValue(child, sourceFile);
63
- foundFunctions.push(functions);
64
- }
65
- });
66
- }
67
-
68
- node.forEachChild(child => {
69
- findDataAttributesAndFunctions(child, sourceFile, foundDataAttributes, foundFunctions);
70
- });
71
- return {
72
- foundDataAttributes,
73
- foundFunctions,
74
- };
75
- }
76
-
77
- export function getAttributeValuePair(node: ts.Node, sourceFile: ts.SourceFile): string[] {
78
- const result = [];
79
- node.forEachChild(child => {
80
- result.push(child.getText(sourceFile));
81
- });
82
- return result;
83
- }
84
-
85
- export function getFunctionDeclarationValue(node: ts.Node, sourceFile: ts.SourceFile): FoundAlpineFunction {
86
- const result = {
87
- name: null,
88
- isDefaultExport: false,
89
- hasExport: false,
90
- };
91
- node.forEachChild(child => {
92
- if (child.kind === ts.SyntaxKind.ExportKeyword) {
93
- result.hasExport = true;
94
- }
95
- if (child.kind === ts.SyntaxKind.DefaultKeyword) {
96
- result.isDefaultExport = true;
97
- }
98
- if (child.kind === ts.SyntaxKind.Identifier) {
99
- result.name = child.getText(sourceFile);
100
- }
101
- });
102
- return result;
103
- }
104
-
105
- // Convert entry point files into one big bundle file
106
- export function convertEntryPointsToSingleFile(entryPoints: string[], tempWritePath: string) {
107
- fs.writeFileSync(
108
- tempWritePath,
109
- entryPoints
110
- .map(entry => `import "${entry}"`)
111
- .join(';\n')
112
- );
113
- }
114
-
115
- export function removeClientScriptInTSXFile(pathName: string) {
116
- const content = fs.readFileSync(pathName, 'utf-8');
117
- const source = ts.createSourceFile(
118
- pathName,
119
- content,
120
- ts.ScriptTarget.Latest
121
- );
122
- let toRemoveFrom: number;
123
- let clientDataStart: number;
124
- const clientImportsToHoist = [];
125
- const clientImportsToReplace = [];
126
- source.forEachChild((child) => {
127
- if (child.kind === ts.SyntaxKind.ExpressionStatement) {
128
- const text = child.getText(source);
129
- // Remove from here
130
- if (text.startsWith('<script')) {
131
- toRemoveFrom = child.pos;
132
- clientDataStart = child.end;
133
- }
134
- }
135
- // Hoist the client imports to above the <script /> tag
136
- if (child.kind === ts.SyntaxKind.ImportDeclaration && child.pos >= clientDataStart) {
137
- const text = child.getText(source);
138
- child.forEachChild(child => {
139
- if (child.kind === ts.SyntaxKind.StringLiteral) {
140
- // Keep track of client imports needed for path replacement to be absolute
141
- const text = child.getText(source);
142
- const importPath = text.replace(/[\"\']/g, '');
143
- const isRelativeImport = importPath.startsWith('.') || importPath.startsWith('/');
144
- if (!isRelativeImport) return;
145
- clientImportsToReplace.push({
146
- old: importPath,
147
- new: path.join(path.dirname(pathName), importPath),
148
- });
149
- }
150
- });
151
- clientImportsToHoist.push(text);
152
- }
153
- });
154
- let clientContent = !isNaN(clientDataStart) ? content.slice(clientDataStart) : '';
155
- for (const clientImport of clientImportsToReplace) {
156
- clientContent = clientContent.replace(clientImport.old, clientImport.new);
157
- }
158
- return {
159
- content: !isNaN(toRemoveFrom) ?
160
- clientImportsToHoist.join('\n') + content.slice(0, toRemoveFrom) :
161
- content,
162
- clientContent,
163
- fullContent: content,
164
- toRemoveFrom,
165
- clientDataStart,
166
- };
167
- }
168
-
169
- export function printRecursiveFrom(
170
- node: ts.Node, indentLevel: number, sourceFile: ts.SourceFile
171
- ) {
172
- const indentation = '-'.repeat(indentLevel);
173
- const syntaxKind = ts.SyntaxKind[node.kind];
174
- const nodeText = node.getText(sourceFile);
175
- console.log(`${indentation}${syntaxKind}: ${nodeText}`);
176
-
177
- node.forEachChild(child =>
178
- printRecursiveFrom(child, indentLevel + 1, sourceFile)
179
- );
180
- }
package/src/express.ts DELETED
@@ -1,120 +0,0 @@
1
- import express, { NextFunction, Express, Request, Response } from 'express';
2
- import { globSync } from 'glob';
3
- import { config } from './util/get-config';
4
- import { verifyUser } from './auth';
5
- import requestIP from 'request-ip';
6
- import { ServerRequest } from '../types';
7
-
8
- const doctypeHTML = '<!DOCTYPE html>';
9
-
10
- export async function createRouter() {
11
- const methods = ['get', 'post', 'put', 'patch', 'delete'];
12
- const router = express.Router();
13
- const routes = globSync(config.pagesDir + '/**/*.{tsx,ts}');
14
- const routeMap = routes.map(route => {
15
- return {
16
- route: route.split(config.pagesDir).pop().replace('.tsx', '').replace('.js', '').replace('.ts', '').replace('/index', '/'),
17
- path: route.replace(config.srcDir, config.distDir).replace('.tsx', '.js').replace('.ts', '.js'),
18
- originalRoute: route,
19
- };
20
- });
21
- const routeResults = [];
22
-
23
- for (const route of routeMap) {
24
- const isJSX = route.originalRoute.endsWith('.tsx') || route.originalRoute.endsWith('.jsx');
25
- // Import route
26
- const routeItem = process.env.NODE_ENV === 'development' ? null : (await import(route.path)).default;
27
- // Configure result,methods for the route
28
- const slugRoute = route.route.toLowerCase().replace(/[ ]/g, '');
29
- const foundMethod = methods.find(method => slugRoute.endsWith(`.${method}`));
30
- const isDynamicRoute = slugRoute.match(/\[(.*)\]/g);
31
- let formattedRouteItem = slugRoute;
32
- if (foundMethod) formattedRouteItem = formattedRouteItem.split('.').shift();
33
- // Handle dynamic routing
34
- if (isDynamicRoute) {
35
- const result = [...formattedRouteItem.matchAll(/(\[)(.*?)(\])/g)];
36
- for (const match of result) {
37
- formattedRouteItem = formattedRouteItem.replace(match[0], ':' + match[2]);
38
- }
39
- }
40
- // Push to the route results array
41
- routeResults.push({
42
- formattedRouteItem,
43
- foundMethod,
44
- route,
45
- });
46
- router[foundMethod || 'get'](formattedRouteItem, async (req: Request, res: Response) => {
47
- try {
48
- // Check if it's a string response from the routeItem or is a different response
49
- if (routeItem) {
50
- if (isJSX) {
51
- res.send(doctypeHTML + (await routeItem(req, res)));
52
- } else {
53
- await routeItem(req, res);
54
- }
55
- return;
56
- }
57
- const defaultRouteImport = (await import(route.path + `?cache=${Date.now()}`)).default;
58
- // Require every time only if in development mode
59
- if (isJSX) {
60
- res.send(doctypeHTML + (await defaultRouteImport(req, res)));
61
- } else {
62
- await defaultRouteImport(req, res);
63
- }
64
- } catch (err) {
65
- console.error(err);
66
- res.status(err?.status || 500).send(err?.message || 'Error');
67
- }
68
- });
69
- }
70
- return {
71
- router,
72
- routeResults,
73
- };
74
- }
75
-
76
- async function verifyUserMiddleware(req: ServerRequest, _res: Response, next: NextFunction) {
77
- // @ts-ignore
78
- const { usertoken, } = req.cookies;
79
- if (!usertoken) {
80
- req.user = null;
81
- }
82
- try {
83
- const { user, } = await verifyUser(usertoken);
84
- req.user = user;
85
- } catch (err) {
86
- req.user = null;
87
- }
88
- next();
89
- }
90
-
91
- export async function createXPineRouter(app: any, beforeErrorRoute?: (app: Express) => void) {
92
- app.use(express.static(config.distPublicDir));
93
- app.use(verifyUserMiddleware);
94
- app.use(requestIP.mw());
95
-
96
- const { router, routeResults, } = await createRouter();
97
- app.use(function replaceableRouter(req: Request, res: Response, next: NextFunction) {
98
- router(req, res, next);
99
- });
100
-
101
- const found404 = routeResults?.find(item => item?.formattedRouteItem === '/404');
102
- const import404 = process.env.NODE_ENV === 'development' ? null : (await import(found404.route.path)).default;
103
-
104
- if (beforeErrorRoute) beforeErrorRoute(app);
105
-
106
- // error handler
107
- app.use(async function (req: Request, res: Response) {
108
- // render the error page
109
- res.status(404);
110
-
111
- if (import404) {
112
- res.send(doctypeHTML + (await import404(req, res)));
113
- } else if (found404 && process.env.NODE_ENV === 'development') {
114
- const import404Item = (await import(found404.route.path + `?cache=${Date.now()}`)).default
115
- res.send(doctypeHTML + (await import404Item(req, res)));
116
- } else {
117
- res.send('Error');
118
- }
119
- });
120
- }
@@ -1,64 +0,0 @@
1
- import expressWs from 'express-ws';
2
- import http from 'http';
3
- import express from 'express';
4
- import EventEmitter from 'events';
5
- import chokidar from 'chokidar';
6
- import { buildApp } from './scripts/build';
7
- import path from 'path';
8
- import { config } from './util/get-config';
9
- import { setupEnv } from './util/env';
10
-
11
- setupEnv();
12
-
13
- export async function runDevServer() {
14
- process.env.NODE_ENV = 'development';
15
- const startServer = await import(config.serverDistAppPath + `?cache=${Date.now()}`);
16
-
17
- // Initial server set up
18
- await buildApp(true);
19
- let appServer = await startServer.default();
20
-
21
- // Watch files
22
- const watcher = chokidar.watch(config.srcDir, {
23
- ignoreInitial: true,
24
- // Ignore map and prisma files
25
- ignored: (pathName) => pathName.endsWith('.map') || pathName.startsWith(path.join(config.serverDir, './prisma')),
26
- });
27
- watcher.on('all', async (event, path) => {
28
- const shouldReloadServer = (path.startsWith(config.serverDir) && !path.startsWith(config.runDir)) ||
29
- ['add', 'unlink'].includes(event) && path.startsWith(config.pagesDir);
30
- if (shouldReloadServer) {
31
- // We modified files in the server, restart the server
32
- appServer.server.close();
33
- await buildApp(true);
34
- const startServer = await import(config.serverDistAppPath + `?cache=${Date.now()}`);
35
- appServer = await startServer.default();
36
- return;
37
- }
38
- await buildApp(true);
39
- refreshEmitter.emit('refresh');
40
- });
41
-
42
- // Create web socket sever
43
- const wsApp = express();
44
- const wsServer = http.createServer(wsApp);
45
- expressWs(wsApp, wsServer);
46
- class RefreshEmitter extends EventEmitter { };
47
- const refreshEmitter = new RefreshEmitter();
48
-
49
- // @ts-ignore
50
- wsApp.ws('/dev-server', function (ws) {
51
- refreshEmitter.removeAllListeners();
52
- refreshEmitter.on('refresh', () => {
53
- ws.send('refresh:client');
54
- });
55
- });
56
-
57
- const wsPort = 3001;
58
- wsServer.listen(wsPort);
59
- wsServer.on('listening', () => {
60
- console.info(`Dev server listening on port ${wsPort}`);
61
- });
62
- }
63
-
64
-
@@ -1,36 +0,0 @@
1
- import fs from 'fs-extra';
2
- import { build } from 'esbuild';
3
- import { config } from '../util/get-config';
4
- import path from 'path';
5
-
6
- // Extensions to look for in the bundle
7
- const packageJson = JSON.parse(fs.readFileSync(config.packageJsonPath, 'utf-8'));
8
- const allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
9
- const dirname = import.meta.dirname;
10
-
11
- export async function buildXPine() {
12
- await build({
13
- entryPoints: [
14
- // The contents of XPine itself
15
- path.join(dirname, '../../index.ts'),
16
- // The script for xpine-build
17
- path.join(dirname, './xpine-build.ts'),
18
- // The script for xpine-dev
19
- path.join(dirname, './xpine-dev.ts'),
20
- // Static files
21
- path.join(dirname, '../static/dev-server.mjs'),
22
- path.join(dirname, '../static/spa.mjs'),
23
- ],
24
- format: 'esm',
25
- platform: 'node',
26
- outdir: path.join(dirname, '../../dist'),
27
- bundle: true,
28
- sourcemap: 'inline',
29
- external: allPackages,
30
- jsx: 'transform',
31
- minify: false,
32
- plugins: [],
33
- });
34
- }
35
-
36
- buildXPine();