@hot-updater/plugin-api-keys 1.0.0-rc.20 → 1.0.0-rc.22
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 +2 -2
- package/dist/server/apiKeys.d.cts +2 -34
- package/dist/server/apiKeys.d.mts +2 -34
- package/dist/server/cli.cjs +11 -104
- package/dist/server/cli.mjs +11 -104
- package/dist/server/index.cjs +4 -4
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.mts +2 -2
- package/dist/server/index.mjs +2 -2
- package/dist/server/model.cjs +2 -2
- package/dist/server/model.d.cts +1 -1
- package/dist/server/model.d.mts +1 -1
- package/dist/server/model.mjs +1 -1
- package/dist/server/official.cjs +12 -0
- package/dist/server/official.mjs +12 -0
- package/dist/server/schema.cjs +1 -1
- package/dist/server/schema.d.cts +1 -1
- package/dist/server/schema.d.mts +1 -1
- package/dist/server/schema.mjs +1 -1
- package/package.json +7 -9
- package/dist/internal.cjs +0 -11
- package/dist/internal.d.cts +0 -3
- package/dist/internal.d.mts +0 -3
- package/dist/internal.mjs +0 -3
- package/dist/server/cli.d.cts +0 -17
- package/dist/server/cli.d.mts +0 -17
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @hot-updater/plugin-api-keys
|
|
2
2
|
|
|
3
3
|
Hot Updater's API keys plugin. It protects the server's client routes with API
|
|
4
|
-
keys
|
|
5
|
-
|
|
4
|
+
keys and stores their SHA-256 digests; the built-in `hot-updater api-key`
|
|
5
|
+
manages them.
|
|
6
6
|
|
|
7
7
|
You don't install it on its own. `@hot-updater/server` depends on it and
|
|
8
8
|
re-exports its `./server` entry:
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiKeyRow } from "./model.cjs";
|
|
2
2
|
//#region src/server/apiKeys.d.ts
|
|
3
3
|
declare const API_KEY_HEADER_NAME = "x-api-key";
|
|
4
|
-
declare const normalizeApiKeyHeaderName: (value?: unknown) => string;
|
|
5
|
-
declare const hashApiKey: (apiKey: string) => Promise<string>;
|
|
6
4
|
type ApiKeyMetadata = Omit<ApiKeyRow, "hash">;
|
|
7
5
|
interface CreatedApiKey {
|
|
8
6
|
/** Plaintext credential. It cannot be recovered after this call returns. */
|
|
@@ -25,35 +23,5 @@ interface ApiKeyManagementAPI {
|
|
|
25
23
|
readonly id: string;
|
|
26
24
|
}): Promise<ApiKeyMetadata | null>;
|
|
27
25
|
}
|
|
28
|
-
declare const registerApiKey: (input: {
|
|
29
|
-
readonly apiKey: string;
|
|
30
|
-
readonly apiKeys: ApiKeyModel;
|
|
31
|
-
readonly createdAtMs?: number;
|
|
32
|
-
readonly name: string;
|
|
33
|
-
}) => Promise<CreatedApiKey>;
|
|
34
|
-
declare const createApiKey: (input: {
|
|
35
|
-
readonly apiKeys: ApiKeyModel;
|
|
36
|
-
readonly name: string;
|
|
37
|
-
}) => Promise<CreatedApiKey>;
|
|
38
|
-
/**
|
|
39
|
-
* Provisions the client API key used by managed init.
|
|
40
|
-
*
|
|
41
|
-
* A saved plaintext key is registered idempotently; otherwise a new key is
|
|
42
|
-
* created. Callers must persist or display the returned plaintext because the
|
|
43
|
-
* database stores only its hash.
|
|
44
|
-
*/
|
|
45
|
-
declare const provisionApiKey: (input: {
|
|
46
|
-
readonly apiKeys: ApiKeyModel;
|
|
47
|
-
readonly existingApiKey?: string;
|
|
48
|
-
readonly name: string;
|
|
49
|
-
}) => Promise<CreatedApiKey>;
|
|
50
|
-
declare const authenticateApiKey: (input: {
|
|
51
|
-
readonly apiKeys: ApiKeyModel;
|
|
52
|
-
readonly headerName?: string;
|
|
53
|
-
readonly request: Request;
|
|
54
|
-
}) => Promise<boolean>;
|
|
55
|
-
declare const createApiKeyManagement: (input: {
|
|
56
|
-
readonly apiKeys: ApiKeyModel;
|
|
57
|
-
}) => ApiKeyManagementAPI;
|
|
58
26
|
//#endregion
|
|
59
|
-
export { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey
|
|
27
|
+
export { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiKeyRow } from "./model.mjs";
|
|
2
2
|
//#region src/server/apiKeys.d.ts
|
|
3
3
|
declare const API_KEY_HEADER_NAME = "x-api-key";
|
|
4
|
-
declare const normalizeApiKeyHeaderName: (value?: unknown) => string;
|
|
5
|
-
declare const hashApiKey: (apiKey: string) => Promise<string>;
|
|
6
4
|
type ApiKeyMetadata = Omit<ApiKeyRow, "hash">;
|
|
7
5
|
interface CreatedApiKey {
|
|
8
6
|
/** Plaintext credential. It cannot be recovered after this call returns. */
|
|
@@ -25,35 +23,5 @@ interface ApiKeyManagementAPI {
|
|
|
25
23
|
readonly id: string;
|
|
26
24
|
}): Promise<ApiKeyMetadata | null>;
|
|
27
25
|
}
|
|
28
|
-
declare const registerApiKey: (input: {
|
|
29
|
-
readonly apiKey: string;
|
|
30
|
-
readonly apiKeys: ApiKeyModel;
|
|
31
|
-
readonly createdAtMs?: number;
|
|
32
|
-
readonly name: string;
|
|
33
|
-
}) => Promise<CreatedApiKey>;
|
|
34
|
-
declare const createApiKey: (input: {
|
|
35
|
-
readonly apiKeys: ApiKeyModel;
|
|
36
|
-
readonly name: string;
|
|
37
|
-
}) => Promise<CreatedApiKey>;
|
|
38
|
-
/**
|
|
39
|
-
* Provisions the client API key used by managed init.
|
|
40
|
-
*
|
|
41
|
-
* A saved plaintext key is registered idempotently; otherwise a new key is
|
|
42
|
-
* created. Callers must persist or display the returned plaintext because the
|
|
43
|
-
* database stores only its hash.
|
|
44
|
-
*/
|
|
45
|
-
declare const provisionApiKey: (input: {
|
|
46
|
-
readonly apiKeys: ApiKeyModel;
|
|
47
|
-
readonly existingApiKey?: string;
|
|
48
|
-
readonly name: string;
|
|
49
|
-
}) => Promise<CreatedApiKey>;
|
|
50
|
-
declare const authenticateApiKey: (input: {
|
|
51
|
-
readonly apiKeys: ApiKeyModel;
|
|
52
|
-
readonly headerName?: string;
|
|
53
|
-
readonly request: Request;
|
|
54
|
-
}) => Promise<boolean>;
|
|
55
|
-
declare const createApiKeyManagement: (input: {
|
|
56
|
-
readonly apiKeys: ApiKeyModel;
|
|
57
|
-
}) => ApiKeyManagementAPI;
|
|
58
26
|
//#endregion
|
|
59
|
-
export { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey
|
|
27
|
+
export { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey };
|
package/dist/server/cli.cjs
CHANGED
|
@@ -6,110 +6,17 @@ const generateApiKey = () => {
|
|
|
6
6
|
const bytes = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32));
|
|
7
7
|
return btoa(String.fromCharCode(...bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
key: "prefix",
|
|
21
|
-
label: "Prefix",
|
|
22
|
-
format: ui.muted
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
key: "status",
|
|
26
|
-
label: "Status",
|
|
27
|
-
format: (value) => value.trim() === "active" ? ui.success(value) : ui.danger(value)
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
key: "created",
|
|
31
|
-
label: "Created",
|
|
32
|
-
format: ui.muted
|
|
33
|
-
}
|
|
34
|
-
], records.map((record) => ({
|
|
35
|
-
created: new Date(record.created_at_ms).toISOString(),
|
|
36
|
-
id: record.id,
|
|
37
|
-
name: record.name,
|
|
38
|
-
prefix: record.prefix,
|
|
39
|
-
status: record.revoked_at_ms === null ? "active" : "revoked"
|
|
40
|
-
})));
|
|
41
|
-
/**
|
|
42
|
-
* `hot-updater api-key create|list|revoke`, and the API key that init
|
|
43
|
-
* provisions for an app, sent in `headerName`.
|
|
44
|
-
*/
|
|
45
|
-
const apiKeysCli = (headerName) => ({
|
|
46
|
-
commands: [{
|
|
47
|
-
name: "api-key",
|
|
48
|
-
description: "Manage API keys",
|
|
49
|
-
commands: [
|
|
50
|
-
{
|
|
51
|
-
name: "create",
|
|
52
|
-
description: "Create an API key",
|
|
53
|
-
options: [{
|
|
54
|
-
flags: "--name <name>",
|
|
55
|
-
description: "name used to identify the API key",
|
|
56
|
-
required: true
|
|
57
|
-
}],
|
|
58
|
-
async run({ api, options, ui }) {
|
|
59
|
-
const created = await api.create({ name: String(options.name) });
|
|
60
|
-
ui.message(ui.block("API key created", [
|
|
61
|
-
ui.kv("Name", created.record.name),
|
|
62
|
-
ui.kv("ID", ui.id(created.record.id)),
|
|
63
|
-
ui.kv("API key", ui.warning(created.apiKey))
|
|
64
|
-
]));
|
|
65
|
-
ui.warn("Save this API key now. It will not be shown again.");
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: "list",
|
|
70
|
-
description: "List API keys",
|
|
71
|
-
options: [{
|
|
72
|
-
flags: "--json",
|
|
73
|
-
description: "output API key metadata as JSON"
|
|
74
|
-
}],
|
|
75
|
-
async run({ api, options, ui }) {
|
|
76
|
-
const records = [...await api.list()].sort((left, right) => right.created_at_ms - left.created_at_ms);
|
|
77
|
-
if (options.json) ui.print(JSON.stringify(records, null, 2));
|
|
78
|
-
else ui.message(formatList(ui, records));
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: "revoke",
|
|
83
|
-
description: "Revoke an API key",
|
|
84
|
-
arguments: [{
|
|
85
|
-
name: "id",
|
|
86
|
-
description: "API key id"
|
|
87
|
-
}],
|
|
88
|
-
options: [{
|
|
89
|
-
flags: "-y, --yes",
|
|
90
|
-
description: "skip confirmation prompt"
|
|
91
|
-
}],
|
|
92
|
-
async run({ api, args, options, ui }) {
|
|
93
|
-
const id = String(args.id);
|
|
94
|
-
if (!options.yes) await ui.confirm(`Revoke API key ${id}?`);
|
|
95
|
-
const revoked = await api.revoke({ id });
|
|
96
|
-
if (revoked === null) throw new Error(`API key "${id}" was not found.`);
|
|
97
|
-
ui.message(ui.block("API key revoked", [ui.kv("Name", revoked.name), ui.kv("ID", ui.id(revoked.id))]));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
]
|
|
101
|
-
}],
|
|
102
|
-
clientCredential: {
|
|
103
|
-
label: "API key",
|
|
104
|
-
header: headerName,
|
|
105
|
-
env: API_KEY_ENV,
|
|
106
|
-
generate: generateApiKey,
|
|
107
|
-
provision: async (api, { existing, name }) => (await api.provision({
|
|
108
|
-
...existing === void 0 ? {} : { existingApiKey: existing },
|
|
109
|
-
name
|
|
110
|
-
})).apiKey
|
|
111
|
-
}
|
|
112
|
-
});
|
|
9
|
+
/** The API key that init provisions for an app, sent in `headerName`. */
|
|
10
|
+
const apiKeysCli = (headerName) => ({ clientCredential: {
|
|
11
|
+
label: "API key",
|
|
12
|
+
header: headerName,
|
|
13
|
+
env: API_KEY_ENV,
|
|
14
|
+
generate: generateApiKey,
|
|
15
|
+
provision: async (api, { existing, name }) => (await api.provision({
|
|
16
|
+
...existing === void 0 ? {} : { existingApiKey: existing },
|
|
17
|
+
name
|
|
18
|
+
})).apiKey
|
|
19
|
+
} });
|
|
113
20
|
//#endregion
|
|
114
21
|
exports.API_KEY_ENV = API_KEY_ENV;
|
|
115
22
|
exports.apiKeysCli = apiKeysCli;
|
package/dist/server/cli.mjs
CHANGED
|
@@ -6,109 +6,16 @@ const generateApiKey = () => {
|
|
|
6
6
|
const bytes = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32));
|
|
7
7
|
return btoa(String.fromCharCode(...bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
key: "prefix",
|
|
21
|
-
label: "Prefix",
|
|
22
|
-
format: ui.muted
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
key: "status",
|
|
26
|
-
label: "Status",
|
|
27
|
-
format: (value) => value.trim() === "active" ? ui.success(value) : ui.danger(value)
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
key: "created",
|
|
31
|
-
label: "Created",
|
|
32
|
-
format: ui.muted
|
|
33
|
-
}
|
|
34
|
-
], records.map((record) => ({
|
|
35
|
-
created: new Date(record.created_at_ms).toISOString(),
|
|
36
|
-
id: record.id,
|
|
37
|
-
name: record.name,
|
|
38
|
-
prefix: record.prefix,
|
|
39
|
-
status: record.revoked_at_ms === null ? "active" : "revoked"
|
|
40
|
-
})));
|
|
41
|
-
/**
|
|
42
|
-
* `hot-updater api-key create|list|revoke`, and the API key that init
|
|
43
|
-
* provisions for an app, sent in `headerName`.
|
|
44
|
-
*/
|
|
45
|
-
const apiKeysCli = (headerName) => ({
|
|
46
|
-
commands: [{
|
|
47
|
-
name: "api-key",
|
|
48
|
-
description: "Manage API keys",
|
|
49
|
-
commands: [
|
|
50
|
-
{
|
|
51
|
-
name: "create",
|
|
52
|
-
description: "Create an API key",
|
|
53
|
-
options: [{
|
|
54
|
-
flags: "--name <name>",
|
|
55
|
-
description: "name used to identify the API key",
|
|
56
|
-
required: true
|
|
57
|
-
}],
|
|
58
|
-
async run({ api, options, ui }) {
|
|
59
|
-
const created = await api.create({ name: String(options.name) });
|
|
60
|
-
ui.message(ui.block("API key created", [
|
|
61
|
-
ui.kv("Name", created.record.name),
|
|
62
|
-
ui.kv("ID", ui.id(created.record.id)),
|
|
63
|
-
ui.kv("API key", ui.warning(created.apiKey))
|
|
64
|
-
]));
|
|
65
|
-
ui.warn("Save this API key now. It will not be shown again.");
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: "list",
|
|
70
|
-
description: "List API keys",
|
|
71
|
-
options: [{
|
|
72
|
-
flags: "--json",
|
|
73
|
-
description: "output API key metadata as JSON"
|
|
74
|
-
}],
|
|
75
|
-
async run({ api, options, ui }) {
|
|
76
|
-
const records = [...await api.list()].sort((left, right) => right.created_at_ms - left.created_at_ms);
|
|
77
|
-
if (options.json) ui.print(JSON.stringify(records, null, 2));
|
|
78
|
-
else ui.message(formatList(ui, records));
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: "revoke",
|
|
83
|
-
description: "Revoke an API key",
|
|
84
|
-
arguments: [{
|
|
85
|
-
name: "id",
|
|
86
|
-
description: "API key id"
|
|
87
|
-
}],
|
|
88
|
-
options: [{
|
|
89
|
-
flags: "-y, --yes",
|
|
90
|
-
description: "skip confirmation prompt"
|
|
91
|
-
}],
|
|
92
|
-
async run({ api, args, options, ui }) {
|
|
93
|
-
const id = String(args.id);
|
|
94
|
-
if (!options.yes) await ui.confirm(`Revoke API key ${id}?`);
|
|
95
|
-
const revoked = await api.revoke({ id });
|
|
96
|
-
if (revoked === null) throw new Error(`API key "${id}" was not found.`);
|
|
97
|
-
ui.message(ui.block("API key revoked", [ui.kv("Name", revoked.name), ui.kv("ID", ui.id(revoked.id))]));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
]
|
|
101
|
-
}],
|
|
102
|
-
clientCredential: {
|
|
103
|
-
label: "API key",
|
|
104
|
-
header: headerName,
|
|
105
|
-
env: API_KEY_ENV,
|
|
106
|
-
generate: generateApiKey,
|
|
107
|
-
provision: async (api, { existing, name }) => (await api.provision({
|
|
108
|
-
...existing === void 0 ? {} : { existingApiKey: existing },
|
|
109
|
-
name
|
|
110
|
-
})).apiKey
|
|
111
|
-
}
|
|
112
|
-
});
|
|
9
|
+
/** The API key that init provisions for an app, sent in `headerName`. */
|
|
10
|
+
const apiKeysCli = (headerName) => ({ clientCredential: {
|
|
11
|
+
label: "API key",
|
|
12
|
+
header: headerName,
|
|
13
|
+
env: API_KEY_ENV,
|
|
14
|
+
generate: generateApiKey,
|
|
15
|
+
provision: async (api, { existing, name }) => (await api.provision({
|
|
16
|
+
...existing === void 0 ? {} : { existingApiKey: existing },
|
|
17
|
+
name
|
|
18
|
+
})).apiKey
|
|
19
|
+
} });
|
|
113
20
|
//#endregion
|
|
114
21
|
export { API_KEY_ENV, apiKeysCli };
|
package/dist/server/index.cjs
CHANGED
|
@@ -2,9 +2,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_apiKeys = require("./apiKeys.cjs");
|
|
3
3
|
const require_cli = require("./cli.cjs");
|
|
4
4
|
const require_model = require("./model.cjs");
|
|
5
|
+
const require_official = require("./official.cjs");
|
|
5
6
|
const require_schema = require("./schema.cjs");
|
|
6
|
-
let
|
|
7
|
-
let _hot_updater_plugin_core_server_plugin = require("@hot-updater/plugin-core/server-plugin");
|
|
7
|
+
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
8
8
|
//#region src/server/index.ts
|
|
9
9
|
/**
|
|
10
10
|
* API keys: protects client routes with keys whose SHA-256 digests
|
|
@@ -12,7 +12,7 @@ let _hot_updater_plugin_core_server_plugin = require("@hot-updater/plugin-core/s
|
|
|
12
12
|
*/
|
|
13
13
|
const apiKeys = (options = {}) => {
|
|
14
14
|
const headerName = require_apiKeys.normalizeApiKeyHeaderName(options.headerName ?? "x-api-key");
|
|
15
|
-
const plugin = (0,
|
|
15
|
+
const plugin = (0, _hot_updater_plugin_core.definePlugin)({
|
|
16
16
|
id: "apiKeys",
|
|
17
17
|
namespace: false,
|
|
18
18
|
provides: { clientAuth: true },
|
|
@@ -46,7 +46,7 @@ const apiKeys = (options = {}) => {
|
|
|
46
46
|
},
|
|
47
47
|
cli: require_cli.apiKeysCli(headerName)
|
|
48
48
|
});
|
|
49
|
-
return
|
|
49
|
+
return require_official.markOfficial(plugin);
|
|
50
50
|
};
|
|
51
51
|
//#endregion
|
|
52
52
|
exports.API_KEY_HEADER_NAME = require_apiKeys.API_KEY_HEADER_NAME;
|
package/dist/server/index.d.cts
CHANGED
|
@@ -10,8 +10,8 @@ interface ApiKeysOptions {
|
|
|
10
10
|
* API keys: protects client routes with keys whose SHA-256 digests
|
|
11
11
|
* are stored, and manages them in-process.
|
|
12
12
|
*/
|
|
13
|
-
declare const apiKeys: (options?: ApiKeysOptions) => import("@hot-updater/plugin-core
|
|
14
|
-
readonly api_keys: import("@hot-updater/plugin-core
|
|
13
|
+
declare const apiKeys: (options?: ApiKeysOptions) => import("@hot-updater/plugin-core").HotUpdaterPlugin<"apiKeys", {
|
|
14
|
+
readonly api_keys: import("@hot-updater/plugin-core").TableDefinition<{
|
|
15
15
|
readonly id: {
|
|
16
16
|
readonly type: "string";
|
|
17
17
|
readonly maxLength: 255;
|
package/dist/server/index.d.mts
CHANGED
|
@@ -10,8 +10,8 @@ interface ApiKeysOptions {
|
|
|
10
10
|
* API keys: protects client routes with keys whose SHA-256 digests
|
|
11
11
|
* are stored, and manages them in-process.
|
|
12
12
|
*/
|
|
13
|
-
declare const apiKeys: (options?: ApiKeysOptions) => import("@hot-updater/plugin-core
|
|
14
|
-
readonly api_keys: import("@hot-updater/plugin-core
|
|
13
|
+
declare const apiKeys: (options?: ApiKeysOptions) => import("@hot-updater/plugin-core").HotUpdaterPlugin<"apiKeys", {
|
|
14
|
+
readonly api_keys: import("@hot-updater/plugin-core").TableDefinition<{
|
|
15
15
|
readonly id: {
|
|
16
16
|
readonly type: "string";
|
|
17
17
|
readonly maxLength: 255;
|
package/dist/server/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { API_KEY_HEADER_NAME, authenticateApiKey, createApiKeyManagement, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey } from "./apiKeys.mjs";
|
|
2
2
|
import { apiKeysCli } from "./cli.mjs";
|
|
3
3
|
import { createApiKeyModel } from "./model.mjs";
|
|
4
|
+
import { markOfficial } from "./official.mjs";
|
|
4
5
|
import { apiKeysSchema } from "./schema.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { definePlugin } from "@hot-updater/plugin-core/server-plugin";
|
|
6
|
+
import { definePlugin } from "@hot-updater/plugin-core";
|
|
7
7
|
//#region src/server/index.ts
|
|
8
8
|
/**
|
|
9
9
|
* API keys: protects client routes with keys whose SHA-256 digests
|
package/dist/server/model.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let
|
|
1
|
+
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
2
2
|
//#region src/server/model.ts
|
|
3
3
|
const toRow = (row) => ({
|
|
4
4
|
id: row.id,
|
|
@@ -19,7 +19,7 @@ const createApiKeyModel = (db) => ({
|
|
|
19
19
|
return "created";
|
|
20
20
|
});
|
|
21
21
|
} catch (error) {
|
|
22
|
-
if (error instanceof
|
|
22
|
+
if (error instanceof _hot_updater_plugin_core.DatabaseConstraintError && error.reason === "unique") return "existing";
|
|
23
23
|
throw error;
|
|
24
24
|
}
|
|
25
25
|
},
|
package/dist/server/model.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiKeysSchema } from "./schema.cjs";
|
|
2
|
-
import { HotUpdaterDatabase } from "@hot-updater/plugin-core
|
|
2
|
+
import { HotUpdaterDatabase } from "@hot-updater/plugin-core";
|
|
3
3
|
//#region src/server/model.d.ts
|
|
4
4
|
interface ApiKeyRow {
|
|
5
5
|
readonly id: string;
|
package/dist/server/model.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiKeysSchema } from "./schema.mjs";
|
|
2
|
-
import { HotUpdaterDatabase } from "@hot-updater/plugin-core
|
|
2
|
+
import { HotUpdaterDatabase } from "@hot-updater/plugin-core";
|
|
3
3
|
//#region src/server/model.d.ts
|
|
4
4
|
interface ApiKeyRow {
|
|
5
5
|
readonly id: string;
|
package/dist/server/model.mjs
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/server/official.ts
|
|
2
|
+
/**
|
|
3
|
+
* The brand of Hot Updater's own plugins, a registered symbol that
|
|
4
|
+
* `@hot-updater/server` reads to reserve the id "apiKeys" for this plugin.
|
|
5
|
+
* Each official plugin package keeps this copy, so none imports another's
|
|
6
|
+
* internals for it.
|
|
7
|
+
*/
|
|
8
|
+
const OFFICIAL = Symbol.for("@hot-updater/server/official-plugin");
|
|
9
|
+
/** Marks a plugin one of Hot Updater's own factories made. */
|
|
10
|
+
const markOfficial = (plugin) => Object.defineProperty(plugin, OFFICIAL, { value: true });
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.markOfficial = markOfficial;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/server/official.ts
|
|
2
|
+
/**
|
|
3
|
+
* The brand of Hot Updater's own plugins, a registered symbol that
|
|
4
|
+
* `@hot-updater/server` reads to reserve the id "apiKeys" for this plugin.
|
|
5
|
+
* Each official plugin package keeps this copy, so none imports another's
|
|
6
|
+
* internals for it.
|
|
7
|
+
*/
|
|
8
|
+
const OFFICIAL = Symbol.for("@hot-updater/server/official-plugin");
|
|
9
|
+
/** Marks a plugin one of Hot Updater's own factories made. */
|
|
10
|
+
const markOfficial = (plugin) => Object.defineProperty(plugin, OFFICIAL, { value: true });
|
|
11
|
+
//#endregion
|
|
12
|
+
export { markOfficial };
|
package/dist/server/schema.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/server/schema.ts
|
|
2
2
|
/** v1's `api_keys` columns; the plaintext key is never stored, only its SHA-256 digest. */
|
|
3
|
-
const apiKeysSchema = { api_keys: (0, require("@hot-updater/plugin-core
|
|
3
|
+
const apiKeysSchema = { api_keys: (0, require("@hot-updater/plugin-core").defineTable)({
|
|
4
4
|
id: {
|
|
5
5
|
type: "string",
|
|
6
6
|
maxLength: 255
|
package/dist/server/schema.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/server/schema.d.ts
|
|
2
2
|
/** v1's `api_keys` columns; the plaintext key is never stored, only its SHA-256 digest. */
|
|
3
3
|
declare const apiKeysSchema: {
|
|
4
|
-
readonly api_keys: import("@hot-updater/plugin-core
|
|
4
|
+
readonly api_keys: import("@hot-updater/plugin-core").TableDefinition<{
|
|
5
5
|
readonly id: {
|
|
6
6
|
readonly type: "string";
|
|
7
7
|
readonly maxLength: 255;
|
package/dist/server/schema.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/server/schema.d.ts
|
|
2
2
|
/** v1's `api_keys` columns; the plaintext key is never stored, only its SHA-256 digest. */
|
|
3
3
|
declare const apiKeysSchema: {
|
|
4
|
-
readonly api_keys: import("@hot-updater/plugin-core
|
|
4
|
+
readonly api_keys: import("@hot-updater/plugin-core").TableDefinition<{
|
|
5
5
|
readonly id: {
|
|
6
6
|
readonly type: "string";
|
|
7
7
|
readonly maxLength: 255;
|
package/dist/server/schema.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineTable } from "@hot-updater/plugin-core
|
|
1
|
+
import { defineTable } from "@hot-updater/plugin-core";
|
|
2
2
|
//#region src/server/schema.ts
|
|
3
3
|
/** v1's `api_keys` columns; the plaintext key is never stored, only its SHA-256 digest. */
|
|
4
4
|
const apiKeysSchema = { api_keys: defineTable({
|
package/package.json
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/plugin-api-keys",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.22",
|
|
5
5
|
"description": "Hot Updater's API keys plugin: protects client routes with API keys and manages them",
|
|
6
6
|
"exports": {
|
|
7
|
-
"./internal": {
|
|
8
|
-
"import": "./dist/internal.mjs",
|
|
9
|
-
"require": "./dist/internal.cjs"
|
|
10
|
-
},
|
|
11
7
|
"./server": {
|
|
12
8
|
"import": "./dist/server/index.mjs",
|
|
13
9
|
"require": "./dist/server/index.cjs"
|
|
@@ -31,11 +27,13 @@
|
|
|
31
27
|
"dist",
|
|
32
28
|
"package.json"
|
|
33
29
|
],
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@hot-updater/plugin-core": "1.0.0-rc.20"
|
|
36
|
-
},
|
|
37
30
|
"devDependencies": {
|
|
38
|
-
"@types/node": "^20"
|
|
31
|
+
"@types/node": "^20",
|
|
32
|
+
"vitest": "4.1.4",
|
|
33
|
+
"@hot-updater/plugin-core": "1.0.0-rc.22"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@hot-updater/plugin-core": "^1.0.0-rc.22"
|
|
39
37
|
},
|
|
40
38
|
"scripts": {
|
|
41
39
|
"build": "tsdown",
|
package/dist/internal.cjs
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_apiKeys = require("./server/apiKeys.cjs");
|
|
3
|
-
const require_cli = require("./server/cli.cjs");
|
|
4
|
-
exports.apiKeysCli = require_cli.apiKeysCli;
|
|
5
|
-
exports.authenticateApiKey = require_apiKeys.authenticateApiKey;
|
|
6
|
-
exports.createApiKey = require_apiKeys.createApiKey;
|
|
7
|
-
exports.createApiKeyManagement = require_apiKeys.createApiKeyManagement;
|
|
8
|
-
exports.hashApiKey = require_apiKeys.hashApiKey;
|
|
9
|
-
exports.normalizeApiKeyHeaderName = require_apiKeys.normalizeApiKeyHeaderName;
|
|
10
|
-
exports.provisionApiKey = require_apiKeys.provisionApiKey;
|
|
11
|
-
exports.registerApiKey = require_apiKeys.registerApiKey;
|
package/dist/internal.d.cts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey } from "./server/apiKeys.cjs";
|
|
2
|
-
import { ApiKeysCliApi, apiKeysCli } from "./server/cli.cjs";
|
|
3
|
-
export { type ApiKeysCliApi, apiKeysCli, authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey };
|
package/dist/internal.d.mts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey } from "./server/apiKeys.mjs";
|
|
2
|
-
import { ApiKeysCliApi, apiKeysCli } from "./server/cli.mjs";
|
|
3
|
-
export { type ApiKeysCliApi, apiKeysCli, authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey };
|
package/dist/internal.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey } from "./server/apiKeys.mjs";
|
|
2
|
-
import { apiKeysCli } from "./server/cli.mjs";
|
|
3
|
-
export { apiKeysCli, authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey };
|
package/dist/server/cli.d.cts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ApiKeyManagementAPI, CreatedApiKey } from "./apiKeys.cjs";
|
|
2
|
-
import { PluginCli } from "@hot-updater/plugin-core/server-plugin";
|
|
3
|
-
//#region src/server/cli.d.ts
|
|
4
|
-
/** The part of the apiKeys() API the CLI uses. */
|
|
5
|
-
interface ApiKeysCliApi extends ApiKeyManagementAPI {
|
|
6
|
-
provision(input: {
|
|
7
|
-
readonly existingApiKey?: string;
|
|
8
|
-
readonly name: string;
|
|
9
|
-
}): Promise<CreatedApiKey>;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* `hot-updater api-key create|list|revoke`, and the API key that init
|
|
13
|
-
* provisions for an app, sent in `headerName`.
|
|
14
|
-
*/
|
|
15
|
-
declare const apiKeysCli: (headerName: string) => PluginCli<ApiKeysCliApi>;
|
|
16
|
-
//#endregion
|
|
17
|
-
export { ApiKeysCliApi, apiKeysCli };
|
package/dist/server/cli.d.mts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ApiKeyManagementAPI, CreatedApiKey } from "./apiKeys.mjs";
|
|
2
|
-
import { PluginCli } from "@hot-updater/plugin-core/server-plugin";
|
|
3
|
-
//#region src/server/cli.d.ts
|
|
4
|
-
/** The part of the apiKeys() API the CLI uses. */
|
|
5
|
-
interface ApiKeysCliApi extends ApiKeyManagementAPI {
|
|
6
|
-
provision(input: {
|
|
7
|
-
readonly existingApiKey?: string;
|
|
8
|
-
readonly name: string;
|
|
9
|
-
}): Promise<CreatedApiKey>;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* `hot-updater api-key create|list|revoke`, and the API key that init
|
|
13
|
-
* provisions for an app, sent in `headerName`.
|
|
14
|
-
*/
|
|
15
|
-
declare const apiKeysCli: (headerName: string) => PluginCli<ApiKeysCliApi>;
|
|
16
|
-
//#endregion
|
|
17
|
-
export { ApiKeysCliApi, apiKeysCli };
|