@vyriy/static 0.5.3 → 0.5.5

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 CHANGED
@@ -17,9 +17,16 @@ vyriy-static
17
17
  vyriy-static dist
18
18
  vyriy-static build
19
19
  vyriy-static public
20
+ vyriy-static --port 3000 dist
20
21
  ```
21
22
 
22
- When no directory is provided, the server tries `dist`, `build`, `public`, `out`, and then the current directory.
23
+ When no directory is provided to the CLI, it tries `dist`, `build`, `public`, `out`, and then the current directory.
24
+
25
+ CLI flags:
26
+
27
+ - `--port <port>` or `-p <port>` sets the local server port.
28
+ - `--help` or `-h` prints command help.
29
+ - `--version` or `-v` prints the package version.
23
30
 
24
31
  ## API
25
32
 
@@ -38,12 +45,20 @@ import { createRouter } from '@vyriy/router';
38
45
  export const assets = useStatic();
39
46
  export const app = useSpa({ directory: 'dist', index: 'index.html' });
40
47
 
41
- export const router = withStatic(createRouter(), { directory: 'dist' }).static('/');
48
+ export const router = withStatic(createRouter())
49
+ .get('/api', () => ({ body: JSON.stringify({ ok: true }) }))
50
+ .static('/dist', { directory: 'dist' })
51
+ .static('/', { directory: 'public' });
42
52
  export const spaRouter = withSpa(createRouter(), 'dist');
43
53
 
44
54
  const code = await staticServer({ directory: 'dist' });
45
55
  ```
46
56
 
47
- `useStatic({ directory, index, error })` serves files from a directory. `useSpa(options)` serves static files and falls back to the configured index file for missing `GET` and `HEAD` paths. `withStatic(router, options).static(path)` adds prefix-based static mounts. `withSpa(router, directoryOrOptions)` adds static-first SPA fallback behavior.
57
+ - `useStatic({ directory, index, error })` serves files from a directory.
58
+ - `useSpa(options)` serves static files and falls back to the configured index file for missing `GET` and `HEAD` paths.
59
+ - `withStatic(router).static(path, options)` adds prefix-based static mounts.
60
+ - `withStatic(router, options).static(path)` keeps a shared default for static mounts.
61
+ - `withSpa(router, directoryOrOptions)` adds static-first SPA fallback behavior.
48
62
 
49
63
  Defaults are `directory: 'dist'`, `index: 'index.html'`, and `error: '404.html'`.
64
+ When `staticServer()` is called without options, it tries `dist`, `build`, `public`, `out`, and then the current directory.
package/bin/index.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { runStaticCli } from '../index.js';
3
+ await runStaticCli(process.argv.slice(2));
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@vyriy/static",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Static file and SPA serving helpers for Vyriy servers.",
5
5
  "type": "module",
6
- "bin": "./bin/vyriy-static.js",
6
+ "bin": {
7
+ "vs": "./bin/index.js",
8
+ "vyriy-static": "./bin/index.js"
9
+ },
7
10
  "dependencies": {
8
- "@vyriy/handler": "0.5.3",
9
- "@vyriy/router": "0.5.3",
10
- "@vyriy/server": "0.5.3"
11
+ "@vyriy/handler": "0.5.5",
12
+ "@vyriy/router": "0.5.5",
13
+ "@vyriy/server": "0.5.5"
11
14
  },
12
15
  "agents": "./AGENTS.md",
13
16
  "license": "MIT",
package/server.d.ts CHANGED
@@ -1,2 +1,14 @@
1
1
  import type { StaticServer } from './types.js';
2
+ export type StaticBinCommand = {
3
+ readonly type: 'help' | 'version';
4
+ } | {
5
+ readonly type: 'serve';
6
+ readonly directory?: string;
7
+ readonly port?: string;
8
+ };
9
+ export type RunStaticCli = (args?: readonly string[], command?: string, alias?: false | string) => Promise<void>;
10
+ export declare const staticVersion: string;
11
+ export declare const createStaticHelpText: (command?: string, alias?: false | string) => string;
12
+ export declare const parseStaticBinArgs: (args: readonly string[]) => StaticBinCommand;
13
+ export declare const runStaticCli: RunStaticCli;
2
14
  export declare const staticServer: StaticServer;
