intlayer-editor 9.6.0 → 9.7.1
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/bin/intlayer-editor.mjs +29 -7
- package/client/dist/assets/CodeBlockShiki-BaQlmvsF.js +2 -0
- package/client/dist/assets/MarkDownRender-CufSxUcK.js +25 -0
- package/client/dist/assets/MarkDownRender-HV9SKc56.js +1 -0
- package/client/dist/assets/MarkdownEditor-BSbSD-tQ.js +174 -0
- package/client/dist/assets/{astro-JHDYjn39.js → astro-BZ97kZFP.js} +1 -1
- package/client/dist/assets/codeTransformer-pmm6yJGh.js +9 -0
- package/client/dist/assets/compat-BqYysBkt.js +1 -0
- package/client/dist/assets/css-BGIxQoYs.js +1 -0
- package/client/dist/assets/css-DgaLhXQH.js +1 -0
- package/client/dist/assets/dist-VBWB9uC8.js +11 -0
- package/client/dist/assets/extractUrlFromSitemap-Chj1JVpo.js +1 -0
- package/client/dist/assets/html-BCy9P6D2.js +1 -0
- package/client/dist/assets/{html-B2cKP6UN.js → html-DSw1lh5G.js} +1 -1
- package/client/dist/assets/index-65aMFXUF.css +2 -0
- package/client/dist/assets/index-MyctEsPU.js +116 -0
- package/client/dist/assets/javascript-CpIGwZ_Y.js +1 -0
- package/client/dist/assets/json-C3WlssX3.js +1 -0
- package/client/dist/assets/purify.es-Dqk5qvad.js +3 -0
- package/client/dist/assets/shikiBundle-DbyGgq42.js +12 -0
- package/client/dist/assets/{svelte-tEuLYt3E.js → svelte-CdeT-Ich.js} +1 -1
- package/client/dist/assets/tsx-CGosfAUg.js +1 -0
- package/client/dist/assets/typescript-Bb1J8qyy.js +1 -0
- package/client/dist/assets/{vue-Bg0byEaI.js → vue-jUI-lpPb.js} +1 -1
- package/client/dist/assets/wasm-inlined-4KdTHw0F.js +1 -0
- package/client/dist/index.html +3 -6
- package/package.json +37 -37
- package/server/dist/_virtual/_rolldown/runtime.cjs +1 -2
- package/server/dist/controllers/auth.controller.cjs +79 -0
- package/server/dist/controllers/auth.controller.cjs.map +1 -0
- package/server/dist/controllers/auth.controller.d.ts +34 -0
- package/server/dist/controllers/auth.controller.mjs +75 -0
- package/server/dist/controllers/auth.controller.mjs.map +1 -0
- package/server/dist/controllers/configuration.controller.cjs +10 -5
- package/server/dist/controllers/configuration.controller.cjs.map +1 -1
- package/server/dist/controllers/configuration.controller.d.ts +8 -3
- package/server/dist/controllers/configuration.controller.mjs +10 -5
- package/server/dist/controllers/configuration.controller.mjs.map +1 -1
- package/server/dist/controllers/dictionary.controller.cjs +4 -4
- package/server/dist/controllers/dictionary.controller.cjs.map +1 -1
- package/server/dist/controllers/dictionary.controller.d.ts +1 -2
- package/server/dist/controllers/dictionary.controller.mjs +3 -3
- package/server/dist/controllers/dictionary.controller.mjs.map +1 -1
- package/server/dist/export.cjs +2 -2
- package/server/dist/export.d.ts +2 -2
- package/server/dist/index.cjs +56 -19
- package/server/dist/index.cjs.map +1 -1
- package/server/dist/index.mjs +56 -19
- package/server/dist/index.mjs.map +1 -1
- package/server/dist/routes/auth.routes.cjs +34 -0
- package/server/dist/routes/auth.routes.cjs.map +1 -0
- package/server/dist/routes/auth.routes.d.ts +20 -0
- package/server/dist/routes/auth.routes.mjs +32 -0
- package/server/dist/routes/auth.routes.mjs.map +1 -0
- package/server/dist/routes/config.routes.cjs +2 -3
- package/server/dist/routes/config.routes.d.ts +0 -2
- package/server/dist/routes/config.routes.mjs +1 -2
- package/server/dist/routes/dictionary.routes.cjs +2 -3
- package/server/dist/routes/dictionary.routes.d.ts +0 -2
- package/server/dist/routes/dictionary.routes.mjs +1 -2
- package/server/dist/services/editorAuth.service.cjs +142 -0
- package/server/dist/services/editorAuth.service.cjs.map +1 -0
- package/server/dist/services/editorAuth.service.d.ts +41 -0
- package/server/dist/services/editorAuth.service.mjs +136 -0
- package/server/dist/services/editorAuth.service.mjs.map +1 -0
- package/server/dist/types/Routes.d.ts +0 -2
- package/server/dist/utils/checkPortAvailability.cjs +40 -15
- package/server/dist/utils/checkPortAvailability.cjs.map +1 -1
- package/server/dist/utils/checkPortAvailability.d.ts +14 -3
- package/server/dist/utils/checkPortAvailability.mjs +39 -15
- package/server/dist/utils/checkPortAvailability.mjs.map +1 -1
- package/server/dist/utils/httpStatusCodes.cjs +1 -2
- package/server/dist/utils/httpStatusCodes.d.ts +9 -20
- package/server/dist/utils/httpStatusCodes.mjs +1 -2
- package/server/dist/utils/responseData.cjs +2 -3
- package/server/dist/utils/responseData.d.ts +1 -2
- package/server/dist/utils/responseData.mjs +1 -2
- package/client/dist/assets/CodeBlockShiki-DtgHBhf-.js +0 -2
- package/client/dist/assets/MarkDownRender-B5rc5xdv.js +0 -25
- package/client/dist/assets/MarkDownRender-BJfBvDXr.js +0 -1
- package/client/dist/assets/MarkdownEditor-CKaCMWJN.js +0 -160
- package/client/dist/assets/codeTransformer-DVPQQcdP.js +0 -9
- package/client/dist/assets/css-CdtkT07m.js +0 -1
- package/client/dist/assets/css-LbU1hoFO.js +0 -1
- package/client/dist/assets/dist-BHukwvnD.js +0 -11
- package/client/dist/assets/dist-CcmWBeAo.js +0 -1
- package/client/dist/assets/dynamic-BG2syiTL.js +0 -41
- package/client/dist/assets/html-DYtkB_T1.js +0 -1
- package/client/dist/assets/index-BtBJMAbp.js +0 -59
- package/client/dist/assets/index-D82ZIHVs.css +0 -2
- package/client/dist/assets/javascript-Yelw-5ZN.js +0 -1
- package/client/dist/assets/json-CaljABEy.js +0 -1
- package/client/dist/assets/purify.es-Bvo9QlJ8.js +0 -3
- package/client/dist/assets/react-Cvdyeg_0.js +0 -1
- package/client/dist/assets/rolldown-runtime-hePW80VL.js +0 -1
- package/client/dist/assets/shikiBundle-vOk0aVqf.js +0 -12
- package/client/dist/assets/tsx-5f3ulCja.js +0 -1
- package/client/dist/assets/typescript-Utq2Cl8c.js +0 -1
- package/client/dist/assets/wasm-BnjxR4X6.js +0 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
4
|
+
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors, 1);
|
|
5
|
+
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
6
|
+
let _intlayer_api = require("@intlayer/api");
|
|
7
|
+
let _intlayer_cli = require("@intlayer/cli");
|
|
8
|
+
|
|
9
|
+
// src/services/editorAuth.service.ts
|
|
10
|
+
/** Time after which an unanswered login is given up. */
|
|
11
|
+
const LOGIN_TIMEOUT_MS = 3e5;
|
|
12
|
+
/** Margin before expiry under which a cached access token is renewed. */
|
|
13
|
+
const TOKEN_RENEWAL_MARGIN_MS = 6e4;
|
|
14
|
+
/** Credentials picked during an editor-triggered login, kept for this run. */
|
|
15
|
+
let runtimeCredentials = null;
|
|
16
|
+
/** Access token exchanged from the access key, reused until it expires. */
|
|
17
|
+
let accessKeyAuthCache = null;
|
|
18
|
+
/** Identity bound to each CLI session token, resolved once per token. */
|
|
19
|
+
const sessionIdentityCache = /* @__PURE__ */ new Map();
|
|
20
|
+
/** Aborts the login flow waiting for the browser callback, if any. */
|
|
21
|
+
let pendingLoginController = null;
|
|
22
|
+
const isExpiringSoon = (expiresAt) => expiresAt !== null && new Date(expiresAt).getTime() - TOKEN_RENEWAL_MARGIN_MS <= Date.now();
|
|
23
|
+
const getCredentials = (configuration) => {
|
|
24
|
+
if (runtimeCredentials) return runtimeCredentials;
|
|
25
|
+
const { clientId, clientSecret } = configuration.editor;
|
|
26
|
+
return clientId && clientSecret ? {
|
|
27
|
+
clientId,
|
|
28
|
+
clientSecret
|
|
29
|
+
} : null;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the `intlayer login` session token, shared with the CLI through
|
|
33
|
+
* the temp directory. `null` when absent, expired, or rejected by the CMS.
|
|
34
|
+
*/
|
|
35
|
+
const resolveSessionAuth = async (configuration) => {
|
|
36
|
+
const sessionData = await (0, _intlayer_cli.readCliSessionToken)(configuration);
|
|
37
|
+
if (!sessionData) return null;
|
|
38
|
+
if (!sessionIdentityCache.has(sessionData.token)) try {
|
|
39
|
+
const result = await (0, _intlayer_api.getIntlayerAPIProxy)(void 0, configuration, sessionData.token).oAuth.getCliSessionMe();
|
|
40
|
+
sessionIdentityCache.set(sessionData.token, {
|
|
41
|
+
user: result.data?.user ?? null,
|
|
42
|
+
organization: result.data?.organization ?? null,
|
|
43
|
+
project: result.data?.project ?? null
|
|
44
|
+
});
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
accessToken: sessionData.token,
|
|
50
|
+
expiresAt: sessionData.expiresAt,
|
|
51
|
+
authType: "session",
|
|
52
|
+
...sessionIdentityCache.get(sessionData.token)
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Exchanges the access key for an access token. The client secret stays on
|
|
57
|
+
* the server: only the resulting short-lived token reaches the browser.
|
|
58
|
+
*/
|
|
59
|
+
const resolveAccessKeyAuth = async (configuration) => {
|
|
60
|
+
const credentials = getCredentials(configuration);
|
|
61
|
+
if (!credentials) return null;
|
|
62
|
+
if (accessKeyAuthCache?.clientId === credentials.clientId && !isExpiringSoon(accessKeyAuthCache.expiresAt)) {
|
|
63
|
+
const { clientId: _clientId, ...cachedAuth } = accessKeyAuthCache;
|
|
64
|
+
return cachedAuth;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const token = (await (0, _intlayer_api.getOAuthAPI)(void 0, { editor: {
|
|
68
|
+
...configuration.editor,
|
|
69
|
+
...credentials
|
|
70
|
+
} }).getOAuth2AccessToken()).data;
|
|
71
|
+
if (!token?.accessToken) return null;
|
|
72
|
+
const accessKeyAuth = {
|
|
73
|
+
accessToken: token.accessToken,
|
|
74
|
+
expiresAt: token.accessTokenExpiresAt ? new Date(token.accessTokenExpiresAt).toISOString() : null,
|
|
75
|
+
authType: "accessKey",
|
|
76
|
+
user: token.user,
|
|
77
|
+
organization: token.organization,
|
|
78
|
+
project: token.project
|
|
79
|
+
};
|
|
80
|
+
accessKeyAuthCache = {
|
|
81
|
+
...accessKeyAuth,
|
|
82
|
+
clientId: credentials.clientId
|
|
83
|
+
};
|
|
84
|
+
return accessKeyAuth;
|
|
85
|
+
} catch {
|
|
86
|
+
accessKeyAuthCache = null;
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Resolves the CMS identity of the editor, in the same order as the CLI:
|
|
92
|
+
* `intlayer login` session first, then the access key.
|
|
93
|
+
*/
|
|
94
|
+
const resolveEditorAuth = async (configuration) => await resolveSessionAuth(configuration) ?? await resolveAccessKeyAuth(configuration);
|
|
95
|
+
/**
|
|
96
|
+
* Signs the editor out: drops the `intlayer login` session (shared with the
|
|
97
|
+
* CLI), the pending login and the access key loaded during this run. An access
|
|
98
|
+
* key set in the configuration stays in use, as for the CLI.
|
|
99
|
+
*/
|
|
100
|
+
const logoutEditor = async (configuration) => {
|
|
101
|
+
pendingLoginController?.abort();
|
|
102
|
+
runtimeCredentials = null;
|
|
103
|
+
accessKeyAuthCache = null;
|
|
104
|
+
sessionIdentityCache.clear();
|
|
105
|
+
await (0, _intlayer_cli.clearCliSessionToken)(configuration);
|
|
106
|
+
};
|
|
107
|
+
/** Whether an editor-triggered login is waiting for the browser callback. */
|
|
108
|
+
const isEditorLoginPending = () => pendingLoginController !== null;
|
|
109
|
+
/**
|
|
110
|
+
* Starts the `intlayer login` browser flow. A login still pending is dropped
|
|
111
|
+
* first, so a closed login tab can be reopened. Resolves once the CMS has
|
|
112
|
+
* called back (the session token being stored for both the editor and the
|
|
113
|
+
* CLI), or when the login is dropped or times out.
|
|
114
|
+
*/
|
|
115
|
+
const startEditorLogin = async (configuration, configOptions) => {
|
|
116
|
+
pendingLoginController?.abort();
|
|
117
|
+
const appLogger = (0, _intlayer_config_logger.getAppLogger)(configuration);
|
|
118
|
+
const loginController = new AbortController();
|
|
119
|
+
const timeout = setTimeout(() => loginController.abort(), LOGIN_TIMEOUT_MS);
|
|
120
|
+
pendingLoginController = loginController;
|
|
121
|
+
await (0, _intlayer_cli.login)({
|
|
122
|
+
exitAfter: false,
|
|
123
|
+
configOptions,
|
|
124
|
+
signal: loginController.signal,
|
|
125
|
+
onCredentials: (credentials) => {
|
|
126
|
+
runtimeCredentials = credentials;
|
|
127
|
+
accessKeyAuthCache = null;
|
|
128
|
+
appLogger("Access key loaded for this editor session. Insert it in your .env file to keep it:");
|
|
129
|
+
appLogger(`${(0, _intlayer_config_logger.colorize)("INTLAYER_CLIENT_ID=", _intlayer_config_colors.GREY_LIGHT)}${(0, _intlayer_config_logger.colorize)(credentials.clientId, _intlayer_config_colors.BLUE)}`);
|
|
130
|
+
appLogger(`${(0, _intlayer_config_logger.colorize)("INTLAYER_CLIENT_SECRET=", _intlayer_config_colors.GREY_LIGHT)}${(0, _intlayer_config_logger.colorize)(credentials.clientSecret, _intlayer_config_colors.BLUE)}`);
|
|
131
|
+
}
|
|
132
|
+
}).finally(() => {
|
|
133
|
+
clearTimeout(timeout);
|
|
134
|
+
if (pendingLoginController === loginController) pendingLoginController = null;
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
exports.isEditorLoginPending = isEditorLoginPending;
|
|
139
|
+
exports.logoutEditor = logoutEditor;
|
|
140
|
+
exports.resolveEditorAuth = resolveEditorAuth;
|
|
141
|
+
exports.startEditorLogin = startEditorLogin;
|
|
142
|
+
//# sourceMappingURL=editorAuth.service.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorAuth.service.cjs","names":["readCliSessionToken","getIntlayerAPIProxy","getOAuthAPI","clearCliSessionToken","getAppLogger","login","colorize","ANSIColors"],"sources":["../../src/services/editorAuth.service.ts"],"sourcesContent":["import { getIntlayerAPIProxy, getOAuthAPI } from '@intlayer/api';\nimport type { OrganizationAPI } from '@intlayer/backend-contract/organization';\nimport type { ProjectAPI } from '@intlayer/backend-contract/project';\nimport type { UserAPI } from '@intlayer/backend-contract/user';\nimport {\n clearCliSessionToken,\n login,\n readCliSessionToken,\n} from '@intlayer/cli';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport type { GetConfigurationOptions } from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/** Access-key credentials used for the client-credentials exchange. */\ntype EditorCredentials = {\n clientId: string;\n clientSecret: string;\n};\n\n/**\n * Identity the editor client uses to call the CMS, sent as a bearer token.\n *\n * - `session`: the user's short-lived `intlayer login` session token\n * - `accessKey`: an access token exchanged from the project access key\n */\nexport type EditorAuth = {\n accessToken: string;\n /** ISO date, `null` when the token never expires. */\n expiresAt: string | null;\n authType: 'session' | 'accessKey';\n user?: UserAPI | null;\n organization?: OrganizationAPI | null;\n project?: ProjectAPI | null;\n};\n\n/** Time after which an unanswered login is given up. */\nconst LOGIN_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Margin before expiry under which a cached access token is renewed. */\nconst TOKEN_RENEWAL_MARGIN_MS = 60 * 1000;\n\n/** Credentials picked during an editor-triggered login, kept for this run. */\nlet runtimeCredentials: EditorCredentials | null = null;\n\n/** Access token exchanged from the access key, reused until it expires. */\nlet accessKeyAuthCache: (EditorAuth & { clientId: string }) | null = null;\n\n/** Identity bound to a CLI session token. */\ntype SessionIdentity = Pick<EditorAuth, 'user' | 'organization' | 'project'>;\n\n/** Identity bound to each CLI session token, resolved once per token. */\nconst sessionIdentityCache = new Map<string, SessionIdentity>();\n\n/** Aborts the login flow waiting for the browser callback, if any. */\nlet pendingLoginController: AbortController | null = null;\n\nconst isExpiringSoon = (expiresAt: string | null): boolean =>\n expiresAt !== null &&\n new Date(expiresAt).getTime() - TOKEN_RENEWAL_MARGIN_MS <= Date.now();\n\nconst getCredentials = (\n configuration: IntlayerConfig\n): EditorCredentials | null => {\n if (runtimeCredentials) return runtimeCredentials;\n\n const { clientId, clientSecret } = configuration.editor;\n\n return clientId && clientSecret ? { clientId, clientSecret } : null;\n};\n\n/**\n * Resolves the `intlayer login` session token, shared with the CLI through\n * the temp directory. `null` when absent, expired, or rejected by the CMS.\n */\nconst resolveSessionAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> => {\n const sessionData = await readCliSessionToken(configuration);\n\n if (!sessionData) return null;\n\n if (!sessionIdentityCache.has(sessionData.token)) {\n try {\n const result = await getIntlayerAPIProxy(\n undefined,\n configuration,\n sessionData.token\n ).oAuth.getCliSessionMe();\n\n sessionIdentityCache.set(sessionData.token, {\n user: result.data?.user ?? null,\n organization: result.data?.organization ?? null,\n project: result.data?.project ?? null,\n });\n } catch {\n // Revoked or unreachable: fall back to the access key, if any\n return null;\n }\n }\n\n return {\n accessToken: sessionData.token,\n expiresAt: sessionData.expiresAt,\n authType: 'session',\n ...sessionIdentityCache.get(sessionData.token),\n };\n};\n\n/**\n * Exchanges the access key for an access token. The client secret stays on\n * the server: only the resulting short-lived token reaches the browser.\n */\nconst resolveAccessKeyAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> => {\n const credentials = getCredentials(configuration);\n\n if (!credentials) return null;\n\n if (\n accessKeyAuthCache?.clientId === credentials.clientId &&\n !isExpiringSoon(accessKeyAuthCache.expiresAt)\n ) {\n const { clientId: _clientId, ...cachedAuth } = accessKeyAuthCache;\n return cachedAuth;\n }\n\n try {\n const result = await getOAuthAPI(undefined, {\n editor: { ...configuration.editor, ...credentials },\n }).getOAuth2AccessToken();\n\n const token = result.data;\n\n if (!token?.accessToken) return null;\n\n const accessKeyAuth: EditorAuth = {\n accessToken: token.accessToken,\n expiresAt: token.accessTokenExpiresAt\n ? new Date(token.accessTokenExpiresAt).toISOString()\n : null,\n authType: 'accessKey',\n user: token.user,\n organization: token.organization,\n project: token.project,\n };\n\n accessKeyAuthCache = { ...accessKeyAuth, clientId: credentials.clientId };\n\n return accessKeyAuth;\n } catch {\n accessKeyAuthCache = null;\n return null;\n }\n};\n\n/**\n * Resolves the CMS identity of the editor, in the same order as the CLI:\n * `intlayer login` session first, then the access key.\n */\nexport const resolveEditorAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> =>\n (await resolveSessionAuth(configuration)) ??\n (await resolveAccessKeyAuth(configuration));\n\n/**\n * Signs the editor out: drops the `intlayer login` session (shared with the\n * CLI), the pending login and the access key loaded during this run. An access\n * key set in the configuration stays in use, as for the CLI.\n */\nexport const logoutEditor = async (\n configuration: IntlayerConfig\n): Promise<void> => {\n pendingLoginController?.abort();\n runtimeCredentials = null;\n accessKeyAuthCache = null;\n sessionIdentityCache.clear();\n\n await clearCliSessionToken(configuration);\n};\n\n/** Whether an editor-triggered login is waiting for the browser callback. */\nexport const isEditorLoginPending = (): boolean =>\n pendingLoginController !== null;\n\n/**\n * Starts the `intlayer login` browser flow. A login still pending is dropped\n * first, so a closed login tab can be reopened. Resolves once the CMS has\n * called back (the session token being stored for both the editor and the\n * CLI), or when the login is dropped or times out.\n */\nexport const startEditorLogin = async (\n configuration: IntlayerConfig,\n configOptions?: GetConfigurationOptions\n): Promise<void> => {\n pendingLoginController?.abort();\n\n const appLogger = getAppLogger(configuration);\n const loginController = new AbortController();\n const timeout = setTimeout(() => loginController.abort(), LOGIN_TIMEOUT_MS);\n\n pendingLoginController = loginController;\n\n await login({\n exitAfter: false,\n configOptions,\n signal: loginController.signal,\n onCredentials: (credentials) => {\n runtimeCredentials = credentials;\n accessKeyAuthCache = null;\n\n appLogger(\n 'Access key loaded for this editor session. Insert it in your .env file to keep it:'\n );\n appLogger(\n `${colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT)}${colorize(credentials.clientId, ANSIColors.BLUE)}`\n );\n appLogger(\n `${colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT)}${colorize(credentials.clientSecret, ANSIColors.BLUE)}`\n );\n },\n }).finally(() => {\n clearTimeout(timeout);\n\n if (pendingLoginController === loginController) {\n pendingLoginController = null;\n }\n });\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { OrganizationAPI } from "@intlayer/backend-contract/organization";
|
|
2
|
+
import { ProjectAPI } from "@intlayer/backend-contract/project";
|
|
3
|
+
import { UserAPI } from "@intlayer/backend-contract/user";
|
|
4
|
+
import { GetConfigurationOptions } from "@intlayer/config/node";
|
|
5
|
+
import { IntlayerConfig } from "@intlayer/types/config";
|
|
6
|
+
/**
|
|
7
|
+
* Identity the editor client uses to call the CMS, sent as a bearer token.
|
|
8
|
+
*
|
|
9
|
+
* - `session`: the user's short-lived `intlayer login` session token
|
|
10
|
+
* - `accessKey`: an access token exchanged from the project access key
|
|
11
|
+
*/
|
|
12
|
+
export type EditorAuth = {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
/** ISO date, `null` when the token never expires. */
|
|
15
|
+
expiresAt: string | null;
|
|
16
|
+
authType: 'session' | 'accessKey';
|
|
17
|
+
user?: UserAPI | null;
|
|
18
|
+
organization?: OrganizationAPI | null;
|
|
19
|
+
project?: ProjectAPI | null;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the CMS identity of the editor, in the same order as the CLI:
|
|
23
|
+
* `intlayer login` session first, then the access key.
|
|
24
|
+
*/
|
|
25
|
+
export declare const resolveEditorAuth: (configuration: IntlayerConfig) => Promise<EditorAuth | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Signs the editor out: drops the `intlayer login` session (shared with the
|
|
28
|
+
* CLI), the pending login and the access key loaded during this run. An access
|
|
29
|
+
* key set in the configuration stays in use, as for the CLI.
|
|
30
|
+
*/
|
|
31
|
+
export declare const logoutEditor: (configuration: IntlayerConfig) => Promise<void>;
|
|
32
|
+
/** Whether an editor-triggered login is waiting for the browser callback. */
|
|
33
|
+
export declare const isEditorLoginPending: () => boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Starts the `intlayer login` browser flow. A login still pending is dropped
|
|
36
|
+
* first, so a closed login tab can be reopened. Resolves once the CMS has
|
|
37
|
+
* called back (the session token being stored for both the editor and the
|
|
38
|
+
* CLI), or when the login is dropped or times out.
|
|
39
|
+
*/
|
|
40
|
+
export declare const startEditorLogin: (configuration: IntlayerConfig, configOptions?: GetConfigurationOptions) => Promise<void>;
|
|
41
|
+
//# sourceMappingURL=editorAuth.service.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import * as ANSIColors from "@intlayer/config/colors";
|
|
2
|
+
import { colorize, getAppLogger } from "@intlayer/config/logger";
|
|
3
|
+
import { getIntlayerAPIProxy, getOAuthAPI } from "@intlayer/api";
|
|
4
|
+
import { clearCliSessionToken, login, readCliSessionToken } from "@intlayer/cli";
|
|
5
|
+
|
|
6
|
+
// src/services/editorAuth.service.ts
|
|
7
|
+
/** Time after which an unanswered login is given up. */
|
|
8
|
+
const LOGIN_TIMEOUT_MS = 3e5;
|
|
9
|
+
/** Margin before expiry under which a cached access token is renewed. */
|
|
10
|
+
const TOKEN_RENEWAL_MARGIN_MS = 6e4;
|
|
11
|
+
/** Credentials picked during an editor-triggered login, kept for this run. */
|
|
12
|
+
let runtimeCredentials = null;
|
|
13
|
+
/** Access token exchanged from the access key, reused until it expires. */
|
|
14
|
+
let accessKeyAuthCache = null;
|
|
15
|
+
/** Identity bound to each CLI session token, resolved once per token. */
|
|
16
|
+
const sessionIdentityCache = /* @__PURE__ */ new Map();
|
|
17
|
+
/** Aborts the login flow waiting for the browser callback, if any. */
|
|
18
|
+
let pendingLoginController = null;
|
|
19
|
+
const isExpiringSoon = (expiresAt) => expiresAt !== null && new Date(expiresAt).getTime() - TOKEN_RENEWAL_MARGIN_MS <= Date.now();
|
|
20
|
+
const getCredentials = (configuration) => {
|
|
21
|
+
if (runtimeCredentials) return runtimeCredentials;
|
|
22
|
+
const { clientId, clientSecret } = configuration.editor;
|
|
23
|
+
return clientId && clientSecret ? {
|
|
24
|
+
clientId,
|
|
25
|
+
clientSecret
|
|
26
|
+
} : null;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the `intlayer login` session token, shared with the CLI through
|
|
30
|
+
* the temp directory. `null` when absent, expired, or rejected by the CMS.
|
|
31
|
+
*/
|
|
32
|
+
const resolveSessionAuth = async (configuration) => {
|
|
33
|
+
const sessionData = await readCliSessionToken(configuration);
|
|
34
|
+
if (!sessionData) return null;
|
|
35
|
+
if (!sessionIdentityCache.has(sessionData.token)) try {
|
|
36
|
+
const result = await getIntlayerAPIProxy(void 0, configuration, sessionData.token).oAuth.getCliSessionMe();
|
|
37
|
+
sessionIdentityCache.set(sessionData.token, {
|
|
38
|
+
user: result.data?.user ?? null,
|
|
39
|
+
organization: result.data?.organization ?? null,
|
|
40
|
+
project: result.data?.project ?? null
|
|
41
|
+
});
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
accessToken: sessionData.token,
|
|
47
|
+
expiresAt: sessionData.expiresAt,
|
|
48
|
+
authType: "session",
|
|
49
|
+
...sessionIdentityCache.get(sessionData.token)
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Exchanges the access key for an access token. The client secret stays on
|
|
54
|
+
* the server: only the resulting short-lived token reaches the browser.
|
|
55
|
+
*/
|
|
56
|
+
const resolveAccessKeyAuth = async (configuration) => {
|
|
57
|
+
const credentials = getCredentials(configuration);
|
|
58
|
+
if (!credentials) return null;
|
|
59
|
+
if (accessKeyAuthCache?.clientId === credentials.clientId && !isExpiringSoon(accessKeyAuthCache.expiresAt)) {
|
|
60
|
+
const { clientId: _clientId, ...cachedAuth } = accessKeyAuthCache;
|
|
61
|
+
return cachedAuth;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const token = (await getOAuthAPI(void 0, { editor: {
|
|
65
|
+
...configuration.editor,
|
|
66
|
+
...credentials
|
|
67
|
+
} }).getOAuth2AccessToken()).data;
|
|
68
|
+
if (!token?.accessToken) return null;
|
|
69
|
+
const accessKeyAuth = {
|
|
70
|
+
accessToken: token.accessToken,
|
|
71
|
+
expiresAt: token.accessTokenExpiresAt ? new Date(token.accessTokenExpiresAt).toISOString() : null,
|
|
72
|
+
authType: "accessKey",
|
|
73
|
+
user: token.user,
|
|
74
|
+
organization: token.organization,
|
|
75
|
+
project: token.project
|
|
76
|
+
};
|
|
77
|
+
accessKeyAuthCache = {
|
|
78
|
+
...accessKeyAuth,
|
|
79
|
+
clientId: credentials.clientId
|
|
80
|
+
};
|
|
81
|
+
return accessKeyAuth;
|
|
82
|
+
} catch {
|
|
83
|
+
accessKeyAuthCache = null;
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Resolves the CMS identity of the editor, in the same order as the CLI:
|
|
89
|
+
* `intlayer login` session first, then the access key.
|
|
90
|
+
*/
|
|
91
|
+
const resolveEditorAuth = async (configuration) => await resolveSessionAuth(configuration) ?? await resolveAccessKeyAuth(configuration);
|
|
92
|
+
/**
|
|
93
|
+
* Signs the editor out: drops the `intlayer login` session (shared with the
|
|
94
|
+
* CLI), the pending login and the access key loaded during this run. An access
|
|
95
|
+
* key set in the configuration stays in use, as for the CLI.
|
|
96
|
+
*/
|
|
97
|
+
const logoutEditor = async (configuration) => {
|
|
98
|
+
pendingLoginController?.abort();
|
|
99
|
+
runtimeCredentials = null;
|
|
100
|
+
accessKeyAuthCache = null;
|
|
101
|
+
sessionIdentityCache.clear();
|
|
102
|
+
await clearCliSessionToken(configuration);
|
|
103
|
+
};
|
|
104
|
+
/** Whether an editor-triggered login is waiting for the browser callback. */
|
|
105
|
+
const isEditorLoginPending = () => pendingLoginController !== null;
|
|
106
|
+
/**
|
|
107
|
+
* Starts the `intlayer login` browser flow. A login still pending is dropped
|
|
108
|
+
* first, so a closed login tab can be reopened. Resolves once the CMS has
|
|
109
|
+
* called back (the session token being stored for both the editor and the
|
|
110
|
+
* CLI), or when the login is dropped or times out.
|
|
111
|
+
*/
|
|
112
|
+
const startEditorLogin = async (configuration, configOptions) => {
|
|
113
|
+
pendingLoginController?.abort();
|
|
114
|
+
const appLogger = getAppLogger(configuration);
|
|
115
|
+
const loginController = new AbortController();
|
|
116
|
+
const timeout = setTimeout(() => loginController.abort(), LOGIN_TIMEOUT_MS);
|
|
117
|
+
pendingLoginController = loginController;
|
|
118
|
+
await login({
|
|
119
|
+
exitAfter: false,
|
|
120
|
+
configOptions,
|
|
121
|
+
signal: loginController.signal,
|
|
122
|
+
onCredentials: (credentials) => {
|
|
123
|
+
runtimeCredentials = credentials;
|
|
124
|
+
accessKeyAuthCache = null;
|
|
125
|
+
appLogger("Access key loaded for this editor session. Insert it in your .env file to keep it:");
|
|
126
|
+
appLogger(`${colorize("INTLAYER_CLIENT_ID=", ANSIColors.GREY_LIGHT)}${colorize(credentials.clientId, ANSIColors.BLUE)}`);
|
|
127
|
+
appLogger(`${colorize("INTLAYER_CLIENT_SECRET=", ANSIColors.GREY_LIGHT)}${colorize(credentials.clientSecret, ANSIColors.BLUE)}`);
|
|
128
|
+
}
|
|
129
|
+
}).finally(() => {
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
if (pendingLoginController === loginController) pendingLoginController = null;
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export { isEditorLoginPending, logoutEditor, resolveEditorAuth, startEditorLogin };
|
|
136
|
+
//# sourceMappingURL=editorAuth.service.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorAuth.service.mjs","names":[],"sources":["../../src/services/editorAuth.service.ts"],"sourcesContent":["import { getIntlayerAPIProxy, getOAuthAPI } from '@intlayer/api';\nimport type { OrganizationAPI } from '@intlayer/backend-contract/organization';\nimport type { ProjectAPI } from '@intlayer/backend-contract/project';\nimport type { UserAPI } from '@intlayer/backend-contract/user';\nimport {\n clearCliSessionToken,\n login,\n readCliSessionToken,\n} from '@intlayer/cli';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport type { GetConfigurationOptions } from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\n/** Access-key credentials used for the client-credentials exchange. */\ntype EditorCredentials = {\n clientId: string;\n clientSecret: string;\n};\n\n/**\n * Identity the editor client uses to call the CMS, sent as a bearer token.\n *\n * - `session`: the user's short-lived `intlayer login` session token\n * - `accessKey`: an access token exchanged from the project access key\n */\nexport type EditorAuth = {\n accessToken: string;\n /** ISO date, `null` when the token never expires. */\n expiresAt: string | null;\n authType: 'session' | 'accessKey';\n user?: UserAPI | null;\n organization?: OrganizationAPI | null;\n project?: ProjectAPI | null;\n};\n\n/** Time after which an unanswered login is given up. */\nconst LOGIN_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Margin before expiry under which a cached access token is renewed. */\nconst TOKEN_RENEWAL_MARGIN_MS = 60 * 1000;\n\n/** Credentials picked during an editor-triggered login, kept for this run. */\nlet runtimeCredentials: EditorCredentials | null = null;\n\n/** Access token exchanged from the access key, reused until it expires. */\nlet accessKeyAuthCache: (EditorAuth & { clientId: string }) | null = null;\n\n/** Identity bound to a CLI session token. */\ntype SessionIdentity = Pick<EditorAuth, 'user' | 'organization' | 'project'>;\n\n/** Identity bound to each CLI session token, resolved once per token. */\nconst sessionIdentityCache = new Map<string, SessionIdentity>();\n\n/** Aborts the login flow waiting for the browser callback, if any. */\nlet pendingLoginController: AbortController | null = null;\n\nconst isExpiringSoon = (expiresAt: string | null): boolean =>\n expiresAt !== null &&\n new Date(expiresAt).getTime() - TOKEN_RENEWAL_MARGIN_MS <= Date.now();\n\nconst getCredentials = (\n configuration: IntlayerConfig\n): EditorCredentials | null => {\n if (runtimeCredentials) return runtimeCredentials;\n\n const { clientId, clientSecret } = configuration.editor;\n\n return clientId && clientSecret ? { clientId, clientSecret } : null;\n};\n\n/**\n * Resolves the `intlayer login` session token, shared with the CLI through\n * the temp directory. `null` when absent, expired, or rejected by the CMS.\n */\nconst resolveSessionAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> => {\n const sessionData = await readCliSessionToken(configuration);\n\n if (!sessionData) return null;\n\n if (!sessionIdentityCache.has(sessionData.token)) {\n try {\n const result = await getIntlayerAPIProxy(\n undefined,\n configuration,\n sessionData.token\n ).oAuth.getCliSessionMe();\n\n sessionIdentityCache.set(sessionData.token, {\n user: result.data?.user ?? null,\n organization: result.data?.organization ?? null,\n project: result.data?.project ?? null,\n });\n } catch {\n // Revoked or unreachable: fall back to the access key, if any\n return null;\n }\n }\n\n return {\n accessToken: sessionData.token,\n expiresAt: sessionData.expiresAt,\n authType: 'session',\n ...sessionIdentityCache.get(sessionData.token),\n };\n};\n\n/**\n * Exchanges the access key for an access token. The client secret stays on\n * the server: only the resulting short-lived token reaches the browser.\n */\nconst resolveAccessKeyAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> => {\n const credentials = getCredentials(configuration);\n\n if (!credentials) return null;\n\n if (\n accessKeyAuthCache?.clientId === credentials.clientId &&\n !isExpiringSoon(accessKeyAuthCache.expiresAt)\n ) {\n const { clientId: _clientId, ...cachedAuth } = accessKeyAuthCache;\n return cachedAuth;\n }\n\n try {\n const result = await getOAuthAPI(undefined, {\n editor: { ...configuration.editor, ...credentials },\n }).getOAuth2AccessToken();\n\n const token = result.data;\n\n if (!token?.accessToken) return null;\n\n const accessKeyAuth: EditorAuth = {\n accessToken: token.accessToken,\n expiresAt: token.accessTokenExpiresAt\n ? new Date(token.accessTokenExpiresAt).toISOString()\n : null,\n authType: 'accessKey',\n user: token.user,\n organization: token.organization,\n project: token.project,\n };\n\n accessKeyAuthCache = { ...accessKeyAuth, clientId: credentials.clientId };\n\n return accessKeyAuth;\n } catch {\n accessKeyAuthCache = null;\n return null;\n }\n};\n\n/**\n * Resolves the CMS identity of the editor, in the same order as the CLI:\n * `intlayer login` session first, then the access key.\n */\nexport const resolveEditorAuth = async (\n configuration: IntlayerConfig\n): Promise<EditorAuth | null> =>\n (await resolveSessionAuth(configuration)) ??\n (await resolveAccessKeyAuth(configuration));\n\n/**\n * Signs the editor out: drops the `intlayer login` session (shared with the\n * CLI), the pending login and the access key loaded during this run. An access\n * key set in the configuration stays in use, as for the CLI.\n */\nexport const logoutEditor = async (\n configuration: IntlayerConfig\n): Promise<void> => {\n pendingLoginController?.abort();\n runtimeCredentials = null;\n accessKeyAuthCache = null;\n sessionIdentityCache.clear();\n\n await clearCliSessionToken(configuration);\n};\n\n/** Whether an editor-triggered login is waiting for the browser callback. */\nexport const isEditorLoginPending = (): boolean =>\n pendingLoginController !== null;\n\n/**\n * Starts the `intlayer login` browser flow. A login still pending is dropped\n * first, so a closed login tab can be reopened. Resolves once the CMS has\n * called back (the session token being stored for both the editor and the\n * CLI), or when the login is dropped or times out.\n */\nexport const startEditorLogin = async (\n configuration: IntlayerConfig,\n configOptions?: GetConfigurationOptions\n): Promise<void> => {\n pendingLoginController?.abort();\n\n const appLogger = getAppLogger(configuration);\n const loginController = new AbortController();\n const timeout = setTimeout(() => loginController.abort(), LOGIN_TIMEOUT_MS);\n\n pendingLoginController = loginController;\n\n await login({\n exitAfter: false,\n configOptions,\n signal: loginController.signal,\n onCredentials: (credentials) => {\n runtimeCredentials = credentials;\n accessKeyAuthCache = null;\n\n appLogger(\n 'Access key loaded for this editor session. Insert it in your .env file to keep it:'\n );\n appLogger(\n `${colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT)}${colorize(credentials.clientId, ANSIColors.BLUE)}`\n );\n appLogger(\n `${colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT)}${colorize(credentials.clientSecret, ANSIColors.BLUE)}`\n );\n },\n }).finally(() => {\n clearTimeout(timeout);\n\n if (pendingLoginController === loginController) {\n pendingLoginController = null;\n }\n });\n};\n"],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
//#region src/types/Routes.d.ts
|
|
2
1
|
export type Route = {
|
|
3
2
|
urlModel: string;
|
|
4
3
|
url: string | ((args: any) => string);
|
|
5
4
|
method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
6
5
|
};
|
|
7
6
|
export type Routes = Record<string, Route>;
|
|
8
|
-
//#endregion
|
|
9
7
|
//# sourceMappingURL=Routes.d.ts.map
|
|
@@ -1,24 +1,49 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require(
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
3
|
let node_net = require("node:net");
|
|
4
4
|
node_net = require_runtime.__toESM(node_net, 1);
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
server.listen(port);
|
|
6
|
+
// src/utils/checkPortAvailability.ts
|
|
7
|
+
/**
|
|
8
|
+
* Resolves `false` when `port` is already bound on `host`.
|
|
9
|
+
*
|
|
10
|
+
* Probe the same host the server listens on: on macOS an IPv6 `::` probe
|
|
11
|
+
* succeeds even when `0.0.0.0:port` is taken.
|
|
12
|
+
*/
|
|
13
|
+
const checkPortAvailability = (port, host = "0.0.0.0") => new Promise((resolve) => {
|
|
14
|
+
const server = node_net.default.createServer();
|
|
15
|
+
server.once("error", (error) => {
|
|
16
|
+
resolve(error.code !== "EADDRINUSE");
|
|
19
17
|
});
|
|
18
|
+
server.once("listening", () => {
|
|
19
|
+
server.close();
|
|
20
|
+
resolve(true);
|
|
21
|
+
});
|
|
22
|
+
server.listen(port, host);
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Loopback hosts probed besides the listening one: a server bound to a single
|
|
26
|
+
* loopback address (e.g. a dev server on `::1`) would shadow the editor for
|
|
27
|
+
* `localhost` while leaving `0.0.0.0` free.
|
|
28
|
+
*/
|
|
29
|
+
const LOOPBACK_HOSTS = ["127.0.0.1", "::1"];
|
|
30
|
+
/**
|
|
31
|
+
* First port from `startPort` free on `host` and on the loopback addresses,
|
|
32
|
+
* trying the next ones in order.
|
|
33
|
+
*
|
|
34
|
+
* @returns The port, or `undefined` when the `attempts` ports are all taken.
|
|
35
|
+
*/
|
|
36
|
+
const findAvailablePort = async (startPort, host = "0.0.0.0", attempts = 20) => {
|
|
37
|
+
for (let port = startPort; port < startPort + attempts; port++) {
|
|
38
|
+
let isAvailable = true;
|
|
39
|
+
for (const probedHost of [host, ...LOOPBACK_HOSTS]) {
|
|
40
|
+
isAvailable = await checkPortAvailability(port, probedHost);
|
|
41
|
+
if (!isAvailable) break;
|
|
42
|
+
}
|
|
43
|
+
if (isAvailable) return port;
|
|
44
|
+
}
|
|
20
45
|
};
|
|
21
46
|
|
|
22
|
-
//#endregion
|
|
23
47
|
exports.checkPortAvailability = checkPortAvailability;
|
|
48
|
+
exports.findAvailablePort = findAvailablePort;
|
|
24
49
|
//# sourceMappingURL=checkPortAvailability.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkPortAvailability.cjs","names":["net"],"sources":["../../src/utils/checkPortAvailability.ts"],"sourcesContent":["import net from 'node:net';\n\nexport const checkPortAvailability = (port: number): Promise<boolean>
|
|
1
|
+
{"version":3,"file":"checkPortAvailability.cjs","names":["net"],"sources":["../../src/utils/checkPortAvailability.ts"],"sourcesContent":["import net from 'node:net';\n\n/**\n * Resolves `false` when `port` is already bound on `host`.\n *\n * Probe the same host the server listens on: on macOS an IPv6 `::` probe\n * succeeds even when `0.0.0.0:port` is taken.\n */\nexport const checkPortAvailability = (\n port: number,\n host = '0.0.0.0'\n): Promise<boolean> =>\n new Promise((resolve) => {\n const server = net.createServer();\n\n server.once('error', (error: NodeJS.ErrnoException) => {\n resolve(error.code !== 'EADDRINUSE');\n });\n\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port, host);\n });\n\n/**\n * Loopback hosts probed besides the listening one: a server bound to a single\n * loopback address (e.g. a dev server on `::1`) would shadow the editor for\n * `localhost` while leaving `0.0.0.0` free.\n */\nconst LOOPBACK_HOSTS = ['127.0.0.1', '::1'] as const;\n\n/**\n * First port from `startPort` free on `host` and on the loopback addresses,\n * trying the next ones in order.\n *\n * @returns The port, or `undefined` when the `attempts` ports are all taken.\n */\nexport const findAvailablePort = async (\n startPort: number,\n host = '0.0.0.0',\n attempts = 20\n): Promise<number | undefined> => {\n for (let port = startPort; port < startPort + attempts; port++) {\n let isAvailable = true;\n\n for (const probedHost of [host, ...LOOPBACK_HOSTS]) {\n isAvailable = await checkPortAvailability(port, probedHost);\n if (!isAvailable) break;\n }\n\n if (isAvailable) return port;\n }\n\n return undefined;\n};\n"],"mappings":";;;;;;;;;;;;AAQA,MAAa,yBACX,MACA,OAAO,cAEP,IAAI,SAAS,YAAY;CACvB,MAAM,SAASA,iBAAI,aAAa;CAEhC,OAAO,KAAK,UAAU,UAAiC;EACrD,QAAQ,MAAM,SAAS,YAAY;CACrC,CAAC;CAED,OAAO,KAAK,mBAAmB;EAC7B,OAAO,MAAM;EACb,QAAQ,IAAI;CACd,CAAC;CAED,OAAO,OAAO,MAAM,IAAI;AAC1B,CAAC;;;;;;AAOH,MAAM,iBAAiB,CAAC,aAAa,KAAK;;;;;;;AAQ1C,MAAa,oBAAoB,OAC/B,WACA,OAAO,WACP,WAAW,OACqB;CAChC,KAAK,IAAI,OAAO,WAAW,OAAO,YAAY,UAAU,QAAQ;EAC9D,IAAI,cAAc;EAElB,KAAK,MAAM,cAAc,CAAC,MAAM,GAAG,cAAc,GAAG;GAClD,cAAc,MAAM,sBAAsB,MAAM,UAAU;GAC1D,IAAI,CAAC,aAAa;EACpB;EAEA,IAAI,aAAa,OAAO;CAC1B;AAGF"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Resolves `false` when `port` is already bound on `host`.
|
|
3
|
+
*
|
|
4
|
+
* Probe the same host the server listens on: on macOS an IPv6 `::` probe
|
|
5
|
+
* succeeds even when `0.0.0.0:port` is taken.
|
|
6
|
+
*/
|
|
7
|
+
export declare const checkPortAvailability: (port: number, host?: string) => Promise<boolean>;
|
|
8
|
+
/**
|
|
9
|
+
* First port from `startPort` free on `host` and on the loopback addresses,
|
|
10
|
+
* trying the next ones in order.
|
|
11
|
+
*
|
|
12
|
+
* @returns The port, or `undefined` when the `attempts` ports are all taken.
|
|
13
|
+
*/
|
|
14
|
+
export declare const findAvailablePort: (startPort: number, host?: string, attempts?: number) => Promise<number | undefined>;
|
|
4
15
|
//# sourceMappingURL=checkPortAvailability.d.ts.map
|
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
});
|
|
15
|
-
server.listen(port);
|
|
3
|
+
// src/utils/checkPortAvailability.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolves `false` when `port` is already bound on `host`.
|
|
6
|
+
*
|
|
7
|
+
* Probe the same host the server listens on: on macOS an IPv6 `::` probe
|
|
8
|
+
* succeeds even when `0.0.0.0:port` is taken.
|
|
9
|
+
*/
|
|
10
|
+
const checkPortAvailability = (port, host = "0.0.0.0") => new Promise((resolve) => {
|
|
11
|
+
const server = net.createServer();
|
|
12
|
+
server.once("error", (error) => {
|
|
13
|
+
resolve(error.code !== "EADDRINUSE");
|
|
16
14
|
});
|
|
15
|
+
server.once("listening", () => {
|
|
16
|
+
server.close();
|
|
17
|
+
resolve(true);
|
|
18
|
+
});
|
|
19
|
+
server.listen(port, host);
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Loopback hosts probed besides the listening one: a server bound to a single
|
|
23
|
+
* loopback address (e.g. a dev server on `::1`) would shadow the editor for
|
|
24
|
+
* `localhost` while leaving `0.0.0.0` free.
|
|
25
|
+
*/
|
|
26
|
+
const LOOPBACK_HOSTS = ["127.0.0.1", "::1"];
|
|
27
|
+
/**
|
|
28
|
+
* First port from `startPort` free on `host` and on the loopback addresses,
|
|
29
|
+
* trying the next ones in order.
|
|
30
|
+
*
|
|
31
|
+
* @returns The port, or `undefined` when the `attempts` ports are all taken.
|
|
32
|
+
*/
|
|
33
|
+
const findAvailablePort = async (startPort, host = "0.0.0.0", attempts = 20) => {
|
|
34
|
+
for (let port = startPort; port < startPort + attempts; port++) {
|
|
35
|
+
let isAvailable = true;
|
|
36
|
+
for (const probedHost of [host, ...LOOPBACK_HOSTS]) {
|
|
37
|
+
isAvailable = await checkPortAvailability(port, probedHost);
|
|
38
|
+
if (!isAvailable) break;
|
|
39
|
+
}
|
|
40
|
+
if (isAvailable) return port;
|
|
41
|
+
}
|
|
17
42
|
};
|
|
18
43
|
|
|
19
|
-
|
|
20
|
-
export { checkPortAvailability };
|
|
44
|
+
export { checkPortAvailability, findAvailablePort };
|
|
21
45
|
//# sourceMappingURL=checkPortAvailability.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkPortAvailability.mjs","names":[],"sources":["../../src/utils/checkPortAvailability.ts"],"sourcesContent":["import net from 'node:net';\n\nexport const checkPortAvailability = (port: number): Promise<boolean>
|
|
1
|
+
{"version":3,"file":"checkPortAvailability.mjs","names":[],"sources":["../../src/utils/checkPortAvailability.ts"],"sourcesContent":["import net from 'node:net';\n\n/**\n * Resolves `false` when `port` is already bound on `host`.\n *\n * Probe the same host the server listens on: on macOS an IPv6 `::` probe\n * succeeds even when `0.0.0.0:port` is taken.\n */\nexport const checkPortAvailability = (\n port: number,\n host = '0.0.0.0'\n): Promise<boolean> =>\n new Promise((resolve) => {\n const server = net.createServer();\n\n server.once('error', (error: NodeJS.ErrnoException) => {\n resolve(error.code !== 'EADDRINUSE');\n });\n\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port, host);\n });\n\n/**\n * Loopback hosts probed besides the listening one: a server bound to a single\n * loopback address (e.g. a dev server on `::1`) would shadow the editor for\n * `localhost` while leaving `0.0.0.0` free.\n */\nconst LOOPBACK_HOSTS = ['127.0.0.1', '::1'] as const;\n\n/**\n * First port from `startPort` free on `host` and on the loopback addresses,\n * trying the next ones in order.\n *\n * @returns The port, or `undefined` when the `attempts` ports are all taken.\n */\nexport const findAvailablePort = async (\n startPort: number,\n host = '0.0.0.0',\n attempts = 20\n): Promise<number | undefined> => {\n for (let port = startPort; port < startPort + attempts; port++) {\n let isAvailable = true;\n\n for (const probedHost of [host, ...LOOPBACK_HOSTS]) {\n isAvailable = await checkPortAvailability(port, probedHost);\n if (!isAvailable) break;\n }\n\n if (isAvailable) return port;\n }\n\n return undefined;\n};\n"],"mappings":";;;;;;;;;AAQA,MAAa,yBACX,MACA,OAAO,cAEP,IAAI,SAAS,YAAY;CACvB,MAAM,SAAS,IAAI,aAAa;CAEhC,OAAO,KAAK,UAAU,UAAiC;EACrD,QAAQ,MAAM,SAAS,YAAY;CACrC,CAAC;CAED,OAAO,KAAK,mBAAmB;EAC7B,OAAO,MAAM;EACb,QAAQ,IAAI;CACd,CAAC;CAED,OAAO,OAAO,MAAM,IAAI;AAC1B,CAAC;;;;;;AAOH,MAAM,iBAAiB,CAAC,aAAa,KAAK;;;;;;;AAQ1C,MAAa,oBAAoB,OAC/B,WACA,OAAO,WACP,WAAW,OACqB;CAChC,KAAK,IAAI,OAAO,WAAW,OAAO,YAAY,UAAU,QAAQ;EAC9D,IAAI,cAAc;EAElB,KAAK,MAAM,cAAc,CAAC,MAAM,GAAG,cAAc,GAAG;GAClD,cAAc,MAAM,sBAAsB,MAAM,UAAU;GAC1D,IAAI,CAAC,aAAa;EACpB;EAEA,IAAI,aAAa,OAAO;CAC1B;AAGF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
2
|
+
// src/utils/httpStatusCodes.ts
|
|
3
3
|
/**
|
|
4
4
|
* Enum for HTTP response status codes.
|
|
5
5
|
* Contains all the possible HTTP response codes according to the standard.
|
|
@@ -396,6 +396,5 @@ let HttpStatusCodes = /* @__PURE__ */ function(HttpStatusCodes) {
|
|
|
396
396
|
return HttpStatusCodes;
|
|
397
397
|
}({});
|
|
398
398
|
|
|
399
|
-
//#endregion
|
|
400
399
|
exports.HttpStatusCodes = HttpStatusCodes;
|
|
401
400
|
//# sourceMappingURL=httpStatusCodes.cjs.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/utils/httpStatusCodes.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Enum for HTTP response status codes.
|
|
4
3
|
* Contains all the possible HTTP response codes according to the standard.
|
|
@@ -155,8 +154,7 @@ export declare enum HttpStatusCodes {
|
|
|
155
154
|
/**
|
|
156
155
|
* Used to return some response headers before final HTTP message.
|
|
157
156
|
*/
|
|
158
|
-
PROCESSING_102 = 102 // WebDAV
|
|
159
|
-
,
|
|
157
|
+
PROCESSING_102 = 102, // WebDAV
|
|
160
158
|
/**
|
|
161
159
|
* Early hints - part of optimization to improve page load time.
|
|
162
160
|
*/
|
|
@@ -192,13 +190,11 @@ export declare enum HttpStatusCodes {
|
|
|
192
190
|
/**
|
|
193
191
|
* Multi-status response providing status for multiple independent operations.
|
|
194
192
|
*/
|
|
195
|
-
MULTI_STATUS_207 = 207 // WebDAV
|
|
196
|
-
,
|
|
193
|
+
MULTI_STATUS_207 = 207, // WebDAV
|
|
197
194
|
/**
|
|
198
195
|
* The members of a DAV binding have already been enumerated in a preceding part of the request.
|
|
199
196
|
*/
|
|
200
|
-
ALREADY_REPORTED_208 = 208 // WebDAV
|
|
201
|
-
,
|
|
197
|
+
ALREADY_REPORTED_208 = 208, // WebDAV
|
|
202
198
|
/**
|
|
203
199
|
* The server has fulfilled a GET request for the resource, and the response is a representation of the result of one or more instance manipulations applied to the current instance.
|
|
204
200
|
*/
|
|
@@ -310,8 +306,7 @@ export declare enum HttpStatusCodes {
|
|
|
310
306
|
/**
|
|
311
307
|
* The server refuses the attempt to brew coffee with a teapot.
|
|
312
308
|
*/
|
|
313
|
-
IM_A_TEAPOT_418 = 418 // Easter egg from the HTCPCP/1.0 protocol.
|
|
314
|
-
,
|
|
309
|
+
IM_A_TEAPOT_418 = 418, // Easter egg from the HTCPCP/1.0 protocol.
|
|
315
310
|
/**
|
|
316
311
|
* The request was directed at a server that is not able to produce a response.
|
|
317
312
|
*/
|
|
@@ -319,18 +314,15 @@ export declare enum HttpStatusCodes {
|
|
|
319
314
|
/**
|
|
320
315
|
* The request was well-formed but was unable to be followed due to semantic errors.
|
|
321
316
|
*/
|
|
322
|
-
UNPROCESSABLE_ENTITY_422 = 422 // WebDAV
|
|
323
|
-
,
|
|
317
|
+
UNPROCESSABLE_ENTITY_422 = 422, // WebDAV
|
|
324
318
|
/**
|
|
325
319
|
* The resource that is being accessed is locked.
|
|
326
320
|
*/
|
|
327
|
-
LOCKED_423 = 423 // WebDAV
|
|
328
|
-
,
|
|
321
|
+
LOCKED_423 = 423, // WebDAV
|
|
329
322
|
/**
|
|
330
323
|
* The request failed due to failure of a previous request.
|
|
331
324
|
*/
|
|
332
|
-
FAILED_DEPENDENCY_424 = 424 // WebDAV
|
|
333
|
-
,
|
|
325
|
+
FAILED_DEPENDENCY_424 = 424, // WebDAV
|
|
334
326
|
/**
|
|
335
327
|
* Indicates that the server is unwilling to risk processing a request that might be replayed.
|
|
336
328
|
*/
|
|
@@ -386,13 +378,11 @@ export declare enum HttpStatusCodes {
|
|
|
386
378
|
/**
|
|
387
379
|
* The server is unable to store the representation needed to complete the request.
|
|
388
380
|
*/
|
|
389
|
-
INSUFFICIENT_STORAGE_507 = 507 // WebDAV
|
|
390
|
-
,
|
|
381
|
+
INSUFFICIENT_STORAGE_507 = 507, // WebDAV
|
|
391
382
|
/**
|
|
392
383
|
* The server detected an infinite loop while processing a request.
|
|
393
384
|
*/
|
|
394
|
-
LOOP_DETECTED_508 = 508 // WebDAV
|
|
395
|
-
,
|
|
385
|
+
LOOP_DETECTED_508 = 508, // WebDAV
|
|
396
386
|
/**
|
|
397
387
|
* Further extensions to the request are required for the server to fulfill it.
|
|
398
388
|
*/
|
|
@@ -402,5 +392,4 @@ export declare enum HttpStatusCodes {
|
|
|
402
392
|
*/
|
|
403
393
|
NETWORK_AUTHENTICATION_REQUIRED_511 = 511
|
|
404
394
|
}
|
|
405
|
-
//#endregion
|
|
406
395
|
//# sourceMappingURL=httpStatusCodes.d.ts.map
|