@memberjunction/cli 2.13.2 → 2.13.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ $ npm install -g @memberjunction/cli
12
12
  $ mj COMMAND
13
13
  running command...
14
14
  $ mj (--version)
15
- @memberjunction/cli/2.13.2 linux-x64 node-v20.18.1
15
+ @memberjunction/cli/2.13.4 linux-x64 node-v20.18.1
16
16
  $ mj --help [COMMAND]
17
17
  USAGE
18
18
  $ mj COMMAND
@@ -21,12 +21,50 @@ USAGE
21
21
  <!-- usagestop -->
22
22
  # Commands
23
23
  <!-- commands -->
24
+ * [`mj bump`](#mj-bump)
24
25
  * [`mj clean`](#mj-clean)
26
+ * [`mj codegen`](#mj-codegen)
25
27
  * [`mj help [COMMAND]`](#mj-help-command)
26
28
  * [`mj install`](#mj-install)
27
29
  * [`mj migrate`](#mj-migrate)
28
30
  * [`mj version`](#mj-version)
29
31
 
32
+ ## `mj bump`
33
+
34
+ Bumps MemberJunction dependency versions
35
+
36
+ ```
37
+ USAGE
38
+ $ mj bump [-v] [-r] [-t <value>] [-q] [-d]
39
+
40
+ FLAGS
41
+ -d, --dry Dry run, do not write changes to package.json files
42
+ -q, --quiet Only output paths for updated packages
43
+ -r, --recursive Bump version in current directory and all subdirectories
44
+ -t, --tag=<value> Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version
45
+ -v, --verbose Enable additional logging
46
+
47
+ DESCRIPTION
48
+ Bumps MemberJunction dependency versions
49
+
50
+ EXAMPLES
51
+ Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version
52
+
53
+ $ mj bump
54
+
55
+ Preview all recursive packages bumps without writing any changes.
56
+
57
+ $ mj bump -rdv
58
+
59
+ Recursively bump all @memberjunction/* dependencies in all packages to version v2.10.0 and output only the paths
60
+ containing the updated package.json files. Pipe the output to xargs to run npm install in each directory and update
61
+ the package-lock.json files as well.
62
+
63
+ $ mj bump -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}
64
+ ```
65
+
66
+ _See code: [src/commands/bump/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.4/src/commands/bump/index.ts)_
67
+
30
68
  ## `mj clean`
31
69
 
32
70
  Resets the MemberJunction database to a pre-installation state
@@ -45,7 +83,27 @@ EXAMPLES
45
83
  $ mj clean
46
84
  ```
47
85
 
48
- _See code: [src/commands/clean/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.2/src/commands/clean/index.ts)_
86
+ _See code: [src/commands/clean/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.4/src/commands/clean/index.ts)_
87
+
88
+ ## `mj codegen`
89
+
90
+ Run CodeGen to generate code and update metadata for MemberJunction
91
+
92
+ ```
93
+ USAGE
94
+ $ mj codegen [--skipdb]
95
+
96
+ FLAGS
97
+ --skipdb Skip database migration
98
+
99
+ DESCRIPTION
100
+ Run CodeGen to generate code and update metadata for MemberJunction
101
+
102
+ EXAMPLES
103
+ $ mj codegen
104
+ ```
105
+
106
+ _See code: [src/commands/codegen/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.4/src/commands/codegen/index.ts)_
49
107
 
50
108
  ## `mj help [COMMAND]`
51
109
 
@@ -85,7 +143,7 @@ EXAMPLES
85
143
  $ mj install
86
144
  ```
87
145
 
88
- _See code: [src/commands/install/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.2/src/commands/install/index.ts)_
146
+ _See code: [src/commands/install/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.4/src/commands/install/index.ts)_
89
147
 
90
148
  ## `mj migrate`
91
149
 
@@ -93,10 +151,11 @@ Migrate MemberJunction database to latest version
93
151
 
94
152
  ```
95
153
  USAGE
96
- $ mj migrate [-v]
154
+ $ mj migrate [-v] [-t <value>]
97
155
 
98
156
  FLAGS
99
- -v, --verbose Enable additional logging
157
+ -t, --tag=<value> Version tag to use for running remote migrations
158
+ -v, --verbose Enable additional logging
100
159
 
101
160
  DESCRIPTION
102
161
  Migrate MemberJunction database to latest version
@@ -105,7 +164,7 @@ EXAMPLES
105
164
  $ mj migrate
106
165
  ```
107
166
 
108
- _See code: [src/commands/migrate/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.2/src/commands/migrate/index.ts)_
167
+ _See code: [src/commands/migrate/index.ts](https://github.com/MemberJunction/MJ/blob/v2.13.4/src/commands/migrate/index.ts)_
109
168
 
110
169
  ## `mj version`
111
170
 
package/bin/dev.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node_modules/.bin/ts-node
2
+ require('dotenv').config()
2
3
  ;(async () => {
3
4
  const oclif = await import('@oclif/core')
4
5
  await oclif.execute({ development: true, dir: __dirname })
package/bin/run.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
-
2
+ require('dotenv').config()
3
3
  ;(async () => {
4
4
  const oclif = await import('@oclif/core')
5
5
  await oclif.execute({development: false, dir: __dirname})
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Bump extends Command {
3
+ static description: string;
4
+ static examples: {
5
+ command: string;
6
+ description: string;
7
+ }[];
8
+ static flags: {
9
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ recursive: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ tag: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ quiet: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ dry: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const core_1 = require("@oclif/core");
30
+ const node_fs_1 = require("node:fs");
31
+ const zod_1 = require("zod");
32
+ const fg = __importStar(require("fast-glob"));
33
+ const ora_classic_1 = __importDefault(require("ora-classic"));
34
+ const node_path_1 = require("node:path");
35
+ // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
36
+ const semverRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
37
+ const tagSchema = zod_1.z
38
+ .string()
39
+ .optional()
40
+ .transform((tag) => tag?.replace(/^v/, ''))
41
+ .refine((tag) => !tag || semverRegex.test(tag));
42
+ /**
43
+ * No-op used to suppress logging output
44
+ * @returns No return value
45
+ */
46
+ const suppressLogging = () => null;
47
+ class Bump extends core_1.Command {
48
+ static description = 'Bumps MemberJunction dependency versions';
49
+ static examples = [
50
+ {
51
+ command: '<%= config.bin %> <%= command.id %>',
52
+ description: "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version",
53
+ },
54
+ {
55
+ command: '<%= config.bin %> <%= command.id %> -rdv',
56
+ description: 'Preview all recursive packages bumps without writing any changes.',
57
+ },
58
+ {
59
+ command: '<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}',
60
+ description: 'Recursively bump all @memberjunction/* dependencies in all packages to version v2.10.0 and output only the paths containing the updated package.json files. Pipe the output to xargs to run npm install in each directory and update the package-lock.json files as well.',
61
+ },
62
+ ];
63
+ static flags = {
64
+ verbose: core_1.Flags.boolean({ char: 'v', description: 'Enable additional logging' }),
65
+ recursive: core_1.Flags.boolean({ char: 'r', description: 'Bump version in current directory and all subdirectories' }),
66
+ tag: core_1.Flags.string({ char: 't', description: 'Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version' }),
67
+ quiet: core_1.Flags.boolean({ char: 'q', description: 'Only output paths for updated packages' }),
68
+ dry: core_1.Flags.boolean({ char: 'd', description: 'Dry run, do not write changes to package.json files' }),
69
+ };
70
+ async run() {
71
+ const { flags } = await this.parse(Bump);
72
+ const verboseLogger = flags.verbose && !flags.quiet ? this.log.bind(this) : suppressLogging;
73
+ const normalLogger = flags.quiet ? suppressLogging : this.log.bind(this);
74
+ const quietLogger = flags.quiet ? this.log.bind(this) : suppressLogging;
75
+ // Get the target version from the tag flag or the CLI version
76
+ const tagArgument = tagSchema.safeParse(flags.tag);
77
+ if (flags.tag && tagArgument.success === false) {
78
+ this.error(`Invalid tag argument: '${flags.tag}'; must be a valid semver version string (e.g. v2.10.0)`);
79
+ }
80
+ const targetVersion = flags.tag && tagArgument.success ? tagArgument.data : this.config.pjson.version;
81
+ normalLogger(`Bumping all @memberjunction/* dependencies to version ${targetVersion}`);
82
+ flags.recursive && normalLogger('Recursively updating all package.json files');
83
+ // get list of package.json files to edit
84
+ const packageJsonFiles = fg.sync(`${flags.recursive ? '**/' : ''}package.json`, { ignore: ['node_modules/**'] });
85
+ if (packageJsonFiles.length === 0) {
86
+ this.error('No package.json files found');
87
+ }
88
+ if (flags.dry) {
89
+ normalLogger('Dry run, no changes will be made to package.json files');
90
+ }
91
+ const skipped = [];
92
+ const mjRegx = /"@memberjunction\/([^"]+)":(\s*)("[^"]+")/g;
93
+ const banner = 'Bumping packages... ';
94
+ const spinner = (0, ora_classic_1.default)(banner);
95
+ spinner.start();
96
+ normalLogger('');
97
+ try {
98
+ for (let i = 0; i < packageJsonFiles.length; i++) {
99
+ const packageJson = `./${packageJsonFiles[i]}`;
100
+ const packageJsonContents = (0, node_fs_1.readFileSync)(packageJson).toString();
101
+ if (!mjRegx.test(packageJsonContents)) {
102
+ skipped.push(packageJson);
103
+ continue;
104
+ }
105
+ verboseLogger(`\tBumping ${(0, node_path_1.dirname)(packageJson)}`);
106
+ spinner.text = `${banner} ${i + 1 - skipped.length}/${packageJsonFiles.length - skipped.length}`;
107
+ const bumpedPackageJson = packageJsonContents.replaceAll(mjRegx, `"@memberjunction/$1":$2"${targetVersion}"`);
108
+ if (!flags.dry) {
109
+ (0, node_fs_1.writeFileSync)(packageJson, bumpedPackageJson);
110
+ }
111
+ // In quiet mode, we only output the paths of the updated package.json files so they can be piped to another command
112
+ quietLogger((0, node_path_1.dirname)(packageJson));
113
+ }
114
+ spinner.succeed(`Bumped ${packageJsonFiles.length - skipped.length}/${packageJsonFiles.length} packages`);
115
+ }
116
+ catch (error) {
117
+ spinner.fail();
118
+ this.error(error instanceof Error ? error : 'Command failed');
119
+ }
120
+ }
121
+ }
122
+ exports.default = Bump;
@@ -23,7 +23,7 @@ class Clean extends core_1.Command {
23
23
  if (!config_1.config) {
24
24
  this.error('No configuration found');
25
25
  }
26
- const flywayConfig = (0, config_1.getFlywayConfig)(config_1.config);
26
+ const flywayConfig = await (0, config_1.getFlywayConfig)(config_1.config);
27
27
  const flyway = new node_flyway_1.Flyway(flywayConfig);
28
28
  this.log('Resetting MJ database to pre-installation state');
29
29
  this.log('Note that users and roles have not been dropped');
@@ -0,0 +1,11 @@
1
+ import { Command } from '@oclif/core';
2
+ import { ParserOutput } from '@oclif/core/lib/interfaces/parser';
3
+ export default class CodeGen extends Command {
4
+ static description: string;
5
+ static examples: string[];
6
+ static flags: {
7
+ skipdb: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
8
+ };
9
+ flags: ParserOutput<CodeGen>['flags'];
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const config_1 = require("../../config");
5
+ const codegen_lib_1 = require("@memberjunction/codegen-lib");
6
+ class CodeGen extends core_1.Command {
7
+ static description = 'Run CodeGen to generate code and update metadata for MemberJunction';
8
+ static examples = [
9
+ `<%= config.bin %> <%= command.id %>
10
+ `,
11
+ ];
12
+ static flags = {
13
+ skipdb: core_1.Flags.boolean({ description: 'Skip database migration' }),
14
+ };
15
+ flags;
16
+ async run() {
17
+ const parsed = await this.parse(CodeGen);
18
+ this.flags = parsed.flags;
19
+ const config = (0, config_1.updatedConfig)();
20
+ if (!config) {
21
+ this.error('No configuration found');
22
+ }
23
+ // Initialize configuration
24
+ (0, codegen_lib_1.initializeConfig)(process.cwd());
25
+ // Call the function with the determined argument
26
+ (0, codegen_lib_1.runMemberJunctionCodeGeneration)(this.flags.skipDb);
27
+ }
28
+ }
29
+ exports.default = CodeGen;
@@ -5,7 +5,7 @@ type Config = z.infer<typeof configSchema>;
5
5
  declare const configSchema: z.ZodObject<{
6
6
  dbUrl: z.ZodString;
7
7
  dbInstance: z.ZodString;
8
- dbTrustServerCertificate: z.ZodEnum<["Y", "N"]>;
8
+ dbTrustServerCertificate: z.ZodEffects<z.ZodDefault<z.ZodBoolean>, "N" | "Y", boolean | undefined>;
9
9
  dbDatabase: z.ZodString;
10
10
  dbPort: z.ZodNumber;
11
11
  codeGenLogin: z.ZodString;
@@ -19,7 +19,7 @@ declare const configSchema: z.ZodObject<{
19
19
  auth0ClientId: z.ZodOptional<z.ZodString>;
20
20
  auth0ClientSecret: z.ZodOptional<z.ZodString>;
21
21
  auth0Domain: z.ZodOptional<z.ZodString>;
22
- createNewUser: z.ZodOptional<z.ZodEnum<["Y", "N"]>>;
22
+ createNewUser: z.ZodOptional<z.ZodBoolean>;
23
23
  userEmail: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>>>;
24
24
  userFirstName: z.ZodOptional<z.ZodString>;
25
25
  userLastName: z.ZodOptional<z.ZodString>;
@@ -31,7 +31,7 @@ declare const configSchema: z.ZodObject<{
31
31
  dbDatabase: string;
32
32
  dbPort: number;
33
33
  codeGenLogin: string;
34
- dbTrustServerCertificate: "Y" | "N";
34
+ dbTrustServerCertificate: "N" | "Y";
35
35
  dbUrl: string;
36
36
  dbInstance: string;
37
37
  codeGenPwD: string;
@@ -45,7 +45,7 @@ declare const configSchema: z.ZodObject<{
45
45
  auth0ClientId?: string | undefined;
46
46
  auth0ClientSecret?: string | undefined;
47
47
  auth0Domain?: string | undefined;
48
- createNewUser?: "Y" | "N" | undefined;
48
+ createNewUser?: boolean | undefined;
49
49
  userFirstName?: string | undefined;
50
50
  userLastName?: string | undefined;
51
51
  userName?: string | undefined;
@@ -56,20 +56,20 @@ declare const configSchema: z.ZodObject<{
56
56
  dbDatabase: string;
57
57
  dbPort: number;
58
58
  codeGenLogin: string;
59
- dbTrustServerCertificate: "Y" | "N";
60
59
  dbUrl: string;
61
60
  dbInstance: string;
62
61
  codeGenPwD: string;
63
62
  mjAPILogin: string;
64
63
  mjAPIPwD: string;
65
64
  authType: "MSAL" | "AUTH0" | "BOTH";
65
+ dbTrustServerCertificate?: boolean | undefined;
66
66
  graphQLPort?: number | undefined;
67
67
  msalWebClientId?: string | undefined;
68
68
  msalTenantId?: string | undefined;
69
69
  auth0ClientId?: string | undefined;
70
70
  auth0ClientSecret?: string | undefined;
71
71
  auth0Domain?: string | undefined;
72
- createNewUser?: "Y" | "N" | undefined;
72
+ createNewUser?: boolean | undefined;
73
73
  userEmail?: string | undefined;
74
74
  userFirstName?: string | undefined;
75
75
  userLastName?: string | undefined;
@@ -91,7 +91,7 @@ export default class Install extends Command {
91
91
  dbDatabase: string;
92
92
  dbPort: number;
93
93
  codeGenLogin: string;
94
- dbTrustServerCertificate: "Y" | "N";
94
+ dbTrustServerCertificate: "N" | "Y";
95
95
  dbUrl: string;
96
96
  dbInstance: string;
97
97
  codeGenPwD: string;
@@ -105,7 +105,7 @@ export default class Install extends Command {
105
105
  auth0ClientId?: string | undefined;
106
106
  auth0ClientSecret?: string | undefined;
107
107
  auth0Domain?: string | undefined;
108
- createNewUser?: "Y" | "N" | undefined;
108
+ createNewUser?: boolean | undefined;
109
109
  userFirstName?: string | undefined;
110
110
  userLastName?: string | undefined;
111
111
  userName?: string | undefined;
@@ -133,13 +133,12 @@ export default class Install extends Command {
133
133
  updateEnvironmentFiles(dirPath: string, config: Record<string, string | undefined>): Promise<void>;
134
134
  renameFolderToMJ_BASE(dbDatabase: string): void;
135
135
  /**
136
- * Updates newUserSetup in the config.json file.
137
- * @param {string} dirPath - The path to the directory containing the config.json file.
136
+ * Updates newUserSetup in the mj.config.cjs file.
138
137
  * @param {string} userName - The new UserName to set.
139
138
  * @param {string} firstName - The new FirstName to set.
140
139
  * @param {string} lastName - The new LastName to set.
141
140
  * @param {string} email - The new Email to set.
142
141
  */
143
- updateConfigNewUserSetup(dirPath: string, userName?: string, firstName?: string, lastName?: string, email?: string): Promise<void>;
142
+ updateConfigNewUserSetup(userName?: string, firstName?: string, lastName?: string, email?: string): Promise<void>;
144
143
  }
145
144
  export {};
@@ -27,6 +27,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const prompts_1 = require("@inquirer/prompts");
30
+ const dotenv = __importStar(require("dotenv"));
31
+ const recast = __importStar(require("recast"));
30
32
  const core_1 = require("@oclif/core");
31
33
  const fs = __importStar(require("fs-extra"));
32
34
  const node_child_process_1 = require("node:child_process");
@@ -44,7 +46,10 @@ const MJEXPLORER_DIR = 'MJExplorer';
44
46
  const configSchema = zod_1.z.object({
45
47
  dbUrl: zod_1.z.string().min(1),
46
48
  dbInstance: zod_1.z.string(),
47
- dbTrustServerCertificate: zod_1.z.enum(['Y', 'N']),
49
+ dbTrustServerCertificate: zod_1.z.coerce
50
+ .boolean()
51
+ .default(false)
52
+ .transform((v) => (v ? 'Y' : 'N')),
48
53
  dbDatabase: zod_1.z.string().min(1),
49
54
  dbPort: zod_1.z.number({ coerce: true }).int().positive(),
50
55
  codeGenLogin: zod_1.z.string(),
@@ -58,7 +63,7 @@ const configSchema = zod_1.z.object({
58
63
  auth0ClientId: zod_1.z.string().optional(),
59
64
  auth0ClientSecret: zod_1.z.string().optional(),
60
65
  auth0Domain: zod_1.z.string().optional(),
61
- createNewUser: zod_1.z.enum(['Y', 'N']).optional(),
66
+ createNewUser: zod_1.z.coerce.boolean().optional(),
62
67
  userEmail: zod_1.z.string().email().or(zod_1.z.literal('')).optional().default(''),
63
68
  userFirstName: zod_1.z.string().optional(),
64
69
  userLastName: zod_1.z.string().optional(),
@@ -83,17 +88,12 @@ class Install extends core_1.Command {
83
88
  this.flags = parsed.flags;
84
89
  this.checkNodeVersion();
85
90
  this.checkAvailableDiskSpace(2);
86
- this.verifyDirs(CODEGEN_DIR, GENERATED_ENTITIES_DIR, SQL_SCRIPTS_DIR, MJAPI_DIR, MJEXPLORER_DIR);
91
+ this.verifyDirs(GENERATED_ENTITIES_DIR, SQL_SCRIPTS_DIR, MJAPI_DIR, MJEXPLORER_DIR);
87
92
  this.userConfig = await this.getUserConfiguration();
88
93
  this.log('Setting up MemberJunction Distribution...');
89
94
  if (this.flags.verbose) {
90
95
  this.logJson({ userConfig: this.userConfig, flags: this.flags });
91
96
  }
92
- // if the user asked for a new user via our config file, need to push that info down to the CodeGen config.json file
93
- if (this.userConfig.createNewUser === 'Y') {
94
- this.log(' Setting up config.json...');
95
- await this.updateConfigNewUserSetup(CODEGEN_DIR, this.userConfig.userName, this.userConfig.userFirstName, this.userConfig.userLastName, this.userConfig.userEmail);
96
- }
97
97
  //*******************************************************************
98
98
  // Process GeneratedEntities
99
99
  //*******************************************************************
@@ -101,16 +101,18 @@ class Install extends core_1.Command {
101
101
  this.log('Running npm install...');
102
102
  (0, node_child_process_1.execSync)('npm install', { stdio: 'inherit', cwd: GENERATED_ENTITIES_DIR });
103
103
  //*******************************************************************
104
- // Process CodeGen
104
+ // Process Config
105
105
  //*******************************************************************
106
- this.log('\nProcessing CodeGen...');
106
+ this.log('\nProcessing Config...');
107
107
  this.log(' Updating ');
108
- this.log(' Setting up .env and config.json...');
109
- const codeGenENV = `#Database Setup
108
+ this.log(' Setting up .env and mj.config.cjs...');
109
+ const dotenvContent = `#Database Setup
110
110
  DB_HOST='${this.userConfig.dbUrl}'
111
111
  DB_PORT=${this.userConfig.dbPort}
112
- DB_USERNAME='${this.userConfig.codeGenLogin}'
113
- DB_PASSWORD='${this.userConfig.codeGenPwD}'
112
+ CODEGEN_DB_USERNAME='${this.userConfig.codeGenLogin}'
113
+ CODEGEN_DB_PASSWORD='${this.userConfig.codeGenPwD}'
114
+ DB_USERNAME='${this.userConfig.mjAPILogin}'
115
+ DB_PASSWORD='${this.userConfig.mjAPIPwD}'
114
116
  DB_DATABASE='${this.userConfig.dbDatabase}'
115
117
  ${this.userConfig.dbInstance ? "DB_INSTANCE_NAME='" + this.userConfig.dbInstance + "'" : ''}
116
118
  ${this.userConfig.dbTrustServerCertificate === 'Y' ? 'DB_TRUST_SERVER_CERTIFICATE=1' : ''}
@@ -121,34 +123,12 @@ OUTPUT_CODE='${this.userConfig.dbDatabase}'
121
123
  # Name of the schema that MJ has been setup in. This defaults to __mj
122
124
  MJ_CORE_SCHEMA='__mj'
123
125
 
124
- # If using Advanced Generation, populate this with the API key for the AI vendor you are using
125
- # Also, you need to configure the settings under advancedGeneration in the config.json file, including choosing the vendor.
126
+ # If using Advanced Generation or the MJAI library, populate this with the API key for the AI vendor you are using
127
+ # Also, you need to configure the settings under advancedGeneration in the mj.config.cjs file, including choosing the vendor.
126
128
  AI_VENDOR_API_KEY__OpenAILLM='${this.userConfig.openAIAPIKey}'
127
129
  AI_VENDOR_API_KEY__MistralLLM='${this.userConfig.mistralAPIKey}'
128
130
  AI_VENDOR_API_KEY__AnthropicLLM='${this.userConfig.anthropicAPIKey}'
129
131
 
130
- #CONFIG_FILE is the name of the file that has the configuration parameters for CodeGen
131
- CONFIG_FILE='config.json'
132
- `;
133
- fs.writeFileSync(node_path_1.default.join(CODEGEN_DIR, '.env'), codeGenENV);
134
- this.log(' Running npm link for GeneratedEntities...');
135
- (0, node_child_process_1.execSync)('npm link ../GeneratedEntities', { stdio: 'inherit', cwd: CODEGEN_DIR });
136
- //*******************************************************************
137
- // Process MJAPI
138
- //*******************************************************************
139
- this.log('\n\nBootstrapping MJAPI...');
140
- this.log(' Running npm link for generated code...');
141
- (0, node_child_process_1.execSync)('npm link ../GeneratedEntities ../GeneratedActions', { stdio: 'inherit', cwd: MJAPI_DIR });
142
- this.log(' Setting up MJAPI .env file...');
143
- const mjAPIENV = `#Database Setup
144
- DB_HOST='${this.userConfig.dbUrl}'
145
- DB_PORT=${this.userConfig.dbPort}
146
- DB_USERNAME='${this.userConfig.mjAPILogin}'
147
- DB_PASSWORD='${this.userConfig.mjAPIPwD}'
148
- DB_DATABASE='${this.userConfig.dbDatabase}'
149
- ${this.userConfig.dbInstance ? "DB_INSTANCE_NAME='" + this.userConfig.dbInstance + "'" : ''}
150
- ${this.userConfig.dbTrustServerCertificate === 'Y' ? 'DB_TRUST_SERVER_CERTIFICATE=1' : ''}
151
-
152
132
  PORT=${this.userConfig.graphQLPort}
153
133
 
154
134
  UPDATE_USER_CACHE_WHEN_NOT_FOUND=1
@@ -164,28 +144,30 @@ AUTH0_CLIENT_ID=${this.userConfig.auth0ClientId}
164
144
  AUTH0_CLIENT_SECRET=${this.userConfig.auth0ClientSecret}
165
145
  AUTH0_DOMAIN=${this.userConfig.auth0Domain}
166
146
 
167
- # Name of the schema that MJ has been setup in. This defaults to __mj
168
- MJ_CORE_SCHEMA='__mj'
169
-
170
- # If you are using MJAI library, provide your API KEYS here for the various services
171
- # Format is AI_VENDOR_API_KEY__<DriverClass> Where DriverClass is the DriverClass field from the AI Models Entity in MemberJunction
172
- AI_VENDOR_API_KEY__OpenAILLM = '${this.userConfig.openAIAPIKey}'
173
- AI_VENDOR_API_KEY__AnthropicLLM = '${this.userConfig.anthropicAPIKey}'
174
- AI_VENDOR_API_KEY__MistralLLM = '${this.userConfig.mistralAPIKey}'
175
-
176
147
  # Skip API URL, KEY and Org ID
177
148
  # YOU MUST ENTER IN THE CORRECT URL and ORG ID for your Skip API USE BELOW
178
149
  ASK_SKIP_API_URL = 'http://localhost:8000'
179
150
  ASK_SKIP_ORGANIZATION_ID = 1
180
-
181
- CONFIG_FILE='config.json'
182
151
  `;
183
- fs.writeFileSync(node_path_1.default.join(MJAPI_DIR, '.env'), mjAPIENV);
152
+ fs.writeFileSync('.env', dotenvContent);
153
+ //*******************************************************************
154
+ // Process CodeGen
155
+ //*******************************************************************
156
+ this.log('\nProcessing CodeGen...');
157
+ this.log(' Running npm link for GeneratedEntities...');
158
+ (0, node_child_process_1.execSync)('npm link ../GeneratedEntities', { stdio: 'inherit', cwd: CODEGEN_DIR });
159
+ //*******************************************************************
160
+ // Process MJAPI
161
+ //*******************************************************************
162
+ this.log('\n\nBootstrapping MJAPI...');
163
+ this.log(' Running npm link for generated code...');
164
+ (0, node_child_process_1.execSync)('npm link ../GeneratedEntities ../GeneratedActions', { stdio: 'inherit', cwd: MJAPI_DIR });
184
165
  this.log('Running CodeGen...');
185
166
  this.renameFolderToMJ_BASE(this.userConfig.dbDatabase);
186
167
  // next, run CodeGen
187
168
  // We do not manually run the compilation for GeneratedEntities because CodeGen handles that, but notice above that we did npm install for GeneratedEntities otherwise when CodeGen attempts to compile it, it will fail.
188
- (0, node_child_process_1.execSync)('npx ts-node src/index.ts', { stdio: 'inherit', cwd: CODEGEN_DIR });
169
+ dotenv.config();
170
+ this.config.runCommand('codegen');
189
171
  // Process MJExplorer
190
172
  this.log('\nProcessing MJExplorer...');
191
173
  this.log('\n Updating environment files...');
@@ -221,7 +203,7 @@ CONFIG_FILE='config.json'
221
203
  }
222
204
  }
223
205
  if (!userConfig) {
224
- this.log('\n>>> Please answer the following questions to setup the .env files for CodeGen. After this process you can manually edit the .env file in CodeGen as desired.');
206
+ this.log('\n>>> Please answer the following questions to setup the .env files for CodeGen. After this process you can manually edit the .env file as desired.');
225
207
  const dbUrl = await (0, prompts_1.input)({
226
208
  message: 'Enter the database server hostname:',
227
209
  validate: (v) => configSchema.shape.dbDatabase.safeParse(v).success,
@@ -256,7 +238,7 @@ CONFIG_FILE='config.json'
256
238
  const authType = await (0, prompts_1.select)({
257
239
  message: 'Will you be using Microsoft Entra (formerly Azure AD), Auth0, or both for authentication services for MJAPI:',
258
240
  choices: [
259
- { name: 'Microsoft Entra', value: 'MSAL' },
241
+ { name: 'Microsoft Entra (MSAL)', value: 'MSAL' },
260
242
  { name: 'Auth0', value: 'AUTH0' },
261
243
  { name: 'Both', value: 'BOTH' },
262
244
  ],
@@ -422,29 +404,48 @@ CONFIG_FILE='config.json'
422
404
  }
423
405
  }
424
406
  /**
425
- * Updates newUserSetup in the config.json file.
426
- * @param {string} dirPath - The path to the directory containing the config.json file.
407
+ * Updates newUserSetup in the mj.config.cjs file.
427
408
  * @param {string} userName - The new UserName to set.
428
409
  * @param {string} firstName - The new FirstName to set.
429
410
  * @param {string} lastName - The new LastName to set.
430
411
  * @param {string} email - The new Email to set.
431
412
  */
432
- async updateConfigNewUserSetup(dirPath, userName, firstName, lastName, email) {
413
+ async updateConfigNewUserSetup(userName, firstName, lastName, email) {
433
414
  try {
434
- const configFilePath = node_path_1.default.join(dirPath, 'config.json');
435
- // Read the config.json file
436
- const data = await fs.readFile(configFilePath, 'utf8');
437
- const config = JSON.parse(data);
438
- // Update the newUserSetup object
439
- if (!config.newUserSetup)
440
- config.newUserSetup = {};
441
- config.newUserSetup.UserName = userName;
442
- config.newUserSetup.FirstName = firstName;
443
- config.newUserSetup.LastName = lastName;
444
- config.newUserSetup.Email = email;
445
- // Write the updated configuration back to config.json
446
- await fs.writeFile(configFilePath, JSON.stringify(config, null, 2), 'utf8');
447
- this.log(` Updated config.json in ${dirPath}`);
415
+ // Read the mj.config.cjs file
416
+ const configFileContent = await fs.readFile('mj.config.cjs', 'utf8');
417
+ // Parse the content into an AST
418
+ const ast = recast.parse(configFileContent);
419
+ // Modify the AST
420
+ const n = recast.types.namedTypes;
421
+ const b = recast.types.builders;
422
+ recast.types.visit(ast, {
423
+ visitObjectExpression(path) {
424
+ const properties = path.node.properties;
425
+ // Check if newUserSetup key exists
426
+ const newUserSetupProperty = properties.find((prop) => n.Property.check(prop) && n.Identifier.check(prop.key) && prop.key.name === 'newUserSetup');
427
+ const newUserSetupValue = b.objectExpression([
428
+ b.property('init', b.identifier('userName'), b.literal(userName || '')),
429
+ b.property('init', b.identifier('firstName'), b.literal(firstName || '')),
430
+ b.property('init', b.identifier('lastName'), b.literal(lastName || '')),
431
+ b.property('init', b.identifier('email'), b.literal(email || '')),
432
+ ]);
433
+ if (newUserSetupProperty && newUserSetupProperty.type === 'Property') {
434
+ // Overwrite the existing newUserSetup key with an object
435
+ newUserSetupProperty.value = newUserSetupValue;
436
+ }
437
+ else {
438
+ // Add a new newUserSetup key
439
+ properties.push(b.property('init', b.identifier('newUserSetup'), newUserSetupValue));
440
+ }
441
+ return false; // Stop traversing this path
442
+ },
443
+ });
444
+ // Serialize the AST back to a string
445
+ const updatedConfigFileContent = recast.prettyPrint(ast).code;
446
+ // Write the updated content back to the file
447
+ await fs.writeFile('mj.config.cjs', updatedConfigFileContent);
448
+ this.log(` Updated mj.config.cjs`);
448
449
  }
449
450
  catch (err) {
450
451
  this.logToStderr('Error:', err);
@@ -1,11 +1,10 @@
1
1
  import { Command } from '@oclif/core';
2
- import { ParserOutput } from '@oclif/core/lib/interfaces/parser';
3
2
  export default class Migrate extends Command {
4
3
  static description: string;
5
4
  static examples: string[];
6
5
  static flags: {
7
- verbose: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
6
+ verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ tag: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
8
  };
9
- flags: ParserOutput<Migrate>['flags'];
10
9
  run(): Promise<void>;
11
10
  }
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const core_1 = require("@oclif/core");
7
7
  const node_flyway_1 = require("node-flyway");
8
- const config_1 = require("../../config");
9
8
  const ora_classic_1 = __importDefault(require("ora-classic"));
9
+ const config_1 = require("../../config");
10
10
  class Migrate extends core_1.Command {
11
11
  static description = 'Migrate MemberJunction database to latest version';
12
12
  static examples = [
@@ -15,27 +15,29 @@ class Migrate extends core_1.Command {
15
15
  ];
16
16
  static flags = {
17
17
  verbose: core_1.Flags.boolean({ char: 'v', description: 'Enable additional logging' }),
18
+ tag: core_1.Flags.string({ char: 't', description: 'Version tag to use for running remote migrations' }),
18
19
  };
19
- flags;
20
20
  async run() {
21
- const parsed = await this.parse(Migrate);
22
- this.flags = parsed.flags;
21
+ const { flags } = await this.parse(Migrate);
23
22
  if (!config_1.config) {
24
23
  this.error('No configuration found');
25
24
  }
26
- const flywayConfig = (0, config_1.getFlywayConfig)(config_1.config);
25
+ const flywayConfig = await (0, config_1.getFlywayConfig)(config_1.config, flags.tag);
27
26
  const flyway = new node_flyway_1.Flyway(flywayConfig);
28
- if (this.flags.verbose) {
27
+ if (flags.verbose) {
29
28
  this.log(`Connecting to ${flywayConfig.url}`);
30
29
  this.log(`Migrating ${config_1.config.coreSchema} schema using migrations from:\n\t- ${flywayConfig.migrationLocations.join('\n\t- ')}\n`);
31
30
  }
31
+ if (flags.tag) {
32
+ this.log(`Migrating to ${flags.tag}`);
33
+ }
32
34
  const spinner = (0, ora_classic_1.default)('Running migrations...');
33
35
  spinner.start();
34
36
  const result = await flyway.migrate();
35
37
  if (result.success) {
36
38
  spinner.succeed();
37
39
  this.log(`Migrations complete in ${result.additionalDetails.executionTime / 1000}s`);
38
- if (result.flywayResponse?.success && this.flags.verbose) {
40
+ if (result.flywayResponse?.success && flags.verbose) {
39
41
  this.log(`\tUpdated to ${result.flywayResponse?.targetSchemaVersion}`);
40
42
  }
41
43
  }
@@ -43,7 +45,7 @@ class Migrate extends core_1.Command {
43
45
  spinner.fail();
44
46
  if (result.error) {
45
47
  this.logToStderr(result.error.message);
46
- if (this.flags.verbose) {
48
+ if (flags.verbose) {
47
49
  this.logToStderr(`ERROR CODE: ${result.error.errorCode}`);
48
50
  this.logToStderr(result.error.stackTrace);
49
51
  }
package/dist/config.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { z } from 'zod';
2
1
  import { FlywayConfig } from 'node-flyway/dist/types/types';
2
+ import { z } from 'zod';
3
3
  export type MJConfig = z.infer<typeof mjConfigSchema>;
4
4
  declare const mjConfigSchema: z.ZodObject<{
5
5
  dbHost: z.ZodDefault<z.ZodString>;
@@ -8,9 +8,10 @@ declare const mjConfigSchema: z.ZodObject<{
8
8
  codeGenLogin: z.ZodString;
9
9
  codeGenPassword: z.ZodString;
10
10
  migrationsLocation: z.ZodDefault<z.ZodOptional<z.ZodString>>;
11
- dbTrustServerCertificate: z.ZodDefault<z.ZodEnum<["Y", "N"]>>;
11
+ dbTrustServerCertificate: z.ZodDefault<z.ZodBoolean>;
12
12
  coreSchema: z.ZodDefault<z.ZodOptional<z.ZodString>>;
13
- cleanDisabled: z.ZodDefault<z.ZodBoolean>;
13
+ cleanDisabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
+ mjRepoUrl: z.ZodCatch<z.ZodString>;
14
15
  }, "strip", z.ZodTypeAny, {
15
16
  cleanDisabled: boolean;
16
17
  dbHost: string;
@@ -19,8 +20,9 @@ declare const mjConfigSchema: z.ZodObject<{
19
20
  codeGenLogin: string;
20
21
  codeGenPassword: string;
21
22
  migrationsLocation: string;
22
- dbTrustServerCertificate: "Y" | "N";
23
+ dbTrustServerCertificate: boolean;
23
24
  coreSchema: string;
25
+ mjRepoUrl: string;
24
26
  }, {
25
27
  dbDatabase: string;
26
28
  codeGenLogin: string;
@@ -29,8 +31,9 @@ declare const mjConfigSchema: z.ZodObject<{
29
31
  dbHost?: string | undefined;
30
32
  dbPort?: number | undefined;
31
33
  migrationsLocation?: string | undefined;
32
- dbTrustServerCertificate?: "Y" | "N" | undefined;
34
+ dbTrustServerCertificate?: boolean | undefined;
33
35
  coreSchema?: string | undefined;
36
+ mjRepoUrl?: unknown;
34
37
  }>;
35
38
  export declare const config: {
36
39
  cleanDisabled: boolean;
@@ -40,9 +43,22 @@ export declare const config: {
40
43
  codeGenLogin: string;
41
44
  codeGenPassword: string;
42
45
  migrationsLocation: string;
43
- dbTrustServerCertificate: "Y" | "N";
46
+ dbTrustServerCertificate: boolean;
47
+ coreSchema: string;
48
+ mjRepoUrl: string;
49
+ } | undefined;
50
+ export declare const updatedConfig: () => {
51
+ cleanDisabled: boolean;
52
+ dbHost: string;
53
+ dbDatabase: string;
54
+ dbPort: number;
55
+ codeGenLogin: string;
56
+ codeGenPassword: string;
57
+ migrationsLocation: string;
58
+ dbTrustServerCertificate: boolean;
44
59
  coreSchema: string;
60
+ mjRepoUrl: string;
45
61
  } | undefined;
46
62
  export declare const createFlywayUrl: (mjConfig: MJConfig) => string;
47
- export declare const getFlywayConfig: (mjConfig: MJConfig) => FlywayConfig;
63
+ export declare const getFlywayConfig: (mjConfig: MJConfig, tag?: string) => Promise<FlywayConfig>;
48
64
  export {};
package/dist/config.js CHANGED
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFlywayConfig = exports.createFlywayUrl = exports.config = void 0;
4
- const zod_1 = require("zod");
3
+ exports.getFlywayConfig = exports.createFlywayUrl = exports.updatedConfig = exports.config = void 0;
5
4
  const cosmiconfig_1 = require("cosmiconfig");
6
- const explorer = (0, cosmiconfig_1.cosmiconfigSync)('mj');
5
+ const node_fs_1 = require("node:fs");
6
+ const node_os_1 = require("node:os");
7
+ const simple_git_1 = require("simple-git");
8
+ const zod_1 = require("zod");
9
+ const MJ_REPO_URL = 'https://github.com/MemberJunction/MJ.git';
10
+ const explorer = (0, cosmiconfig_1.cosmiconfigSync)('mj', { searchStrategy: 'global' });
7
11
  const result = explorer.search(process.cwd());
8
12
  const mjConfigSchema = zod_1.z.object({
9
13
  dbHost: zod_1.z.string().default('localhost'),
@@ -12,21 +16,39 @@ const mjConfigSchema = zod_1.z.object({
12
16
  codeGenLogin: zod_1.z.string(),
13
17
  codeGenPassword: zod_1.z.string(),
14
18
  migrationsLocation: zod_1.z.string().optional().default('filesystem:./migrations'),
15
- dbTrustServerCertificate: zod_1.z.enum(['Y', 'N']).default('Y'),
19
+ dbTrustServerCertificate: zod_1.z.coerce.boolean().default(false),
16
20
  coreSchema: zod_1.z.string().optional().default('__mj'),
17
- cleanDisabled: zod_1.z.boolean().default(true),
21
+ cleanDisabled: zod_1.z.boolean().optional().default(true),
22
+ mjRepoUrl: zod_1.z.string().url().catch(MJ_REPO_URL),
18
23
  });
19
24
  const parsedConfig = mjConfigSchema.safeParse(result?.config);
20
25
  exports.config = parsedConfig.success ? parsedConfig.data : undefined;
26
+ const updatedConfig = () => {
27
+ const maybeConfig = mjConfigSchema.safeParse(explorer.search(process.cwd())?.config);
28
+ return maybeConfig.success ? maybeConfig.data : undefined;
29
+ };
30
+ exports.updatedConfig = updatedConfig;
21
31
  const createFlywayUrl = (mjConfig) => {
22
- return `jdbc:sqlserver://${mjConfig.dbHost}:${mjConfig.dbPort}; databaseName=${mjConfig.dbDatabase}${mjConfig.dbTrustServerCertificate === 'Y' ? '; trustServerCertificate=true' : ''}`;
32
+ return `jdbc:sqlserver://${mjConfig.dbHost}:${mjConfig.dbPort}; databaseName=${mjConfig.dbDatabase}${mjConfig.dbTrustServerCertificate ? '; trustServerCertificate=true' : ''}`;
23
33
  };
24
34
  exports.createFlywayUrl = createFlywayUrl;
25
- const getFlywayConfig = (mjConfig) => ({
26
- url: (0, exports.createFlywayUrl)(mjConfig),
27
- user: mjConfig.codeGenLogin,
28
- password: mjConfig.codeGenPassword,
29
- migrationLocations: [mjConfig.migrationsLocation],
30
- advanced: { schemas: [mjConfig.coreSchema], cleanDisabled: mjConfig.cleanDisabled === false ? false : undefined },
31
- });
35
+ const getFlywayConfig = async (mjConfig, tag) => {
36
+ let location = mjConfig.migrationsLocation;
37
+ if (tag) {
38
+ // when tag is set, we want to fetch migrations from the github repo using the tag specified
39
+ // we save those to a tmp dir and set that tmp dir as the migration location
40
+ const tmp = (0, node_fs_1.mkdtempSync)((0, node_os_1.tmpdir)());
41
+ const git = (0, simple_git_1.simpleGit)(tmp);
42
+ await git.clone(mjConfig.mjRepoUrl, tmp, ['--sparse', '--depth=1', '--branch', tag]);
43
+ await git.raw(['sparse-checkout', 'set', 'migrations']);
44
+ location = `filesystem:${tmp}`;
45
+ }
46
+ return {
47
+ url: (0, exports.createFlywayUrl)(mjConfig),
48
+ user: mjConfig.codeGenLogin,
49
+ password: mjConfig.codeGenPassword,
50
+ migrationLocations: [location],
51
+ advanced: { schemas: [mjConfig.coreSchema], cleanDisabled: mjConfig.cleanDisabled === false ? false : undefined },
52
+ };
53
+ };
32
54
  exports.getFlywayConfig = getFlywayConfig;
@@ -1,6 +1,23 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const figlet_1 = __importDefault(require("figlet"));
3
7
  const hook = async function (options) {
8
+ // Skip banners if --quiet flag is present (or appears to be present)
9
+ if (options.argv?.some((arg) => arg === '--quiet' || (/^-[^-]+/.test(arg) && arg.includes('q')))) {
10
+ return;
11
+ }
12
+ options.context.log(process.stdout.columns >= 81
13
+ ? figlet_1.default.textSync('MemberJunction', {
14
+ font: 'Standard',
15
+ horizontalLayout: 'default',
16
+ verticalLayout: 'default',
17
+ width: 100,
18
+ whitespaceBreak: true,
19
+ })
20
+ : '~ M e m b e r J u n c t i o n ~');
4
21
  if (options.Command.id !== 'version') {
5
22
  options.context.log(options.config.userAgent + '\n');
6
23
  }
@@ -1,5 +1,108 @@
1
1
  {
2
2
  "commands": {
3
+ "bump": {
4
+ "aliases": [],
5
+ "args": {},
6
+ "description": "Bumps MemberJunction dependency versions",
7
+ "examples": [
8
+ {
9
+ "command": "<%= config.bin %> <%= command.id %>",
10
+ "description": "Bump all @memberjunction/* dependencies in the current directory's package.json to the CLI version"
11
+ },
12
+ {
13
+ "command": "<%= config.bin %> <%= command.id %> -rdv",
14
+ "description": "Preview all recursive packages bumps without writing any changes."
15
+ },
16
+ {
17
+ "command": "<%= config.bin %> <%= command.id %> -rqt v2.10.0 | xargs -n1 -I{} npm install --prefix {}",
18
+ "description": "Recursively bump all @memberjunction/* dependencies in all packages to version v2.10.0 and output only the paths containing the updated package.json files. Pipe the output to xargs to run npm install in each directory and update the package-lock.json files as well."
19
+ }
20
+ ],
21
+ "flags": {
22
+ "verbose": {
23
+ "char": "v",
24
+ "description": "Enable additional logging",
25
+ "name": "verbose",
26
+ "allowNo": false,
27
+ "type": "boolean"
28
+ },
29
+ "recursive": {
30
+ "char": "r",
31
+ "description": "Bump version in current directory and all subdirectories",
32
+ "name": "recursive",
33
+ "allowNo": false,
34
+ "type": "boolean"
35
+ },
36
+ "tag": {
37
+ "char": "t",
38
+ "description": "Version tag to bump target for bump (e.g. v2.10.0), defaults to the CLI version",
39
+ "name": "tag",
40
+ "hasDynamicHelp": false,
41
+ "multiple": false,
42
+ "type": "option"
43
+ },
44
+ "quiet": {
45
+ "char": "q",
46
+ "description": "Only output paths for updated packages",
47
+ "name": "quiet",
48
+ "allowNo": false,
49
+ "type": "boolean"
50
+ },
51
+ "dry": {
52
+ "char": "d",
53
+ "description": "Dry run, do not write changes to package.json files",
54
+ "name": "dry",
55
+ "allowNo": false,
56
+ "type": "boolean"
57
+ }
58
+ },
59
+ "hasDynamicHelp": false,
60
+ "hiddenAliases": [],
61
+ "id": "bump",
62
+ "pluginAlias": "@memberjunction/cli",
63
+ "pluginName": "@memberjunction/cli",
64
+ "pluginType": "core",
65
+ "strict": true,
66
+ "enableJsonFlag": false,
67
+ "isESM": false,
68
+ "relativePath": [
69
+ "dist",
70
+ "commands",
71
+ "bump",
72
+ "index.js"
73
+ ]
74
+ },
75
+ "codegen": {
76
+ "aliases": [],
77
+ "args": {},
78
+ "description": "Run CodeGen to generate code and update metadata for MemberJunction",
79
+ "examples": [
80
+ "<%= config.bin %> <%= command.id %>\n"
81
+ ],
82
+ "flags": {
83
+ "skipdb": {
84
+ "description": "Skip database migration",
85
+ "name": "skipdb",
86
+ "allowNo": false,
87
+ "type": "boolean"
88
+ }
89
+ },
90
+ "hasDynamicHelp": false,
91
+ "hiddenAliases": [],
92
+ "id": "codegen",
93
+ "pluginAlias": "@memberjunction/cli",
94
+ "pluginName": "@memberjunction/cli",
95
+ "pluginType": "core",
96
+ "strict": true,
97
+ "enableJsonFlag": false,
98
+ "isESM": false,
99
+ "relativePath": [
100
+ "dist",
101
+ "commands",
102
+ "codegen",
103
+ "index.js"
104
+ ]
105
+ },
3
106
  "clean": {
4
107
  "aliases": [],
5
108
  "args": {},
@@ -32,10 +135,10 @@
32
135
  "index.js"
33
136
  ]
34
137
  },
35
- "migrate": {
138
+ "install": {
36
139
  "aliases": [],
37
140
  "args": {},
38
- "description": "Migrate MemberJunction database to latest version",
141
+ "description": "Install MemberJunction",
39
142
  "examples": [
40
143
  "<%= config.bin %> <%= command.id %>\n"
41
144
  ],
@@ -50,7 +153,7 @@
50
153
  },
51
154
  "hasDynamicHelp": false,
52
155
  "hiddenAliases": [],
53
- "id": "migrate",
156
+ "id": "install",
54
157
  "pluginAlias": "@memberjunction/cli",
55
158
  "pluginName": "@memberjunction/cli",
56
159
  "pluginType": "core",
@@ -60,14 +163,14 @@
60
163
  "relativePath": [
61
164
  "dist",
62
165
  "commands",
63
- "migrate",
166
+ "install",
64
167
  "index.js"
65
168
  ]
66
169
  },
67
- "install": {
170
+ "migrate": {
68
171
  "aliases": [],
69
172
  "args": {},
70
- "description": "Install MemberJunction",
173
+ "description": "Migrate MemberJunction database to latest version",
71
174
  "examples": [
72
175
  "<%= config.bin %> <%= command.id %>\n"
73
176
  ],
@@ -78,11 +181,19 @@
78
181
  "name": "verbose",
79
182
  "allowNo": false,
80
183
  "type": "boolean"
184
+ },
185
+ "tag": {
186
+ "char": "t",
187
+ "description": "Version tag to use for running remote migrations",
188
+ "name": "tag",
189
+ "hasDynamicHelp": false,
190
+ "multiple": false,
191
+ "type": "option"
81
192
  }
82
193
  },
83
194
  "hasDynamicHelp": false,
84
195
  "hiddenAliases": [],
85
- "id": "install",
196
+ "id": "migrate",
86
197
  "pluginAlias": "@memberjunction/cli",
87
198
  "pluginName": "@memberjunction/cli",
88
199
  "pluginType": "core",
@@ -92,10 +203,10 @@
92
203
  "relativePath": [
93
204
  "dist",
94
205
  "commands",
95
- "install",
206
+ "migrate",
96
207
  "index.js"
97
208
  ]
98
209
  }
99
210
  },
100
- "version": "2.13.2"
211
+ "version": "2.13.4"
101
212
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/cli",
3
- "version": "2.13.2",
3
+ "version": "2.13.4",
4
4
  "description": "MemberJunction command line tools",
5
5
  "keywords": [
6
6
  "oclif"
@@ -50,16 +50,20 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@inquirer/prompts": "^5.0.1",
53
+ "@memberjunction/codegen-lib": "2.13.4",
53
54
  "@oclif/core": "^3",
54
55
  "@oclif/plugin-help": "^6",
55
56
  "@oclif/plugin-version": "^2.0.17",
56
57
  "@oclif/plugin-warn-if-update-available": "^3.0.16",
57
58
  "cosmiconfig": "9.0.0",
58
59
  "dotenv": "16.4.5",
60
+ "fast-glob": "^3.3.2",
59
61
  "figlet": "^1.7.0",
60
62
  "fs-extra": "^11.2.0",
61
63
  "node-flyway": "0.0.11",
62
64
  "ora-classic": "^5.4.2",
65
+ "recast": "^0.23.9",
66
+ "simple-git": "^3.27.0",
63
67
  "zod": "^3.23.4"
64
68
  },
65
69
  "devDependencies": {
@@ -1,3 +0,0 @@
1
- import { Hook } from '@oclif/core';
2
- declare const hook: Hook<'init'>;
3
- export default hook;
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const figlet_1 = __importDefault(require("figlet"));
7
- const hook = async function (options) {
8
- options.context.log(process.stdout.columns >= 81
9
- ? figlet_1.default.textSync('MemberJunction', {
10
- font: 'Standard',
11
- horizontalLayout: 'default',
12
- verticalLayout: 'default',
13
- width: 100,
14
- whitespaceBreak: true,
15
- })
16
- : '~ M e m b e r J u n c t i o n ~');
17
- };
18
- exports.default = hook;