@logto/cli 1.19.0 → 1.21.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.
Files changed (32) hide show
  1. package/lib/commands/database/alteration/utils.js +12 -2
  2. package/lib/commands/database/seed/tables.js +2 -1
  3. package/lib/index.js +0 -4
  4. package/lib/package-json.d.ts +1 -8
  5. package/lib/package-json.js +6 -13
  6. package/lib/utils.d.ts +0 -1
  7. package/lib/utils.js +1 -19
  8. package/package.json +6 -13
  9. package/lib/commands/proxy/index.d.ts +0 -4
  10. package/lib/commands/proxy/index.js +0 -80
  11. package/lib/commands/proxy/types.d.ts +0 -16
  12. package/lib/commands/proxy/types.js +0 -1
  13. package/lib/commands/proxy/utils.d.ts +0 -27
  14. package/lib/commands/proxy/utils.js +0 -123
  15. package/lib/commands/translate/create.d.ts +0 -8
  16. package/lib/commands/translate/create.js +0 -37
  17. package/lib/commands/translate/index.d.ts +0 -3
  18. package/lib/commands/translate/index.js +0 -27
  19. package/lib/commands/translate/list-tags.d.ts +0 -3
  20. package/lib/commands/translate/list-tags.js +0 -19
  21. package/lib/commands/translate/openai.d.ts +0 -11
  22. package/lib/commands/translate/openai.js +0 -73
  23. package/lib/commands/translate/prompts.d.ts +0 -18
  24. package/lib/commands/translate/prompts.js +0 -48
  25. package/lib/commands/translate/sync-keys/index.d.ts +0 -13
  26. package/lib/commands/translate/sync-keys/index.js +0 -73
  27. package/lib/commands/translate/sync-keys/utils.d.ts +0 -57
  28. package/lib/commands/translate/sync-keys/utils.js +0 -295
  29. package/lib/commands/translate/sync.d.ts +0 -10
  30. package/lib/commands/translate/sync.js +0 -44
  31. package/lib/commands/translate/utils.d.ts +0 -14
  32. package/lib/commands/translate/utils.js +0 -130
@@ -27,8 +27,18 @@ export const getAlterationFiles = async () => {
27
27
  return [];
28
28
  }
29
29
  // We need to copy alteration files to execute in the CLI context to make `slonik` available
30
- await fs.rm(localAlterationDirectory, { force: true, recursive: true });
31
- await fs.cp(alterationDirectory, localAlterationDirectory, { recursive: true });
30
+ // Notice that we don't remove the folder,
31
+ // this ensures that the writabiliy remains (and also allows this to be a separately-mounted directory.
32
+ if (!existsSync(localAlterationDirectory)) {
33
+ await fs.mkdir(localAlterationDirectory, { recursive: true });
34
+ }
35
+ const oldFiles = await fs.readdir(localAlterationDirectory);
36
+ await Promise.all(oldFiles.map(async (file) => fs.rm(path.join(localAlterationDirectory, file), { force: true, recursive: true })));
37
+ const newFiles = await fs.readdir(alterationDirectory);
38
+ await Promise.all(newFiles.map(async (file) => fs.cp(path.join(alterationDirectory, file), path.join(localAlterationDirectory, file), {
39
+ recursive: true,
40
+ preserveTimestamps: true,
41
+ })));
32
42
  const directory = await fs.readdir(localAlterationDirectory);
33
43
  const files = directory.filter((file) => alterationFilenameRegex.test(file));
34
44
  return files
@@ -103,7 +103,8 @@ export const seedTables = async (connection, latestTimestamp, isCloud) => {
103
103
  await assignScopesToRole(connection, adminTenantId, applicationRole.id, ...cloudAdditionalScopes
104
104
  .filter(({ name }) => name === CloudScope.SendSms ||
105
105
  name === CloudScope.SendEmail ||
106
- name === CloudScope.FetchCustomJwt)
106
+ name === CloudScope.FetchCustomJwt ||
107
+ name === CloudScope.ReportSubscriptionUpdates)
107
108
  .map(({ id }) => id));
