~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


773fddaa Peter John

2 years ago
remove packages
Files changed (51) hide show
  1. .gitignore +1 -2
  2. __render.js +0 -208
  3. {packages/parotta → bin}/cli.js +89 -92
  4. packages/create-parotta/index.js → bin/create-app.js +0 -0
  5. bun.lockb +0 -0
  6. {packages/example → example}/.gitignore +0 -0
  7. {packages/example → example}/.vscode/extensions.json +0 -0
  8. {packages/example → example}/.vscode/settings.json +0 -0
  9. {packages/example → example}/Dockerfile +0 -0
  10. example/bun.lockb +0 -0
  11. {packages/example → example}/components/Counter/Counter.jsx +0 -0
  12. {packages/example → example}/components/Timer/Timer.jsx +0 -0
  13. {packages/example → example}/components/Todo/Todo.css +0 -0
  14. {packages/example → example}/components/Todo/Todo.jsx +0 -0
  15. {packages/example → example}/containers/TodoList/TodoList.jsx +0 -0
  16. {packages/example → example}/db/index.js +1 -1
  17. {packages/example → example}/db/migrations/0000_empty_shatterstar.sql +0 -0
  18. {packages/example → example}/db/migrations/meta/0000_snapshot.json +0 -0
  19. {packages/example → example}/db/migrations/meta/_journal.json +0 -0
  20. {packages/example → example}/drizzle.config.json +0 -0
  21. {packages/example → example}/jsconfig.json +0 -0
  22. example/main.js +3 -0
  23. {packages/example → example}/package.json +5 -1
  24. {packages/example → example}/pages/404/page.css +0 -0
  25. {packages/example → example}/pages/404/page.jsx +0 -0
  26. {packages/example → example}/pages/about/page.css +0 -0
  27. {packages/example → example}/pages/about/page.jsx +0 -0
  28. {packages/example → example}/pages/layout.css +0 -0
  29. {packages/example → example}/pages/layout.jsx +0 -0
  30. {packages/example → example}/pages/page.css +0 -0
  31. {packages/example → example}/pages/page.jsx +0 -0
  32. {packages/example → example}/pages/page.spec.js +0 -0
  33. {packages/example → example}/pages/todos/page.css +0 -0
  34. {packages/example → example}/pages/todos/page.jsx +0 -0
  35. {packages/example → example}/playwright.config.js +0 -0
  36. {packages/example → example}/readme.md +6 -2
  37. {packages/example → example}/services/auth.service.js +0 -0
  38. {packages/example → example}/services/todos.service.js +0 -0
  39. {packages/example → example}/static/favicon.ico +0 -0
  40. {packages/example → example}/static/logo192.png +0 -0
  41. {packages/example → example}/static/logo512.png +0 -0
  42. {packages/example → example}/static/manifest.json +0 -0
  43. {packages/example → example}/static/robots.txt +0 -0
  44. package-lock.json +0 -694
  45. package.json +26 -4
  46. packages/create-parotta/package.json +0 -16
  47. packages/example/bun.lockb +0 -0
  48. packages/parotta/bun.lockb +0 -0
  49. packages/parotta/package.json +0 -20
  50. readme.md +5 -4
  51. packages/parotta/runtime.js → runtime.js +6 -3
