instaserve 1.1.2 → 1.1.4

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.
Files changed (3) hide show
  1. package/instaserve +20 -10
  2. package/module.mjs +17 -9
  3. package/package.json +1 -1
package/instaserve CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  import chalk from 'chalk'
4
4
  import fs from 'node:fs'
5
+ import path from 'node:path'
6
+ import { pathToFileURL } from 'node:url'
5
7
 
6
8
  console.log(chalk.cyan('\nInstaserve - Instant Web Stack\n'))
7
9
  console.log(chalk.yellow('Usage:'))
@@ -25,9 +27,9 @@ const args = process.argv.slice(2)
25
27
 
26
28
  // Handle generate-routes command
27
29
  if (args[0] === 'generate-routes') {
28
- const routesFile = './routes.js'
30
+ const routesFile = path.resolve(process.cwd(), './routes.js')
29
31
  if (fs.existsSync(routesFile)) {
30
- console.error(chalk.red(`Error: ${routesFile} already exists`))
32
+ console.error(chalk.red(`Error: routes.js already exists`))
31
33
  process.exit(1)
32
34
  }
33
35
 
@@ -62,7 +64,7 @@ if (args[0] === 'generate-routes') {
62
64
  `
63
65
 
64
66
  fs.writeFileSync(routesFile, sampleRoutes)
65
- console.log(chalk.green(`✓ Created ${routesFile}`))
67
+ console.log(chalk.green(`✓ Created routes.js`))
66
68
  process.exit(0)
67
69
  }
68
70
 
@@ -85,34 +87,42 @@ for (let i = 0; i < args.length; i++) {
85
87
 
86
88
  // Load routes file
87
89
  let routes = {}
88
- const routesFile = params.api || './routes.js'
90
+ let routesFilePath = null
91
+ const routesFileParam = params.api || './routes.js'
89
92
  const routesFileSpecified = !!params.api
90
93
 
94
+ // Resolve to absolute path from current working directory
95
+ const routesFile = path.isAbsolute(routesFileParam)
96
+ ? routesFileParam
97
+ : path.resolve(process.cwd(), routesFileParam)
98
+
91
99
  if (routesFileSpecified && !fs.existsSync(routesFile)) {
92
- console.error(chalk.red(`Error: Routes file "${routesFile}" does not exist`))
100
+ console.error(chalk.red(`Error: Routes file "${routesFileParam}" does not exist`))
93
101
  process.exit(1)
94
102
  }
95
103
 
96
104
  if (fs.existsSync(routesFile)) {
97
105
  try {
98
- const imported = await import(routesFile)
106
+ const routesFileURL = pathToFileURL(routesFile).href
107
+ const imported = await import(routesFileURL)
99
108
  routes = imported.default || imported
100
109
 
101
110
  if (!routes || typeof routes !== 'object' || Array.isArray(routes)) {
102
- console.error(chalk.red(`Error: Routes file "${routesFile}" must export a default object`))
111
+ console.error(chalk.red(`Error: Routes file "${routesFileParam}" must export a default object`))
103
112
  process.exit(1)
104
113
  }
105
114
 
106
115
  for (const [key, handler] of Object.entries(routes)) {
107
116
  if (typeof handler !== 'function') {
108
- console.error(chalk.red(`Error: Route "${key}" in "${routesFile}" must be a function`))
117
+ console.error(chalk.red(`Error: Route "${key}" in "${routesFileParam}" must be a function`))
109
118
  process.exit(1)
110
119
  }
111
120
  }
121
+ routesFilePath = routesFile
112
122
  } catch (e) {
113
- console.error(chalk.red(`Error: Could not load routes file "${routesFile}": ${e.message}`))
123
+ console.error(chalk.red(`Error: Could not load routes file "${routesFileParam}": ${e.message}`))
114
124
  process.exit(1)
115
125
  }
116
126
  }
117
127
 
118
- server(routes)
128
+ server(routes, params.port ? parseInt(params.port) : undefined, params.ip, routesFilePath)
package/module.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import http from 'node:http'
2
2
  import https from 'node:https'
3
3
  import fs from 'node:fs'
4
+ import path from 'node:path'
4
5
 
5
6
  const args = process.argv.slice(2)
6
7
  const params = {}
@@ -18,9 +19,9 @@ for (let i = 0; i < args.length; i++) {
18
19
  }
19
20
  }
20
21
 
21
- function public_file(r, s) {
22
+ function public_file(r, s, publicDir) {
22
23
  if (r.url == '/') r.url = '/index.html'
23
- const fn = `${params.public || './public'}${r.url.replace(/\.\./g, '')}`
24
+ const fn = path.resolve(publicDir, r.url.replace(/\.\./g, '').replace(/^\//, ''))
24
25
  if (fs.existsSync(fn)) {
25
26
  const content = fs.readFileSync(fn, 'utf-8')
26
27
  if (fn.match(/.js$/)) {
@@ -34,8 +35,11 @@ function public_file(r, s) {
34
35
  return false // Indicate no file was served
35
36
  }
36
37
 
37
- export default async function (routes, port = params.port || 3000, ip = params.ip || '127.0.0.1') {
38
- const publicDir = params.public || './public'
38
+ export default async function (routes, port = params.port || 3000, ip = params.ip || '127.0.0.1', routesFilePath = null) {
39
+ const publicDirParam = params.public || './public'
40
+ const publicDir = path.isAbsolute(publicDirParam)
41
+ ? publicDirParam
42
+ : path.resolve(process.cwd(), publicDirParam)
39
43
  if (publicDir.includes('..')) {
40
44
  throw new Error('Public directory path cannot contain ".."')
41
45
  }
@@ -73,12 +77,13 @@ export default async function (routes, port = params.port || 3000, ip = params.i
73
77
  if(responseSent || s.writableEnded) return
74
78
 
75
79
  // Try to serve public file
76
- if(public_file(r, s)) {
80
+ if(public_file(r, s, publicDir)) {
77
81
  responseSent = true
78
82
  return
79
83
  }
80
84
 
81
- const url = rrurl.split('/')[1].split('?')[0]
85
+ const urlParts = rrurl.split('/')
86
+ const url = urlParts.length > 1 ? urlParts[1].split('?')[0] : ''
82
87
  if (routes[url]) {
83
88
  const resp = routes[url](r, s, data)
84
89
  if (!responseSent && !s.writableEnded) {
@@ -105,8 +110,8 @@ export default async function (routes, port = params.port || 3000, ip = params.i
105
110
 
106
111
  let server
107
112
  if (params.secure) {
108
- const certPath = './cert.pem'
109
- const keyPath = './key.pem'
113
+ const certPath = path.resolve(process.cwd(), './cert.pem')
114
+ const keyPath = path.resolve(process.cwd(), './key.pem')
110
115
 
111
116
  if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
112
117
  throw new Error('Certificate files not found. Run ./generate-certs.sh first.')
@@ -125,7 +130,10 @@ export default async function (routes, port = params.port || 3000, ip = params.i
125
130
  server.listen(port || 3000, ip || '')
126
131
 
127
132
  const protocol = params.secure ? 'https' : 'http'
128
- console.log(`started on: ${protocol}://${(process.env.ip || ip)}:${(process.env.port || port)}, public: ${publicDir}, ${Object.keys(routes).length > 0 ? `using routes: ${Object.keys(routes)}` : 'not using routes'}`)
133
+ const routesInfo = Object.keys(routes).length > 0
134
+ ? (routesFilePath ? `using routes: ${Object.keys(routes)} (${routesFilePath})` : `using routes: ${Object.keys(routes)}`)
135
+ : 'not using routes'
136
+ console.log(`started on: ${protocol}://${(process.env.ip || ip)}:${(process.env.port || port)}, public: ${publicDir}, ${routesInfo}`)
129
137
 
130
138
  return {
131
139
  routes: routes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instaserve",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Instant web stack",
5
5
  "main": "module.mjs",
6
6
  "bin": "./instaserve",