package/server.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { server } from '@vyriy/server';
3
+ import packageJson from './package.json' with { type: 'json' };
3
4
  import { useStatic } from './use-static.js';
4
5
  const DIRECTORIES = [
5
6
  'dist',
@@ -7,8 +8,73 @@ const DIRECTORIES = [
7
8
  'public',
8
9
  'out',
9
10
  ];
11
+ const getOptionValue = (args, name, alias) => {
12
+ const inline = args.find((arg) => arg.startsWith(`${name}=`));
13
+ if (inline) {
14
+ return inline.slice(name.length + 1);
15
+ }
16
+ const index = args.findIndex((arg) => arg === name || arg === alias);
17
+ return index >= 0 ? args[index + 1] : undefined;
18
+ };
19
+ const isOptionValue = (args, index) => {
20
+ const previous = args[index - 1];
21
+ return previous === '--port' || previous === '-p';
22
+ };
10
23
  const resolveDirectory = (directory) => directory ?? DIRECTORIES.find((candidate) => existsSync(candidate)) ?? '.';
11
24
  const createStaticHandler = useStatic;
25
+ export const staticVersion = packageJson.version;
26
+ export const createStaticHelpText = (command = 'vyriy-static', alias = 'vs') => {
27
+ const aliasText = alias ? ` ${alias} [directory] Alias for ${command}\n` : '';
28
+ const aliasExampleText = alias ? `\n ${alias} .` : '';
29
+ return `Vyriy Static Server
30
+
31
+ Usage:
32
+ ${command} [directory] Serve a static directory (defaults to dist when it exists)
33
+ ${command} --port 3000 dist Serve a directory on a specific port
34
+ ${aliasText}\
35
+ ${command} --help, -h Show help
36
+ ${command} --version, -v Show version
37
+
38
+ Options:
39
+ -p, --port <port> Port passed through the PORT environment variable
40
+
41
+ Examples:
42
+ ${command}
43
+ ${command} public
44
+ ${command} --port 3000 dist${aliasExampleText}`;
45
+ };
46
+ export const parseStaticBinArgs = (args) => {
47
+ if (args.includes('--help') || args.includes('-h')) {
48
+ return { type: 'help' };
49
+ }
50
+ if (args.includes('--version') || args.includes('-v')) {
51
+ return { type: 'version' };
52
+ }
53
+ return {
54
+ type: 'serve',
55
+ directory: args.find((arg, index) => !arg.startsWith('-') && !isOptionValue(args, index)),
56
+ port: getOptionValue(args, '--port', '-p'),
57
+ };
58
+ };
59
+ export const runStaticCli = async (args = [], command = 'vyriy-static', alias = 'vs') => {
60
+ const parsed = parseStaticBinArgs(args);
61
+ switch (parsed.type) {
62
+ case 'help':
63
+ console.log(createStaticHelpText(command, alias));
64
+ process.exitCode = 0;
65
+ break;
66
+ case 'version':
67
+ console.log(staticVersion);
68
+ process.exitCode = 0;
69
+ break;
70
+ case 'serve':
71
+ if (parsed.port) {
72
+ process.env.PORT = parsed.port;
73
+ }
74
+ process.exitCode = await staticServer({ directory: parsed.directory });
75
+ break;
76
+ }
77
+ };
12
78
  export const staticServer = async (options = {}) => {
13
79
  await Promise.resolve(server(createStaticHandler({ ...options, directory: resolveDirectory(options.directory) })));
14
80
  return 0;
package/types.d.ts CHANGED
@@ -5,10 +5,11 @@ export type StaticOptions = {
5
5
  readonly index?: string;
6
6
  readonly error?: string;
7
7
  };
8
+ export type StaticMountOptions = StaticOptions | string;
8
9
  export type StaticHandler = Handler<ApiEvent, ApiResult>;
9
10
  export type StaticServer = (options?: StaticOptions) => Promise<number>;
10
11
  export type StaticRouterApi = Omit<RouterApi, 'delete' | 'fallback' | 'get' | 'patch' | 'post' | 'put'> & {
11
- static(path: string): StaticRouterApi;
12
+ static(path: string, options?: StaticMountOptions): StaticRouterApi;
12
13
  } & {
13
14
  [Method in Extract<keyof RouterApi, 'delete' | 'fallback' | 'get' | 'patch' | 'post' | 'put'>]: (...args: Parameters<RouterApi[Method]>) => StaticRouterApi;
14
15
  };
package/with-spa.js CHANGED
@@ -17,6 +17,9 @@ export const withSpa = (router, directoryOrOptions = {}) => {
17
17
  router.get(path, handler);
18
18
  return api;
19
19
  },
20
+ handle() {
21
+ return (event) => api.route(event);
22
+ },
20
23
  patch(path, handler) {
21
24
  router.patch(path, handler);
22
25
  return api;
package/with-static.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import type { StaticOptions, StaticRouterApi } from './types.js';
1
+ import type { StaticMountOptions, StaticRouterApi } from './types.js';
2
2
  import type { RouterApi } from '@vyriy/router';
3
- export declare const withStatic: (router: RouterApi, options?: StaticOptions) => StaticRouterApi;
3
+ export declare const withStatic: (router: RouterApi, options?: StaticMountOptions) => StaticRouterApi;
package/with-static.js CHANGED
@@ -20,10 +20,10 @@ const toStaticPath = (mount, requestPath) => {
20
20
  return undefined;
21
21
  };
22
22
  const isStaticMethod = (method) => method === 'GET' || method === 'HEAD';
23
- export const withStatic = (router, options = {}) => {
23
+ const toStaticOptions = (options) => typeof options === 'string' ? { directory: options } : (options ?? {});
24
+ export const withStatic = (router, options) => {
24
25
  const mounts = [];
25
26
  const createStaticHandler = useStatic;
26
- const staticHandler = createStaticHandler(options);
27
27
  const api = {
28
28
  delete(path, handler) {
29
29
  router.delete(path, handler);
@@ -37,6 +37,9 @@ export const withStatic = (router, options = {}) => {
37
37
  router.get(path, handler);
38
38
  return api;
39
39
  },
40
+ handle() {
41
+ return (event) => api.route(event);
42
+ },
40
43
  patch(path, handler) {
41
44
  router.patch(path, handler);
42
45
  return api;
@@ -55,11 +58,11 @@ export const withStatic = (router, options = {}) => {
55
58
  return result;
56
59
  }
57
60
  for (const mount of mounts) {
58
- const staticPath = toStaticPath(mount, event.path);
61
+ const staticPath = toStaticPath(mount.path, event.path);
59
62
  if (staticPath === undefined) {
60
63
  continue;
61
64
  }
62
- const staticResult = await staticHandler({
65
+ const staticResult = await mount.handler({
63
66
  ...event,
64
67
  path: staticPath,
65
68
  }, {});
@@ -67,8 +70,13 @@ export const withStatic = (router, options = {}) => {
67
70
  }
68
71
  return result;
69
72
  },
70
- static(path) {
71
- mounts.push(normalizeMount(path));
73
+ static(path, mountOptions) {
74
+ const staticOptions = mountOptions ?? options;
75
+ mounts.push({
76
+ handler: createStaticHandler(toStaticOptions(staticOptions)),
77
+ path: normalizeMount(path),
78
+ });
79
+ mounts.sort((left, right) => right.path.length - left.path.length);
72
80
  return api;
73
81
  },
74
82
  };
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import { staticServer } from '../index.js';
3
- process.exitCode = await staticServer({
4
- directory: process.argv.find((arg, index) => index > 1 && !arg.startsWith('-')) ?? '.',
5
- });