.gitignore CHANGED
@@ -1,2 +1 @@
1
- node_modules
1
+ node_modules
2
- .vercel
__render.js DELETED
@@ -1,208 +0,0 @@
1
- import React from 'react';
2
- import { renderToReadableStream } from 'react-dom/server';
3
- import { StreamProvider, SuspenseData } from './hooks';
4
-
5
- function wrapStreamEnd(streamEnd, didError) {
6
- return (
7
- streamEnd
8
- // Needed because of the `afterReactBugCatch()` hack above, otherwise `onBoundaryError` triggers after `streamEnd` resolved
9
- .then(() => new Promise((r) => setTimeout(r, 0)))
10
- .then(() => !didError)
11
- )
12
- }
13
-
14
- function createBuffer(streamOperations) {
15
- const buffer = []
16
- let state = 'UNSTARTED'
17
- let writePermission = null // Set to `null` because React fails to hydrate if something is injected before the first react write
18
-
19
- return { injectToStream, onBeforeWrite, onBeforeEnd }
20
-
21
- function injectToStream(chunk, options) {
22
- if (state === 'ENDED') {
23
- console.error(`Cannot inject following chunk after stream has ended: \`${chunk}\``)
24
- }
25
- buffer.push({ chunk, flush: options?.flush })
26
- flushBuffer()
27
- }
28
-
29
- function flushBuffer() {
30
- if (!writePermission) {
31
- return
32
- }
33
- if (buffer.length === 0) {
34
- return
35
- }
36
- if (state !== 'STREAMING') {
37
- console.error(state === 'UNSTARTED')
38
- return
39
- }
40
- let flushStream = false
41
- buffer.forEach((bufferEntry) => {
42
- // assert(streamOperations.operations)
43
- const { writeChunk } = streamOperations.operations
44
- writeChunk(bufferEntry.chunk)
45
- if (bufferEntry.flush) {
46
- flushStream = true
47
- }
48
- })
49
- buffer.length = 0
50
- // assert(streamOperations.operations)
51
- if (flushStream && streamOperations.operations.flush !== null) {
52
- streamOperations.operations.flush()
53
- }
54
- }
55
-
56
- function onBeforeWrite(chunk) {
57
- // state === 'UNSTARTED' && debug('>>> START')
58
- state = 'STREAMING'
59
- if (writePermission) {
60
- flushBuffer()
61
- }
62
- if (writePermission == true || writePermission === null) {
63
- writePermission = false
64
- // debug('writePermission =', writePermission)
65
- setTimeout(() => {
66
- // debug('>>> setTimeout()')
67
- writePermission = true
68
- // debug('writePermission =', writePermission)
69
- flushBuffer()
70
- })
71
- }
72
- }
73
-
74
- function onBeforeEnd() {
75
- writePermission = true
76
- // debug('writePermission =', writePermission)
77
- flushBuffer()
78
- // assert(buffer.length === 0)
79
- state = 'ENDED'
80
- // debug('>>> END')
81
- }
82
- }
83
-
84
-
85
- const createReadableWrapper = (readableFromReact) => {
86
- const streamOperations = {
87
- operations: null
88
- }
89
- let controllerOfUserStream;
90
- let onEnded;
91
- const streamEnd = new Promise((r) => {
92
- onEnded = () => r()
93
- })
94
- const readableForUser = new ReadableStream({
95
- start(controller) {
96
- controllerOfUserStream = controller
97
- onReady(onEnded)
98
- }
99
- })
100
- const { injectToStream, onBeforeWrite, onBeforeEnd } = createBuffer(streamOperations)
101
- return { readableForUser, streamEnd, injectToStream }
102
- async function onReady(onEnded) {
103
- streamOperations.operations = {
104
- writeChunk(chunk) {
105
- controllerOfUserStream.enqueue(encodeForWebStream(chunk))
106
- },
107
- flush: null
108
- }
109
-
110
- const reader = readableFromReact.getReader()
111
-
112
- while (true) {
113
- let result;
114
- try {
115
- result = await reader.read()
116
- } catch (err) {
117
- controllerOfUserStream.close()
118
- throw err
119
- }
120
- const { value, done } = result
121
- if (done) {
122
- break
123
- }
124
- onBeforeWrite(value)
125
- streamOperations.operations.writeChunk(value)
126
- }
127
-
128
- // Collect `injectToStream()` calls stuck in an async call
129
- setTimeout(() => {
130
- onBeforeEnd()
131
- controllerOfUserStream.close()
132
- onEnded()
133
- }, 0)
134
- }
135
- }
136
-
137
- let encoder;
138
- function encodeForWebStream(thing) {
139
- if (!encoder) {
140
- encoder = new TextEncoder()
141
- }
142
- if (typeof thing === 'string') {
143
- return encoder.encode(thing)
144
- }
145
- return thing
146
- }
147
-
148
- export const renderToWebStream = async (element, disable) => {
149
- let didError = false
150
- let firstErr = null
151
- let reactBug = null
152
- const onError = (err) => {
153
- didError = true
154
- firstErr = firstErr || err
155
- afterReactBugCatch(() => {
156
- // Is not a React internal error (i.e. a React bug)
157
- if (err !== reactBug) {
158
- options.onBoundaryError?.(err)
159
- }
160
- })
161
- }
162
- const readableOriginal = await renderToReadableStream(element, { onError })
163
- const { allReady } = readableOriginal
164
- let promiseResolved = false
165
- // Upon React internal errors (i.e. React bugs), React rejects `allReady`.
166
- // React doesn't reject `allReady` upon boundary errors.
167
- allReady.catch((err) => {
168
- // debug('react bug')
169
- didError = true
170
- firstErr = firstErr || err
171
- reactBug = err
172
- // Only log if it wasn't used as rejection for `await renderToStream()`
173
- if (reactBug !== firstErr || promiseResolved) {
174
- console.error(reactBug)
175
- }
176
- })
177
- if (didError) throw firstErr
178
- if (disable) await allReady
179
- if (didError) throw firstErr
180
- const { readableForUser, streamEnd, injectToStream } = createReadableWrapper(readableOriginal)
181
- promiseResolved = true
182
- return {
183
- readable: readableForUser,
184
- streamEnd: wrapStreamEnd(streamEnd, didError),
185
- injectToStream
186
- }
187
- }
188
-
189
- export const renderToStream = async (element, options = {}) => {
190
- const buffer = []
191
- let injectToStream = (chunk) => buffer.push(chunk);
192
- const disable = options.disable //?? resolveSeoStrategy(options).disableStream)
193
- const result = await renderToWebStream(React.createElement(
194
- StreamProvider,
195
- {
196
- value: {
197
- injectToStream: (chunk) => {
198
- injectToStream(chunk)
199
- }
200
- }
201
- },
202
- React.createElement(SuspenseData, null, element)
203
- ), disable, options);
204
- injectToStream = result.injectToStream
205
- buffer.forEach((chunk) => injectToStream(chunk));
206
- buffer.length = 0;
207
- return result
208
- }
{packages/parotta → bin}/cli.js RENAMED
@@ -1,30 +1,26 @@
1
1
  #!/usr/bin/env bun --hot
2
2
 
3
- import React from 'react';
4
3
  import path from 'path';
5
4
  import fs from 'fs';
6
5
  import walkdir from 'walkdir';
7
6
  import postcss from "postcss"
8
7
  import autoprefixer from "autoprefixer";
9
8
  import postcssCustomMedia from "postcss-custom-media";
10
- // import postcssNormalize from 'postcss-normalize';
11
9
  import postcssNesting from "postcss-nesting";
12
10
  import { createMemoryHistory } from "history";
13
11
  import { createRouter } from 'radix3';
14
12
  import mimeTypes from "mime-types";
13
+ import React from "react";
14
+ import { renderToReadableStream } from "react-dom/server";
15
- import { HeadApp, BodyApp } from "./runtime";
15
+ import { HeadApp, BodyApp } from "../runtime";
16
- import { renderToReadableStream } from 'react-dom/server';
17
- // import { renderToStream } from './render';
18
16
 
19
- const version = (await import(path.join(import.meta.dir, "package.json"))).default.version;
17
+ const version = (await import(path.join(import.meta.dir, "../package.json"))).default.version;
20
18
  console.log(`parotta v${version}`)
21
19
  console.log(`running with cwd=${path.basename(process.cwd())} node_env=${process.env.NODE_ENV}`);
22
- // console.log("deleting cache");
23
- // rmSync(path.join(process.cwd(), ".cache"), { force: true, recursive: true })
24
20
 
25
21
  const isProd = process.env.NODE_ENV === "production";
26
22
 
