~repos /edge-city

#react#js#ssr

git clone https://pyrossh.dev/repos/edge-city.git

edge-city is a next level meta-framework for react that runs only on edge runtimes


0568068f Peter John

2 years ago
add services
Files changed (2) hide show
  1. packages/cli/index.js +33 -170
  2. packages/runtime/index.js +20 -0
packages/cli/index.js CHANGED
@@ -44,12 +44,7 @@ const isProd = process.env.NODE_ENV === "production";
44
44
  const routes = walkdir.sync(path.join(process.cwd(), "pages"))
45
45
  .filter((p) => p.includes("page.jsx"));
46
46
  const services = walkdir.sync(path.join(process.cwd(), "services"))
47
- .map((s) => s.replace(process.cwd(), ""))
48
47
  .filter((s) => s.includes(".service.js"))
49
- .forEach((s) => {
50
- const serviceName = s.replace(".service.js", "");
51
- routes[serviceName + "/*"] = { key: serviceName, service: s };
52
- });
53
48
 
54
49
  const mapDeps = (dir) => {
55
50
  return walkdir.sync(path.join(process.cwd(), dir))
@@ -121,20 +116,21 @@ const buildRouteMap = () => {
121
116
  // });
122
117
 
123
118
 
124
- const buildServer = async (r) => {
119
+ const buildServer = async (src, type) => {
125
120
  const buildStart = Date.now();
126
- const shortName = r.replace(process.cwd(), "").replace("/pages", "");
121
+ const shortName = src.replace(process.cwd(), "");
122
+ const outName = type === "service" ? shortName.replace(".service.js", "") + "/index.js" : shortName.replace("/pages", "").replace("page.jsx", "index.js");
127
- const outfile = `${process.cwd()}/build/functions${shortName.replace("page.jsx", "index.js")}`;
123
+ const outfile = `${process.cwd()}/build/functions${outName}`;
128
124
  const result = await esbuild.build({
129
125
  bundle: true,
130
126
  target: ['es2022'],
131
- entryPoints: [r],
127
+ entryPoints: [src],
132
128
  outfile: outfile,
133
129
  format: 'esm',
134
130
  keepNames: true,
135
131
  external: ["node:*"],
136
132
  color: true,
137
- treeShaking: false,
133
+ treeShaking: true,
138
134
  // metafile: true,
139
135
  jsxDev: !isProd,
140
136
  jsx: 'automatic',
@@ -156,91 +152,43 @@ const buildServer = async (r) => {
156
152
  );
157
153
  }
158
154
 
159
- const bundleBun = async (r) => {
155
+ // const bundleBun = async (r, type) => {
160
- const buildStart = Date.now();
156
+ // const buildStart = Date.now();
161
- const shortName = r.replace(process.cwd(), "").replace("/page.jsx", "");
157
+ // const shortName = r.replace(process.cwd(), "").replace("/page.jsx", "");
162
- const result = await Bun.build({
158
+ // const result = await Bun.build({
163
- entrypoints: [r],
159
+ // entrypoints: [r],
164
- outdir: `${process.cwd()}/bb/functions/${shortName}`,
160
+ // outdir: `${process.cwd()}/bb/functions/${shortName}`,
165
- });
161
+ // });
166
- if (!result.success) {
162
+ // if (!result.success) {
167
- console.error("Build failed");
163
+ // console.error("Build failed");
168
- for (const message of result.logs) {
164
+ // for (const message of result.logs) {
169
- // Bun will pretty print the message object
165
+ // // Bun will pretty print the message object
170
- console.error(message);
166
+ // console.error(message);
167
+ // }
171
- }
168
+ // }
172
- }
173
- for (const o of result.outputs) {
169
+ // for (const o of result.outputs) {
174
- const outLength = (await o.arrayBuffer()).byteLength;
170
+ // const outLength = (await o.arrayBuffer()).byteLength;
175
- const builtTime = ms(Date.now() - buildStart);
171
+ // const builtTime = ms(Date.now() - buildStart);
176
- console.log(
172
+ // console.log(
177
- `✓ Bundled ${o.kind} ${o.path.replace(process.cwd() + "/bb", "")} ${pc.cyan(`(${bytes(outLength)})`)} ${pc.gray(`[${builtTime}]`)}`
173
+ // `✓ Bundled ${o.kind} ${o.path.replace(process.cwd() + "/bb", "")} ${pc.cyan(`(${bytes(outLength)})`)} ${pc.gray(`[${builtTime}]`)}`
178
- );
174
+ // );
175
+ // }
179
- }
176
+ // }
180
- }
181
177
 
182
178
  const main = async () => {
183
179
  createDirs();
184
180
  buildImportMap();
185
181
  buildRouteMap();
186
182
  for (const r of routes) {
187
- buildServer(r);
183
+ await buildServer(r, "page");
184
+ }
185
+ for (const s of services) {
186
+ await buildServer(s, "service");
188
187
  }
189
188
  }
190
189
 
191
190
  main();
192
191
 
193
- // const createServerRouter = async () => {
194
- // const routes = {};
195
- // const dirs = walkdir.sync(path.join(process.cwd(), "pages"))
196
- // .map((s) => s.replace(process.cwd(), "")
197
- // .replace("/pages", "")
198
- // // .replaceAll("[", ":")
199
- // // .replaceAll("]", "")
200
- // )
201
-
202
- // dirs.filter((p) => p.includes('page.jsx'))
203
- // .map((s) => ({ path: s, route: s.replace("/page.jsx", "") }))
204
- // .forEach((page) => {
205
- // const key = page.route || "/";
206
- // routes[key] = { key: key, page: page.path };
207
- // });
208
- // walkdir.sync(path.join(process.cwd(), "static"))
209
- // .map((s) => s.replace(process.cwd(), "").replace("/static", ""))
210
- // .forEach((route) => {
211
- // routes[route] = { key: route, file: route }
212
- // });
213
-
214
- // return createRouter({
215
- // strictTrailingSlash: true,
216
- // routes: routes,
217
- // });
218
- // }
219
-
220
- // const createClientRouter = async () => {
221
- // const routes = await walkdir.sync(path.join(process.cwd(), "pages"))
222
- // .filter((p) => p.includes("page.jsx"))
223
- // .filter((p) => !p.includes("/_"))
224
- // .map((s) => s.replace(process.cwd(), ""))
225
- // .map((s) => s.replace("/pages", ""))
226
- // .map((s) => s.replace("/page.jsx", ""))
227
- // .reduce(async (accp, r) => {
228
- // const acc = await accp;
229
- // const src = await import(`${process.cwd()}/pages${r}/page.jsx`);
230
- // if (!result.success) {
231
- // console.error("Build failed");
232
- // for (const message of result.logs) {
233
- // // Bun will pretty print the message object
234
- // console.error(message);
235
- // }
236
- // }
237
- // acc[r === "" ? "/" : r] = src.default;
238
- // return acc
239
- // }, Promise.resolve({}));
240
- // // console.log(clientRoutes);
241
- // };
242
-
243
-
244
192
  // const serverRouter = await createServerRouter();
245
193
  // const clientRouter = await createClientRouter();
246
194
  // const transpiler = new Bun.Transpiler({
@@ -253,27 +201,6 @@ main();
253
201
  // // jsxOptimizationInline: false,
254
202
  // });
255
203
 
256
- // const renderApi = async (key, filePath, req) => {
257
- // const url = new URL(req.url);
258
- // const params = req.method === "POST" ? await req.json() : Object.fromEntries(url.searchParams);
259
- // const funcName = url.pathname.replace(`${key}/`, "");
260
- // const js = await import(path.join(process.cwd(), filePath));
261
- // try {
262
- // const result = await js[funcName](params);
263
- // return new Response(JSON.stringify(result), {
264
- // headers: { 'Content-Type': 'application/json' },
265
- // status: 200,
266
- // });
267
- // } catch (err) {
268
- // const message = err.format ? err.format() : err;
269
- // return new Response(JSON.stringify(message), {
270
- // headers: { 'Content-Type': 'application/json' },
271
- // status: 400,
272
- // });
273
- // }
274
-
275
- // }
276
-
277
204
  // const renderCss = async (src) => {
278
205
  // try {
279
206
  // const cssText = await Bun.file(src).text();
@@ -334,68 +261,4 @@ main();
334
261
  // status: 404,
335
262
  // });
336
263
  // }
337
- // }
264
+ // }
338
-
339
- // const sendFile = async (src) => {
340
- // try {
341
- // const contentType = mimeTypes.lookup(src) || "application/octet-stream";
342
- // const stream = await Bun.file(src).stream();
343
- // return new Response(stream, {
344
- // headers: { 'Content-Type': contentType },
345
- // status: 200,
346
- // });
347
- // } catch (err) {
348
- // return new Response(`Not Found`, {
349
- // headers: { 'Content-Type': 'text/html' },
350
- // status: 404,
351
- // });
352
- // }
353
- // }
354
-
355
- // // const mf = new Miniflare({
356
- // // script: `
357
- // // addEventListener("fetch", (event) => {
358
- // // event.respondWith(new Response("Hello Miniflare!"));
359
- // // });
360
- // // `,
361
- // // });
362
- // // const res = await mf.dispatchFetch("http://localhost:3000/");
363
- // // console.log(await res.text()); // Hello Miniflare!
364
-
365
- // const server = async (req) => {
366
- // const url = new URL(req.url);
367
- // console.log(req.method, url.pathname);
368
- // // maybe this is needed
369
- // if (url.pathname.startsWith("/parotta/")) {
370
- // return renderJs(path.join(import.meta.dir, url.pathname.replace("/parotta/", "")));
371
- // }
372
- // if (url.pathname.endsWith(".css")) {
373
- // return renderCss(path.join(process.cwd(), url.pathname));
374
- // }
375
- // if (url.pathname.endsWith(".js") || url.pathname.endsWith(".jsx")) {
376
- // return renderJs(path.join(process.cwd(), url.pathname));
377
- // }
378
- // const match = serverRouter.lookup(url.pathname);
379
- // if (match && !match.key.includes("/_")) {
380
- // if (match.file) {
381
- // return sendFile(path.join(process.cwd(), `/static${match.file}`));
382
- // }
383
- // if (match.page && req.headers.get("Accept")?.includes('text/html')) {
384
- // return renderPage(url);
385
- // }
386
- // if (match.service) {
387
- // return renderApi(match.key, match.service, req);
388
- // }
389
- // }
390
- // if (req.headers.get("Accept")?.includes('text/html')) {
391
- // // not found html page
392
- // return renderPage(new URL(`${url.protocol}//${url.host}/_404`));
393
- // }
394
- // // not found generic page
395
- // return new Response(`{"message": "not found"}`, {
396
- // headers: { 'Content-Type': 'application/json' },
397
- // status: 404,
398
- // });
399
- // }
400
-
401
- // export default server;
packages/runtime/index.js CHANGED
@@ -330,4 +330,24 @@ export const renderPage = async (PageComponent, req) => {
330
330
  headers: { 'Content-Type': 'text/html' },
331
331
  status: 200,
332
332
  });
333
+ }
334
+
335
+ export const renderApi = async (key, filePath, req) => {
336
+ const url = new URL(req.url);
337
+ const params = req.method === "POST" ? await req.json() : Object.fromEntries(url.searchParams);
338
+ const funcName = url.pathname.replace(`${key}/`, "");
339
+ const js = await import(path.join(process.cwd(), filePath));
340
+ try {
341
+ const result = await js[funcName](params);
342
+ return new Response(JSON.stringify(result), {
343
+ headers: { 'Content-Type': 'application/json' },
344
+ status: 200,
345
+ });
346
+ } catch (err) {
347
+ const message = err.format ? err.format() : err;
348
+ return new Response(JSON.stringify(message), {
349
+ headers: { 'Content-Type': 'application/json' },
350
+ status: 400,
351
+ });
352
+ }
333
353
  }