@logto/cli 1.0.0-beta.11 → 1.0.0-beta.13

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.
@@ -1,4 +1,4 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const add: CommandModule<{
3
3
  path?: string;
4
4
  }, {
@@ -1,3 +1,3 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const connector: CommandModule;
3
3
  export default connector;
@@ -1,4 +1,4 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const list: CommandModule<{
3
3
  path?: string;
4
4
  }, {
@@ -1,4 +1,4 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const remove: CommandModule<{
3
3
  path?: string;
4
4
  }, {
@@ -15,10 +15,6 @@ export declare const npmPackResultGuard: z.ZodArray<z.ZodObject<{
15
15
  export declare const inquireInstancePath: (initialPath?: string) => Promise<string>;
16
16
  export declare const normalizePackageName: (name: string) => string;
17
17
  export declare const isOfficialConnector: (packageName: string) => boolean;
18
- export declare type ConnectorPackage = {
19
- name: string;
20
- path: string;
21
- };
22
- export declare const getConnectorPackagesFrom: (instancePath?: string) => Promise<ConnectorPackage[]>;
18
+ export declare const getConnectorPackagesFrom: (instancePath?: string) => Promise<import("../../utilities").ConnectorPackage[]>;
23
19
  export declare const addConnectors: (instancePath: string, packageNames: string[]) => Promise<void>;
24
20
  export declare const addOfficialConnectors: (instancePath: string) => Promise<void>;
@@ -81,25 +81,9 @@ exports.normalizePackageName = normalizePackageName;
81
81
  const getConnectorDirectory = (instancePath) => path_1.default.join(instancePath, coreDirectory, constants_1.connectorDirectory);
82
82
  const isOfficialConnector = (packageName) => packageName.startsWith('@logto/connector-');
83
83
  exports.isOfficialConnector = isOfficialConnector;
84
- const getConnectorPackageName = async (directory) => {
85
- const filePath = path_1.default.join(directory, 'package.json');
86
- if (!(0, fs_1.existsSync)(filePath)) {
87
- return;
88
- }
89
- const json = await (0, promises_1.readFile)(filePath, 'utf8');
90
- const { name } = zod_1.z.object({ name: zod_1.z.string() }).parse(JSON.parse(json));
91
- if (name.startsWith('connector-') || Boolean(name.split('/')[1]?.startsWith('connector-'))) {
92
- return name;
93
- }
94
- };
95
84
  const getConnectorPackagesFrom = async (instancePath) => {
96
85
  const directory = getConnectorDirectory(await (0, exports.inquireInstancePath)(instancePath));
97
- const content = await (0, promises_1.readdir)(directory, 'utf8');
98
- const rawPackages = await Promise.all(content.map(async (value) => {
99
- const currentDirectory = path_1.default.join(directory, value);
100
- return { name: await getConnectorPackageName(currentDirectory), path: currentDirectory };
101
- }));
102
- return rawPackages.filter((packageInfo) => typeof packageInfo.name === 'string');
86
+ return (0, utilities_1.getConnectorPackagesFromDirectory)(directory);
103
87
  };
104
88
  exports.getConnectorPackagesFrom = getConnectorPackagesFrom;
105
89
  const addConnectors = async (instancePath, packageNames) => {
@@ -1,6 +1,6 @@
1
- import { DatabasePool } from 'slonik';
2
- import { CommandModule } from 'yargs';
3
- import { AlterationFile } from './type';
1
+ import type { DatabasePool } from 'slonik';
2
+ import type { CommandModule } from 'yargs';
3
+ import type { AlterationFile } from './type';
4
4
  export declare const getAlterationFiles: () => Promise<AlterationFile[]>;
5
5
  export declare const getLatestAlterationTimestamp: () => Promise<number>;
6
6
  export declare const getUndeployedAlterations: (pool: DatabasePool) => Promise<AlterationFile[]>;
@@ -1,2 +1,2 @@
1
- import { AlterationFile } from './type';
1
+ import type { AlterationFile } from './type';
2
2
  export declare const chooseAlterationsByVersion: (alterations: readonly AlterationFile[], initialVersion?: string) => Promise<AlterationFile[]>;
@@ -1,3 +1,3 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const config: CommandModule;
3
3
  export default config;
@@ -9,6 +9,7 @@ const chalk_1 = __importDefault(require("chalk"));
9
9
  const database_1 = require("../../database");
10
10
  const logto_config_1 = require("../../queries/logto-config");
11
11
  const utilities_1 = require("../../utilities");
12
+ const utilities_2 = require("./utilities");
12
13
  const validKeysDisplay = chalk_1.default.green(schemas_1.logtoConfigKeys.join(', '));
13
14
  const validateKeys = (keys) => {
14
15
  const invalidKey = (Array.isArray(keys) ? keys : [keys]).find(
@@ -19,6 +20,17 @@ const validateKeys = (keys) => {
19
20
  utilities_1.log.error(`Invalid config key ${chalk_1.default.red(invalidKey)} found, expected one of ${validKeysDisplay}`);
20
21
  }
21
22
  };
23
+ const validRotateKeys = Object.freeze([
24
+ schemas_1.LogtoOidcConfigKey.PrivateKeys,
25
+ schemas_1.LogtoOidcConfigKey.CookieKeys,
26
+ ]);
27
+ const validateRotateKey = (key) => {
28
+ // Using `.includes()` will result a type error
29
+ // eslint-disable-next-line unicorn/prefer-includes
30
+ if (!validRotateKeys.some((element) => element === key)) {
31
+ utilities_1.log.error(`Invalid config key ${chalk_1.default.red(key)} found, expected one of ${validKeysDisplay}`);
32
+ }
33
+ };
22
34
  const getConfig = {
23
35
  command: 'get <key> [keys...]',
24
36
  describe: 'Get config value(s) of the given key(s) in Logto database',
@@ -73,10 +85,87 @@ const setConfig = {
73
85
  utilities_1.log.info(`Update ${chalk_1.default.green(key)} succeeded`);
74
86
  },
75
87
  };
88
+ const rotateConfig = {
89
+ command: 'rotate <key>',
90
+ describe: 'Generate a new private or secret key for the given config key and prepend to the key array',
91
+ builder: (yargs) => yargs.positional('key', {
92
+ describe: `The key to rotate, one of ${chalk_1.default.green(validRotateKeys.join(', '))}`,
93
+ type: 'string',
94
+ demandOption: true,
95
+ }),
96
+ handler: async ({ key }) => {
97
+ validateRotateKey(key);
98
+ const pool = await (0, database_1.createPoolFromConfig)();
99
+ const { rows } = await (0, logto_config_1.getRowsByKeys)(pool, [key]);
100
+ if (!rows[0]) {
101
+ utilities_1.log.warn('No key found, create a new one');
102
+ }
103
+ const getValue = async () => {
104
+ const parsed = schemas_1.logtoConfigGuards[key].safeParse(rows[0]?.value);
105
+ const original = parsed.success ? parsed.data : [];
106
+ // No need for default. It's already exhaustive
107
+ // eslint-disable-next-line default-case
108
+ switch (key) {
109
+ case schemas_1.LogtoOidcConfigKey.PrivateKeys:
110
+ return [await (0, utilities_2.generateOidcPrivateKey)(), ...original];
111
+ case schemas_1.LogtoOidcConfigKey.CookieKeys:
112
+ return [(0, utilities_2.generateOidcCookieKey)(), ...original];
113
+ }
114
+ };
115
+ const rotated = await getValue();
116
+ await (0, logto_config_1.updateValueByKey)(pool, key, rotated);
117
+ await pool.end();
118
+ utilities_1.log.info(`Rotate ${chalk_1.default.green(key)} succeeded, now it has ${rotated.length} keys`);
119
+ },
120
+ };
121
+ const trimConfig = {
122
+ command: 'trim <key> [length]',
123
+ describe: 'Remove the last [length] number of private or secret keys for the given config key',
124
+ builder: (yargs) => yargs
125
+ .positional('key', {
126
+ describe: `The config key to trim, one of ${chalk_1.default.green(validRotateKeys.join(', '))}`,
127
+ type: 'string',
128
+ demandOption: true,
129
+ })
130
+ .positional('length', {
131
+ describe: 'Number of private or secret keys to trim',
132
+ type: 'number',
133
+ default: 1,
134
+ demandOption: true,
135
+ }),
136
+ handler: async ({ key, length }) => {
137
+ validateRotateKey(key);
138
+ if (length < 1) {
139
+ utilities_1.log.error('Invalid length provided');
140
+ }
141
+ const pool = await (0, database_1.createPoolFromConfig)();
142
+ const { rows } = await (0, logto_config_1.getRowsByKeys)(pool, [key]);
143
+ if (!rows[0]) {
144
+ utilities_1.log.warn('No key found, create a new one');
145
+ }
146
+ const getValue = async () => {
147
+ const value = schemas_1.logtoConfigGuards[key].parse(rows[0]?.value);
148
+ if (value.length - length < 1) {
149
+ await pool.end();
150
+ utilities_1.log.error(`You should keep at least one key in the array, current length=${value.length}`);
151
+ }
152
+ return value.slice(0, -length);
153
+ };
154
+ const trimmed = await getValue();
155
+ await (0, logto_config_1.updateValueByKey)(pool, key, trimmed);
156
+ await pool.end();
157
+ utilities_1.log.info(`Trim ${chalk_1.default.green(key)} succeeded, now it has ${trimmed.length} keys`);
158
+ },
159
+ };
76
160
  const config = {
77
161
  command: ['config', 'configs'],
78
162
  describe: 'Commands for Logto database config',
79
- builder: (yargs) => yargs.command(getConfig).command(setConfig).demandCommand(1),
163
+ builder: (yargs) => yargs
164
+ .command(getConfig)
165
+ .command(setConfig)
166
+ .command(rotateConfig)
167
+ .command(trimConfig)
168
+ .demandCommand(1),
80
169
  handler: essentials_1.noop,
81
170
  };
82
171
  exports.default = config;
@@ -1,3 +1,3 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  declare const database: CommandModule;
3
3
  export default database;
@@ -1,5 +1,5 @@
1
- import { DatabasePool } from 'slonik';
2
- import { CommandModule } from 'yargs';
1
+ import type { DatabasePool } from 'slonik';
2
+ import type { CommandModule } from 'yargs';
3
3
  declare const seedChoices: readonly ["all", "oidc"];
4
4
  declare type SeedChoice = typeof seedChoices[number];
5
5
  export declare const seedByPool: (pool: DatabasePool, type: SeedChoice) => Promise<void>;
@@ -1,4 +1,5 @@
1
- import { LogtoOidcConfigKey, LogtoOidcConfigType } from '@logto/schemas';
1
+ import type { LogtoOidcConfigType } from '@logto/schemas';
2
+ import { LogtoOidcConfigKey } from '@logto/schemas';
2
3
  /**
3
4
  * Each config reader will do the following things in order:
4
5
  * 1. Try to read value from env (mimic the behavior from the original core)
@@ -1,12 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.oidcConfigReaders = void 0;
4
- const crypto_1 = require("crypto");
5
4
  const promises_1 = require("fs/promises");
6
- const util_1 = require("util");
7
5
  const schemas_1 = require("@logto/schemas");
8
6
  const essentials_1 = require("@silverhand/essentials");
9
- const nanoid_1 = require("nanoid");
7
+ const utilities_1 = require("../utilities");
10
8
  const isBase64FormatPrivateKey = (key) => !key.includes('-');
11
9
  /**
12
10
  * Each config reader will do the following things in order:
@@ -46,27 +44,15 @@ exports.oidcConfigReaders = {
46
44
  fromEnv: true,
47
45
  };
48
46
  }
49
- // Generate a new key
50
- const { privateKey } = await (0, util_1.promisify)(crypto_1.generateKeyPair)('rsa', {
51
- modulusLength: 4096,
52
- publicKeyEncoding: {
53
- type: 'spki',
54
- format: 'pem',
55
- },
56
- privateKeyEncoding: {
57
- type: 'pkcs8',
58
- format: 'pem',
59
- },
60
- });
61
47
  return {
62
- value: [privateKey],
48
+ value: [await (0, utilities_1.generateOidcPrivateKey)()],
63
49
  fromEnv: false,
64
50
  };
65
51
  },
66
52
  [schemas_1.LogtoOidcConfigKey.CookieKeys]: async () => {
67
53
  const envKey = 'OIDC_COOKIE_KEYS';
68
54
  const keys = (0, essentials_1.getEnvAsStringArray)(envKey);
69
- return { value: keys.length > 0 ? keys : [(0, nanoid_1.nanoid)()], fromEnv: keys.length > 0 };
55
+ return { value: keys.length > 0 ? keys : [(0, utilities_1.generateOidcCookieKey)()], fromEnv: keys.length > 0 };
70
56
  },
71
57
  [schemas_1.LogtoOidcConfigKey.RefreshTokenReuseInterval]: async () => {
72
58
  const envKey = 'OIDC_REFRESH_TOKEN_REUSE_INTERVAL';
@@ -0,0 +1,2 @@
1
+ export declare const generateOidcPrivateKey: () => Promise<string>;
2
+ export declare const generateOidcCookieKey: () => string;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateOidcCookieKey = exports.generateOidcPrivateKey = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const util_1 = require("util");
6
+ const nanoid_1 = require("nanoid");
7
+ const generateOidcPrivateKey = async () => {
8
+ const { privateKey } = await (0, util_1.promisify)(crypto_1.generateKeyPair)('rsa', {
9
+ modulusLength: 4096,
10
+ publicKeyEncoding: {
11
+ type: 'spki',
12
+ format: 'pem',
13
+ },
14
+ privateKeyEncoding: {
15
+ type: 'pkcs8',
16
+ format: 'pem',
17
+ },
18
+ });
19
+ return privateKey;
20
+ };
21
+ exports.generateOidcPrivateKey = generateOidcPrivateKey;
22
+ const generateOidcCookieKey = () => (0, nanoid_1.nanoid)();
23
+ exports.generateOidcCookieKey = generateOidcCookieKey;
@@ -1,4 +1,4 @@
1
- import { CommandModule } from 'yargs';
1
+ import type { CommandModule } from 'yargs';
2
2
  export declare type InstallArgs = {
3
3
  path?: string;
4
4
  skipSeed: boolean;
@@ -44,13 +44,14 @@ const seed_1 = require("../database/seed");
44
44
  exports.defaultPath = path_1.default.join(os_1.default.homedir(), 'logto');
45
45
  const pgRequired = new semver.SemVer('14.0.0');
46
46
  const validateNodeVersion = () => {
47
- const required = new semver.SemVer('16.0.0');
47
+ const required = [new semver.SemVer('16.13.0'), new semver.SemVer('18.12.0')];
48
+ const requiredVersionString = required.map((version) => '^' + version.version).join(' || ');
48
49
  const current = new semver.SemVer((0, child_process_1.execSync)('node -v', { encoding: 'utf8', stdio: 'pipe' }));
49
- if (required.compare(current) > 0) {
50
- utilities_1.log.error(`Logto requires NodeJS >=${required.version}, but ${current.version} found.`);
50
+ if (required.every((version) => version.major !== current.major)) {
51
+ utilities_1.log.error(`Logto requires NodeJS ${requiredVersionString}, but ${current.version} found.`);
51
52
  }
52
- if (current.major > required.major) {
53
- utilities_1.log.warn(`Logto is tested under NodeJS ^${required.version}, but version ${current.version} found.`);
53
+ if (required.some((version) => version.major === current.major && version.compare(current) > 0)) {
54
+ utilities_1.log.warn(`Logto is tested under NodeJS ${requiredVersionString}, but version ${current.version} found.`);
54
55
  }
55
56
  };
56
57
  exports.validateNodeVersion = validateNodeVersion;
package/lib/database.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SchemaLike } from '@logto/schemas';
1
+ import type { SchemaLike } from '@logto/schemas';
2
2
  export declare const defaultDatabaseUrl = "postgresql://localhost:5432/logto";
3
3
  export declare const getDatabaseUrlFromConfig: () => Promise<string>;
4
4
  export declare const createPoolFromConfig: () => Promise<import("slonik").DatabasePool>;
package/lib/database.js CHANGED
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertInto = exports.createPoolAndDatabaseIfNeeded = exports.createPoolFromConfig = exports.getDatabaseUrlFromConfig = exports.defaultDatabaseUrl = void 0;
7
7
  const shared_1 = require("@logto/shared");
8
+ const essentials_1 = require("@silverhand/essentials");
8
9
  const decamelize_1 = __importDefault(require("decamelize"));
9
10
  const slonik_1 = require("slonik");
10
11
  const slonik_interceptor_preset_1 = require("slonik-interceptor-preset");
@@ -19,6 +20,7 @@ const getDatabaseUrlFromConfig = async () => (await (0, utilities_1.getCliConfig
19
20
  exports.getDatabaseUrlFromConfig = getDatabaseUrlFromConfig;
20
21
  const createPoolFromConfig = async () => {
21
22
  const databaseUrl = await (0, exports.getDatabaseUrlFromConfig)();
23
+ (0, essentials_1.assert)((0, slonik_1.parseDsn)(databaseUrl).databaseName, new Error('Database name is required in URL'));
22
24
  return (0, slonik_1.createPool)(databaseUrl, {
23
25
  interceptors: (0, slonik_interceptor_preset_1.createInterceptors)(),
24
26
  });
@@ -47,7 +49,9 @@ const createPoolAndDatabaseIfNeeded = async () => {
47
49
  // - Database name is required to connect in the previous pool
48
50
  // - It will throw error when creating database using '?'
49
51
  const databaseName = dsn.databaseName ?? '?';
50
- const maintenancePool = await (0, slonik_1.createPool)((0, slonik_1.stringifyDsn)({ ...dsn, databaseName: 'postgres' }));
52
+ const maintenancePool = await (0, slonik_1.createPool)((0, slonik_1.stringifyDsn)({ ...dsn, databaseName: 'postgres' }), {
53
+ interceptors: (0, slonik_interceptor_preset_1.createInterceptors)(),
54
+ });
51
55
  await maintenancePool.query((0, slonik_1.sql) `
52
56
  create database ${slonik_1.sql.identifier([databaseName])}
53
57
  with
@@ -83,5 +83,4 @@ export declare const packageJson: {
83
83
  ignorePatterns: string[];
84
84
  };
85
85
  prettier: string;
86
- gitHead: string;
87
86
  };
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.packageJson = void 0;
4
4
  exports.packageJson = {
5
5
  "name": "@logto/cli",
6
- "version": "1.0.0-beta.11",
6
+ "version": "1.0.0-beta.13",
7
7
  "description": "Logto CLI.",
8
8
  "author": "Silverhand Inc. <contact@silverhand.io>",
9
9
  "homepage": "https://github.com/logto-io/logto#readme",
@@ -37,20 +37,20 @@ exports.packageJson = {
37
37
  "prepack": "pnpm build"
38
38
  },
39
39
  "engines": {
40
- "node": "^16.0.0"
40
+ "node": "^16.13.0 || ^18.12.0"
41
41
  },
42
42
  "bugs": {
43
43
  "url": "https://github.com/logto-io/logto/issues"
44
44
  },
45
45
  "dependencies": {
46
- "@logto/schemas": "^1.0.0-beta.11",
47
- "@logto/shared": "^1.0.0-beta.11",
46
+ "@logto/schemas": "workspace:^",
47
+ "@logto/shared": "workspace:^",
48
48
  "@silverhand/essentials": "^1.3.0",
49
49
  "chalk": "^4.1.2",
50
50
  "decamelize": "^5.0.0",
51
51
  "dotenv": "^16.0.0",
52
52
  "fs-extra": "^10.1.0",
53
- "got": "^11.8.2",
53
+ "got": "^11.8.5",
54
54
  "hpagent": "^1.0.0",
55
55
  "inquirer": "^8.2.2",
56
56
  "nanoid": "^3.3.4",
@@ -63,10 +63,10 @@ exports.packageJson = {
63
63
  "slonik-sql-tag-raw": "^1.1.4",
64
64
  "tar": "^6.1.11",
65
65
  "yargs": "^17.6.0",
66
- "zod": "^3.18.0"
66
+ "zod": "^3.19.1"
67
67
  },
68
68
  "devDependencies": {
69
- "@silverhand/eslint-config": "1.2.0",
69
+ "@silverhand/eslint-config": "1.3.0",
70
70
  "@silverhand/jest-config": "1.2.2",
71
71
  "@silverhand/ts-config": "1.2.1",
72
72
  "@types/fs-extra": "^9.0.13",
@@ -90,6 +90,5 @@ exports.packageJson = {
90
90
  "src/package-json.ts"
91
91
  ]
92
92
  },
93
- "prettier": "@silverhand/eslint-config/.prettierrc",
94
- "gitHead": "33c10ce21600e048a448d8a598cf51b589854b15"
93
+ "prettier": "@silverhand/eslint-config/.prettierrc"
95
94
  };
@@ -1,5 +1,6 @@
1
- import { LogtoConfig, logtoConfigGuards, LogtoConfigKey } from '@logto/schemas';
2
- import { DatabasePool, DatabaseTransactionConnection } from 'slonik';
1
+ import type { LogtoConfig, LogtoConfigKey } from '@logto/schemas';
2
+ import { logtoConfigGuards } from '@logto/schemas';
3
+ import type { DatabasePool, DatabaseTransactionConnection } from 'slonik';
3
4
  import { z } from 'zod';
4
5
  export declare const doesConfigsTableExist: (pool: DatabasePool) => Promise<boolean>;
5
6
  export declare const getRowsByKeys: (pool: DatabasePool | DatabaseTransactionConnection, keys: LogtoConfigKey[]) => Promise<import("slonik").QueryResult<LogtoConfig>>;
@@ -1,5 +1,5 @@
1
- import { QueryResult, QueryResultRow } from 'slonik';
2
- import { PrimitiveValueExpression } from 'slonik/dist/src/types.d';
1
+ import type { QueryResult, QueryResultRow } from 'slonik';
2
+ import type { PrimitiveValueExpression } from 'slonik/dist/src/types.d';
3
3
  export declare type QueryType = (sql: string, values: readonly PrimitiveValueExpression[]) => Promise<QueryResult<QueryResultRow>>;
4
4
  /**
5
5
  * Slonik Query Mock Utils
@@ -1,4 +1,4 @@
1
- import { Optional } from '@silverhand/essentials';
1
+ import type { Optional } from '@silverhand/essentials';
2
2
  import ora from 'ora';
3
3
  export declare const safeExecSync: (command: string) => string | undefined;
4
4
  declare type Log = Readonly<{
@@ -32,4 +32,9 @@ export declare const getCliConfigWithPrompt: ({ key, readableKey, comments, defa
32
32
  * findLastIndex immediately returns that element index. Otherwise, findLastIndex returns -1.
33
33
  */
34
34
  export declare function findLastIndex<T>(array: readonly T[], predicate: (value: T, index: number, object: readonly T[]) => boolean): number;
35
+ export declare type ConnectorPackage = {
36
+ name: string;
37
+ path: string;
38
+ };
39
+ export declare const getConnectorPackagesFromDirectory: (directory: string) => Promise<ConnectorPackage[]>;
35
40
  export {};
package/lib/utilities.js CHANGED
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findLastIndex = exports.getCliConfigWithPrompt = exports.cliConfig = exports.ConfigKey = exports.isTty = exports.oraPromise = exports.getPathInModule = exports.downloadFile = exports.log = exports.safeExecSync = void 0;
6
+ exports.getConnectorPackagesFromDirectory = exports.findLastIndex = exports.getCliConfigWithPrompt = exports.cliConfig = exports.ConfigKey = exports.isTty = exports.oraPromise = exports.getPathInModule = exports.downloadFile = exports.log = exports.safeExecSync = void 0;
7
7
  const child_process_1 = require("child_process");
8
8
  const fs_1 = require("fs");
9
+ const promises_1 = require("fs/promises");
9
10
  const path_1 = __importDefault(require("path"));
10
11
  const essentials_1 = require("@silverhand/essentials");
11
12
  const chalk_1 = __importDefault(require("chalk"));
@@ -13,6 +14,7 @@ const got_1 = __importDefault(require("got"));
13
14
  const hpagent_1 = require("hpagent");
14
15
  const inquirer_1 = __importDefault(require("inquirer"));
15
16
  const ora_1 = __importDefault(require("ora"));
17
+ const zod_1 = require("zod");
16
18
  const safeExecSync = (command) => {
17
19
  try {
18
20
  return (0, child_process_1.execSync)(command, { encoding: 'utf8', stdio: 'pipe' });
@@ -134,3 +136,23 @@ function findLastIndex(array, predicate) {
134
136
  return -1;
135
137
  }
136
138
  exports.findLastIndex = findLastIndex;
139
+ const getConnectorPackageName = async (directory) => {
140
+ const filePath = path_1.default.join(directory, 'package.json');
141
+ if (!(0, fs_1.existsSync)(filePath)) {
142
+ return;
143
+ }
144
+ const json = await (0, promises_1.readFile)(filePath, 'utf8');
145
+ const { name } = zod_1.z.object({ name: zod_1.z.string() }).parse(JSON.parse(json));
146
+ if (name.startsWith('connector-') || Boolean(name.split('/')[1]?.startsWith('connector-'))) {
147
+ return name;
148
+ }
149
+ };
150
+ const getConnectorPackagesFromDirectory = async (directory) => {
151
+ const content = await (0, promises_1.readdir)(directory, 'utf8');
152
+ const rawPackages = await Promise.all(content.map(async (value) => {
153
+ const currentDirectory = path_1.default.join(directory, value);
154
+ return { name: await getConnectorPackageName(currentDirectory), path: currentDirectory };
155
+ }));
156
+ return rawPackages.filter((packageInfo) => typeof packageInfo.name === 'string');
157
+ };
158
+ exports.getConnectorPackagesFromDirectory = getConnectorPackagesFromDirectory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/cli",
3
- "version": "1.0.0-beta.11",
3
+ "version": "1.0.0-beta.13",
4
4
  "description": "Logto CLI.",
5
5
  "author": "Silverhand Inc. <contact@silverhand.io>",
6
6
  "homepage": "https://github.com/logto-io/logto#readme",
@@ -20,34 +20,21 @@
20
20
  "type": "git",
21
21
  "url": "git+https://github.com/logto-io/logto.git"
22
22
  },
23
- "scripts": {
24
- "precommit": "lint-staged",
25
- "prepare:package-json": "node -p \"'export const packageJson = ' + JSON.stringify(require('./package.json'), undefined, 2) + ';'\" > src/package-json.ts",
26
- "build": "rimraf lib && pnpm prepare:package-json && tsc -p tsconfig.build.json",
27
- "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
28
- "start": "node .",
29
- "start:dev": "ts-node --files src/index.ts",
30
- "lint": "eslint --ext .ts src",
31
- "lint:report": "pnpm lint --format json --output-file report.json",
32
- "test": "jest",
33
- "test:ci": "jest",
34
- "prepack": "pnpm build"
35
- },
36
23
  "engines": {
37
- "node": "^16.0.0"
24
+ "node": "^16.13.0 || ^18.12.0"
38
25
  },
39
26
  "bugs": {
40
27
  "url": "https://github.com/logto-io/logto/issues"
41
28
  },
42
29
  "dependencies": {
43
- "@logto/schemas": "^1.0.0-beta.11",
44
- "@logto/shared": "^1.0.0-beta.11",
30
+ "@logto/schemas": "^1.0.0-beta.13",
31
+ "@logto/shared": "^1.0.0-beta.13",
45
32
  "@silverhand/essentials": "^1.3.0",
46
33
  "chalk": "^4.1.2",
47
34
  "decamelize": "^5.0.0",
48
35
  "dotenv": "^16.0.0",
49
36
  "fs-extra": "^10.1.0",
50
- "got": "^11.8.2",
37
+ "got": "^11.8.5",
51
38
  "hpagent": "^1.0.0",
52
39
  "inquirer": "^8.2.2",
53
40
  "nanoid": "^3.3.4",
@@ -60,10 +47,10 @@
60
47
  "slonik-sql-tag-raw": "^1.1.4",
61
48
  "tar": "^6.1.11",
62
49
  "yargs": "^17.6.0",
63
- "zod": "^3.18.0"
50
+ "zod": "^3.19.1"
64
51
  },
65
52
  "devDependencies": {
66
- "@silverhand/eslint-config": "1.2.0",
53
+ "@silverhand/eslint-config": "1.3.0",
67
54
  "@silverhand/jest-config": "1.2.2",
68
55
  "@silverhand/ts-config": "1.2.1",
69
56
  "@types/fs-extra": "^9.0.13",
@@ -88,5 +75,16 @@
88
75
  ]
89
76
  },
90
77
  "prettier": "@silverhand/eslint-config/.prettierrc",
91
- "gitHead": "33c10ce21600e048a448d8a598cf51b589854b15"
92
- }
78
+ "scripts": {
79
+ "precommit": "lint-staged",
80
+ "prepare:package-json": "node -p \"'export const packageJson = ' + JSON.stringify(require('./package.json'), undefined, 2) + ';'\" > src/package-json.ts",
81
+ "build": "rimraf lib && pnpm prepare:package-json && tsc -p tsconfig.build.json",
82
+ "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
83
+ "start": "node .",
84
+ "start:dev": "ts-node --files src/index.ts",
85
+ "lint": "eslint --ext .ts src",
86
+ "lint:report": "pnpm lint --format json --output-file report.json",
87
+ "test": "jest",
88
+ "test:ci": "jest"
89
+ }
90
+ }