@karmaniverous/jeeves-server-core 0.4.0 → 0.5.0
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 +49 -12
- package/dist/openapi.json.js +4038 -0
- package/dist/scripts/openapiInfo.d.ts +15 -0
- package/dist/src/catalog/browserSafe.test.d.ts +4 -0
- package/dist/src/catalog/contentEntries.d.ts +468 -0
- package/dist/src/catalog/contentEntries.js +150 -0
- package/dist/src/catalog/contentSchemas.d.ts +179 -0
- package/dist/src/catalog/contentSchemas.js +195 -0
- package/dist/src/catalog/descriptions.d.ts +52 -0
- package/dist/src/catalog/descriptions.js +54 -0
- package/dist/src/catalog/eventEntries.d.ts +70 -0
- package/dist/src/catalog/eventEntries.js +59 -0
- package/dist/src/catalog/fileMutateSchema.d.ts +41 -0
- package/dist/src/catalog/fileMutateSchema.js +77 -0
- package/dist/src/catalog/index.d.ts +15 -0
- package/dist/src/catalog/index.js +10 -0
- package/dist/src/catalog/oauthEntries.d.ts +125 -0
- package/dist/src/catalog/oauthEntries.js +92 -0
- package/dist/src/catalog/route.d.ts +137 -0
- package/dist/src/catalog/route.js +92 -0
- package/dist/src/catalog/runnerEntries.d.ts +145 -0
- package/dist/src/catalog/runnerEntries.js +69 -0
- package/dist/src/catalog/schemas.test.d.ts +4 -0
- package/dist/src/catalog/serverCatalog.d.ts +1143 -0
- package/dist/src/catalog/serverCatalog.js +37 -0
- package/dist/src/catalog/serverCatalog.test.d.ts +4 -0
- package/dist/src/catalog/sharingEntries.d.ts +200 -0
- package/dist/src/catalog/sharingEntries.js +146 -0
- package/dist/src/catalog/statusSchemas.d.ts +87 -0
- package/dist/src/catalog/statusSchemas.js +119 -0
- package/dist/src/catalog/utilityEntries.d.ts +151 -0
- package/dist/src/catalog/utilityEntries.js +62 -0
- package/dist/src/catalog/utilitySchemas.d.ts +98 -0
- package/dist/src/catalog/utilitySchemas.js +131 -0
- package/dist/src/configAuthSchema.d.ts +100 -0
- package/dist/src/configAuthSchema.js +119 -0
- package/dist/src/configFeatureSchemas.d.ts +43 -0
- package/dist/src/configFeatureSchemas.js +53 -0
- package/dist/src/configPrintStyles.d.ts +63 -0
- package/dist/src/configPrintStyles.js +98 -0
- package/dist/src/configPrintStyles.test.d.ts +1 -0
- package/dist/src/crypto.d.ts +6 -13
- package/dist/src/crypto.js +7 -32
- package/dist/src/crypto.test.d.ts +7 -0
- package/dist/src/errors.d.ts +51 -0
- package/dist/src/errors.js +97 -0
- package/dist/src/errors.test.d.ts +4 -0
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +17 -3
- package/dist/src/openapi.d.ts +13 -0
- package/dist/src/openapi.js +17 -0
- package/dist/src/openapi.test.d.ts +4 -0
- package/dist/src/schema.d.ts +20 -122
- package/dist/src/schema.js +17 -153
- package/dist/src/types.d.ts +2 -0
- package/openapi.json +3934 -0
- package/package.json +26 -13
- package/dist/src/endpoints.d.ts +0 -34
- package/dist/src/endpoints.js +0 -248
- /package/dist/src/{endpoints.test.d.ts → configAuthSchema.test.d.ts} +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schemas for optional features: logging, OAuth credential
|
|
3
|
+
* management and branding.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/** Logging configuration. Not hot-reloadable — changes require service restart. */
|
|
9
|
+
export declare const loggingConfigSchema: z.ZodObject<{
|
|
10
|
+
level: z.ZodOptional<z.ZodString>;
|
|
11
|
+
file: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
/** Inferred logging config type. */
|
|
14
|
+
export type LoggingConfig = z.infer<typeof loggingConfigSchema>;
|
|
15
|
+
/** OAuth provider configuration */
|
|
16
|
+
export declare const oauthProviderSchema: z.ZodObject<{
|
|
17
|
+
authUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
|
|
18
|
+
tokenUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
|
|
19
|
+
pkce: z.ZodDefault<z.ZodBoolean>;
|
|
20
|
+
defaultScopes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
/** OAuth configuration */
|
|
23
|
+
export declare const oauthSchema: z.ZodObject<{
|
|
24
|
+
credentialDir: z.ZodString;
|
|
25
|
+
providers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
26
|
+
authUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
|
|
27
|
+
tokenUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
|
|
28
|
+
pkce: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
defaultScopes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
30
|
+
}, z.core.$strip>>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
/** Theme overrides for light and dark modes */
|
|
33
|
+
export declare const themeOverridesSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
34
|
+
/** Instance branding configuration */
|
|
35
|
+
export declare const brandingSchema: z.ZodObject<{
|
|
36
|
+
name: z.ZodDefault<z.ZodString>;
|
|
37
|
+
emoji: z.ZodDefault<z.ZodString>;
|
|
38
|
+
theme: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
light: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
40
|
+
dark: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
41
|
+
}, z.core.$strip>>;
|
|
42
|
+
emailTemplate: z.ZodOptional<z.ZodString>;
|
|
43
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Config schemas for optional features: logging, OAuth credential
|
|
5
|
+
* management and branding.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/** Logging configuration. Not hot-reloadable — changes require service restart. */
|
|
10
|
+
const loggingConfigSchema = z.object({
|
|
11
|
+
/** Log level. */
|
|
12
|
+
level: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe('Logging level (trace, debug, info, warn, error, fatal).'),
|
|
16
|
+
/** Log file path. */
|
|
17
|
+
file: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Path to log file (logs to stdout if omitted).'),
|
|
21
|
+
});
|
|
22
|
+
/** OAuth provider configuration */
|
|
23
|
+
const oauthProviderSchema = z.object({
|
|
24
|
+
authUrl: z.string().pipe(z.url()),
|
|
25
|
+
tokenUrl: z.string().pipe(z.url()),
|
|
26
|
+
pkce: z.boolean().default(false),
|
|
27
|
+
defaultScopes: z.array(z.string()).default([]),
|
|
28
|
+
});
|
|
29
|
+
/** OAuth configuration */
|
|
30
|
+
const oauthSchema = z.object({
|
|
31
|
+
credentialDir: z.string(),
|
|
32
|
+
providers: z.record(z.string(), oauthProviderSchema).default({}),
|
|
33
|
+
});
|
|
34
|
+
/** Theme overrides for light and dark modes */
|
|
35
|
+
const themeOverridesSchema = z.record(z.string(), z.string());
|
|
36
|
+
/** Instance branding configuration */
|
|
37
|
+
const brandingSchema = z.object({
|
|
38
|
+
/** Instance display name (used in page title, navbar, emails) */
|
|
39
|
+
name: z.string().default('Jeeves Server'),
|
|
40
|
+
/** Instance emoji (used as home icon in navbar) */
|
|
41
|
+
emoji: z.string().default('🎩'),
|
|
42
|
+
/** CSS variable overrides grouped by theme mode */
|
|
43
|
+
theme: z
|
|
44
|
+
.object({
|
|
45
|
+
light: themeOverridesSchema.optional(),
|
|
46
|
+
dark: themeOverridesSchema.optional(),
|
|
47
|
+
})
|
|
48
|
+
.optional(),
|
|
49
|
+
/** Handlebars template for magic link emails. Supports \{\{magicLink\}\}, \{\{branding.name\}\}, \{\{branding.emoji\}\} */
|
|
50
|
+
emailTemplate: z.string().optional(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export { brandingSchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, themeOverridesSchema };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config schemas for named PDF print styles (`printStyles`, #316) and the
|
|
3
|
+
* absolute-path check they share with other path settings.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/**
|
|
9
|
+
* Whether a path is absolute on POSIX (`/…`), Windows (`C:\…`, `C:/…`) or
|
|
10
|
+
* UNC (`\\server\…`), whatever platform validates the config.
|
|
11
|
+
*
|
|
12
|
+
* @param p - The path.
|
|
13
|
+
* @returns `true` when absolute.
|
|
14
|
+
*/
|
|
15
|
+
export declare const isAbsolutePath: (p: string) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* An absolute file system path.
|
|
18
|
+
*
|
|
19
|
+
* @param label - What the path is, for the error message.
|
|
20
|
+
* @returns The schema.
|
|
21
|
+
*/
|
|
22
|
+
export declare const absolutePathSchema: (label: string) => z.ZodString;
|
|
23
|
+
/** Paper formats Chromium's `page.pdf()` accepts (any case). */
|
|
24
|
+
export declare const PRINT_PAPER_FORMATS: readonly ["letter", "legal", "tabloid", "ledger", "a0", "a1", "a2", "a3", "a4", "a5", "a6"];
|
|
25
|
+
/** Page size and margins of a print style. */
|
|
26
|
+
export declare const printPageSchema: z.ZodObject<{
|
|
27
|
+
format: z.ZodOptional<z.ZodString>;
|
|
28
|
+
width: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
29
|
+
height: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
30
|
+
margin: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
/** One print style: a stylesheet, with optional page options and templates. */
|
|
33
|
+
export declare const printStyleSchema: z.ZodObject<{
|
|
34
|
+
css: z.ZodString;
|
|
35
|
+
page: z.ZodOptional<z.ZodObject<{
|
|
36
|
+
format: z.ZodOptional<z.ZodString>;
|
|
37
|
+
width: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
38
|
+
height: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
39
|
+
margin: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
headerTemplate: z.ZodOptional<z.ZodString>;
|
|
42
|
+
footerTemplate: z.ZodOptional<z.ZodString>;
|
|
43
|
+
assets: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
/** Print style name: lower-case letters, digits and hyphens. */
|
|
46
|
+
export declare const PRINT_STYLE_NAME: RegExp;
|
|
47
|
+
/** Named print styles, chosen by documents with `jeeves: { print: <name> }`. */
|
|
48
|
+
export declare const printStylesSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
49
|
+
css: z.ZodString;
|
|
50
|
+
page: z.ZodOptional<z.ZodObject<{
|
|
51
|
+
format: z.ZodOptional<z.ZodString>;
|
|
52
|
+
width: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
53
|
+
height: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
54
|
+
margin: z.ZodOptional<z.ZodString>;
|
|
55
|
+
}, z.core.$strip>>;
|
|
56
|
+
headerTemplate: z.ZodOptional<z.ZodString>;
|
|
57
|
+
footerTemplate: z.ZodOptional<z.ZodString>;
|
|
58
|
+
assets: z.ZodOptional<z.ZodString>;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
/** A configured print style. */
|
|
61
|
+
export type PrintStyleConfig = z.infer<typeof printStyleSchema>;
|
|
62
|
+
/** A print style's page options. */
|
|
63
|
+
export type PrintPageConfig = z.infer<typeof printPageSchema>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Config schemas for named PDF print styles (`printStyles`, #316) and the
|
|
5
|
+
* absolute-path check they share with other path settings.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether a path is absolute on POSIX (`/…`), Windows (`C:\…`, `C:/…`) or
|
|
11
|
+
* UNC (`\\server\…`), whatever platform validates the config.
|
|
12
|
+
*
|
|
13
|
+
* @param p - The path.
|
|
14
|
+
* @returns `true` when absolute.
|
|
15
|
+
*/
|
|
16
|
+
const isAbsolutePath = (p) => p.startsWith('/') || /^[A-Za-z]:[\\/]/.test(p) || p.startsWith('\\\\');
|
|
17
|
+
/**
|
|
18
|
+
* An absolute file system path.
|
|
19
|
+
*
|
|
20
|
+
* @param label - What the path is, for the error message.
|
|
21
|
+
* @returns The schema.
|
|
22
|
+
*/
|
|
23
|
+
const absolutePathSchema = (label) => z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.refine(isAbsolutePath, { message: `${label} must be an absolute path` });
|
|
27
|
+
/** Paper formats Chromium's `page.pdf()` accepts (any case). */
|
|
28
|
+
const PRINT_PAPER_FORMATS = [
|
|
29
|
+
'letter',
|
|
30
|
+
'legal',
|
|
31
|
+
'tabloid',
|
|
32
|
+
'ledger',
|
|
33
|
+
'a0',
|
|
34
|
+
'a1',
|
|
35
|
+
'a2',
|
|
36
|
+
'a3',
|
|
37
|
+
'a4',
|
|
38
|
+
'a5',
|
|
39
|
+
'a6',
|
|
40
|
+
];
|
|
41
|
+
/** A page dimension: a CSS length string (`210mm`) or pixels. */
|
|
42
|
+
const pageLengthSchema = z.union([z.string().min(1), z.number().positive()]);
|
|
43
|
+
/** Page size and margins of a print style. */
|
|
44
|
+
const printPageSchema = z
|
|
45
|
+
.object({
|
|
46
|
+
/** Paper format (`Letter`, `A4`, …); exclusive with width/height. */
|
|
47
|
+
format: z
|
|
48
|
+
.string()
|
|
49
|
+
.refine((f) => PRINT_PAPER_FORMATS.includes(f.toLowerCase()), { message: `format must be one of ${PRINT_PAPER_FORMATS.join(', ')}` })
|
|
50
|
+
.optional(),
|
|
51
|
+
/** Page width; requires height. */
|
|
52
|
+
width: pageLengthSchema.optional(),
|
|
53
|
+
/** Page height; requires width. */
|
|
54
|
+
height: pageLengthSchema.optional(),
|
|
55
|
+
/** CSS margin shorthand: one to four lengths (`14mm 14mm 16mm 14mm`). */
|
|
56
|
+
margin: z
|
|
57
|
+
.string()
|
|
58
|
+
.regex(/^\s*\S+(?:\s+\S+){0,3}\s*$/, {
|
|
59
|
+
message: 'margin must be one to four CSS lengths',
|
|
60
|
+
})
|
|
61
|
+
.optional(),
|
|
62
|
+
})
|
|
63
|
+
.superRefine((page, ctx) => {
|
|
64
|
+
const sized = page.width !== undefined || page.height !== undefined;
|
|
65
|
+
if (page.format !== undefined && sized)
|
|
66
|
+
ctx.addIssue({
|
|
67
|
+
code: 'custom',
|
|
68
|
+
message: 'Use format or width and height, not both',
|
|
69
|
+
path: ['format'],
|
|
70
|
+
});
|
|
71
|
+
if (sized && (page.width === undefined || page.height === undefined))
|
|
72
|
+
ctx.addIssue({
|
|
73
|
+
code: 'custom',
|
|
74
|
+
message: 'width and height must be given together',
|
|
75
|
+
path: [page.width === undefined ? 'width' : 'height'],
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
/** One print style: a stylesheet, with optional page options and templates. */
|
|
79
|
+
const printStyleSchema = z.object({
|
|
80
|
+
/** Stylesheet injected after the default print CSS. */
|
|
81
|
+
css: absolutePathSchema('css'),
|
|
82
|
+
/** Page size and margins for `page.pdf()`. */
|
|
83
|
+
page: printPageSchema.optional(),
|
|
84
|
+
/** Chromium header template (HTML). */
|
|
85
|
+
headerTemplate: absolutePathSchema('headerTemplate').optional(),
|
|
86
|
+
/** Chromium footer template (HTML). */
|
|
87
|
+
footerTemplate: absolutePathSchema('footerTemplate').optional(),
|
|
88
|
+
/** Directory whose files the CSS and templates may inline. */
|
|
89
|
+
assets: absolutePathSchema('assets').optional(),
|
|
90
|
+
});
|
|
91
|
+
/** Print style name: lower-case letters, digits and hyphens. */
|
|
92
|
+
const PRINT_STYLE_NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
93
|
+
/** Named print styles, chosen by documents with `jeeves: { print: <name> }`. */
|
|
94
|
+
const printStylesSchema = z.record(z.string().regex(PRINT_STYLE_NAME, {
|
|
95
|
+
message: 'Print style names are lower-case letters, digits and hyphens, starting with a letter or digit',
|
|
96
|
+
}), printStyleSchema);
|
|
97
|
+
|
|
98
|
+
export { PRINT_PAPER_FORMATS, PRINT_STYLE_NAME, absolutePathSchema, isAbsolutePath, printPageSchema, printStyleSchema, printStylesSchema };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/src/crypto.d.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cryptographic utilities for HMAC key computation and verification.
|
|
3
3
|
*
|
|
4
|
+
* The link-key functions (`computeInsiderKey`, `computeOutsiderKeyWithExpiry`,
|
|
5
|
+
* `computePathKey`) are re-exported from `@karmaniverous/jeeves`, which holds
|
|
6
|
+
* the one implementation (#307). The deep-share key and the timing-safe
|
|
7
|
+
* comparison stay here: jeeves has no equivalent.
|
|
8
|
+
*
|
|
4
9
|
* @packageDocumentation
|
|
5
10
|
*/
|
|
6
|
-
|
|
7
|
-
* Compute path-specific key: HMAC-SHA256(apiKey, normalizedPath)
|
|
8
|
-
*/
|
|
9
|
-
export declare function computePathKey(apiKey: string, urlPath: string): string;
|
|
10
|
-
/**
|
|
11
|
-
* Compute insider key: HMAC-SHA256(apiKey, "insider")
|
|
12
|
-
* Works for any path, grants full navigation
|
|
13
|
-
*/
|
|
14
|
-
export declare function computeInsiderKey(apiKey: string): string;
|
|
15
|
-
/**
|
|
16
|
-
* Compute outsider key with expiry: HMAC-SHA256(apiKey, path + "|" + expiry)
|
|
17
|
-
*/
|
|
18
|
-
export declare function computeOutsiderKeyWithExpiry(apiKey: string, urlPath: string, expiry: string | number): string;
|
|
11
|
+
export { computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey, } from '@karmaniverous/jeeves';
|
|
19
12
|
/**
|
|
20
13
|
* Deep share key parameters
|
|
21
14
|
*/
|
package/dist/src/crypto.js
CHANGED
|
@@ -1,41 +1,16 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
+
export { computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey } from '@karmaniverous/jeeves';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Cryptographic utilities for HMAC key computation and verification.
|
|
5
6
|
*
|
|
7
|
+
* The link-key functions (`computeInsiderKey`, `computeOutsiderKeyWithExpiry`,
|
|
8
|
+
* `computePathKey`) are re-exported from `@karmaniverous/jeeves`, which holds
|
|
9
|
+
* the one implementation (#307). The deep-share key and the timing-safe
|
|
10
|
+
* comparison stay here: jeeves has no equivalent.
|
|
11
|
+
*
|
|
6
12
|
* @packageDocumentation
|
|
7
13
|
*/
|
|
8
|
-
/**
|
|
9
|
-
* Compute path-specific key: HMAC-SHA256(apiKey, normalizedPath)
|
|
10
|
-
*/
|
|
11
|
-
function computePathKey(apiKey, urlPath) {
|
|
12
|
-
const normalized = urlPath.toLowerCase().replace(/^\/+|\/+$/g, '');
|
|
13
|
-
const hash = crypto
|
|
14
|
-
.createHmac('sha256', apiKey)
|
|
15
|
-
.update(normalized)
|
|
16
|
-
.digest('hex');
|
|
17
|
-
return hash.substring(0, 32);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Compute insider key: HMAC-SHA256(apiKey, "insider")
|
|
21
|
-
* Works for any path, grants full navigation
|
|
22
|
-
*/
|
|
23
|
-
function computeInsiderKey(apiKey) {
|
|
24
|
-
const hash = crypto
|
|
25
|
-
.createHmac('sha256', apiKey)
|
|
26
|
-
.update('insider')
|
|
27
|
-
.digest('hex');
|
|
28
|
-
return hash.substring(0, 32);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Compute outsider key with expiry: HMAC-SHA256(apiKey, path + "|" + expiry)
|
|
32
|
-
*/
|
|
33
|
-
function computeOutsiderKeyWithExpiry(apiKey, urlPath, expiry) {
|
|
34
|
-
const normalized = urlPath.toLowerCase().replace(/^\/+|\/+$/g, '');
|
|
35
|
-
const data = `${normalized}|${String(expiry)}`;
|
|
36
|
-
const hash = crypto.createHmac('sha256', apiKey).update(data).digest('hex');
|
|
37
|
-
return hash.substring(0, 32);
|
|
38
|
-
}
|
|
39
14
|
/**
|
|
40
15
|
* Compute deep share key: HMAC-SHA256(seed, path + "|" + d + "|" + dirs + "|" + stack + "|" + exp)
|
|
41
16
|
* Used for share links with depth \> 0 or dirs enabled.
|
|
@@ -58,4 +33,4 @@ function timingSafeEqual(a, b) {
|
|
|
58
33
|
}
|
|
59
34
|
}
|
|
60
35
|
|
|
61
|
-
export { computeDeepShareKey,
|
|
36
|
+
export { computeDeepShareKey, timingSafeEqual };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known-vector tests for the link-key functions core re-exports from
|
|
3
|
+
* `@karmaniverous/jeeves` (#307). Every vector was computed with core's own
|
|
4
|
+
* implementation before it was deleted (branch base f0b1417): equal output
|
|
5
|
+
* here means links signed before and after the switch stay valid.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client's half of the server error contract (#315): every `SERVER_*` code an error body can carry (`SERVER_ERROR_CODES`) and the HTTP status each is sent with (`SERVER_ERROR_STATUS`). The body is Fastify's standard error body (`errorBodySchema` from `@karmaniverous/jeeves/catalog`). Pure data.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Every `SERVER_*` code a non-2xx jeeves-server response can carry. The body
|
|
8
|
+
* is `{ statusCode, code?, error, message }`; other codes come from jeeves
|
|
9
|
+
* (`JEEVES_*`) and Fastify (`FST_ERR_*`), and an unexpected failure is a
|
|
10
|
+
* masked 500 with no `code`. The status of each is in
|
|
11
|
+
* {@link SERVER_ERROR_STATUS}.
|
|
12
|
+
*
|
|
13
|
+
* - `SERVER_UNAUTHORIZED` (401): no valid credential for the route.
|
|
14
|
+
* - `SERVER_FORBIDDEN` (403): an admin route called by an identity with
|
|
15
|
+
* scopes.
|
|
16
|
+
* - `SERVER_OUT_OF_SCOPE` (403): a path outside the caller's scopes.
|
|
17
|
+
* - `SERVER_INSIDER_REQUIRED` (403): a share credential on a route that
|
|
18
|
+
* needs an insider.
|
|
19
|
+
* - `SERVER_INVALID_PATH` (400): a path that is empty, has a `..` segment or
|
|
20
|
+
* is not absolute where an absolute path is required.
|
|
21
|
+
* - `SERVER_NOT_FOUND` (404): no file, directory, page, route or credential
|
|
22
|
+
* there (a path under no configured root included).
|
|
23
|
+
* - `SERVER_NOT_A_FILE` (400): a file route addressed a directory.
|
|
24
|
+
* - `SERVER_NOT_A_DIRECTORY` (400): a directory route addressed a file.
|
|
25
|
+
* - `SERVER_EXPORT_UNSUPPORTED` (400): no export in that format for that
|
|
26
|
+
* path.
|
|
27
|
+
* - `SERVER_EXPORT_FAILED` (502): the document did not render.
|
|
28
|
+
* - `SERVER_ARCHIVE_TOO_LARGE` (413): the directory exceeds `maxZipSizeMb`.
|
|
29
|
+
* - `SERVER_CHROME_UNAVAILABLE` (503): no usable Chrome for the export.
|
|
30
|
+
* - `SERVER_WATCHER_UNAVAILABLE` (502): jeeves-watcher failed or can't be
|
|
31
|
+
* reached.
|
|
32
|
+
* - `SERVER_RUNNER_UNAVAILABLE` (503): jeeves-runner can't be reached.
|
|
33
|
+
* - `SERVER_MACHINE_KEY_NOT_ROTATABLE` (403): `rotateKey` with a machine
|
|
34
|
+
* key (machine seeds rotate through config).
|
|
35
|
+
* - `SERVER_EMAIL_UNAVAILABLE` (500): the sign-in email could not be sent.
|
|
36
|
+
* - `SERVER_INTERNAL_KEY_MISSING` (500): no `_internal` key is configured.
|
|
37
|
+
* - `SERVER_CONFLICT` (409): a block edit raced another change.
|
|
38
|
+
* - `SERVER_SIGN_IN_REJECTED` (403): sign-in refused for that account.
|
|
39
|
+
* - `SERVER_INVALID_REQUEST` (400): a request field is missing or invalid in
|
|
40
|
+
* a way the route checks itself (a line range, an action's fields, an
|
|
41
|
+
* OAuth origin).
|
|
42
|
+
* - `SERVER_NOT_CONFIGURED` (501): the feature the route serves is not
|
|
43
|
+
* configured on this server (OAuth).
|
|
44
|
+
* - `SERVER_OAUTH_REFRESH_FAILED` (401): a stored OAuth credential expired
|
|
45
|
+
* and could not be refreshed; the account must be authorized again.
|
|
46
|
+
*/
|
|
47
|
+
export declare const SERVER_ERROR_CODES: readonly ["SERVER_UNAUTHORIZED", "SERVER_FORBIDDEN", "SERVER_OUT_OF_SCOPE", "SERVER_INSIDER_REQUIRED", "SERVER_INVALID_PATH", "SERVER_NOT_FOUND", "SERVER_NOT_A_FILE", "SERVER_NOT_A_DIRECTORY", "SERVER_EXPORT_UNSUPPORTED", "SERVER_EXPORT_FAILED", "SERVER_ARCHIVE_TOO_LARGE", "SERVER_CHROME_UNAVAILABLE", "SERVER_WATCHER_UNAVAILABLE", "SERVER_RUNNER_UNAVAILABLE", "SERVER_MACHINE_KEY_NOT_ROTATABLE", "SERVER_EMAIL_UNAVAILABLE", "SERVER_INTERNAL_KEY_MISSING", "SERVER_CONFLICT", "SERVER_SIGN_IN_REJECTED", "SERVER_INVALID_REQUEST", "SERVER_NOT_CONFIGURED", "SERVER_OAUTH_REFRESH_FAILED"];
|
|
48
|
+
/** A `SERVER_*` error code. */
|
|
49
|
+
export type ServerErrorCode = (typeof SERVER_ERROR_CODES)[number];
|
|
50
|
+
/** The HTTP status each `SERVER_*` code is sent with (one per code). */
|
|
51
|
+
export declare const SERVER_ERROR_STATUS: Readonly<Record<ServerErrorCode, number>>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client's half of the server error contract (#315): every `SERVER_*` code an error body can carry (`SERVER_ERROR_CODES`) and the HTTP status each is sent with (`SERVER_ERROR_STATUS`). The body is Fastify's standard error body (`errorBodySchema` from `@karmaniverous/jeeves/catalog`). Pure data.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Every `SERVER_*` code a non-2xx jeeves-server response can carry. The body
|
|
8
|
+
* is `{ statusCode, code?, error, message }`; other codes come from jeeves
|
|
9
|
+
* (`JEEVES_*`) and Fastify (`FST_ERR_*`), and an unexpected failure is a
|
|
10
|
+
* masked 500 with no `code`. The status of each is in
|
|
11
|
+
* {@link SERVER_ERROR_STATUS}.
|
|
12
|
+
*
|
|
13
|
+
* - `SERVER_UNAUTHORIZED` (401): no valid credential for the route.
|
|
14
|
+
* - `SERVER_FORBIDDEN` (403): an admin route called by an identity with
|
|
15
|
+
* scopes.
|
|
16
|
+
* - `SERVER_OUT_OF_SCOPE` (403): a path outside the caller's scopes.
|
|
17
|
+
* - `SERVER_INSIDER_REQUIRED` (403): a share credential on a route that
|
|
18
|
+
* needs an insider.
|
|
19
|
+
* - `SERVER_INVALID_PATH` (400): a path that is empty, has a `..` segment or
|
|
20
|
+
* is not absolute where an absolute path is required.
|
|
21
|
+
* - `SERVER_NOT_FOUND` (404): no file, directory, page, route or credential
|
|
22
|
+
* there (a path under no configured root included).
|
|
23
|
+
* - `SERVER_NOT_A_FILE` (400): a file route addressed a directory.
|
|
24
|
+
* - `SERVER_NOT_A_DIRECTORY` (400): a directory route addressed a file.
|
|
25
|
+
* - `SERVER_EXPORT_UNSUPPORTED` (400): no export in that format for that
|
|
26
|
+
* path.
|
|
27
|
+
* - `SERVER_EXPORT_FAILED` (502): the document did not render.
|
|
28
|
+
* - `SERVER_ARCHIVE_TOO_LARGE` (413): the directory exceeds `maxZipSizeMb`.
|
|
29
|
+
* - `SERVER_CHROME_UNAVAILABLE` (503): no usable Chrome for the export.
|
|
30
|
+
* - `SERVER_WATCHER_UNAVAILABLE` (502): jeeves-watcher failed or can't be
|
|
31
|
+
* reached.
|
|
32
|
+
* - `SERVER_RUNNER_UNAVAILABLE` (503): jeeves-runner can't be reached.
|
|
33
|
+
* - `SERVER_MACHINE_KEY_NOT_ROTATABLE` (403): `rotateKey` with a machine
|
|
34
|
+
* key (machine seeds rotate through config).
|
|
35
|
+
* - `SERVER_EMAIL_UNAVAILABLE` (500): the sign-in email could not be sent.
|
|
36
|
+
* - `SERVER_INTERNAL_KEY_MISSING` (500): no `_internal` key is configured.
|
|
37
|
+
* - `SERVER_CONFLICT` (409): a block edit raced another change.
|
|
38
|
+
* - `SERVER_SIGN_IN_REJECTED` (403): sign-in refused for that account.
|
|
39
|
+
* - `SERVER_INVALID_REQUEST` (400): a request field is missing or invalid in
|
|
40
|
+
* a way the route checks itself (a line range, an action's fields, an
|
|
41
|
+
* OAuth origin).
|
|
42
|
+
* - `SERVER_NOT_CONFIGURED` (501): the feature the route serves is not
|
|
43
|
+
* configured on this server (OAuth).
|
|
44
|
+
* - `SERVER_OAUTH_REFRESH_FAILED` (401): a stored OAuth credential expired
|
|
45
|
+
* and could not be refreshed; the account must be authorized again.
|
|
46
|
+
*/
|
|
47
|
+
const SERVER_ERROR_CODES = [
|
|
48
|
+
'SERVER_UNAUTHORIZED',
|
|
49
|
+
'SERVER_FORBIDDEN',
|
|
50
|
+
'SERVER_OUT_OF_SCOPE',
|
|
51
|
+
'SERVER_INSIDER_REQUIRED',
|
|
52
|
+
'SERVER_INVALID_PATH',
|
|
53
|
+
'SERVER_NOT_FOUND',
|
|
54
|
+
'SERVER_NOT_A_FILE',
|
|
55
|
+
'SERVER_NOT_A_DIRECTORY',
|
|
56
|
+
'SERVER_EXPORT_UNSUPPORTED',
|
|
57
|
+
'SERVER_EXPORT_FAILED',
|
|
58
|
+
'SERVER_ARCHIVE_TOO_LARGE',
|
|
59
|
+
'SERVER_CHROME_UNAVAILABLE',
|
|
60
|
+
'SERVER_WATCHER_UNAVAILABLE',
|
|
61
|
+
'SERVER_RUNNER_UNAVAILABLE',
|
|
62
|
+
'SERVER_MACHINE_KEY_NOT_ROTATABLE',
|
|
63
|
+
'SERVER_EMAIL_UNAVAILABLE',
|
|
64
|
+
'SERVER_INTERNAL_KEY_MISSING',
|
|
65
|
+
'SERVER_CONFLICT',
|
|
66
|
+
'SERVER_SIGN_IN_REJECTED',
|
|
67
|
+
'SERVER_INVALID_REQUEST',
|
|
68
|
+
'SERVER_NOT_CONFIGURED',
|
|
69
|
+
'SERVER_OAUTH_REFRESH_FAILED',
|
|
70
|
+
];
|
|
71
|
+
/** The HTTP status each `SERVER_*` code is sent with (one per code). */
|
|
72
|
+
const SERVER_ERROR_STATUS = {
|
|
73
|
+
SERVER_UNAUTHORIZED: 401,
|
|
74
|
+
SERVER_FORBIDDEN: 403,
|
|
75
|
+
SERVER_OUT_OF_SCOPE: 403,
|
|
76
|
+
SERVER_INSIDER_REQUIRED: 403,
|
|
77
|
+
SERVER_INVALID_PATH: 400,
|
|
78
|
+
SERVER_NOT_FOUND: 404,
|
|
79
|
+
SERVER_NOT_A_FILE: 400,
|
|
80
|
+
SERVER_NOT_A_DIRECTORY: 400,
|
|
81
|
+
SERVER_EXPORT_UNSUPPORTED: 400,
|
|
82
|
+
SERVER_EXPORT_FAILED: 502,
|
|
83
|
+
SERVER_ARCHIVE_TOO_LARGE: 413,
|
|
84
|
+
SERVER_CHROME_UNAVAILABLE: 503,
|
|
85
|
+
SERVER_WATCHER_UNAVAILABLE: 502,
|
|
86
|
+
SERVER_RUNNER_UNAVAILABLE: 503,
|
|
87
|
+
SERVER_MACHINE_KEY_NOT_ROTATABLE: 403,
|
|
88
|
+
SERVER_EMAIL_UNAVAILABLE: 500,
|
|
89
|
+
SERVER_INTERNAL_KEY_MISSING: 500,
|
|
90
|
+
SERVER_CONFLICT: 409,
|
|
91
|
+
SERVER_SIGN_IN_REJECTED: 403,
|
|
92
|
+
SERVER_INVALID_REQUEST: 400,
|
|
93
|
+
SERVER_NOT_CONFIGURED: 501,
|
|
94
|
+
SERVER_OAUTH_REFRESH_FAILED: 401,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export { SERVER_ERROR_CODES, SERVER_ERROR_STATUS };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* jeeves-server-core's main entry: the endpoint catalog with its schemas and error codes (also on the browser-safe `./catalog` sub-path), the OpenAPI document, the config schema, URL-key helpers and the Node-only link-key functions.
|
|
3
3
|
*
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
|
+
export * from './catalog/index.js';
|
|
7
|
+
export { absolutePathSchema, isAbsolutePath, PRINT_PAPER_FORMATS, PRINT_STYLE_NAME, type PrintPageConfig, printPageSchema, type PrintStyleConfig, printStyleSchema, printStylesSchema, } from './configPrintStyles.js';
|
|
6
8
|
export { computeDeepShareKey, computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey, type DeepShareParams, timingSafeEqual, } from './crypto.js';
|
|
7
|
-
export {
|
|
9
|
+
export { SERVER_OPENAPI_DOCUMENT } from './openapi.js';
|
|
8
10
|
export { type AuthMode, authModeSchema, authSchema, type Branding, brandingSchema, DEFAULT_BRANDING, DEPRECATED_CONFIG_PROPS, emailAuthSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, type JeevesConfig, jeevesConfigSchema, keyEntrySchema, type LoggingConfig, loggingConfigSchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema, themeOverridesSchema, } from './schema.js';
|
|
9
11
|
export type { AuthStatusResponse, DriveEntry, ExportCacheClearResponse, ExportLink, FileMutationAction, LinkInfoResponse, OAuthStartRequest, OAuthStartResponse, RotateKeyResponse, ShareForRequest, ShareForResponse, ShareRequest, ShareResponse, } from './types.js';
|
|
10
12
|
export { getUrlKey, LEGACY_URL_KEY_PARAM, URL_KEY_PARAM } from './urlKey.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
1
|
+
export { SERVER_ERROR_CODES, SERVER_ERROR_STATUS } from './errors.js';
|
|
2
|
+
export { breadcrumbSchema, browseResponseSchema, directoryEntrySchema, directoryListingSchema, driveSchema, drivesResponseSchema, exportCacheClearResponseSchema, exportLinkSchema, fileContentQuerySchema, fileContentResponseSchema, fileMetadataSchema, fileWriteBodySchema, fileWriteResponseSchema, headingSchema, linkInfoResponseSchema, okResponseSchema } from './catalog/contentSchemas.js';
|
|
3
|
+
export { eventLogEntrySchema, receiveEventResponseSchema } from './catalog/eventEntries.js';
|
|
4
|
+
export { FILE_MUTATION_ACTIONS, FILE_MUTATION_REQUIRED_FIELDS, fileMutateBodySchema } from './catalog/fileMutateSchema.js';
|
|
5
|
+
export { oauthCredentialQuerySchema, oauthStartBodySchema, oauthStartResponseSchema, oauthStatusResponseSchema, oauthTokenResponseSchema } from './catalog/oauthEntries.js';
|
|
6
|
+
export { shareQuerySchema } from './catalog/route.js';
|
|
7
|
+
export { SERVER_CATALOG } from './catalog/serverCatalog.js';
|
|
8
|
+
export { linkResponseSchema, resolvePathResponseSchema, rotateKeyResponseSchema, shareBodySchema, shareForBodySchema, shareForResponseSchema, shareResponseSchema } from './catalog/sharingEntries.js';
|
|
9
|
+
export { eventQueueHealthSchema, serverHealthSchema, serviceProbeSchema } from './catalog/statusSchemas.js';
|
|
10
|
+
export { authStatusQuerySchema, authStatusResponseSchema, healthResponseSchema, insiderKeyResponseSchema, pathKeyResponseSchema, searchBodySchema, searchResponseSchema, searchResultSchema, sendMagicLinkBodySchema, sendMagicLinkResponseSchema } from './catalog/utilitySchemas.js';
|
|
11
|
+
export { PRINT_PAPER_FORMATS, PRINT_STYLE_NAME, absolutePathSchema, isAbsolutePath, printPageSchema, printStyleSchema, printStylesSchema } from './configPrintStyles.js';
|
|
12
|
+
export { computeDeepShareKey, timingSafeEqual } from './crypto.js';
|
|
13
|
+
export { SERVER_OPENAPI_DOCUMENT } from './openapi.js';
|
|
14
|
+
export { DEFAULT_BRANDING, DEPRECATED_CONFIG_PROPS, jeevesConfigSchema } from './schema.js';
|
|
4
15
|
export { LEGACY_URL_KEY_PARAM, URL_KEY_PARAM, getUrlKey } from './urlKey.js';
|
|
16
|
+
export { authModeSchema, authSchema, emailAuthSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, keyEntrySchema, scopesObjectSchema, scopesSchema } from './configAuthSchema.js';
|
|
17
|
+
export { brandingSchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, themeOverridesSchema } from './configFeatureSchemas.js';
|
|
18
|
+
export { computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey } from '@karmaniverous/jeeves';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jeeves-server-core's committed OpenAPI 3.1 document for `SERVER_CATALOG`, bundled as `SERVER_OPENAPI_DOCUMENT` (the service serves it at `GET /openapi.json`). Also published as the `@karmaniverous/jeeves-server-core/openapi.json` sub-path for out-of-repo generators. Pure.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The OpenAPI document generated from `SERVER_CATALOG` (`npm run openapi`).
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Typed loosely so core's declarations don't depend on OpenAPI type
|
|
11
|
+
* packages.
|
|
12
|
+
*/
|
|
13
|
+
export declare const SERVER_OPENAPI_DOCUMENT: Readonly<Record<string, unknown>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import document from '../openapi.json.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* jeeves-server-core's committed OpenAPI 3.1 document for `SERVER_CATALOG`, bundled as `SERVER_OPENAPI_DOCUMENT` (the service serves it at `GET /openapi.json`). Also published as the `@karmaniverous/jeeves-server-core/openapi.json` sub-path for out-of-repo generators. Pure.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The OpenAPI document generated from `SERVER_CATALOG` (`npm run openapi`).
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* Typed loosely so core's declarations don't depend on OpenAPI type
|
|
13
|
+
* packages.
|
|
14
|
+
*/
|
|
15
|
+
const SERVER_OPENAPI_DOCUMENT = document;
|
|
16
|
+
|
|
17
|
+
export { SERVER_OPENAPI_DOCUMENT };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The committed OpenAPI document: in step with `SERVER_CATALOG` (drift; run `npm run openapi`), a valid OpenAPI 3.1 document with one operation per entry, security per access class and the core version, exported and published as a sub-path, regenerated after a release bump.
|
|
3
|
+
*/
|
|
4
|
+
export {};
|