108
109
  await Promise.all([
109
110
  seedLegacyManagementApiUserRole(connection),
package/lib/index.js CHANGED
@@ -5,8 +5,6 @@ import { hideBin } from 'yargs/helpers';
5
5
  import connector from './commands/connector/index.js';
6
6
  import database from './commands/database/index.js';
7
7
  import install from './commands/install/index.js';
8
- import proxy from './commands/proxy/index.js';
9
- import translate from './commands/translate/index.js';
10
8
  import { packageJson } from './package-json.js';
11
9
  import { cliConfig, ConfigKey, consoleLog } from './utils.js';
12
10
  void yargs(hideBin(process.argv))
@@ -44,8 +42,6 @@ void yargs(hideBin(process.argv))
44
42
  .command(install)
45
43
  .command(database)
46
44
  .command(connector)
47
- .command(translate)
48
- .command(proxy)
49
45
  .demandCommand(1)
50
46
  .showHelpOnFail(false, `Specify ${chalk.green('--help')} for available options`)
51
47
  .strict()
@@ -41,9 +41,6 @@ export declare const packageJson: {
41
41
  dependencies: {
42
42
  "@logto/connector-kit": string;
43
43
  "@logto/core-kit": string;
44
- "@logto/language-kit": string;
45
- "@logto/phrases": string;
46
- "@logto/phrases-experience": string;
47
44
  "@logto/schemas": string;
48
45
  "@logto/shared": string;
49
46
  "@silverhand/essentials": string;
@@ -53,19 +50,14 @@ export declare const packageJson: {
53
50
  dotenv: string;
54
51
  got: string;
55
52
  hpagent: string;
56
- "http-proxy-middleware": string;
57
53
  inquirer: string;
58
- mime: string;
59
54
  nanoid: string;
60
55
  ora: string;
61
56
  "p-limit": string;
62
- "p-queue": string;
63
57
  "p-retry": string;
64
58
  "pg-protocol": string;
65
- roarr: string;
66
59
  semver: string;
67
60
  tar: string;
68
- typescript: string;
69
61
  yargs: string;
70
62
  zod: string;
71
63
  };
@@ -84,6 +76,7 @@ export declare const packageJson: {
84
76
  "lint-staged": string;
85
77
  prettier: string;
86
78
  sinon: string;
79
+ typescript: string;
87
80
  vitest: string;
88
81
  };
89
82
  eslintConfig: {
@@ -1,6 +1,6 @@
1
1
  export const packageJson = {
2
2
  "name": "@logto/cli",
3
- "version": "1.19.0",
3
+ "version": "1.21.0",
4
4
  "description": "Logto CLI.",
5
5
  "author": "Silverhand Inc. <contact@silverhand.io>",
6
6
  "homepage": "https://github.com/logto-io/logto#readme",
@@ -44,11 +44,8 @@ export const packageJson = {
44
44
  "dependencies": {
45
45
  "@logto/connector-kit": "workspace:^4.0.0",
46
46
  "@logto/core-kit": "workspace:^2.5.0",
47
- "@logto/language-kit": "workspace:^1.1.0",
48
- "@logto/phrases": "workspace:^1.13.0",
49
- "@logto/phrases-experience": "workspace:^1.7.0",
50
- "@logto/schemas": "workspace:1.19.0",
51
- "@logto/shared": "workspace:^3.1.1",
47
+ "@logto/schemas": "workspace:1.21.0",
48
+ "@logto/shared": "workspace:^3.1.2",
52
49
  "@silverhand/essentials": "^2.9.1",
53
50
  "@silverhand/slonik": "31.0.0-beta.2",
54
51
  "chalk": "^5.3.0",
@@ -56,19 +53,14 @@ export const packageJson = {
56
53
  "dotenv": "^16.4.5",
57
54
  "got": "^14.0.0",
58
55
  "hpagent": "^1.2.0",
59
- "http-proxy-middleware": "^3.0.0",
60
56
  "inquirer": "^9.0.0",
61
- "mime": "^4.0.4",
62
57
  "nanoid": "^5.0.1",
63
58
  "ora": "^8.0.1",
64
59
  "p-limit": "^6.0.0",
65
- "p-queue": "^8.0.0",
66
60
  "p-retry": "^6.0.0",
67
61
  "pg-protocol": "^1.6.0",
68
- "roarr": "^7.11.0",
69
62
  "semver": "^7.3.8",
70
63
  "tar": "^7.0.0",
71
- "typescript": "^5.5.3",
72
64
  "yargs": "^17.6.0",
73
65
  "zod": "^3.23.8"
74
66
  },
@@ -82,11 +74,12 @@ export const packageJson = {
82
74
  "@types/tar": "^6.1.12",
83
75
  "@types/yargs": "^17.0.13",
84
76
  "@vitest/coverage-v8": "^2.0.0",
85
- "@withtyped/server": "^0.13.6",
77
+ "@withtyped/server": "^0.14.0",
86
78
  "eslint": "^8.56.0",
87
79
  "lint-staged": "^15.0.0",
88
80
  "prettier": "^3.0.0",
89
- "sinon": "^18.0.0",
81
+ "sinon": "^19.0.0",
82
+ "typescript": "^5.5.3",
90
83
  "vitest": "^2.0.0"
91
84
  },
92
85
  "eslintConfig": {
package/lib/utils.d.ts CHANGED
@@ -34,4 +34,3 @@ export type ConnectorPackage = {
34
34
  path: string;
35
35
  };
36
36
  export declare const getConnectorPackagesFromDirectory: (directory: string) => Promise<ConnectorPackage[]>;
37
- export declare const lintLocaleFiles: (instancePath: string, packageName?: string) => Promise<void>;
package/lib/utils.js CHANGED
@@ -1,9 +1,8 @@
1
- import { execSync, execFile } from 'node:child_process';
1
+ import { execSync } from 'node:child_process';
2
2
  import { createWriteStream, existsSync } from 'node:fs';
3
3
  import { readdir, readFile } from 'node:fs/promises';
4
4
  import { createRequire } from 'node:module';
5
5
  import path from 'node:path';
6
- import { promisify } from 'node:util';
7
6
  import { ConsoleLog } from '@logto/shared';
8
7
  import { assert, conditional, conditionalString } from '@silverhand/essentials';
9
8
  import chalk from 'chalk';
@@ -186,20 +185,3 @@ export const getConnectorPackagesFromDirectory = async (directory) => {
186
185
  }));
187
186
  return rawPackages.filter((packageInfo) => typeof packageInfo.name === 'string');
188
187
  };
189
- const execPromise = promisify(execFile);
190
- export const lintLocaleFiles = async (
191
- /** Logto instance path */
192
- instancePath,
193
- /** Target package name, ignore to lint both `phrases` and `phrases-experience` packages */
194
- packageName) => {
195
- const spinner = ora({
196
- text: 'Running `eslint --fix` for locales',
197
- }).start();
198
- const targetPackages = packageName ? [packageName] : ['phrases', 'phrases-experience'];
199
- await Promise.all(targetPackages.map(async (packageName) => {
200
- const phrasesPath = path.join(instancePath, 'packages', packageName);
201
- const localesPath = path.join(phrasesPath, 'src/locales');
202
- await execPromise('pnpm', ['eslint', '--ext', '.ts', path.relative(phrasesPath, localesPath), '--fix'], { cwd: phrasesPath });
203
- }));
204
- spinner.succeed('Ran `eslint --fix` for locales');
205
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/cli",
3
- "version": "1.19.0",
3
+ "version": "1.21.0",
4
4
  "description": "Logto CLI.",
5
5
  "author": "Silverhand Inc. <contact@silverhand.io>",
6
6
  "homepage": "https://github.com/logto-io/logto#readme",
@@ -30,11 +30,8 @@
30
30
  "dependencies": {
31
31
  "@logto/connector-kit": "^4.0.0",
32
32
  "@logto/core-kit": "^2.5.0",
33
- "@logto/language-kit": "^1.1.0",
34
- "@logto/phrases": "^1.13.0",
35
- "@logto/phrases-experience": "^1.7.0",
36
- "@logto/schemas": "1.19.0",
37
- "@logto/shared": "^3.1.1",
33
+ "@logto/schemas": "1.21.0",
34
+ "@logto/shared": "^3.1.2",
38
35
  "@silverhand/essentials": "^2.9.1",
39
36
  "@silverhand/slonik": "31.0.0-beta.2",
40
37
  "chalk": "^5.3.0",
@@ -42,19 +39,14 @@
42
39
  "dotenv": "^16.4.5",
43
40
  "got": "^14.0.0",
44
41
  "hpagent": "^1.2.0",
45
- "http-proxy-middleware": "^3.0.0",
46
42
  "inquirer": "^9.0.0",
47
- "mime": "^4.0.4",
48
43
  "nanoid": "^5.0.1",
49
44
  "ora": "^8.0.1",
50
45
  "p-limit": "^6.0.0",
51
- "p-queue": "^8.0.0",
52
46
  "p-retry": "^6.0.0",
53
47
  "pg-protocol": "^1.6.0",
54
- "roarr": "^7.11.0",
55
48
  "semver": "^7.3.8",
56
49
  "tar": "^7.0.0",
57
- "typescript": "^5.5.3",
58
50
  "yargs": "^17.6.0",
59
51
  "zod": "^3.23.8"
60
52
  },
@@ -68,11 +60,12 @@
68
60
  "@types/tar": "^6.1.12",
69
61
  "@types/yargs": "^17.0.13",
70
62
  "@vitest/coverage-v8": "^2.0.0",
71
- "@withtyped/server": "^0.13.6",
63
+ "@withtyped/server": "^0.14.0",
72
64
  "eslint": "^8.56.0",
73
65
  "lint-staged": "^15.0.0",
74
66
  "prettier": "^3.0.0",
75
- "sinon": "^18.0.0",
67
+ "sinon": "^19.0.0",
68
+ "typescript": "^5.5.3",
76
69
  "vitest": "^2.0.0"
77
70
  },
78
71
  "eslintConfig": {
@@ -1,4 +0,0 @@
1
- import type { CommandModule } from 'yargs';
2
- import { type ProxyCommandArgs } from './types.js';
3
- declare const proxy: CommandModule<unknown, ProxyCommandArgs>;
4
- export default proxy;
@@ -1,80 +0,0 @@
1
- import http from 'node:http';
2
- import { isValidUrl } from '@logto/core-kit';
3
- import { conditional } from '@silverhand/essentials';
4
- import chalk from 'chalk';
5
- import { consoleLog } from '../../utils.js';
6
- import { checkExperienceInput, createLogtoResponseHandler, createProxy, createStaticFileProxy, isLogtoRequestPath, } from './utils.js';
7
- const proxy = {
8
- command: ['proxy'],
9
- describe: 'Command for Logto proxy',
10
- builder: (yargs) => yargs
11
- .options({
12
- 'experience-uri': {
13
- alias: ['x'],
14
- describe: 'The URI of your custom sign-in experience page.',
15
- type: 'string',
16
- },
17
- 'experience-path': {
18
- alias: ['xp'],
19
- describe: 'The local folder path of your custom sign-in experience assets.',
20
- type: 'string',
21
- },
22
- endpoint: {
23
- alias: 'ep',
24
- describe: 'Logto endpoint URI, which can be found in Logto Console. E.g.: https://<tenant-id>.logto.app/',
25
- type: 'string',
26
- },
27
- port: {
28
- alias: 'p',
29
- describe: 'The port number where the proxy server will be running on. Defaults to 9000.',
30
- type: 'number',
31
- default: 9000,
32
- },
33
- verbose: {
34
- alias: 'v',
35
- describe: 'Show verbose output.',
36
- type: 'boolean',
37
- default: false,
38
- },
39
- })
40
- .global('e'),
41
- handler: async ({ 'experience-uri': url, 'experience-path': path, endpoint, port, verbose }) => {
42
- checkExperienceInput(url, path);
43
- if (!endpoint || !isValidUrl(endpoint)) {
44
- consoleLog.fatal('A valid Logto endpoint URI must be provided.');
45
- }
46
- const logtoEndpointUrl = new URL(endpoint);
47
- const proxyUrl = new URL(`http://localhost:${port}`);
48
- const proxyLogtoRequest = createProxy(logtoEndpointUrl.href, async (proxyResponse, request, response) => createLogtoResponseHandler({
49
- proxyResponse,
50
- request,
51
- response,
52
- logtoEndpointUrl,
53
- proxyUrl,
54
- verbose,
55
- }));
56
- const proxyExperienceServerRequest = conditional(url && createProxy(url));
57
- const proxyExperienceStaticFileRequest = conditional(path && createStaticFileProxy(path));
58
- const server = http.createServer((request, response) => {
59
- if (verbose) {
60
- consoleLog.info(`Incoming request: ${chalk.blue(request.method, request.url)}`);
61
- }
62
- // Proxy the requests to Logto endpoint
63
- if (isLogtoRequestPath(request.url)) {
64
- void proxyLogtoRequest(request, response);
65
- return;
66
- }
67
- if (proxyExperienceServerRequest) {
68
- void proxyExperienceServerRequest(request, response);
69
- return;
70
- }
71
- if (proxyExperienceStaticFileRequest) {
72
- void proxyExperienceStaticFileRequest(request, response);
73
- }
74
- });
75
- server.listen(port, () => {
76
- consoleLog.info(`Proxy server is running on ${chalk.blue(proxyUrl.href)}`);
77
- });
78
- },
79
- };
80
- export default proxy;
@@ -1,16 +0,0 @@
1
- import type * as http from 'node:http';
2
- export type ProxyCommandArgs = {
3
- 'experience-uri'?: string;
4
- 'experience-path'?: string;
5
- endpoint?: string;
6
- port: number;
7
- verbose: boolean;
8
- };
9
- export type ProxyResponseHandler = {
10
- proxyResponse: http.IncomingMessage;
11
- request: http.IncomingMessage;
12
- response: http.ServerResponse;
13
- logtoEndpointUrl: URL;
14
- proxyUrl: URL;
15
- verbose: boolean;
16
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,27 +0,0 @@
1
- import type http from 'node:http';
2
- import { type OnProxyEvent } from 'http-proxy-middleware/dist/types.js';
3
- import { type ProxyResponseHandler } from './types.js';
4
- export declare const createProxy: (targetUrl: string, onProxyResponse?: OnProxyEvent["proxyRes"]) => import("http-proxy-middleware").RequestHandler<http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, (err?: any) => void>;
5
- export declare const createStaticFileProxy: (staticPath: string) => (request: http.IncomingMessage, response: http.ServerResponse) => Promise<void>;
6
- /**
7
- * Intercept the response from Logto endpoint and replace Logto endpoint URLs in the response with the
8
- * proxy URL. The string replace happens in the following cases:
9
- * - The response is a redirect response, and the `location` property in response header may contain Logto
10
- * endpoint URI.
11
- * - The response body is JSON, which consists of properties such as `**_endpoint` and `redirectTo`. These
12
- * properties may contain Logto endpoint URI.
13
- * - The response is HTML content that contains a form. The form action URL may contain Logto endpoint URI.
14
- *
15
- * Note: the `issuer` and `jwks_uri` properties in the `/oidc/.well-known` response should not be replaced,
16
- * even they also contain the Logto endpoint URI.
17
- */
18
- export declare const createLogtoResponseHandler: ({ proxyResponse, request, response, logtoEndpointUrl, proxyUrl, verbose, }: ProxyResponseHandler) => Promise<void>;
19
- export declare const checkExperienceInput: (url?: string, staticPath?: string) => void;
20
- /**
21
- * Check if the request path is a Logto request path.
22
- * @example isLogtoRequestPath('/oidc/.well-known/openid-configuration') // true
23
- * @example isLogtoRequestPath('/oidc/auth') // true
24
- * @example isLogtoRequestPath('/api/interaction/submit') // true
25
- * @example isLogtoRequestPath('/consent') // true
26
- */
27
- export declare const isLogtoRequestPath: (requestPath?: string) => boolean;
@@ -1,123 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { isValidUrl } from '@logto/core-kit';
5
- import { conditional, trySafe } from '@silverhand/essentials';
6
- import chalk from 'chalk';
7
- import { createProxyMiddleware, responseInterceptor } from 'http-proxy-middleware';
8
- import mime from 'mime';
9
- import { consoleLog } from '../../utils.js';
10
- export const createProxy = (targetUrl, onProxyResponse) => {
11
- const hasResponseHandler = Boolean(onProxyResponse);
12
- return createProxyMiddleware({
13
- target: targetUrl,
14
- changeOrigin: true,
15
- selfHandleResponse: hasResponseHandler,
16
- ...conditional(hasResponseHandler && {
17
- on: {
18
- proxyRes: onProxyResponse,
19
- error: (error) => {
20
- consoleLog.error(chalk.red(error));
21
- },
22
- },
23
- }),
24
- });
25
- };
26
- const index = 'index.html';
27
- const indexContentType = 'text/html; charset=utf-8';
28
- const noCache = 'no-cache, no-store, must-revalidate';
29
- const maxAgeSevenDays = 'max-age=604_800_000';
30
- export const createStaticFileProxy = (staticPath) => async (request, response) => {
31
- if (!request.url) {
32
- response.writeHead(400).end();
33
- return;
34
- }
35
- if (request.method === 'HEAD' || request.method === 'GET') {
36
- const fallBackToIndex = !isFileAssetPath(request.url);
37
- const requestPath = path.join(staticPath, fallBackToIndex ? index : request.url);
38
- try {
39
- const content = await fs.readFile(requestPath, 'utf8');
40
- response.setHeader('cache-control', fallBackToIndex ? noCache : maxAgeSevenDays);
41
- response.setHeader('content-type', getMimeType(request.url));
42
- response.writeHead(200);
43
- response.end(content);
44
- }
45
- catch (error) {
46
- consoleLog.error(chalk.red(error));
47
- response.setHeader('content-type', getMimeType(request.url));
48
- response.writeHead(existsSync(request.url) ? 500 : 404);
49
- response.end();
50
- }
51
- }
52
- };
53
- /**
54
- * Intercept the response from Logto endpoint and replace Logto endpoint URLs in the response with the
55
- * proxy URL. The string replace happens in the following cases:
56
- * - The response is a redirect response, and the `location` property in response header may contain Logto
57
- * endpoint URI.
58
- * - The response body is JSON, which consists of properties such as `**_endpoint` and `redirectTo`. These
59
- * properties may contain Logto endpoint URI.
60
- * - The response is HTML content that contains a form. The form action URL may contain Logto endpoint URI.
61
- *
62
- * Note: the `issuer` and `jwks_uri` properties in the `/oidc/.well-known` response should not be replaced,
63
- * even they also contain the Logto endpoint URI.
64
- */
65
- export const createLogtoResponseHandler = async ({ proxyResponse, request, response, logtoEndpointUrl, proxyUrl, verbose, }) => {
66
- const { location } = proxyResponse.headers;
67
- if (location) {
68
- // eslint-disable-next-line @silverhand/fp/no-mutation
69
- proxyResponse.headers.location = location.replace(logtoEndpointUrl.href, proxyUrl.href);
70
- }
71
- void responseInterceptor(async (responseBuffer, proxyResponse) => {
72
- const responseBody = responseBuffer.toString();
73
- if (verbose) {
74
- consoleLog.info(`Response received: ${chalk.green(responseBody)}`);
75
- }
76
- if (proxyResponse.headers['content-type']?.includes('text/html')) {
77
- return responseBody.replace(`action="${logtoEndpointUrl.href}`, `action="${proxyUrl.href}`);
78
- }
79
- if (proxyResponse.headers['content-type']?.includes('application/json')) {
80
- const jsonData = trySafe(() => JSON.parse(responseBody));
81
- if (jsonData && typeof jsonData === 'object') {
82
- const updatedEntries = Object.entries(jsonData).map(([key, value]) => {
83
- if ((key === 'redirectTo' || key.endsWith('_endpoint')) && typeof value === 'string') {
84
- return [key, value.replace(logtoEndpointUrl.href, proxyUrl.href)];
85
- }
86
- return [key, value];
87
- });
88
- return JSON.stringify(Object.fromEntries(updatedEntries));
89
- }
90
- }
91
- return responseBody;
92
- })(proxyResponse, request, response);
93
- };
94
- export const checkExperienceInput = (url, staticPath) => {
95
- if (staticPath && url) {
96
- consoleLog.fatal('Only one of the experience URI or path can be provided.');
97
- }
98
- if (!staticPath && !url) {
99
- consoleLog.fatal('Either a sign-in experience URI or local path must be provided.');
100
- }
101
- if (url && !isValidUrl(url)) {
102
- consoleLog.fatal('A valid sign-in experience URI must be provided. E.g.: http://localhost:4000');
103
- }
104
- if (staticPath && !existsSync(path.join(staticPath, index))) {
105
- consoleLog.fatal('The provided path does not contain a valid index.html file.');
106
- }
107
- };
108
- /**
109
- * Check if the request path is a Logto request path.
110
- * @example isLogtoRequestPath('/oidc/.well-known/openid-configuration') // true
111
- * @example isLogtoRequestPath('/oidc/auth') // true
112
- * @example isLogtoRequestPath('/api/interaction/submit') // true
113
- * @example isLogtoRequestPath('/consent') // true
114
- */
115
- export const isLogtoRequestPath = (requestPath) => ['/oidc/', '/api/'].some((path) => requestPath?.startsWith(path)) || requestPath === '/consent';
116
- const isFileAssetPath = (url) => url.split('/').at(-1)?.includes('.');
117
- const getMimeType = (requestPath) => {
118
- const fallBackToIndex = !isFileAssetPath(requestPath);
119
- if (fallBackToIndex) {
120
- return indexContentType;
121
- }
122
- return mime.getType(requestPath) ?? 'application/octet-stream';
123
- };
@@ -1,8 +0,0 @@
1
- import type { CommandModule } from 'yargs';
2
- declare const create: CommandModule<{
3
- path?: string;
4
- }, {
5
- path?: string;
6
- 'language-tag': string;
7
- }>;
8
- export default create;
@@ -1,37 +0,0 @@
1
- import { isLanguageTag } from '@logto/language-kit';
2
- import { isBuiltInLanguageTag as isPhrasesBuiltInLanguageTag } from '@logto/phrases';
3
- import { isBuiltInLanguageTag as isPhrasesUiBuiltInLanguageTag } from '@logto/phrases-experience';
4
- import { consoleLog, inquireInstancePath } from '../../utils.js';
5
- import { createFullTranslation } from './utils.js';
6
- const create = {
7
- command: ['create <language-tag>', 'c'],
8
- describe: 'Create a new language translation using ChatGPT. Note the environment variable `OPENAI_API_KEY` is required to work.',
9
- builder: (yargs) => yargs.positional('language-tag', {
10
- describe: 'The language tag to create, e.g. `af-ZA`.',
11
- type: 'string',
12
- demandOption: true,
13
- }),
14
- handler: async ({ path: inputPath, languageTag }) => {
15
- if (!isLanguageTag(languageTag)) {
16
- consoleLog.fatal('Invalid language tag. Run `logto translate list-tags` to see available list.');
17
- }
18
- const instancePath = await inquireInstancePath(inputPath);
19
- if (isPhrasesBuiltInLanguageTag(languageTag)) {
20
- consoleLog.info(languageTag + ' is a built-in tag of phrases, updating untranslated phrases');
21
- }
22
- await createFullTranslation({
23
- instancePath,
24
- packageName: 'phrases',
25
- languageTag,
26
- });
27
- if (isPhrasesUiBuiltInLanguageTag(languageTag)) {
28
- consoleLog.info(languageTag + ' is a built-in tag of phrases-experience, updating untranslated phrases');
29
- }
30
- await createFullTranslation({
31
- instancePath,
32
- packageName: 'phrases-experience',
33
- languageTag,
34
- });
35
- },
36
- };
37
- export default create;
@@ -1,3 +0,0 @@
1
- import type { CommandModule } from 'yargs';
2
- declare const translate: CommandModule;
3
- export default translate;
@@ -1,27 +0,0 @@
1
- import { noop } from '@silverhand/essentials';
2
- import create from './create.js';
3
- import listTags from './list-tags.js';
4
- import syncKeys from './sync-keys/index.js';
5
- import sync from './sync.js';
6
- const translate = {
7
- command: ['translate', 't'],
8
- describe: 'Commands for Logto translation',
9
- builder: (yargs) => yargs
10
- .option('path', {
11
- alias: 'p',
12
- type: 'string',
13
- describe: 'The path to your Logto instance directory',
14
- })
15
- .option('skip-core-check', {
16
- alias: 'sc',
17
- type: 'boolean',
18
- describe: 'Skip checking if the core package is existed',
19
- })
20
- .command(create)
21
- .command(listTags)
22
- .command(sync)
23
- .command(syncKeys)
24
- .demandCommand(1),
25
- handler: noop,
26
- };
27
- export default translate;
@@ -1,3 +0,0 @@
1
- import type { CommandModule } from 'yargs';
2
- declare const listTags: CommandModule<Record<string, unknown>>;
3
- export default listTags;
@@ -1,19 +0,0 @@
1
- import { languages } from '@logto/language-kit';
2
- import { isBuiltInLanguageTag as isPhrasesBuiltInLanguageTag } from '@logto/phrases';
3
- import { isBuiltInLanguageTag as isPhrasesUiBuiltInLanguageTag } from '@logto/phrases-experience';
4
- import chalk from 'chalk';
5
- import { consoleLog } from '../../utils.js';
6
- const listTags = {
7
- command: ['list-tags', 'list'],
8
- describe: 'List all available language tags',
9
- handler: async () => {
10
- for (const tag of Object.keys(languages)) {
11
- consoleLog.plain(...[
12
- tag,
13
- isPhrasesBuiltInLanguageTag(tag) && chalk.blue('phrases'),
14
- isPhrasesUiBuiltInLanguageTag(tag) && chalk.blue('phrases-experience'),
15
- ].filter(Boolean));
16
- }
17
- },
18
- };
19
- export default listTags;
@@ -1,11 +0,0 @@
1
- import { type LanguageTag } from '@logto/language-kit';
2
- import { type Got } from 'got';
3
- export declare const createOpenaiApi: () => Got;
4
- type TranslateConfig = {
5
- api: Got;
6
- sourceFilePath: string;
7
- targetLanguage: LanguageTag;
8
- extraPrompt?: string;
9
- };
10
- export declare const translate: ({ api, targetLanguage, sourceFilePath, extraPrompt, }: TranslateConfig) => Promise<string | undefined>;
11
- export {};