@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 +18 -3
- package/bin/index.js +3 -0
- package/package.json +8 -5
- package/server.d.ts +12 -0
- package/server.js +66 -0
- package/types.d.ts +2 -1
- package/with-spa.js +3 -0
- package/with-static.d.ts +2 -2
- package/with-static.js +14 -6
- package/bin/vyriy-static.js +0 -5
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
|
|
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()
|
|
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.
|
|
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
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vyriy/static",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Static file and SPA serving helpers for Vyriy servers.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin":
|
|
6
|
+
"bin": {
|
|
7
|
+
"vs": "./bin/index.js",
|
|
8
|
+
"vyriy-static": "./bin/index.js"
|
|
9
|
+
},
|
|
7
10
|
"dependencies": {
|
|
8
|
-
"@vyriy/handler": "0.5.
|
|
9
|
-
"@vyriy/router": "0.5.
|
|
10
|
-
"@vyriy/server": "0.5.
|
|
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
package/with-static.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StaticMountOptions, StaticRouterApi } from './types.js';
|
|
2
2
|
import type { RouterApi } from '@vyriy/router';
|
|
3
|
-
export declare const withStatic: (router: RouterApi, options?:
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
};
|