27
- const mapServerRoutes = () => {
23
+ const createServerRouter = async () => {
28
24
  const routes = {};
29
25
  const dirs = walkdir.sync(path.join(process.cwd(), "pages"))
30
26
  .map((s) => s.replace(process.cwd(), "")
@@ -56,9 +52,74 @@ const mapServerRoutes = () => {
56
52
  .forEach((route) => {
57
53
  routes[route] = { key: route, file: route }
58
54
  });
55
+
56
+ return createRouter({
57
+ strictTrailingSlash: true,
59
- return routes;
58
+ routes: routes,
59
+ });
60
60
  }
61
61
 
62
+ const createClientRouter = async () => {
63
+ const routes = await walkdir.sync(path.join(process.cwd(), "pages"))
64
+ .filter((p) => p.includes('page.jsx'))
65
+ .map((s) => s.replace(process.cwd(), ""))
66
+ .map((s) => s.replace("/pages", ""))
67
+ .map((s) => s.replace("/page.jsx", ""))
68
+ .reduce(async (accp, r) => {
69
+ const acc = await accp;
70
+ const src = await import(`${process.cwd()}/pages${r}/page.jsx`);
71
+ const exists = fs.existsSync(`${process.cwd()}/pages${r}/layout.jsx`);
72
+ const lpath = exists ? `/pages${r}/layout.jsx` : `/pages/layout.jsx`;
73
+ const lsrc = await import(`${process.cwd()}${lpath}`);
74
+ acc[r === "" ? "/" : r] = {
75
+ Head: src.Head,
76
+ Body: src.Body,
77
+ Layout: lsrc.default,
78
+ LayoutPath: lpath,
79
+ }
80
+ return acc
81
+ }, Promise.resolve({}));
82
+ // console.log(clientRoutes);
83
+ const hydrationScript = `
84
+ import React from "react";
85
+ import { hydrateRoot } from "react-dom/client";
86
+ import { createBrowserHistory } from "history";
87
+ import nProgress from "nprogress";
88
+ import { createRouter } from "radix3";
89
+ import { HeadApp, BodyApp } from "parotta/runtime";
90
+
91
+
92
+ const history = createBrowserHistory();
93
+ const radixRouter = createRouter({
94
+ strictTrailingSlash: true,
95
+ routes: {
96
+ ${Object.keys(routes).map((r) => `"${r}": {
97
+ Head: React.lazy(() => import("/pages${r}/page.jsx").then((js) => ({ default: js.Head }))),
98
+ Body: React.lazy(() => import("/pages${r}/page.jsx").then((js) => ({ default: js.Body }))),
99
+ Layout: React.lazy(() => import("${routes[r].LayoutPath}")),
100
+ LayoutPath: "${routes[r].LayoutPath}",
101
+ }`).join(',\n ')}
102
+ },
103
+ });
104
+
105
+ hydrateRoot(document.head, React.createElement(HeadApp, {
106
+ history,
107
+ radixRouter,
108
+ }))
109
+
110
+ hydrateRoot(document.body, React.createElement(BodyApp, {
111
+ nProgress,
112
+ history,
113
+ radixRouter,
114
+ }));`
115
+ const router = createRouter({
116
+ strictTrailingSlash: true,
117
+ routes: routes,
118
+ });
119
+ router.hydrationScript = hydrationScript;
120
+ return router;
121
+ };
122
+
62
123
  const mapDeps = (dir) => {
63
124
  return walkdir.sync(path.join(process.cwd(), dir))
64
125
  .map((s) => s.replace(process.cwd(), ""))
@@ -74,45 +135,21 @@ const mapDeps = (dir) => {
74
135
  }, {});
75
136
  }
76
137
 
77
- const mapPages = () => walkdir.sync(path.join(process.cwd(), "pages"))
78
- .filter((p) => p.includes('page.jsx'))
79
- .map((s) => s.replace(process.cwd(), ""))
80
- .map((s) => s.replace("/pages", ""))
81
- .map((s) => s.replace("/page.jsx", ""));
82
-
83
- const serverSideRoutes = mapServerRoutes();
84
- const clientSideRoutes = mapPages();
85
-
86
- const serverRouter = createRouter({
138
+ const serverRouter = await createServerRouter();
87
- strictTrailingSlash: true,
88
- routes: serverSideRoutes,
89
- });
90
-
91
- const clientRoutes = await clientSideRoutes.reduce(async (accp, r) => {
139
+ const clientRouter = await createClientRouter();
92
- const acc = await accp;
140
+ const transpiler = new Bun.Transpiler({
93
- const src = await import(`${process.cwd()}/pages${r}/page.jsx`);
94
- const exists = fs.existsSync(`${process.cwd()}/pages${r}/layout.jsx`);
95
- const lpath = exists ? `/pages${r}/layout.jsx` : `/pages/layout.jsx`;
96
- const lsrc = await import(`${process.cwd()}${lpath}`);
97
- acc[r === "" ? "/" : r] = {
98
- Head: src.Head,
99
- Body: src.Body,
100
- Layout: lsrc.default,
141
+ loader: "jsx",
101
- LayoutPath: lpath,
142
+ autoImportJSX: true,
102
- }
103
- return acc
104
- }, Promise.resolve({}));
143
+ jsxOptimizationInline: true,
105
-
106
- // console.log(clientRoutes);
107
144
 
145
+ // TODO
108
- const clientRouter = createRouter({
146
+ // autoImportJSX: false,
109
- strictTrailingSlash: true,
147
+ // jsxOptimizationInline: false,
110
- routes: clientRoutes,
111
148
  });
112
149
 
113
150
  const renderApi = async (key, filePath, req) => {
114
151
  const url = new URL(req.url);
115
- const params = await req.json();
152
+ const params = req.method === "POST" ? await req.json() : Object.fromEntries(url.searchParams);
116
153
  const funcName = url.pathname.replace(`${key}/`, "");
117
154
  const js = await import(path.join(process.cwd(), filePath));
118
155
  const result = await js[funcName](params);
@@ -122,8 +159,6 @@ const renderApi = async (key, filePath, req) => {
122
159
  });
123
160
  }
124
161
 
125
- console.log(clientRoutes)
126
-
127
162
  const renderPage = async (url) => {
128
163
  const packageJson = await import(path.join(process.cwd(), "package.json"));
129
164
  const config = packageJson.default.parotta || { hydrate: true };
@@ -143,7 +178,7 @@ const renderPage = async (url) => {
143
178
  "react-dom/client": `https://esm.sh/react-dom@18.2.0${devTag}/client`,
144
179
  "nprogress": "https://esm.sh/nprogress@0.2.0",
145
180
  // "parotta/runtime": `https://esm.sh/parotta@${version}/runtime.js`,
146
- "parotta/runtime": `/parotta/runtime.js`,
181
+ "parotta/runtime": `../parotta/runtime.js`,
147
182
  ...nodeDeps,
148
183
  ...components,
149
184
  ...containers,
@@ -161,40 +196,12 @@ const renderPage = async (url) => {
161
196
  />
162
197
  </head>
163
198
  <body>
164
- <BodyApp history={history} radixRouter={clientRouter} />
199
+ <BodyApp nProgress={{ start: () => { }, done: () => { } }} history={history} radixRouter={clientRouter} />
165
200
  {config.hydrate &&
166
201
  <>
167
202
  <script type="module" defer={true} dangerouslySetInnerHTML={{
168
- __html: `
169
- import React from "react";
170
- import { hydrateRoot } from "react-dom/client";
171
- import { createBrowserHistory } from "history";
172
- import { createRouter } from "radix3";
173
- import { HeadApp, BodyApp } from "parotta/runtime";
174
-
175
-
176
- const history = createBrowserHistory();
177
- const radixRouter = createRouter({
203
+ __html: clientRouter.hydrationScript
178
- strictTrailingSlash: true,
179
- routes: {
180
- ${Object.keys(clientRoutes).map((r) => `"${r}": {
181
- Head: React.lazy(() => import("/pages${r}/page.jsx").then((js) => ({ default: js.Head }))),
182
- Body: React.lazy(() => import("/pages${r}/page.jsx").then((js) => ({ default: js.Body }))),
183
- Layout: React.lazy(() => import("${clientRoutes[r].LayoutPath}")),
184
- LayoutPath: "${clientRoutes[r].LayoutPath}",
185
- }`).join(',\n ')}
186
- },
187
- });
188
-
189
- hydrateRoot(document.head, React.createElement(HeadApp, {
190
- history,
191
- radixRouter,
192
- }))
193
-
194
- hydrateRoot(document.body, React.createElement(BodyApp, {
195
- history,
196
- radixRouter,
197
- }));`}}>
204
+ }}>
198
205
  </script>
199
206
  </>
200
207
  }
@@ -228,19 +235,9 @@ const renderCss = async (src) => {
228
235
  }
229
236
  }
230
237
 
231
- const transpiler = new Bun.Transpiler({
232
- loader: "jsx",
233
- autoImportJSX: true,
234
- jsxOptimizationInline: true,
235
-
236
- // TODO
237
- // autoImportJSX: false,
238
- // jsxOptimizationInline: false,
239
- });
240
-
241
- const renderJs = async (src) => {
238
+ const renderJs = async (srcFile) => {
242
239
  try {
243
- const jsText = await Bun.file(src).text();
240
+ const jsText = await Bun.file(srcFile).text();
244
241
  const result = await transpiler.transform(jsText);
245
242
  // inject code which calls the api for that function
246
243
  const lines = result.split("\n");
@@ -298,10 +295,10 @@ export default {
298
295
  port: 3000,
299
296
  async fetch(req) {
300
297
  const url = new URL(req.url);
301
- console.log("GET", url.pathname);
298
+ console.log(req.method, url.pathname);
302
299
  // maybe this is needed
303
300
  if (url.pathname.startsWith("/parotta/")) {
304
- return renderJs(path.join(import.meta.dir, url.pathname.replace("/parotta/", "")));
301
+ return renderJs(path.join(import.meta.dir, url.pathname.replace("/parotta/", "../")));
305
302
  }
306
303
  if (url.pathname.endsWith(".css")) {
307
304
  return renderCss(path.join(process.cwd(), url.pathname));
packages/create-parotta/index.js → bin/create-app.js RENAMED
File without changes
bun.lockb CHANGED
Binary file
{packages/example → example}/.gitignore RENAMED
File without changes
{packages/example → example}/.vscode/extensions.json RENAMED
File without changes
{packages/example → example}/.vscode/settings.json RENAMED
File without changes
{packages/example → example}/Dockerfile RENAMED
File without changes
example/bun.lockb ADDED
Binary file
{packages/example → example}/components/Counter/Counter.jsx RENAMED
File without changes
{packages/example → example}/components/Timer/Timer.jsx RENAMED
File without changes
{packages/example → example}/components/Todo/Todo.css RENAMED
File without changes
{packages/example → example}/components/Todo/Todo.jsx RENAMED
File without changes
{packages/example → example}/containers/TodoList/TodoList.jsx RENAMED
File without changes
{packages/example → example}/db/index.js RENAMED
@@ -4,7 +4,7 @@ import { Pool } from '@neondatabase/serverless';
4
4
  import { migrate } from 'drizzle-orm/neon-serverless/migrator';
5
5
  import { highlight } from 'sql-highlight';
6
6
 
7
- export const pool = new Pool({ connectionString: process.env.DATABASE_URL });
7
+ export const pool = new Pool({ connectionString: process.env.PG_CONN_URL });
8
8
  const db = drizzle(pool, {
9
9
  logger: {
10
10
  logQuery: (query, params) => {
{packages/example → example}/db/migrations/0000_empty_shatterstar.sql RENAMED
File without changes
{packages/example → example}/db/migrations/meta/0000_snapshot.json RENAMED
File without changes
{packages/example → example}/db/migrations/meta/_journal.json RENAMED
File without changes
{packages/example → example}/drizzle.config.json RENAMED
File without changes
{packages/example → example}/jsconfig.json RENAMED
File without changes
example/main.js ADDED
@@ -0,0 +1,3 @@
1
+ import DevServer from "parotta/bin/cli";
2
+
3
+ export default DevServer;
{packages/example → example}/package.json RENAMED
@@ -14,6 +14,8 @@
14
14
  "drizzle-auth-adaptor-pg": "^0.0.3",
15
15
  "drizzle-orm": "0.25.4",
16
16
  "next-auth": "^4.22.1",
17
+ "normalize.css": "^8.0.1",
18
+ "parotta": "file:../",
17
19
  "react": "18.2.0",
18
20
  "react-dom": "^18.2.0",
19
21
  "sql-highlight": "^4.3.2"
@@ -27,7 +29,9 @@
27
29
  },
28
30
  "parotta": {
29
31
  "hydrate": true,
32
+ "css": [
30
- "css": "@blueprintjs/core/lib/css/blueprint.css"
33
+ "node_modules/normalize.css/normalize.css"
34
+ ]
31
35
  },
32
36
  "eslintConfig": {
33
37
  "root": true,
{packages/example → example}/pages/404/page.css RENAMED
File without changes
{packages/example → example}/pages/404/page.jsx RENAMED
File without changes
{packages/example → example}/pages/about/page.css RENAMED
File without changes
{packages/example → example}/pages/about/page.jsx RENAMED
File without changes
{packages/example → example}/pages/layout.css RENAMED
File without changes
{packages/example → example}/pages/layout.jsx RENAMED
File without changes
{packages/example → example}/pages/page.css RENAMED
File without changes
{packages/example → example}/pages/page.jsx RENAMED
File without changes
{packages/example → example}/pages/page.spec.js RENAMED
File without changes
{packages/example → example}/pages/todos/page.css RENAMED
File without changes
{packages/example → example}/pages/todos/page.jsx RENAMED
File without changes
{packages/example → example}/playwright.config.js RENAMED
File without changes
{packages/example → example}/readme.md RENAMED
@@ -1,4 +1,4 @@
1
- # parotta-example
1
+ # Sample Parotta Application
2
2
 
3
3
  ## Requirements
4
4
 
@@ -9,6 +9,10 @@
9
9
  1. `bun i`
10
10
  2. `bunx playright install`
11
11
 
12
+ ## Running
13
+
14
+ `bun run dev`
15
+
12
16
  ## Testing
13
17
 
14
- `bun run test`
18
+ `bun test`
{packages/example → example}/services/auth.service.js RENAMED
File without changes
{packages/example → example}/services/todos.service.js RENAMED
File without changes
{packages/example → example}/static/favicon.ico RENAMED
File without changes
{packages/example → example}/static/logo192.png RENAMED
File without changes
{packages/example → example}/static/logo512.png RENAMED
File without changes
{packages/example → example}/static/manifest.json RENAMED
File without changes
{packages/example → example}/static/robots.txt RENAMED
File without changes
package-lock.json DELETED
@@ -1,694 +0,0 @@
1
- {
2
- "name": "quickstart",
3
- "version": "1.0.0",
4
- "lockfileVersion": 2,
5
- "requires": true,
6
- "packages": {
7
- "": {
8
- "workspaces": [
9
- "packages/example",
10
- "packages/parotta"
11
- ]
12
- },
13
- "node_modules/js-tokens": {
14
- "version": "4.0.0",
15
- "license": "MIT"
16
- },
17
- "node_modules/loose-envify": {
18
- "version": "1.4.0",
19
- "license": "MIT",
20
- "dependencies": {
21
- "js-tokens": "^3.0.0 || ^4.0.0"
22
- },
23
- "bin": {
24
- "loose-envify": "cli.js"
25
- }
26
- },
27
- "node_modules/parotta": {
28
- "resolved": "packages/parotta",
29
- "link": true
30
- },
31
- "node_modules/quickstart": {
32
- "resolved": "packages/example",
33
- "link": true
34
- },
35
- "node_modules/react": {
36
- "version": "18.2.0",
37
- "license": "MIT",
38
- "dependencies": {
39
- "loose-envify": "^1.1.0"
40
- },
41
- "engines": {
42
- "node": ">=0.10.0"
43
- }
44
- },
45
- "node_modules/react-dom": {
46
- "version": "18.2.0",
47
- "license": "MIT",
48
- "dependencies": {
49
- "loose-envify": "^1.1.0",
50
- "scheduler": "^0.23.0"
51
- },
52
- "peerDependencies": {
53
- "react": "^18.2.0"
54
- }
55
- },
56
- "node_modules/scheduler": {
57
- "version": "0.23.0",
58
- "license": "MIT",
59
- "dependencies": {
60
- "loose-envify": "^1.1.0"
61
- }
62
- },
63
- "node_modules/swr": {
64
- "version": "2.1.0",
65
- "resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
66
- "integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
67
- "dependencies": {
68
- "use-sync-external-store": "^1.2.0"
69
- },
70
- "engines": {
71
- "pnpm": "7"
72
- },
73
- "peerDependencies": {
74
- "react": "^16.11.0 || ^17.0.0 || ^18.0.0"
75
- }
76
- },
77
- "node_modules/use-sync-external-store": {
78
- "version": "1.2.0",
79
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
80
- "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
81
- "peerDependencies": {
82
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
83
- }
84
- },
85
- "packages/example": {
86
- "name": "quickstart",
87
- "dependencies": {
88
- "react": "18.2.0",
89
- "react-dom": "^18.2.0",
90
- "swr": "2.1.0"
91
- }
92
- },
93
- "packages/parotta": {
94
- "version": "0.2.0",
95
- "dependencies": {
96
- "autoprefixer": "^10.4.14",
97
- "mime-types": "2.1.35",
98
- "postcss": "^8.4.21",
99
- "postcss-custom-media": "^9.1.2",
100
- "postcss-nesting": "^11.2.1",
101
- "postcss-normalize": "^10.0.1",
102
- "radix3": "^1.0.0",
103
- "walkdir": "0.4.1"
104
- },
105
- "bin": {
106
- "parotta": "cli.js"
107
- }
108
- },
109
- "packages/parotta/node_modules/@csstools/cascade-layer-name-parser": {
110
- "version": "1.0.1",
111
- "license": "MIT",
112
- "engines": {
113
- "node": "^14 || ^16 || >=18"
114
- },
115
- "funding": {
116
- "type": "opencollective",
117
- "url": "https://opencollective.com/csstools"
118
- },
119
- "peerDependencies": {
120
- "@csstools/css-parser-algorithms": "^2.0.0",
121
- "@csstools/css-tokenizer": "^2.0.0"
122
- }
123
- },
124
- "packages/parotta/node_modules/@csstools/css-parser-algorithms": {
125
- "version": "2.0.1",
126
- "license": "MIT",
127
- "engines": {
128
- "node": "^14 || ^16 || >=18"
129
- },
130
- "funding": {
131
- "type": "opencollective",
132
- "url": "https://opencollective.com/csstools"
133
- },
134
- "peerDependencies": {
135
- "@csstools/css-tokenizer": "^2.0.0"
136
- }
137
- },
138
- "packages/parotta/node_modules/@csstools/css-tokenizer": {
139
- "version": "2.1.0",
140
- "license": "MIT",
141
- "engines": {
142
- "node": "^14 || ^16 || >=18"
143
- },
144
- "funding": {
145
- "type": "opencollective",
146
- "url": "https://opencollective.com/csstools"
147
- }
148
- },
149
- "packages/parotta/node_modules/@csstools/media-query-list-parser": {
150
- "version": "2.0.1",
151
- "license": "MIT",
152
- "engines": {
153
- "node": "^14 || ^16 || >=18"
154
- },
155
- "funding": {
156
- "type": "opencollective",
157
- "url": "https://opencollective.com/csstools"
158
- },
159
- "peerDependencies": {
160
- "@csstools/css-parser-algorithms": "^2.0.0",
161
- "@csstools/css-tokenizer": "^2.0.0"
162
- }
163
- },
164
- "packages/parotta/node_modules/@csstools/normalize.css": {
165
- "version": "12.0.0",
166
- "license": "CC0-1.0"
167
- },
168
- "packages/parotta/node_modules/@csstools/selector-specificity": {
169
- "version": "2.1.1",
170
- "license": "CC0-1.0",
171
- "engines": {
172
- "node": "^14 || ^16 || >=18"
173
- },
174
- "funding": {
175
- "type": "opencollective",
176
- "url": "https://opencollective.com/csstools"
177
- },
178
- "peerDependencies": {
179
- "postcss": "^8.4",
180
- "postcss-selector-parser": "^6.0.10"
181
- }
182
- },
183
- "packages/parotta/node_modules/autoprefixer": {
184
- "version": "10.4.14",
185
- "funding": [
186
- {
187
- "type": "opencollective",
188
- "url": "https://opencollective.com/postcss/"
189
- },
190
- {
191
- "type": "tidelift",
192
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
193
- }
194
- ],
195
- "license": "MIT",
196
- "dependencies": {
197
- "browserslist": "^4.21.5",
198
- "caniuse-lite": "^1.0.30001464",
199
- "fraction.js": "^4.2.0",
200
- "normalize-range": "^0.1.2",
201
- "picocolors": "^1.0.0",
202
- "postcss-value-parser": "^4.2.0"
203
- },
204
- "bin": {
205
- "autoprefixer": "bin/autoprefixer"
206
- },
207
- "engines": {
208
- "node": "^10 || ^12 || >=14"
209
- },
210
- "peerDependencies": {
211
- "postcss": "^8.1.0"
212
- }
213
- },
214
- "packages/parotta/node_modules/browserslist": {
215
- "version": "4.21.5",
216
- "funding": [
217
- {
218
- "type": "opencollective",
219
- "url": "https://opencollective.com/browserslist"
220
- },
221
- {
222
- "type": "tidelift",
223
- "url": "https://tidelift.com/funding/github/npm/browserslist"
224
- }
225
- ],
226
- "license": "MIT",
227
- "dependencies": {
228
- "caniuse-lite": "^1.0.30001449",
229
- "electron-to-chromium": "^1.4.284",
230
- "node-releases": "^2.0.8",
231
- "update-browserslist-db": "^1.0.10"
232
- },
233
- "bin": {
234
- "browserslist": "cli.js"
235
- },
236
- "engines": {
237
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
238
- }
239
- },
240
- "packages/parotta/node_modules/caniuse-lite": {
241
- "version": "1.0.30001468",
242
- "funding": [
243
- {
244
- "type": "opencollective",
245
- "url": "https://opencollective.com/browserslist"
246
- },
247
- {
248
- "type": "tidelift",
249
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
250
- }
251
- ],
252
- "license": "CC-BY-4.0"
253
- },
254
- "packages/parotta/node_modules/cssesc": {
255
- "version": "3.0.0",
256
- "license": "MIT",
257
- "bin": {
258
- "cssesc": "bin/cssesc"
259
- },
260
- "engines": {
261
- "node": ">=4"
262
- }
263
- },
264
- "packages/parotta/node_modules/electron-to-chromium": {
265
- "version": "1.4.333",
266
- "license": "ISC"
267
- },
268
- "packages/parotta/node_modules/escalade": {
269
- "version": "3.1.1",
270
- "license": "MIT",
271
- "engines": {
272
- "node": ">=6"
273
- }
274
- },
275
- "packages/parotta/node_modules/fraction.js": {
276
- "version": "4.2.0",
277
- "license": "MIT",
278
- "engines": {
279
- "node": "*"
280
- },
281
- "funding": {
282
- "type": "patreon",
283
- "url": "https://www.patreon.com/infusion"
284
- }
285
- },
286
- "packages/parotta/node_modules/mime-db": {
287
- "version": "1.52.0",
288
- "license": "MIT",
289
- "engines": {
290
- "node": ">= 0.6"
291
- }
292
- },
293
- "packages/parotta/node_modules/mime-types": {
294
- "version": "2.1.35",
295
- "license": "MIT",
296
- "dependencies": {
297
- "mime-db": "1.52.0"
298
- },
299
- "engines": {
300
- "node": ">= 0.6"
301
- }
302
- },
303
- "packages/parotta/node_modules/nanoid": {
304
- "version": "3.3.4",
305
- "license": "MIT",
306
- "bin": {
307
- "nanoid": "bin/nanoid.cjs"
308
- },
309
- "engines": {
310
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
311
- }
312
- },
313
- "packages/parotta/node_modules/node-releases": {
314
- "version": "2.0.10",
315
- "license": "MIT"
316
- },
317
- "packages/parotta/node_modules/normalize-range": {
318
- "version": "0.1.2",
319
- "license": "MIT",
320
- "engines": {
321
- "node": ">=0.10.0"
322
- }
323
- },
324
- "packages/parotta/node_modules/picocolors": {
325
- "version": "1.0.0",
326
- "license": "ISC"
327
- },
328
- "packages/parotta/node_modules/postcss": {
329
- "version": "8.4.21",
330
- "funding": [
331
- {
332
- "type": "opencollective",
333
- "url": "https://opencollective.com/postcss/"
334
- },
335
- {
336
- "type": "tidelift",
337
- "url": "https://tidelift.com/funding/github/npm/postcss"
338
- }
339
- ],
340
- "license": "MIT",
341
- "dependencies": {
342
- "nanoid": "^3.3.4",
343
- "picocolors": "^1.0.0",
344
- "source-map-js": "^1.0.2"
345
- },
346
- "engines": {
347
- "node": "^10 || ^12 || >=14"
348
- }
349
- },
350
- "packages/parotta/node_modules/postcss-browser-comments": {
351
- "version": "4.0.0",
352
- "license": "CC0-1.0",
353
- "engines": {
354
- "node": ">=8"
355
- },
356
- "peerDependencies": {
357
- "browserslist": ">=4",
358
- "postcss": ">=8"
359
- }
360
- },
361
- "packages/parotta/node_modules/postcss-custom-media": {
362
- "version": "9.1.2",
363
- "license": "MIT",
364
- "dependencies": {
365
- "@csstools/cascade-layer-name-parser": "^1.0.0",
366
- "@csstools/css-parser-algorithms": "^2.0.0",
367
- "@csstools/css-tokenizer": "^2.0.0",
368
- "@csstools/media-query-list-parser": "^2.0.0"
369
- },
370
- "engines": {
371
- "node": "^14 || ^16 || >=18"
372
- },
373
- "funding": {
374
- "type": "opencollective",
375
- "url": "https://opencollective.com/csstools"
376
- },
377
- "peerDependencies": {
378
- "postcss": "^8.4"
379
- }
380
- },
381
- "packages/parotta/node_modules/postcss-nesting": {
382
- "version": "11.2.1",
383
- "license": "CC0-1.0",
384
- "dependencies": {
385
- "@csstools/selector-specificity": "^2.0.0",
386
- "postcss-selector-parser": "^6.0.10"
387
- },
388
- "engines": {
389
- "node": "^14 || ^16 || >=18"
390
- },
391
- "funding": {
392
- "type": "opencollective",
393
- "url": "https://opencollective.com/csstools"
394
- },
395
- "peerDependencies": {
396
- "postcss": "^8.4"
397
- }
398
- },
399
- "packages/parotta/node_modules/postcss-normalize": {
400
- "version": "10.0.1",
401
- "license": "CC0-1.0",
402
- "dependencies": {
403
- "@csstools/normalize.css": "*",
404
- "postcss-browser-comments": "^4",
405
- "sanitize.css": "*"
406
- },
407
- "engines": {
408
- "node": ">= 12"
409
- },
410
- "peerDependencies": {
411
- "browserslist": ">= 4",
412
- "postcss": ">= 8"
413
- }
414
- },
415
- "packages/parotta/node_modules/postcss-selector-parser": {
416
- "version": "6.0.11",
417
- "license": "MIT",
418
- "dependencies": {
419
- "cssesc": "^3.0.0",
420
- "util-deprecate": "^1.0.2"
421
- },
422
- "engines": {
423
- "node": ">=4"
424
- }
425
- },
426
- "packages/parotta/node_modules/postcss-value-parser": {
427
- "version": "4.2.0",
428
- "license": "MIT"
429
- },
430
- "packages/parotta/node_modules/radix3": {
431
- "version": "1.0.0",
432
- "license": "MIT"
433
- },
434
- "packages/parotta/node_modules/sanitize.css": {
435
- "version": "13.0.0",
436
- "license": "CC0-1.0"
437
- },
438
- "packages/parotta/node_modules/source-map-js": {
439
- "version": "1.0.2",
440
- "license": "BSD-3-Clause",
441
- "engines": {
442
- "node": ">=0.10.0"
443
- }
444
- },
445
- "packages/parotta/node_modules/update-browserslist-db": {
446
- "version": "1.0.10",
447
- "funding": [
448
- {
449
- "type": "opencollective",
450
- "url": "https://opencollective.com/browserslist"
451
- },
452
- {
453
- "type": "tidelift",
454
- "url": "https://tidelift.com/funding/github/npm/browserslist"
455
- }
456
- ],
457
- "license": "MIT",
458
- "dependencies": {
459
- "escalade": "^3.1.1",
460
- "picocolors": "^1.0.0"
461
- },
462
- "bin": {
463
- "browserslist-lint": "cli.js"
464
- },
465
- "peerDependencies": {
466
- "browserslist": ">= 4.21.0"
467
- }
468
- },
469
- "packages/parotta/node_modules/util-deprecate": {
470
- "version": "1.0.2",
471
- "license": "MIT"
472
- },
473
- "packages/parotta/node_modules/walkdir": {
474
- "version": "0.4.1",
475
- "license": "MIT",
476
- "engines": {
477
- "node": ">=6.0.0"
478
- }
479
- }
480
- },
481
- "dependencies": {
482
- "js-tokens": {
483
- "version": "4.0.0"
484
- },
485
- "loose-envify": {
486
- "version": "1.4.0",
487
- "requires": {
488
- "js-tokens": "^3.0.0 || ^4.0.0"
489
- }
490
- },
491
- "parotta": {
492
- "version": "file:packages/parotta",
493
- "requires": {
494
- "autoprefixer": "^10.4.14",
495
- "mime-types": "2.1.35",
496
- "postcss": "^8.4.21",
497
- "postcss-custom-media": "^9.1.2",
498
- "postcss-nesting": "^11.2.1",
499
- "postcss-normalize": "^10.0.1",
500
- "radix3": "^1.0.0",
501
- "walkdir": "0.4.1"
502
- },
503
- "dependencies": {
504
- "@csstools/cascade-layer-name-parser": {
505
- "version": "1.0.1",
506
- "requires": {}
507
- },
508
- "@csstools/css-parser-algorithms": {
509
- "version": "2.0.1",
510
- "requires": {}
511
- },
512
- "@csstools/css-tokenizer": {
513
- "version": "2.1.0"
514
- },
515
- "@csstools/media-query-list-parser": {
516
- "version": "2.0.1",
517
- "requires": {}
518
- },
519
- "@csstools/normalize.css": {
520
- "version": "12.0.0"
521
- },
522
- "@csstools/selector-specificity": {
523
- "version": "2.1.1",
524
- "requires": {}
525
- },
526
- "autoprefixer": {
527
- "version": "10.4.14",
528
- "requires": {
529
- "browserslist": "^4.21.5",
530
- "caniuse-lite": "^1.0.30001464",
531
- "fraction.js": "^4.2.0",
532
- "normalize-range": "^0.1.2",
533
- "picocolors": "^1.0.0",
534
- "postcss-value-parser": "^4.2.0"
535
- }
536
- },
537
- "browserslist": {
538
- "version": "4.21.5",
539
- "requires": {
540
- "caniuse-lite": "^1.0.30001449",
541
- "electron-to-chromium": "^1.4.284",
542
- "node-releases": "^2.0.8",
543
- "update-browserslist-db": "^1.0.10"
544
- }
545
- },
546
- "caniuse-lite": {
547
- "version": "1.0.30001468"
548
- },
549
- "cssesc": {
550
- "version": "3.0.0"
551
- },
552
- "electron-to-chromium": {
553
- "version": "1.4.333"
554
- },
555
- "escalade": {
556
- "version": "3.1.1"
557
- },
558
- "fraction.js": {
559
- "version": "4.2.0"
560
- },
561
- "mime-db": {
562
- "version": "1.52.0"
563
- },
564
- "mime-types": {
565
- "version": "2.1.35",
566
- "requires": {
567
- "mime-db": "1.52.0"
568
- }
569
- },
570
- "nanoid": {
571
- "version": "3.3.4"
572
- },
573
- "node-releases": {
574
- "version": "2.0.10"
575
- },
576
- "normalize-range": {
577
- "version": "0.1.2"
578
- },
579
- "picocolors": {
580
- "version": "1.0.0"
581
- },
582
- "postcss": {
583
- "version": "8.4.21",
584
- "requires": {
585
- "nanoid": "^3.3.4",
586
- "picocolors": "^1.0.0",
587
- "source-map-js": "^1.0.2"
588
- }
589
- },
590
- "postcss-browser-comments": {
591
- "version": "4.0.0",
592
- "requires": {}
593
- },
594
- "postcss-custom-media": {
595
- "version": "9.1.2",
596
- "requires": {
597
- "@csstools/cascade-layer-name-parser": "^1.0.0",
598
- "@csstools/css-parser-algorithms": "^2.0.0",
599
- "@csstools/css-tokenizer": "^2.0.0",
600
- "@csstools/media-query-list-parser": "^2.0.0"
601
- }
602
- },
603
- "postcss-nesting": {
604
- "version": "11.2.1",
605
- "requires": {
606
- "@csstools/selector-specificity": "^2.0.0",
607
- "postcss-selector-parser": "^6.0.10"
608
- }
609
- },
610
- "postcss-normalize": {
611
- "version": "10.0.1",
612
- "requires": {
613
- "@csstools/normalize.css": "*",
614
- "postcss-browser-comments": "^4",
615
- "sanitize.css": "*"
616
- }
617
- },
618
- "postcss-selector-parser": {
619
- "version": "6.0.11",
620
- "requires": {
621
- "cssesc": "^3.0.0",
622
- "util-deprecate": "^1.0.2"
623
- }
624
- },
625
- "postcss-value-parser": {
626
- "version": "4.2.0"
627
- },
628
- "radix3": {
629
- "version": "1.0.0"
630
- },
631
- "sanitize.css": {
632
- "version": "13.0.0"
633
- },
634
- "source-map-js": {
635
- "version": "1.0.2"
636
- },
637
- "update-browserslist-db": {
638
- "version": "1.0.10",
639
- "requires": {
640
- "escalade": "^3.1.1",
641
- "picocolors": "^1.0.0"
642
- }
643
- },
644
- "util-deprecate": {
645
- "version": "1.0.2"
646
- },
647
- "walkdir": {
648
- "version": "0.4.1"
649
- }
650
- }
651
- },
652
- "quickstart": {
653
- "version": "file:packages/example",
654
- "requires": {
655
- "react": "18.2.0",
656
- "react-dom": "^18.2.0",
657
- "swr": "2.1.0"
658
- }
659
- },
660
- "react": {
661
- "version": "18.2.0",
662
- "requires": {
663
- "loose-envify": "^1.1.0"
664
- }
665
- },
666
- "react-dom": {
667
- "version": "18.2.0",
668
- "requires": {
669
- "loose-envify": "^1.1.0",
670
- "scheduler": "^0.23.0"
671
- }
672
- },
673
- "scheduler": {
674
- "version": "0.23.0",
675
- "requires": {
676
- "loose-envify": "^1.1.0"
677
- }
678
- },
679
- "swr": {
680
- "version": "2.1.0",
681
- "resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
682
- "integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
683
- "requires": {
684
- "use-sync-external-store": "^1.2.0"
685
- }
686
- },
687
- "use-sync-external-store": {
688
- "version": "1.2.0",
689
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
690
- "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
691
- "requires": {}
692
- }
693
- }
694
- }
package.json CHANGED
@@ -1,5 +1,27 @@
1
1
  {
2
+ "name": "parotta",
3
+ "version": "0.3.0",
4
+ "type": "module",
2
- "workspaces": [
5
+ "dependencies": {
6
+ "autoprefixer": "^10.4.14",
3
- "packages/*"
7
+ "chalk": "^5.2.0",
8
+ "commander": "10.0.0",
9
+ "extract-files": "^13.0.0",
10
+ "gunzip-file": "^0.1.1",
11
+ "history": "^5.3.0",
12
+ "mime-types": "2.1.35",
13
+ "nprogress": "^0.2.0",
14
+ "postcss": "^8.4.21",
15
+ "postcss-custom-media": "^9.1.2",
16
+ "postcss-nesting": "^11.2.1",
17
+ "radix3": "^1.0.0",
18
+ "react": "^18.2.0",
19
+ "react-dom": "^18.2.0",
20
+ "tar": "^6.1.13",
21
+ "unzip": "^0.1.11",
22
+ "walkdir": "0.4.1"
4
- ]
23
+ },
24
+ "bin": {
25
+ "parotta": "./bin/cli.js"
5
- }
26
+ }
27
+ }
packages/create-parotta/package.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "name": "create-parotta-app",
3
- "version": "0.1.0",
4
- "type": "module",
5
- "dependencies": {
6
- "chalk": "^5.2.0",
7
- "commander": "10.0.0",
8
- "extract-files": "^13.0.0",
9
- "gunzip-file": "^0.1.1",
10
- "tar": "^6.1.13",
11
- "unzip": "^0.1.11"
12
- },
13
- "bin": {
14
- "parotta": "./index.js"
15
- }
16
- }
packages/example/bun.lockb DELETED
Binary file
packages/parotta/bun.lockb DELETED
Binary file
packages/parotta/package.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "name": "parotta",
3
- "version": "0.3.0",
4
- "type": "module",
5
- "dependencies": {
6
- "autoprefixer": "^10.4.14",
7
- "history": "^5.3.0",
8
- "mime-types": "2.1.35",
9
- "nprogress": "^0.2.0",
10
- "postcss": "^8.4.21",
11
- "postcss-custom-media": "^9.1.2",
12
- "postcss-nesting": "^11.2.1",
13
- "postcss-normalize": "^10.0.1",
14
- "radix3": "^1.0.0",
15
- "walkdir": "0.4.1"
16
- },
17
- "bin": {
18
- "parotta": "./cli.js"
19
- }
20
- }
readme.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # parotta
2
2
 
3
- parotta is a next level meta-framework for react that runs only on edge runtimes mainly bun.
3
+ parotta is a next level meta-framework for react that runs only on edge runtimes.
4
+ It uses bun as its bundler/transpiler and development mode as its quick and fast.
4
5
  It uses File System routing with streaming SSR + CSR as the method to render pages. Basically a MPA + SPA Transitional App.
5
6
  It is very opionated and has set of idiomatic ways of doing things.
7
+ It has inbuilt rpc mechanism to access server resources instead of a typical REST API.
6
8
 
7
9
  ### Todo
8
10
  1. Add build step
9
11
  2. Deploy to Node (using edge-runtime), Docker, Deno deploy, Vercel edge functions, Cloudflare workers, Bun edge (whenever it releases)
10
- 3. Hydrate fetch cache
12
+ 3. Hydrate rpc cache
11
- 4. Build a proper example (bunx create-parotta@latest)
12
- 5. Build a Website with Docs using parotta
13
+ 4. Build a Website with Docs using parotta
packages/parotta/runtime.js → runtime.js RENAMED
@@ -2,7 +2,6 @@ import React, {
2
2
  Fragment, Suspense, createElement, createContext,
3
3
  useContext, useState, useEffect, useMemo, useSyncExternalStore, useTransition
4
4
  } from "react";
5
- import nProgress from "nprogress";
6
5
 
7
6
  export const domain = () => typeof window !== 'undefined' ? window.origin : "http://0.0.0.0:3000";
8
7
  export const globalCache = new Map();
@@ -106,7 +105,7 @@ export const HeadApp = ({ history, radixRouter, importMap }) => {
106
105
  });
107
106
  }
108
107
 
109
- export const BodyApp = ({ history, radixRouter }) => {
108
+ export const BodyApp = ({ nProgress, history, radixRouter }) => {
110
109
  const [isPending, startTransition] = useTransition();
111
110
  const [match, setMatch] = useState(() => getMatch(radixRouter, history.location.pathname));
112
111
  useEffect(() => {
@@ -186,7 +185,11 @@ export const Link = (props) => {
186
185
  export const NavLink = ({ children, className, activeClassName, ...props }) => {
187
186
  const { pathname } = useRouter();
188
187
  const classNames = pathname === props.href ? [activeClassName, className] : [className];
189
- return <Link className={classNames} {...props} >{children}</Link>
188
+ return createElement(Link, {
189
+ children,
190
+ className: classNames,
191
+ ...props,
192
+ })
190
193
  }
191
194
 
192
195
  export class ErrorBoundary extends React.Component {