raiko.js 1.0.0 → 1.0.2

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/bin/raiko.mjs CHANGED
@@ -2,7 +2,8 @@
2
2
  // raiko: dev, build, start, deploy, secret, routes, manifest
3
3
  import { spawn, spawnSync } from 'node:child_process'
4
4
  import { existsSync, mkdirSync, readdirSync, statSync, writeFileSync, watch, readFileSync } from 'node:fs'
5
- import { join, relative, resolve } from 'node:path'
5
+ import { join, relative, resolve, dirname } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
6
7
  import { randomBytes } from 'node:crypto'
7
8
 
8
9
  const [cmd = 'help', ...args] = process.argv.slice(2)
@@ -48,6 +49,12 @@ function manifest() {
48
49
  return files.length
49
50
  }
50
51
 
52
+ /** Run a package binary: bunx when Bun is here (works without Node), npx otherwise. */
53
+ function x(pkgBin, a, env) {
54
+ return hasBun() ? run('bun', ['x', '--bun', pkgBin, ...a], env) : run('npx', [pkgBin, ...a], env)
55
+ }
56
+ const xSync = (pkgBin, a, opts) => (hasBun() ? spawnSync('bun', ['x', '--bun', pkgBin, ...a], opts) : spawnSync(process.platform === 'win32' ? 'npx.cmd' : 'npx', [pkgBin, ...a], opts))
57
+
51
58
  function run(bin, a, env = {}) {
52
59
  // no shell: arguments are never interpreted; on Windows the .cmd shims are called by name
53
60
  const exe = process.platform === 'win32' && ['npx', 'npm', 'bunx'].includes(bin) ? `${bin}.cmd` : bin
@@ -64,7 +71,6 @@ switch (cmd) {
64
71
  break
65
72
  }
66
73
  case 'dev': {
67
- banner()
68
74
  if (existsSync(join(cwd, 'app'))) {
69
75
  manifest()
70
76
  try {
@@ -72,9 +78,16 @@ switch (cmd) {
72
78
  } catch {}
73
79
  }
74
80
  const vite = ['vite.config.ts', 'vite.config.js', 'vite.config.mts'].some((f) => existsSync(join(cwd, f)))
75
- if (vite) run('npx', ['vite', ...args.filter((a) => a.startsWith('--'))], { NODE_ENV: 'development' })
76
- else if (hasBun()) run('bun', ['--watch', entry()], { NODE_ENV: 'development' })
77
- else run('npx', ['tsx', 'watch', entry()], { NODE_ENV: 'development' })
81
+ if (!vite && !existsSync(join(cwd, entry()))) {
82
+ console.error(`${red('error[RK0704]')}: no server entry found\n = help: create server.ts, or run ${y('raiko dev path/to/server.ts')}`)
83
+ process.exit(1)
84
+ }
85
+ console.log(` ${dim('starting')} ${vite ? 'vite with the Raiko backend' : entry()} ${dim('...')}\n`)
86
+ const runner = join(dirname(fileURLToPath(import.meta.url)), 'serve-entry.mjs')
87
+ // everything except the entry file goes to Vite, values included (--port 5174)
88
+ if (vite) x('vite', args.filter((a) => !/\.(m|c)?(t|j)sx?$/.test(a)), { NODE_ENV: 'development' })
89
+ else if (hasBun()) run('bun', ['--watch', runner, entry(), 'dev'], { NODE_ENV: 'development' })
90
+ else x('tsx', ['watch', runner, entry(), 'dev'], { NODE_ENV: 'development' })
78
91
  break
79
92
  }
80
93
  case 'build': {
@@ -83,7 +96,7 @@ switch (cmd) {
83
96
  if (existsSync(join(cwd, 'app'))) console.log(`${green('ok')} routes manifest, ${manifest()} files`)
84
97
  const vite = ['vite.config.ts', 'vite.config.js', 'vite.config.mts'].some((f) => existsSync(join(cwd, f)))
85
98
  if (vite) {
86
- const r = spawnSync('npx', ['vite', 'build'], { stdio: 'inherit', env: { ...process.env, NODE_ENV: 'production' } })
99
+ const r = xSync('vite', ['build'], { stdio: 'inherit', env: { ...process.env, NODE_ENV: 'production' } })
87
100
  if (r.status) process.exit(r.status)
88
101
  console.log(`${green('ok')} frontend built, minified and mangled, no source maps`)
89
102
  }
@@ -91,7 +104,7 @@ switch (cmd) {
91
104
  const target = flag('target', hasBun() ? 'bun' : 'node')
92
105
  const r = hasBun()
93
106
  ? spawnSync('bun', ['build', entry(), '--target', target === 'bun' ? 'bun' : 'node', '--outdir', out, '--minify', '--packages', 'external'], { stdio: 'inherit' })
94
- : spawnSync('npx', ['esbuild', entry(), '--bundle', '--platform=node', '--format=esm', '--minify', '--packages=external', `--outdir=${out}`, '--jsx=automatic', '--jsx-import-source=raiko.js'], { stdio: 'inherit' })
107
+ : xSync('esbuild', [entry(), '--bundle', '--platform=node', '--format=esm', '--minify', '--packages=external', `--outdir=${out}`, '--jsx=automatic', '--jsx-import-source=raiko.js'], { stdio: 'inherit' })
95
108
  if (r.status) process.exit(r.status)
96
109
  console.log(`${green('ok')} server bundled to .raiko/out ${dim(`(${Date.now() - t0}ms)`)}\n\n start it with ${y('raiko start')}\n`)
97
110
  break
@@ -102,7 +115,7 @@ switch (cmd) {
102
115
  console.error(`${red('error[RK0701]')}: no build found\n = help: run ${y('raiko build')} first`)
103
116
  process.exit(1)
104
117
  }
105
- run(hasBun() ? 'bun' : 'node', [file], { NODE_ENV: 'production' })
118
+ run(hasBun() ? 'bun' : 'node', [join(dirname(fileURLToPath(import.meta.url)), 'serve-entry.mjs'), file, 'production'], { NODE_ENV: 'production' })
106
119
  break
107
120
  }
108
121
  case 'deploy': {
@@ -112,8 +125,8 @@ switch (cmd) {
112
125
  process.exit(1)
113
126
  }
114
127
  console.log(`\n deploying to ${y(to)}\n`)
115
- if (to === 'vercel') run('npx', ['vercel', '--prod'])
116
- else if (to === 'cloudflare') run('npx', ['wrangler', 'deploy'])
128
+ if (to === 'vercel') x('vercel', ['--prod'])
129
+ else if (to === 'cloudflare') x('wrangler', ['deploy'])
117
130
  else if (to === 'docker') run('docker', ['build', '-t', pkg.name ?? 'raiko-app', '.'])
118
131
  else {
119
132
  console.error(`${red('error[RK0703]')}: unknown target "${to}"`)
@@ -0,0 +1,45 @@
1
+ // Started by `raiko dev` and `raiko start`: imports the app entry and makes sure it is listening,
2
+ // then prints where to open it. Works whether or not the entry calls listen() itself.
3
+ import { pathToFileURL } from 'node:url'
4
+ import { resolve } from 'node:path'
5
+ import { networkInterfaces } from 'node:os'
6
+ import { readFileSync } from 'node:fs'
7
+
8
+ const t0 = performance.now()
9
+ const [file, mode = 'dev'] = process.argv.slice(2)
10
+ const port = Number(process.env.PORT ?? 3000)
11
+ const tty = process.stdout.isTTY
12
+ const c = (n, s) => (tty ? `\x1b[${n}m${s}\x1b[0m` : s)
13
+
14
+ process.env.RAIKO_RUNNER = '1'
15
+ const mod = await import(pathToFileURL(resolve(file)).href)
16
+ const app = mod.default ?? mod.app
17
+ let url = globalThis.__raikoListening
18
+ if (!url) {
19
+ if (!app || typeof app.listen !== 'function') {
20
+ console.error(`\n ${c(31, 'error[RK0705]')}: ${file} does not export the app\n = help: end the file with \`export default app\`\n`)
21
+ process.exit(1)
22
+ }
23
+ try {
24
+ url = (await app.listen(port)).url
25
+ } catch (e) {
26
+ if (e && (e.code === 'EADDRINUSE' || /in use|EADDRINUSE/i.test(String(e.message)))) {
27
+ console.error(`\n ${c(31, 'error[RK0706]')}: port ${port} is already in use\n = help: stop the other server, or run with PORT=${port + 1}\n`)
28
+ process.exit(1)
29
+ }
30
+ throw e
31
+ }
32
+ }
33
+ let version = ''
34
+ try {
35
+ version = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version
36
+ } catch {}
37
+ const lan = Object.values(networkInterfaces()).flat().find((i) => i && i.family === 'IPv4' && !i.internal)?.address
38
+
39
+ console.log(`
40
+ ${c(33, 'raiko.js')} ${version} ${c(2, mode)}
41
+
42
+ - Local: ${c(36, url.replace('0.0.0.0', 'localhost'))}${lan ? `\n - Network: ${c(36, `http://${lan}:${new URL(url).port}`)}` : ''}
43
+
44
+ ${c(32, 'ready')} in ${Math.round(performance.now() - t0)} ms${mode === 'dev' ? c(2, ' (save a file to reload)') : ''}
45
+ `)
@@ -1,4 +1,4 @@
1
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ import { Raiko } from '../chunk-BDDC5OJA.js';
2
2
  import { validate } from '../chunk-4NOVAJBA.js';
3
3
  import '../chunk-SNAWC6GY.js';
4
4
  import '../chunk-Y3YIWI5S.js';
@@ -1,6 +1,6 @@
1
1
  import { PREFETCH_SCRIPT } from '../chunk-U626USOW.js';
2
2
  import { als, RedirectSignal } from '../chunk-MGKXQINB.js';
3
- import { Raiko } from '../chunk-IJNNQKTG.js';
3
+ import { Raiko } from '../chunk-BDDC5OJA.js';
4
4
  import '../chunk-4NOVAJBA.js';
5
5
  import '../chunk-SNAWC6GY.js';
6
6
  import { formToObject } from '../chunk-Y3YIWI5S.js';
@@ -235,7 +235,7 @@ async function appRouter(options = {}) {
235
235
  }
236
236
  const publicDir = options.publicDir === void 0 && manifest ? null : resolve(options.publicDir ?? "public");
237
237
  if (publicDir && existsSync(publicDir)) {
238
- const { staticFiles } = await import('../static-4LGL4QSH.js');
238
+ const { staticFiles } = await import('../static-7FVGQ2UM.js');
239
239
  app.use(staticFiles({ dir: publicDir, prefix: "/" }));
240
240
  const { imageHandler } = await import('../image-FBZPWI2W.js');
241
241
  app.get("/_raiko/image", imageHandler(publicDir));
@@ -1,4 +1,4 @@
1
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ import { Raiko } from '../chunk-BDDC5OJA.js';
2
2
  import '../chunk-4NOVAJBA.js';
3
3
  import '../chunk-SNAWC6GY.js';
4
4
  import '../chunk-Y3YIWI5S.js';
@@ -551,7 +551,7 @@ var Raiko = class _Raiko {
551
551
  * `cluster: true` runs one process per CPU core on the same port.
552
552
  */
553
553
  async listen(port = 3e3, opts = {}) {
554
- const { serve } = await import('./serve-GGEVATIS.js');
554
+ const { serve } = await import('./serve-ALQGRNNC.js');
555
555
  for (const fn of this.startHooks) await fn(this);
556
556
  return serve(this, Number(port), opts);
557
557
  }
@@ -1,4 +1,4 @@
1
- import { Raiko } from './chunk-IJNNQKTG.js';
1
+ import { Raiko } from './chunk-BDDC5OJA.js';
2
2
  import { stat, readFile } from 'node:fs/promises';
3
3
  import { createReadStream } from 'node:fs';
4
4
  import { Readable } from 'node:stream';
@@ -1,4 +1,4 @@
1
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ import { Raiko } from '../chunk-BDDC5OJA.js';
2
2
  import '../chunk-4NOVAJBA.js';
3
3
  import '../chunk-SNAWC6GY.js';
4
4
  import '../chunk-Y3YIWI5S.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Raiko } from './chunk-IJNNQKTG.js';
2
- export { Raiko, Router, joinPath } from './chunk-IJNNQKTG.js';
1
+ import { Raiko } from './chunk-BDDC5OJA.js';
2
+ export { Raiko, Router, joinPath } from './chunk-BDDC5OJA.js';
3
3
  export { t, toJsonSchema, validate, validateSync } from './chunk-4NOVAJBA.js';
4
4
  export { sse } from './chunk-SNAWC6GY.js';
5
5
  import './chunk-Y3YIWI5S.js';
@@ -12,12 +12,16 @@ var raiko = (config) => new Raiko(config);
12
12
  var src_default = Raiko;
13
13
  function isMain(url) {
14
14
  const g = globalThis;
15
- const file = decodeURIComponent(new URL(url).pathname);
16
- if (g.Bun) return g.Bun.main === file;
17
- const a = g.process?.argv?.[1];
18
- if (!a) return false;
19
- const strip = (s) => s.replace(/\\/g, "/").replace(/\.(m|c)?(t|j)sx?$/, "");
20
- return strip(file) === strip(a) || strip(file).endsWith("/" + strip(a).replace(/^\.?\//, ""));
15
+ if (g.process?.env?.RAIKO_RUNNER === "1") return false;
16
+ const norm = (s) => {
17
+ const p = decodeURIComponent(s).replace(/\\/g, "/").replace(/^\/([A-Za-z]:)/, "$1").replace(/\.(m|c)?(t|j)sx?$/, "");
18
+ return /^[A-Za-z]:/.test(p) ? p.toLowerCase() : p;
19
+ };
20
+ const file = norm(new URL(url).pathname);
21
+ const main = g.Bun?.main ?? g.process?.argv?.[1];
22
+ if (!main) return false;
23
+ const m = norm(main);
24
+ return m === file || file.endsWith("/" + m.replace(/^\.?\//, ""));
21
25
  }
22
26
 
23
27
  export { src_default as default, isMain, raiko };
@@ -1,4 +1,4 @@
1
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ import { Raiko } from '../chunk-BDDC5OJA.js';
2
2
  import '../chunk-4NOVAJBA.js';
3
3
  import '../chunk-SNAWC6GY.js';
4
4
  import '../chunk-Y3YIWI5S.js';
package/dist/p2p/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ import { Raiko } from '../chunk-BDDC5OJA.js';
2
2
  import '../chunk-4NOVAJBA.js';
3
3
  import '../chunk-SNAWC6GY.js';
4
4
  import '../chunk-Y3YIWI5S.js';
@@ -1,5 +1,5 @@
1
- export { MIME, staticFiles } from '../chunk-H6BWMS4P.js';
2
- import { Raiko } from '../chunk-IJNNQKTG.js';
1
+ export { MIME, staticFiles } from '../chunk-STFJTCVR.js';
2
+ import { Raiko } from '../chunk-BDDC5OJA.js';
3
3
  import { isTSchema, toJsonSchema } from '../chunk-4NOVAJBA.js';
4
4
  import '../chunk-SNAWC6GY.js';
5
5
  import '../chunk-Y3YIWI5S.js';
@@ -94,6 +94,7 @@ async function serve(app, port, opts) {
94
94
  await stop();
95
95
  await app.stop();
96
96
  };
97
+ globalThis.__raikoListening = result.url;
97
98
  opts.onListen?.(result.url);
98
99
  return result;
99
100
  }
@@ -1,5 +1,5 @@
1
- export { MIME, staticFiles } from './chunk-H6BWMS4P.js';
2
- import './chunk-IJNNQKTG.js';
1
+ export { MIME, staticFiles } from './chunk-STFJTCVR.js';
2
+ import './chunk-BDDC5OJA.js';
3
3
  import './chunk-4NOVAJBA.js';
4
4
  import './chunk-SNAWC6GY.js';
5
5
  import './chunk-Y3YIWI5S.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "raiko.js",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "The full stack TypeScript framework: Next.js style app router, server components, typed API, WebSockets with encryption, auth, admin and email. Runs on Bun, Node, Deno, Cloudflare Workers and Vercel.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -128,6 +128,7 @@
128
128
  "LICENSE"
129
129
  ],
130
130
  "scripts": {
131
+ "dev": "bun --watch examples/hello/server.ts",
131
132
  "build": "tsup && tsc -p tsconfig.build.json",
132
133
  "test": "bun test",
133
134
  "test:node": "node test/node/smoke.mjs",
@@ -155,11 +156,8 @@
155
156
  "@types/bun": "1.1.13",
156
157
  "@types/node": "22.9.0",
157
158
  "@types/react": "18.3.12",
158
- "autocannon": "7.15.0",
159
- "elysia": "1.4.30",
160
159
  "fast-check": "3.23.1",
161
160
  "glyphfox": "1.3.0",
162
- "hono": "4.13.14",
163
161
  "marked": "15.0.4",
164
162
  "react": "18.3.1",
165
163
  "terser": "5.36.0",