@mailmodo/cli 0.0.52-beta.pr55.85 → 0.0.52
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/dist/commands/deploy/index.js +3 -3
- package/dist/commands/init/index.js +9 -2
- package/dist/commands/settings/index.js +10 -1
- package/dist/lib/constants.d.ts +0 -4
- package/dist/lib/constants.js +0 -4
- package/oclif.manifest.json +1 -48
- package/package.json +1 -1
- package/dist/commands/sdk/index.d.ts +0 -14
- package/dist/commands/sdk/index.js +0 -74
- package/dist/lib/utils.d.ts +0 -11
- package/dist/lib/utils.js +0 -40
|
@@ -2,7 +2,7 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import { confirm, input } from '@inquirer/prompts';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
5
|
-
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR
|
|
5
|
+
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR } from '../../lib/constants.js';
|
|
6
6
|
import { ERRORS, INFO, pauseAlready, pauseSuccess, PROMPTS, resumeAlready, resumeSuccess, SEPARATOR, } from '../../lib/messages.js';
|
|
7
7
|
import { loadTemplate, } from '../../lib/yaml-config.js';
|
|
8
8
|
export default class Deploy extends BaseCommand {
|
|
@@ -286,8 +286,8 @@ export default class Deploy extends BaseCommand {
|
|
|
286
286
|
this.log(` ${SEPARATOR}`);
|
|
287
287
|
this.log(` ${chalk.bold('ADD THIS TO YOUR APP (one-time only):')}`);
|
|
288
288
|
this.log(` ${SEPARATOR}\n`);
|
|
289
|
-
this.log(` ${chalk.cyan(sdkSnippet.install ??
|
|
290
|
-
this.log(` ${chalk.dim(
|
|
289
|
+
this.log(` ${chalk.cyan(sdkSnippet.install ?? 'npm install @mailmodo/sdk')}\n`);
|
|
290
|
+
this.log(` ${chalk.dim("import { track, identify } from '@mailmodo/sdk'")}\n`);
|
|
291
291
|
if (sdkSnippet.examples) {
|
|
292
292
|
this.log(` ${chalk.dim('// Example usage:')}`);
|
|
293
293
|
this.log(` ${chalk.dim(sdkSnippet.examples.track)}`);
|
|
@@ -4,7 +4,14 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
5
5
|
import { API_ENDPOINTS, DEFAULT_BRAND_COLOR } from '../../lib/constants.js';
|
|
6
6
|
import { loadYaml, saveTemplate, saveYaml, } from '../../lib/yaml-config.js';
|
|
7
|
-
|
|
7
|
+
function isValidUrl(value) {
|
|
8
|
+
try {
|
|
9
|
+
return Boolean(new URL(value));
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
8
15
|
/**
|
|
9
16
|
* Prints the human-readable analysis summary using the provided line writer.
|
|
10
17
|
* Use stderr when `--json` is set so stdout stays free for machine-readable JSON.
|
|
@@ -117,7 +124,7 @@ export default class Init extends BaseCommand {
|
|
|
117
124
|
return {
|
|
118
125
|
delay: rec.delay || '0',
|
|
119
126
|
id: rec.id,
|
|
120
|
-
trigger:
|
|
127
|
+
trigger: rec.trigger,
|
|
121
128
|
...(rec.condition ? { condition: rec.condition } : {}),
|
|
122
129
|
subject: generated?.subject || `Email for ${rec.id}`,
|
|
123
130
|
template: `mailmodo/${rec.id}.html`,
|
|
@@ -7,7 +7,6 @@ import { resolve } from 'node:path';
|
|
|
7
7
|
import { BaseCommand, FREE_TIER } from '../../lib/base-command.js';
|
|
8
8
|
import { API_ENDPOINTS } from '../../lib/constants.js';
|
|
9
9
|
import { INFO } from '../../lib/messages.js';
|
|
10
|
-
import { settingKeyToProp } from '../../lib/utils.js';
|
|
11
10
|
import { saveYaml } from '../../lib/yaml-config.js';
|
|
12
11
|
const SETTINGS_GROUPS = Object.freeze({
|
|
13
12
|
billing: ['monthly_cap'],
|
|
@@ -21,6 +20,16 @@ const SETUP_HINTS = {
|
|
|
21
20
|
domain: "'mailmodo domain'",
|
|
22
21
|
monthlyCap: "'mailmodo billing --cap <n>'",
|
|
23
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Converts a user-facing snake_case YAML setting key to its
|
|
25
|
+
* corresponding camelCase TypeScript property name.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} key - A snake_case setting key (e.g., "brand_color").
|
|
28
|
+
* @returns {string} The camelCase property name (e.g., "brandColor").
|
|
29
|
+
*/
|
|
30
|
+
function settingKeyToProp(key) {
|
|
31
|
+
return key.replaceAll(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
32
|
+
}
|
|
24
33
|
export default class Settings extends BaseCommand {
|
|
25
34
|
static description = 'View and update project settings';
|
|
26
35
|
static examples = [
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -26,7 +26,6 @@ export declare const API_ENDPOINTS: Readonly<{
|
|
|
26
26
|
PREVIEW: "/preview";
|
|
27
27
|
SEQUENCES: "/sequences";
|
|
28
28
|
SEQUENCES_DEPLOY: "/sequences/deploy";
|
|
29
|
-
SEQUENCES_SDK: "/sequences/sdk";
|
|
30
29
|
SEQUENCES_VALIDATE: "/sequences/validate";
|
|
31
30
|
}>;
|
|
32
31
|
export declare const LOGIN_URL = "https://app-vertex-debug.azurewebsites.net/signup.html";
|
|
@@ -34,6 +33,3 @@ export declare const PREVIEW_PORT = 3421;
|
|
|
34
33
|
export declare const DEFAULT_BRAND_COLOR = "#1A56DB";
|
|
35
34
|
export declare const TEMPLATES_DIR = "mailmodo";
|
|
36
35
|
export declare const YAML_FILE = "mailmodo.yaml";
|
|
37
|
-
export declare const SDK_PACKAGE_NAME = "@mailmodo/sdk";
|
|
38
|
-
export declare const SDK_INSTALL_COMMAND = "npm install @mailmodo/sdk";
|
|
39
|
-
export declare const SDK_IMPORT_SNIPPET = "import { track, identify } from '@mailmodo/sdk'";
|
package/dist/lib/constants.js
CHANGED
|
@@ -32,7 +32,6 @@ export const API_ENDPOINTS = Object.freeze({
|
|
|
32
32
|
PREVIEW: '/preview',
|
|
33
33
|
SEQUENCES: '/sequences',
|
|
34
34
|
SEQUENCES_DEPLOY: '/sequences/deploy',
|
|
35
|
-
SEQUENCES_SDK: '/sequences/sdk',
|
|
36
35
|
SEQUENCES_VALIDATE: '/sequences/validate',
|
|
37
36
|
});
|
|
38
37
|
const DEV_LOGIN_URL = 'https://app-vertex-debug.azurewebsites.net/signup.html';
|
|
@@ -45,6 +44,3 @@ export const PREVIEW_PORT = 3421;
|
|
|
45
44
|
export const DEFAULT_BRAND_COLOR = '#1A56DB';
|
|
46
45
|
export const TEMPLATES_DIR = 'mailmodo';
|
|
47
46
|
export const YAML_FILE = 'mailmodo.yaml';
|
|
48
|
-
export const SDK_PACKAGE_NAME = '@mailmodo/sdk';
|
|
49
|
-
export const SDK_INSTALL_COMMAND = `npm install ${SDK_PACKAGE_NAME}`;
|
|
50
|
-
export const SDK_IMPORT_SNIPPET = `import { track, identify } from '${SDK_PACKAGE_NAME}'`;
|
package/oclif.manifest.json
CHANGED
|
@@ -631,53 +631,6 @@
|
|
|
631
631
|
"index.js"
|
|
632
632
|
]
|
|
633
633
|
},
|
|
634
|
-
"sdk": {
|
|
635
|
-
"aliases": [],
|
|
636
|
-
"args": {},
|
|
637
|
-
"description": "Show the SDK track() / identify() reference for deployed sequences",
|
|
638
|
-
"examples": [
|
|
639
|
-
"<%= config.bin %> sdk",
|
|
640
|
-
"<%= config.bin %> sdk --sequence-id a1b2c3d4",
|
|
641
|
-
"<%= config.bin %> sdk --json"
|
|
642
|
-
],
|
|
643
|
-
"flags": {
|
|
644
|
-
"json": {
|
|
645
|
-
"description": "Output as JSON",
|
|
646
|
-
"name": "json",
|
|
647
|
-
"allowNo": false,
|
|
648
|
-
"type": "boolean"
|
|
649
|
-
},
|
|
650
|
-
"yes": {
|
|
651
|
-
"char": "y",
|
|
652
|
-
"description": "Skip confirmation prompts",
|
|
653
|
-
"name": "yes",
|
|
654
|
-
"allowNo": false,
|
|
655
|
-
"type": "boolean"
|
|
656
|
-
},
|
|
657
|
-
"sequence-id": {
|
|
658
|
-
"description": "Limit output to a single active sequence by ID (default: all active sequences)",
|
|
659
|
-
"name": "sequence-id",
|
|
660
|
-
"hasDynamicHelp": false,
|
|
661
|
-
"multiple": false,
|
|
662
|
-
"type": "option"
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
"hasDynamicHelp": false,
|
|
666
|
-
"hiddenAliases": [],
|
|
667
|
-
"id": "sdk",
|
|
668
|
-
"pluginAlias": "@mailmodo/cli",
|
|
669
|
-
"pluginName": "@mailmodo/cli",
|
|
670
|
-
"pluginType": "core",
|
|
671
|
-
"strict": true,
|
|
672
|
-
"enableJsonFlag": false,
|
|
673
|
-
"isESM": true,
|
|
674
|
-
"relativePath": [
|
|
675
|
-
"dist",
|
|
676
|
-
"commands",
|
|
677
|
-
"sdk",
|
|
678
|
-
"index.js"
|
|
679
|
-
]
|
|
680
|
-
},
|
|
681
634
|
"settings": {
|
|
682
635
|
"aliases": [],
|
|
683
636
|
"args": {},
|
|
@@ -765,5 +718,5 @@
|
|
|
765
718
|
]
|
|
766
719
|
}
|
|
767
720
|
},
|
|
768
|
-
"version": "0.0.52
|
|
721
|
+
"version": "0.0.52"
|
|
769
722
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
2
|
-
export default class Sdk extends BaseCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
'sequence-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
};
|
|
10
|
-
run(): Promise<void>;
|
|
11
|
-
private renderSnippets;
|
|
12
|
-
private renderSequenceBlock;
|
|
13
|
-
private renderCallBlock;
|
|
14
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { BaseCommand } from '../../lib/base-command.js';
|
|
4
|
-
import { API_ENDPOINTS, SDK_IMPORT_SNIPPET, SDK_INSTALL_COMMAND, } from '../../lib/constants.js';
|
|
5
|
-
import { SEPARATOR } from '../../lib/messages.js';
|
|
6
|
-
export default class Sdk extends BaseCommand {
|
|
7
|
-
static description = 'Show the SDK track() / identify() reference for deployed sequences';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> sdk',
|
|
10
|
-
'<%= config.bin %> sdk --sequence-id a1b2c3d4',
|
|
11
|
-
'<%= config.bin %> sdk --json',
|
|
12
|
-
];
|
|
13
|
-
static flags = {
|
|
14
|
-
...BaseCommand.baseFlags,
|
|
15
|
-
'sequence-id': Flags.string({
|
|
16
|
-
description: 'Limit output to a single active sequence by ID (default: all active sequences)',
|
|
17
|
-
}),
|
|
18
|
-
};
|
|
19
|
-
async run() {
|
|
20
|
-
const { flags } = await this.parse(Sdk);
|
|
21
|
-
await this.ensureAuth();
|
|
22
|
-
const params = flags['sequence-id']
|
|
23
|
-
? { sequenceId: flags['sequence-id'] }
|
|
24
|
-
: undefined;
|
|
25
|
-
const response = await this.withApiSpinner({ json: flags.json, text: ' Loading SDK reference...' }, () => this.apiClient.get(API_ENDPOINTS.SEQUENCES_SDK, params));
|
|
26
|
-
if (!response.ok) {
|
|
27
|
-
this.handleApiError(response);
|
|
28
|
-
}
|
|
29
|
-
if (flags.json) {
|
|
30
|
-
this.log(JSON.stringify(response.data, null, 2));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
this.renderSnippets(response.data);
|
|
34
|
-
}
|
|
35
|
-
renderSnippets(data) {
|
|
36
|
-
const snippets = data.sdkSnippets ?? [];
|
|
37
|
-
if (snippets.length === 0) {
|
|
38
|
-
this.log(`\n ${chalk.dim('No active deployed sequences.')}`);
|
|
39
|
-
this.log(` Run ${chalk.cyan('mailmodo deploy')} to deploy one.\n`);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
this.log(`\n ${chalk.bold(String(snippets.length))} active ${snippets.length === 1 ? 'sequence' : 'sequences'}:\n`);
|
|
43
|
-
this.log(` ${SEPARATOR}`);
|
|
44
|
-
this.log(` ${chalk.bold('SDK EVENT REFERENCE')}`);
|
|
45
|
-
this.log(` ${SEPARATOR}\n`);
|
|
46
|
-
this.log(` ${chalk.cyan(SDK_INSTALL_COMMAND)}\n`);
|
|
47
|
-
this.log(` ${chalk.dim(SDK_IMPORT_SNIPPET)}\n`);
|
|
48
|
-
for (const [index, snippet] of snippets.entries()) {
|
|
49
|
-
this.renderSequenceBlock(snippet);
|
|
50
|
-
if (index < snippets.length - 1)
|
|
51
|
-
this.log('');
|
|
52
|
-
}
|
|
53
|
-
this.log(` ${SEPARATOR}\n`);
|
|
54
|
-
}
|
|
55
|
-
renderSequenceBlock(snippet) {
|
|
56
|
-
const productName = snippet.productName || 'Unnamed sequence';
|
|
57
|
-
this.log(` ${chalk.bold(productName)} ${chalk.dim(`(${snippet.sequenceId})`)}`);
|
|
58
|
-
const trackCalls = [...new Set(snippet.sdkSnippet?.trackCalls ?? [])];
|
|
59
|
-
const identifyCalls = [...new Set(snippet.sdkSnippet?.identifyCalls ?? [])];
|
|
60
|
-
this.renderCallBlock('// track() calls', trackCalls);
|
|
61
|
-
this.renderCallBlock('// identify() calls', identifyCalls);
|
|
62
|
-
if (trackCalls.length === 0 && identifyCalls.length === 0) {
|
|
63
|
-
this.log(` ${chalk.dim('No track() or identify() calls available.')}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
renderCallBlock(label, calls) {
|
|
67
|
-
if (calls.length === 0)
|
|
68
|
-
return;
|
|
69
|
-
this.log(` ${chalk.dim(label)}`);
|
|
70
|
-
for (const call of calls) {
|
|
71
|
-
this.log(` ${chalk.dim(call)}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
package/dist/lib/utils.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts a user-facing snake_case YAML setting key to its
|
|
3
|
-
* corresponding camelCase TypeScript property name.
|
|
4
|
-
*
|
|
5
|
-
* @param {string} key - A snake_case setting key (e.g., "brand_color").
|
|
6
|
-
* @returns {string} The camelCase property name (e.g., "brandColor").
|
|
7
|
-
*/
|
|
8
|
-
export declare function settingKeyToProp(key: string): string;
|
|
9
|
-
export declare function generateTriggerPrefix(productName: string): string;
|
|
10
|
-
export declare function normalizeTrigger(trigger: string, productName: string): string;
|
|
11
|
-
export declare function isValidUrl(value: string): boolean;
|
package/dist/lib/utils.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts a user-facing snake_case YAML setting key to its
|
|
3
|
-
* corresponding camelCase TypeScript property name.
|
|
4
|
-
*
|
|
5
|
-
* @param {string} key - A snake_case setting key (e.g., "brand_color").
|
|
6
|
-
* @returns {string} The camelCase property name (e.g., "brandColor").
|
|
7
|
-
*/
|
|
8
|
-
export function settingKeyToProp(key) {
|
|
9
|
-
return key.replaceAll(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
10
|
-
}
|
|
11
|
-
function toCamelCaseAlnum(input) {
|
|
12
|
-
const parts = input
|
|
13
|
-
.trim()
|
|
14
|
-
.split(/[^a-zA-Z0-9]+/)
|
|
15
|
-
.filter(Boolean);
|
|
16
|
-
if (parts.length === 0)
|
|
17
|
-
return '';
|
|
18
|
-
return (parts[0].toLowerCase() +
|
|
19
|
-
parts
|
|
20
|
-
.slice(1)
|
|
21
|
-
.map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())
|
|
22
|
-
.join(''));
|
|
23
|
-
}
|
|
24
|
-
export function generateTriggerPrefix(productName) {
|
|
25
|
-
return `${toCamelCaseAlnum(productName)}$`;
|
|
26
|
-
}
|
|
27
|
-
export function normalizeTrigger(trigger, productName) {
|
|
28
|
-
const prefix = generateTriggerPrefix(productName);
|
|
29
|
-
const dollarIdx = trigger.indexOf('$');
|
|
30
|
-
const eventName = dollarIdx === -1 ? trigger : trigger.slice(dollarIdx + 1);
|
|
31
|
-
return prefix + eventName;
|
|
32
|
-
}
|
|
33
|
-
export function isValidUrl(value) {
|
|
34
|
-
try {
|
|
35
|
-
return Boolean(new URL(value));
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|