speexjs 0.2.0 → 0.2.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/README.md +43 -43
- package/dist/cli/index.js +48 -48
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/server/auth/index.js +1 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/index.js +2 -2
- package/dist/server/middleware/index.js.map +1 -1
- package/package.json +135 -137
|
@@ -100,8 +100,8 @@ function bodyParser() {
|
|
|
100
100
|
}
|
|
101
101
|
function session(options) {
|
|
102
102
|
const opts = {
|
|
103
|
-
name: "
|
|
104
|
-
secret: "
|
|
103
|
+
name: "speexjs_session",
|
|
104
|
+
secret: "speexjs-secret-change-in-production",
|
|
105
105
|
maxAge: 7200,
|
|
106
106
|
httpOnly: true,
|
|
107
107
|
secure: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/middleware/index.ts","../../../src/server/http/status.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createReadStream, existsSync, statSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { createGzip } from \"node:zlib\";\nimport { HttpStatus } from \"../http/status\";\nimport type { RouteContext } from \"../router\";\n\nexport type Middleware = (\n\tctx: RouteContext,\n\tnext: () => Promise<void>,\n) => void | Promise<void>;\n\nexport interface CorsOptions {\n\torigin?: string | string[];\n\tmethods?: string[];\n\tallowedHeaders?: string[];\n\texposedHeaders?: string[];\n\tcredentials?: boolean;\n\tmaxAge?: number;\n}\n\nexport function cors(options?: CorsOptions): Middleware {\n\tconst opts: Required<CorsOptions> = {\n\t\torigin: \"*\",\n\t\tmethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n\t\tallowedHeaders: [\"Content-Type\", \"Authorization\"],\n\t\texposedHeaders: [],\n\t\tcredentials: false,\n\t\tmaxAge: 86400,\n\t\t...options,\n\t};\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst origin = request.headers.get(\"origin\");\n\n\t\tif (origin !== undefined) {\n\t\t\tif (opts.origin === \"*\") {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", \"*\");\n\t\t\t} else if (typeof opts.origin === \"string\") {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", opts.origin);\n\t\t\t} else if (opts.origin.includes(origin)) {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", origin);\n\t\t\t}\n\n\t\t\tif (opts.credentials) {\n\t\t\t\tresponse.header(\"access-control-allow-credentials\", \"true\");\n\t\t\t}\n\n\t\t\tif (opts.exposedHeaders.length > 0) {\n\t\t\t\tresponse.header(\n\t\t\t\t\t\"access-control-expose-headers\",\n\t\t\t\t\topts.exposedHeaders.join(\", \"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (request.method === \"OPTIONS\") {\n\t\t\tresponse.header(\"access-control-allow-methods\", opts.methods.join(\", \"));\n\t\t\tresponse.header(\n\t\t\t\t\"access-control-allow-headers\",\n\t\t\t\topts.allowedHeaders.join(\", \"),\n\t\t\t);\n\t\t\tresponse.header(\"access-control-max-age\", String(opts.maxAge));\n\t\t\tresponse.status(HttpStatus.NO_CONTENT);\n\t\t\treturn;\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function bodyParser(): Middleware {\n\treturn async (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request } = ctx;\n\t\tconst method = request.method;\n\n\t\tif ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(method)) {\n\t\t\tawait request.body();\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport interface SessionOptions {\n\tname?: string;\n\tsecret?: string;\n\tmaxAge?: number;\n\thttpOnly?: boolean;\n\tsecure?: boolean;\n\tsameSite?: \"strict\" | \"lax\" | \"none\";\n}\n\nexport function session(options?: SessionOptions): Middleware {\n\tconst opts = {\n\t\tname: \"speedx_session\",\n\t\tsecret: \"speedx-secret-change-in-production\",\n\t\tmaxAge: 7200,\n\t\thttpOnly: true,\n\t\tsecure: false,\n\t\tsameSite: \"lax\" as const,\n\t\t...options,\n\t};\n\n\tconst sessions = new Map<string, Record<string, unknown>>();\n\n\tfunction generateSessionId(): string {\n\t\treturn randomUUID();\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst sessionId = request.cookie(opts.name) ?? generateSessionId();\n\t\tconst id = sessionId;\n\n\t\tif (!sessions.has(id)) {\n\t\t\tsessions.set(id, {});\n\t\t}\n\t\tconst sessionData = sessions.get(id) as Record<string, unknown>;\n\n\t\t(ctx as unknown as Record<string, unknown>).session = sessionData;\n\n\t\tif (request.cookie(opts.name) === undefined) {\n\t\t\tresponse.cookie(opts.name, id, {\n\t\t\t\tmaxAge: opts.maxAge,\n\t\t\t\thttpOnly: opts.httpOnly,\n\t\t\t\tsecure: opts.secure,\n\t\t\t\tsameSite: opts.sameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t});\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function auth(guard?: string): Middleware {\n\tconst guardName = guard ?? \"default\";\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst user = ctx.container.resolve(`auth.${guardName}`);\n\n\t\tif (user === undefined || user === null) {\n\t\t\tif (ctx.request.wantsJson()) {\n\t\t\t\tctx.response.status(HttpStatus.UNAUTHORIZED).json({\n\t\t\t\t\terror: \"Unauthenticated\",\n\t\t\t\t\tmessage: \"Authentication is required to access this resource\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tctx.response.redirect(\"/login\", HttpStatus.FOUND as 302);\n\t\t\treturn;\n\t\t}\n\n\t\t(ctx as unknown as Record<string, unknown>).user = user;\n\n\t\treturn next();\n\t};\n}\n\nexport function throttle(limit?: number, window?: number): Middleware {\n\tconst maxRequests = limit ?? 60;\n\tconst timeWindow = (window ?? 60) * 1000;\n\tconst hits = new Map<string, { count: number; resetAt: number }>();\n\n\tconst cleanup = setInterval(() => {\n\t\tconst now = Date.now();\n\t\tfor (const [key, value] of hits) {\n\t\t\tif (value.resetAt < now) {\n\t\t\t\thits.delete(key);\n\t\t\t}\n\t\t}\n\t}, 60000);\n\n\tif (cleanup.unref !== undefined) {\n\t\tcleanup.unref();\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst key = ctx.request.ip;\n\n\t\tconst now = Date.now();\n\t\tconst hit = hits.get(key);\n\n\t\tif (hit === undefined || hit.resetAt < now) {\n\t\t\thits.set(key, { count: 1, resetAt: now + timeWindow });\n\t\t\tctx.response.header(\"x-ratelimit-limit\", String(maxRequests));\n\t\t\tctx.response.header(\"x-ratelimit-remaining\", String(maxRequests - 1));\n\t\t\treturn next();\n\t\t}\n\n\t\thit.count++;\n\t\tconst remaining = Math.max(0, maxRequests - hit.count);\n\t\tctx.response.header(\"x-ratelimit-limit\", String(maxRequests));\n\t\tctx.response.header(\"x-ratelimit-remaining\", String(remaining));\n\n\t\tif (hit.count > maxRequests) {\n\t\t\tconst retryAfter = Math.ceil((hit.resetAt - now) / 1000);\n\t\t\tctx.response.header(\"retry-after\", String(retryAfter));\n\t\t\tctx.response.status(HttpStatus.TOO_MANY_REQUESTS).json({\n\t\t\t\terror: \"Too Many Requests\",\n\t\t\t\tmessage: `Rate limit exceeded. Try again in ${retryAfter} seconds.`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function logger(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst start = Date.now();\n\t\tconst { method, path, ip } = ctx.request;\n\n\t\tconst result = next();\n\n\t\tif (result instanceof Promise) {\n\t\t\treturn result.then(() => {\n\t\t\t\tconst duration = Date.now() - start;\n\t\t\t\tconst status = ctx.response.statusCode;\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[${new Date().toISOString()}] ${method} ${path} ${status} ${duration}ms - ${ip}`,\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\n\t\tconst duration = Date.now() - start;\n\t\tconst status = ctx.response.statusCode;\n\t\tconsole.log(\n\t\t\t`[${new Date().toISOString()}] ${method} ${path} ${status} ${duration}ms - ${ip}`,\n\t\t);\n\t};\n}\n\nexport interface StaticOptions {\n\tmaxAge?: number;\n\tindex?: string;\n\tdotfiles?: \"allow\" | \"deny\";\n\textensions?: string[];\n}\n\nexport function staticFiles(root: string, options?: StaticOptions): Middleware {\n\tconst opts = {\n\t\tmaxAge: 0,\n\t\tindex: \"index.html\",\n\t\tdotfiles: \"deny\" as const,\n\t\textensions: [] as string[],\n\t\t...options,\n\t};\n\n\tconst MIME_TYPES: Record<string, string> = {\n\t\t\".html\": \"text/html\",\n\t\t\".css\": \"text/css\",\n\t\t\".js\": \"application/javascript\",\n\t\t\".json\": \"application/json\",\n\t\t\".png\": \"image/png\",\n\t\t\".jpg\": \"image/jpeg\",\n\t\t\".jpeg\": \"image/jpeg\",\n\t\t\".gif\": \"image/gif\",\n\t\t\".svg\": \"image/svg+xml\",\n\t\t\".webp\": \"image/webp\",\n\t\t\".ico\": \"image/x-icon\",\n\t\t\".txt\": \"text/plain\",\n\t\t\".pdf\": \"application/pdf\",\n\t\t\".woff\": \"font/woff\",\n\t\t\".woff2\": \"font/woff2\",\n\t\t\".ttf\": \"font/ttf\",\n\t};\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst filePath = request.path;\n\n\t\tif (opts.dotfiles === \"deny\") {\n\t\t\tconst segments = filePath.split(\"/\");\n\t\t\tfor (const segment of segments) {\n\t\t\t\tif (segment.startsWith(\".\")) {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet fullPath = join(root, filePath);\n\n\t\tif (!existsSync(fullPath)) {\n\t\t\tlet found = false;\n\t\t\tfor (const ext of opts.extensions) {\n\t\t\t\tconst tryPath = fullPath + ext;\n\t\t\t\tif (existsSync(tryPath)) {\n\t\t\t\t\tfullPath = tryPath;\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) return next();\n\t\t}\n\n\t\tconst stats = statSync(fullPath);\n\t\tif (!stats.isFile()) {\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\tconst indexPath = join(fullPath, opts.index);\n\t\t\t\tif (existsSync(indexPath) && statSync(indexPath).isFile()) {\n\t\t\t\t\tfullPath = indexPath;\n\t\t\t\t} else {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn next();\n\t\t\t}\n\t\t}\n\n\t\tconst ext = extname(fullPath);\n\t\tconst mimeType = MIME_TYPES[ext] ?? \"application/octet-stream\";\n\n\t\tresponse\n\t\t\t.header(\"content-type\", mimeType)\n\t\t\t.header(\"content-length\", String(stats.size))\n\t\t\t.header(\"cache-control\", `public, max-age=${opts.maxAge}`)\n\t\t\t.header(\"last-modified\", stats.mtime.toUTCString());\n\n\t\tconst readStream = createReadStream(fullPath);\n\t\treadStream.pipe(response.rawResponse);\n\t\tresponse.rawResponse.statusCode = HttpStatus.OK;\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\treadStream.on(\"end\", () => resolve());\n\t\t\treadStream.on(\"error\", (err: Error) => reject(err));\n\t\t});\n\t};\n}\n\nexport function csrf(): Middleware {\n\tconst tokens = new Set<string>();\n\n\tfunction generateToken(): string {\n\t\treturn randomUUID();\n\t}\n\n\tfunction skipCsrf(method: string): boolean {\n\t\treturn [\"GET\", \"HEAD\", \"OPTIONS\"].includes(method.toUpperCase());\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\n\t\tif (request.path === \"/csrf-token\") {\n\t\t\tconst token = generateToken();\n\t\t\ttokens.add(token);\n\t\t\tresponse.json({ token });\n\t\t\treturn;\n\t\t}\n\n\t\tif (skipCsrf(request.method)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst token =\n\t\t\trequest.headers.get(\"x-csrf-token\") ??\n\t\t\trequest.headers.get(\"x-xsrf-token\");\n\n\t\tif (token === undefined || !tokens.has(token)) {\n\t\t\tresponse.status(HttpStatus.FORBIDDEN).json({\n\t\t\t\terror: \"CSRF token mismatch\",\n\t\t\t\tmessage: \"Invalid or missing CSRF token\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\ttokens.delete(token);\n\n\t\treturn next();\n\t};\n}\n\nexport function compress(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request } = ctx;\n\t\tconst acceptEncoding = request.headers.get(\"accept-encoding\") ?? \"\";\n\n\t\tif (acceptEncoding.includes(\"gzip\")) {\n\t\t\treturn compressWith(ctx, next, \"gzip\");\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nfunction compressWith(\n\tctx: RouteContext,\n\tnext: () => Promise<void>,\n\t_encoding: string,\n): Promise<void> {\n\tconst originalEnd = ctx.response.rawResponse.end.bind(\n\t\tctx.response.rawResponse,\n\t);\n\n\tconst chunks: Buffer[] = [];\n\n\tctx.response.rawResponse.write = ((chunk: unknown) => {\n\t\tif (Buffer.isBuffer(chunk) || typeof chunk === \"string\") {\n\t\t\tchunks.push(Buffer.from(chunk));\n\t\t}\n\t\treturn true;\n\t}) as typeof ctx.response.rawResponse.write;\n\n\tctx.response.rawResponse.end = ((chunk?: unknown, ...args: any[]) => {\n\t\tif (chunk !== undefined && chunk !== null) {\n\t\t\tif (Buffer.isBuffer(chunk) || typeof chunk === \"string\") {\n\t\t\t\tchunks.push(Buffer.from(chunk));\n\t\t\t}\n\t\t}\n\n\t\tctx.response.header(\"content-encoding\", \"gzip\");\n\n\t\tconst gzip = createGzip();\n\t\tconst combined = Buffer.concat(chunks);\n\t\tconst compressed = gzip.end(combined) as unknown as Buffer;\n\n\t\tctx.response.header(\"content-length\", String(compressed.length));\n\t\toriginalEnd(compressed, ...args);\n\t\treturn ctx.response.rawResponse;\n\t}) as typeof ctx.response.rawResponse.end;\n\n\treturn next();\n}\n\nexport function helmet(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { response } = ctx;\n\n\t\tresponse\n\t\t\t.header(\"x-content-type-options\", \"nosniff\")\n\t\t\t.header(\"x-frame-options\", \"SAMEORIGIN\")\n\t\t\t.header(\"x-xss-protection\", \"1; mode=block\")\n\t\t\t.header(\n\t\t\t\t\"strict-transport-security\",\n\t\t\t\t\"max-age=15552000; includeSubDomains\",\n\t\t\t)\n\t\t\t.header(\"referrer-policy\", \"no-referrer-when-downgrade\")\n\t\t\t.header(\n\t\t\t\t\"content-security-policy\",\n\t\t\t\t\"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'\",\n\t\t\t)\n\t\t\t.header(\"permissions-policy\", \"camera=(), microphone=(), geolocation=()\");\n\n\t\treturn next();\n\t};\n}\n\nexport class MiddlewarePipeline {\n\tprivate middlewares: Middleware[] = [];\n\n\tuse(middleware: Middleware): this {\n\t\tthis.middlewares.push(middleware);\n\t\treturn this;\n\t}\n\n\tprepend(middleware: Middleware): this {\n\t\tthis.middlewares.unshift(middleware);\n\t\treturn this;\n\t}\n\n\tremove(name: string): void {\n\t\tthis.middlewares = this.middlewares.filter((mw) => mw.name !== name);\n\t}\n\n\tasync run(ctx: RouteContext, final: () => Promise<void>): Promise<void> {\n\t\tlet index = 0;\n\n\t\tconst next = async (): Promise<void> => {\n\t\t\tif (index >= this.middlewares.length) {\n\t\t\t\tawait final();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst middleware = this.middlewares[index] as Middleware;\n\t\t\tindex++;\n\t\t\tawait middleware(ctx, next);\n\t\t};\n\n\t\tawait next();\n\t}\n\n\tgetMiddlewares(): Middleware[] {\n\t\treturn [...this.middlewares];\n\t}\n}\n","export const HttpStatus = {\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n RESET_CONTENT: 205,\n PARTIAL_CONTENT: 206,\n\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n SEE_OTHER: 303,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n REQUEST_TIMEOUT: 408,\n CONFLICT: 409,\n GONE: 410,\n LENGTH_REQUIRED: 411,\n PRECONDITION_FAILED: 412,\n PAYLOAD_TOO_LARGE: 413,\n URI_TOO_LONG: 414,\n UNSUPPORTED_MEDIA_TYPE: 415,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n} as const\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus]\n\nconst statusTextMap: Record<number, string> = {\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n}\n\nexport function statusText(code: number): string {\n const text = statusTextMap[code]\n if (text !== undefined) return text\n if (code >= 100 && code < 200) return 'Informational'\n if (code >= 200 && code < 300) return 'Success'\n if (code >= 300 && code < 400) return 'Redirection'\n if (code >= 400 && code < 500) return 'Client Error'\n if (code >= 500 && code < 600) return 'Server Error'\n return 'Unknown'\n}\n"],"mappings":"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","names":["duration","status","ext","token"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/middleware/index.ts","../../../src/server/http/status.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createReadStream, existsSync, statSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { createGzip } from \"node:zlib\";\nimport { HttpStatus } from \"../http/status\";\nimport type { RouteContext } from \"../router\";\n\nexport type Middleware = (\n\tctx: RouteContext,\n\tnext: () => Promise<void>,\n) => void | Promise<void>;\n\nexport interface CorsOptions {\n\torigin?: string | string[];\n\tmethods?: string[];\n\tallowedHeaders?: string[];\n\texposedHeaders?: string[];\n\tcredentials?: boolean;\n\tmaxAge?: number;\n}\n\nexport function cors(options?: CorsOptions): Middleware {\n\tconst opts: Required<CorsOptions> = {\n\t\torigin: \"*\",\n\t\tmethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n\t\tallowedHeaders: [\"Content-Type\", \"Authorization\"],\n\t\texposedHeaders: [],\n\t\tcredentials: false,\n\t\tmaxAge: 86400,\n\t\t...options,\n\t};\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst origin = request.headers.get(\"origin\");\n\n\t\tif (origin !== undefined) {\n\t\t\tif (opts.origin === \"*\") {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", \"*\");\n\t\t\t} else if (typeof opts.origin === \"string\") {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", opts.origin);\n\t\t\t} else if (opts.origin.includes(origin)) {\n\t\t\t\tresponse.header(\"access-control-allow-origin\", origin);\n\t\t\t}\n\n\t\t\tif (opts.credentials) {\n\t\t\t\tresponse.header(\"access-control-allow-credentials\", \"true\");\n\t\t\t}\n\n\t\t\tif (opts.exposedHeaders.length > 0) {\n\t\t\t\tresponse.header(\n\t\t\t\t\t\"access-control-expose-headers\",\n\t\t\t\t\topts.exposedHeaders.join(\", \"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (request.method === \"OPTIONS\") {\n\t\t\tresponse.header(\"access-control-allow-methods\", opts.methods.join(\", \"));\n\t\t\tresponse.header(\n\t\t\t\t\"access-control-allow-headers\",\n\t\t\t\topts.allowedHeaders.join(\", \"),\n\t\t\t);\n\t\t\tresponse.header(\"access-control-max-age\", String(opts.maxAge));\n\t\t\tresponse.status(HttpStatus.NO_CONTENT);\n\t\t\treturn;\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function bodyParser(): Middleware {\n\treturn async (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request } = ctx;\n\t\tconst method = request.method;\n\n\t\tif ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(method)) {\n\t\t\tawait request.body();\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport interface SessionOptions {\n\tname?: string;\n\tsecret?: string;\n\tmaxAge?: number;\n\thttpOnly?: boolean;\n\tsecure?: boolean;\n\tsameSite?: \"strict\" | \"lax\" | \"none\";\n}\n\nexport function session(options?: SessionOptions): Middleware {\n\tconst opts = {\n\t\tname: \"speexjs_session\",\n\t\tsecret: \"speexjs-secret-change-in-production\",\n\t\tmaxAge: 7200,\n\t\thttpOnly: true,\n\t\tsecure: false,\n\t\tsameSite: \"lax\" as const,\n\t\t...options,\n\t};\n\n\tconst sessions = new Map<string, Record<string, unknown>>();\n\n\tfunction generateSessionId(): string {\n\t\treturn randomUUID();\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst sessionId = request.cookie(opts.name) ?? generateSessionId();\n\t\tconst id = sessionId;\n\n\t\tif (!sessions.has(id)) {\n\t\t\tsessions.set(id, {});\n\t\t}\n\t\tconst sessionData = sessions.get(id) as Record<string, unknown>;\n\n\t\t(ctx as unknown as Record<string, unknown>).session = sessionData;\n\n\t\tif (request.cookie(opts.name) === undefined) {\n\t\t\tresponse.cookie(opts.name, id, {\n\t\t\t\tmaxAge: opts.maxAge,\n\t\t\t\thttpOnly: opts.httpOnly,\n\t\t\t\tsecure: opts.secure,\n\t\t\t\tsameSite: opts.sameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t});\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function auth(guard?: string): Middleware {\n\tconst guardName = guard ?? \"default\";\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst user = ctx.container.resolve(`auth.${guardName}`);\n\n\t\tif (user === undefined || user === null) {\n\t\t\tif (ctx.request.wantsJson()) {\n\t\t\t\tctx.response.status(HttpStatus.UNAUTHORIZED).json({\n\t\t\t\t\terror: \"Unauthenticated\",\n\t\t\t\t\tmessage: \"Authentication is required to access this resource\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tctx.response.redirect(\"/login\", HttpStatus.FOUND as 302);\n\t\t\treturn;\n\t\t}\n\n\t\t(ctx as unknown as Record<string, unknown>).user = user;\n\n\t\treturn next();\n\t};\n}\n\nexport function throttle(limit?: number, window?: number): Middleware {\n\tconst maxRequests = limit ?? 60;\n\tconst timeWindow = (window ?? 60) * 1000;\n\tconst hits = new Map<string, { count: number; resetAt: number }>();\n\n\tconst cleanup = setInterval(() => {\n\t\tconst now = Date.now();\n\t\tfor (const [key, value] of hits) {\n\t\t\tif (value.resetAt < now) {\n\t\t\t\thits.delete(key);\n\t\t\t}\n\t\t}\n\t}, 60000);\n\n\tif (cleanup.unref !== undefined) {\n\t\tcleanup.unref();\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst key = ctx.request.ip;\n\n\t\tconst now = Date.now();\n\t\tconst hit = hits.get(key);\n\n\t\tif (hit === undefined || hit.resetAt < now) {\n\t\t\thits.set(key, { count: 1, resetAt: now + timeWindow });\n\t\t\tctx.response.header(\"x-ratelimit-limit\", String(maxRequests));\n\t\t\tctx.response.header(\"x-ratelimit-remaining\", String(maxRequests - 1));\n\t\t\treturn next();\n\t\t}\n\n\t\thit.count++;\n\t\tconst remaining = Math.max(0, maxRequests - hit.count);\n\t\tctx.response.header(\"x-ratelimit-limit\", String(maxRequests));\n\t\tctx.response.header(\"x-ratelimit-remaining\", String(remaining));\n\n\t\tif (hit.count > maxRequests) {\n\t\t\tconst retryAfter = Math.ceil((hit.resetAt - now) / 1000);\n\t\t\tctx.response.header(\"retry-after\", String(retryAfter));\n\t\t\tctx.response.status(HttpStatus.TOO_MANY_REQUESTS).json({\n\t\t\t\terror: \"Too Many Requests\",\n\t\t\t\tmessage: `Rate limit exceeded. Try again in ${retryAfter} seconds.`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nexport function logger(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst start = Date.now();\n\t\tconst { method, path, ip } = ctx.request;\n\n\t\tconst result = next();\n\n\t\tif (result instanceof Promise) {\n\t\t\treturn result.then(() => {\n\t\t\t\tconst duration = Date.now() - start;\n\t\t\t\tconst status = ctx.response.statusCode;\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[${new Date().toISOString()}] ${method} ${path} ${status} ${duration}ms - ${ip}`,\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\n\t\tconst duration = Date.now() - start;\n\t\tconst status = ctx.response.statusCode;\n\t\tconsole.log(\n\t\t\t`[${new Date().toISOString()}] ${method} ${path} ${status} ${duration}ms - ${ip}`,\n\t\t);\n\t};\n}\n\nexport interface StaticOptions {\n\tmaxAge?: number;\n\tindex?: string;\n\tdotfiles?: \"allow\" | \"deny\";\n\textensions?: string[];\n}\n\nexport function staticFiles(root: string, options?: StaticOptions): Middleware {\n\tconst opts = {\n\t\tmaxAge: 0,\n\t\tindex: \"index.html\",\n\t\tdotfiles: \"deny\" as const,\n\t\textensions: [] as string[],\n\t\t...options,\n\t};\n\n\tconst MIME_TYPES: Record<string, string> = {\n\t\t\".html\": \"text/html\",\n\t\t\".css\": \"text/css\",\n\t\t\".js\": \"application/javascript\",\n\t\t\".json\": \"application/json\",\n\t\t\".png\": \"image/png\",\n\t\t\".jpg\": \"image/jpeg\",\n\t\t\".jpeg\": \"image/jpeg\",\n\t\t\".gif\": \"image/gif\",\n\t\t\".svg\": \"image/svg+xml\",\n\t\t\".webp\": \"image/webp\",\n\t\t\".ico\": \"image/x-icon\",\n\t\t\".txt\": \"text/plain\",\n\t\t\".pdf\": \"application/pdf\",\n\t\t\".woff\": \"font/woff\",\n\t\t\".woff2\": \"font/woff2\",\n\t\t\".ttf\": \"font/ttf\",\n\t};\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\t\tconst filePath = request.path;\n\n\t\tif (opts.dotfiles === \"deny\") {\n\t\t\tconst segments = filePath.split(\"/\");\n\t\t\tfor (const segment of segments) {\n\t\t\t\tif (segment.startsWith(\".\")) {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet fullPath = join(root, filePath);\n\n\t\tif (!existsSync(fullPath)) {\n\t\t\tlet found = false;\n\t\t\tfor (const ext of opts.extensions) {\n\t\t\t\tconst tryPath = fullPath + ext;\n\t\t\t\tif (existsSync(tryPath)) {\n\t\t\t\t\tfullPath = tryPath;\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) return next();\n\t\t}\n\n\t\tconst stats = statSync(fullPath);\n\t\tif (!stats.isFile()) {\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\tconst indexPath = join(fullPath, opts.index);\n\t\t\t\tif (existsSync(indexPath) && statSync(indexPath).isFile()) {\n\t\t\t\t\tfullPath = indexPath;\n\t\t\t\t} else {\n\t\t\t\t\treturn next();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn next();\n\t\t\t}\n\t\t}\n\n\t\tconst ext = extname(fullPath);\n\t\tconst mimeType = MIME_TYPES[ext] ?? \"application/octet-stream\";\n\n\t\tresponse\n\t\t\t.header(\"content-type\", mimeType)\n\t\t\t.header(\"content-length\", String(stats.size))\n\t\t\t.header(\"cache-control\", `public, max-age=${opts.maxAge}`)\n\t\t\t.header(\"last-modified\", stats.mtime.toUTCString());\n\n\t\tconst readStream = createReadStream(fullPath);\n\t\treadStream.pipe(response.rawResponse);\n\t\tresponse.rawResponse.statusCode = HttpStatus.OK;\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\treadStream.on(\"end\", () => resolve());\n\t\t\treadStream.on(\"error\", (err: Error) => reject(err));\n\t\t});\n\t};\n}\n\nexport function csrf(): Middleware {\n\tconst tokens = new Set<string>();\n\n\tfunction generateToken(): string {\n\t\treturn randomUUID();\n\t}\n\n\tfunction skipCsrf(method: string): boolean {\n\t\treturn [\"GET\", \"HEAD\", \"OPTIONS\"].includes(method.toUpperCase());\n\t}\n\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request, response } = ctx;\n\n\t\tif (request.path === \"/csrf-token\") {\n\t\t\tconst token = generateToken();\n\t\t\ttokens.add(token);\n\t\t\tresponse.json({ token });\n\t\t\treturn;\n\t\t}\n\n\t\tif (skipCsrf(request.method)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst token =\n\t\t\trequest.headers.get(\"x-csrf-token\") ??\n\t\t\trequest.headers.get(\"x-xsrf-token\");\n\n\t\tif (token === undefined || !tokens.has(token)) {\n\t\t\tresponse.status(HttpStatus.FORBIDDEN).json({\n\t\t\t\terror: \"CSRF token mismatch\",\n\t\t\t\tmessage: \"Invalid or missing CSRF token\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\ttokens.delete(token);\n\n\t\treturn next();\n\t};\n}\n\nexport function compress(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { request } = ctx;\n\t\tconst acceptEncoding = request.headers.get(\"accept-encoding\") ?? \"\";\n\n\t\tif (acceptEncoding.includes(\"gzip\")) {\n\t\t\treturn compressWith(ctx, next, \"gzip\");\n\t\t}\n\n\t\treturn next();\n\t};\n}\n\nfunction compressWith(\n\tctx: RouteContext,\n\tnext: () => Promise<void>,\n\t_encoding: string,\n): Promise<void> {\n\tconst originalEnd = ctx.response.rawResponse.end.bind(\n\t\tctx.response.rawResponse,\n\t);\n\n\tconst chunks: Buffer[] = [];\n\n\tctx.response.rawResponse.write = ((chunk: unknown) => {\n\t\tif (Buffer.isBuffer(chunk) || typeof chunk === \"string\") {\n\t\t\tchunks.push(Buffer.from(chunk));\n\t\t}\n\t\treturn true;\n\t}) as typeof ctx.response.rawResponse.write;\n\n\tctx.response.rawResponse.end = ((chunk?: unknown, ...args: any[]) => {\n\t\tif (chunk !== undefined && chunk !== null) {\n\t\t\tif (Buffer.isBuffer(chunk) || typeof chunk === \"string\") {\n\t\t\t\tchunks.push(Buffer.from(chunk));\n\t\t\t}\n\t\t}\n\n\t\tctx.response.header(\"content-encoding\", \"gzip\");\n\n\t\tconst gzip = createGzip();\n\t\tconst combined = Buffer.concat(chunks);\n\t\tconst compressed = gzip.end(combined) as unknown as Buffer;\n\n\t\tctx.response.header(\"content-length\", String(compressed.length));\n\t\toriginalEnd(compressed, ...args);\n\t\treturn ctx.response.rawResponse;\n\t}) as typeof ctx.response.rawResponse.end;\n\n\treturn next();\n}\n\nexport function helmet(): Middleware {\n\treturn (ctx: RouteContext, next: () => Promise<void>) => {\n\t\tconst { response } = ctx;\n\n\t\tresponse\n\t\t\t.header(\"x-content-type-options\", \"nosniff\")\n\t\t\t.header(\"x-frame-options\", \"SAMEORIGIN\")\n\t\t\t.header(\"x-xss-protection\", \"1; mode=block\")\n\t\t\t.header(\n\t\t\t\t\"strict-transport-security\",\n\t\t\t\t\"max-age=15552000; includeSubDomains\",\n\t\t\t)\n\t\t\t.header(\"referrer-policy\", \"no-referrer-when-downgrade\")\n\t\t\t.header(\n\t\t\t\t\"content-security-policy\",\n\t\t\t\t\"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'\",\n\t\t\t)\n\t\t\t.header(\"permissions-policy\", \"camera=(), microphone=(), geolocation=()\");\n\n\t\treturn next();\n\t};\n}\n\nexport class MiddlewarePipeline {\n\tprivate middlewares: Middleware[] = [];\n\n\tuse(middleware: Middleware): this {\n\t\tthis.middlewares.push(middleware);\n\t\treturn this;\n\t}\n\n\tprepend(middleware: Middleware): this {\n\t\tthis.middlewares.unshift(middleware);\n\t\treturn this;\n\t}\n\n\tremove(name: string): void {\n\t\tthis.middlewares = this.middlewares.filter((mw) => mw.name !== name);\n\t}\n\n\tasync run(ctx: RouteContext, final: () => Promise<void>): Promise<void> {\n\t\tlet index = 0;\n\n\t\tconst next = async (): Promise<void> => {\n\t\t\tif (index >= this.middlewares.length) {\n\t\t\t\tawait final();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst middleware = this.middlewares[index] as Middleware;\n\t\t\tindex++;\n\t\t\tawait middleware(ctx, next);\n\t\t};\n\n\t\tawait next();\n\t}\n\n\tgetMiddlewares(): Middleware[] {\n\t\treturn [...this.middlewares];\n\t}\n}\n","export const HttpStatus = {\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n RESET_CONTENT: 205,\n PARTIAL_CONTENT: 206,\n\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n SEE_OTHER: 303,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n REQUEST_TIMEOUT: 408,\n CONFLICT: 409,\n GONE: 410,\n LENGTH_REQUIRED: 411,\n PRECONDITION_FAILED: 412,\n PAYLOAD_TOO_LARGE: 413,\n URI_TOO_LONG: 414,\n UNSUPPORTED_MEDIA_TYPE: 415,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n} as const\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus]\n\nconst statusTextMap: Record<number, string> = {\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n}\n\nexport function statusText(code: number): string {\n const text = statusTextMap[code]\n if (text !== undefined) return text\n if (code >= 100 && code < 200) return 'Informational'\n if (code >= 200 && code < 300) return 'Success'\n if (code >= 300 && code < 400) return 'Redirection'\n if (code >= 400 && code < 500) return 'Client Error'\n if (code >= 500 && code < 600) return 'Server Error'\n return 'Unknown'\n}\n"],"mappings":"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","names":["duration","status","ext","token"]}
|
package/package.json
CHANGED
|
@@ -1,138 +1,136 @@
|
|
|
1
|
-
|
|
2
|
-
"name":
|
|
3
|
-
"version":
|
|
4
|
-
"description":
|
|
5
|
-
"type":
|
|
6
|
-
"main":
|
|
7
|
-
"module":
|
|
8
|
-
"types":
|
|
9
|
-
"bin":
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"exports":
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"sideEffects":
|
|
91
|
-
"files":
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"scripts":
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"dependencies":
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"node": "\u003e=18.0.0"
|
|
137
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "speexjs",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Fullstack JavaScript/TypeScript framework  Server, Client, RPC, Schema, CLI, Database, Auth, Cache, Storage. Zero dependencies. 🇮🇩 Indonesia First.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"speexjs": "dist/cli/index.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./server": {
|
|
18
|
+
"import": "./dist/server/index.js",
|
|
19
|
+
"types": "./dist/server/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./server/http": {
|
|
22
|
+
"import": "./dist/server/http/index.js",
|
|
23
|
+
"types": "./dist/server/http/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./server/router": {
|
|
26
|
+
"import": "./dist/server/router/index.js",
|
|
27
|
+
"types": "./dist/server/router/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./server/middleware": {
|
|
30
|
+
"import": "./dist/server/middleware/index.js",
|
|
31
|
+
"types": "./dist/server/middleware/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./server/controller": {
|
|
34
|
+
"import": "./dist/server/controller/index.js",
|
|
35
|
+
"types": "./dist/server/controller/index.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./server/container": {
|
|
38
|
+
"import": "./dist/server/container/index.js",
|
|
39
|
+
"types": "./dist/server/container/index.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./server/auth": {
|
|
42
|
+
"import": "./dist/server/auth/index.js",
|
|
43
|
+
"types": "./dist/server/auth/index.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./server/gate": {
|
|
46
|
+
"import": "./dist/server/gate/index.js",
|
|
47
|
+
"types": "./dist/server/gate/index.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./server/cache": {
|
|
50
|
+
"import": "./dist/server/cache/index.js",
|
|
51
|
+
"types": "./dist/server/cache/index.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"./server/storage": {
|
|
54
|
+
"import": "./dist/server/storage/index.js",
|
|
55
|
+
"types": "./dist/server/storage/index.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"./server/events": {
|
|
58
|
+
"import": "./dist/server/events/index.js",
|
|
59
|
+
"types": "./dist/server/events/index.d.ts"
|
|
60
|
+
},
|
|
61
|
+
"./server/database": {
|
|
62
|
+
"import": "./dist/server/database/index.js",
|
|
63
|
+
"types": "./dist/server/database/index.d.ts"
|
|
64
|
+
},
|
|
65
|
+
"./client": {
|
|
66
|
+
"import": "./dist/client/index.js",
|
|
67
|
+
"types": "./dist/client/index.d.ts"
|
|
68
|
+
},
|
|
69
|
+
"./client/signals": {
|
|
70
|
+
"import": "./dist/client/signals/index.js",
|
|
71
|
+
"types": "./dist/client/signals/index.d.ts"
|
|
72
|
+
},
|
|
73
|
+
"./client/vdom": {
|
|
74
|
+
"import": "./dist/client/vdom/index.js",
|
|
75
|
+
"types": "./dist/client/vdom/index.d.ts"
|
|
76
|
+
},
|
|
77
|
+
"./client/vdom/jsx-runtime": {
|
|
78
|
+
"import": "./dist/client/vdom/jsx-runtime.js",
|
|
79
|
+
"types": "./dist/client/vdom/jsx-runtime.d.ts"
|
|
80
|
+
},
|
|
81
|
+
"./rpc": {
|
|
82
|
+
"import": "./dist/rpc/index.js",
|
|
83
|
+
"types": "./dist/rpc/index.d.ts"
|
|
84
|
+
},
|
|
85
|
+
"./schema": {
|
|
86
|
+
"import": "./dist/schema/index.js",
|
|
87
|
+
"types": "./dist/schema/index.d.ts"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"sideEffects": false,
|
|
91
|
+
"files": [
|
|
92
|
+
"dist"
|
|
93
|
+
],
|
|
94
|
+
"scripts": {
|
|
95
|
+
"build": "tsup",
|
|
96
|
+
"dev": "tsup --watch",
|
|
97
|
+
"test": "vitest run",
|
|
98
|
+
"test:watch": "vitest",
|
|
99
|
+
"test:coverage": "vitest run --coverage",
|
|
100
|
+
"typecheck": "tsc --noEmit",
|
|
101
|
+
"build:all": "npm run build"
|
|
102
|
+
},
|
|
103
|
+
"dependencies": {},
|
|
104
|
+
"devDependencies": {
|
|
105
|
+
"@biomejs/biome": "^2.5.1",
|
|
106
|
+
"@types/node": "^26.0.1",
|
|
107
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
108
|
+
"tsup": "^8.3.0",
|
|
109
|
+
"typescript": "^5.7.0",
|
|
110
|
+
"vite": "^8.1.0",
|
|
111
|
+
"vitest": "^2.1.0"
|
|
112
|
+
},
|
|
113
|
+
"keywords": [
|
|
114
|
+
"fullstack",
|
|
115
|
+
"framework",
|
|
116
|
+
"typescript",
|
|
117
|
+
"server",
|
|
118
|
+
"client",
|
|
119
|
+
"rpc",
|
|
120
|
+
"validation",
|
|
121
|
+
"database",
|
|
122
|
+
"auth",
|
|
123
|
+
"indonesia"
|
|
124
|
+
],
|
|
125
|
+
"publishConfig": {
|
|
126
|
+
"access": "public"
|
|
127
|
+
},
|
|
128
|
+
"repository": {
|
|
129
|
+
"type": "git",
|
|
130
|
+
"url": "git+https://github.com/superdevids/speexjs.git"
|
|
131
|
+
},
|
|
132
|
+
"license": "MIT",
|
|
133
|
+
"engines": {
|
|
134
|
+
"node": ">=18.0.0"
|
|
135
|
+
}
|
|
138
136
|
}
|