carto-cli 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/ARCHITECTURE.md +497 -0
- package/CHANGELOG.md +28 -0
- package/LICENSE +15 -0
- package/MAP_JSON.md +516 -0
- package/README.md +1595 -0
- package/WORKFLOW_JSON.md +623 -0
- package/dist/api.js +489 -0
- package/dist/auth-oauth.js +485 -0
- package/dist/auth-server.js +432 -0
- package/dist/browser.js +30 -0
- package/dist/colors.js +45 -0
- package/dist/commands/activity.js +427 -0
- package/dist/commands/admin.js +177 -0
- package/dist/commands/ai.js +489 -0
- package/dist/commands/auth.js +652 -0
- package/dist/commands/connections.js +412 -0
- package/dist/commands/credentials.js +606 -0
- package/dist/commands/imports.js +234 -0
- package/dist/commands/maps.js +1022 -0
- package/dist/commands/org.js +195 -0
- package/dist/commands/sql.js +326 -0
- package/dist/commands/users.js +459 -0
- package/dist/commands/workflows.js +1025 -0
- package/dist/config.js +320 -0
- package/dist/download.js +108 -0
- package/dist/help.js +285 -0
- package/dist/http.js +139 -0
- package/dist/index.js +1133 -0
- package/dist/logo.js +11 -0
- package/dist/prompt.js +67 -0
- package/dist/schedule-parser.js +287 -0
- package/jest.config.ts +43 -0
- package/package.json +53 -0
package/dist/logo.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CARTO_LOGO = void 0;
|
|
4
|
+
exports.CARTO_LOGO = `
|
|
5
|
+
██████╗ █████╗ ██████╗ ████████╗ ██████╗ ██████╗██╗ ██╗
|
|
6
|
+
██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██╔═══██╗ ██╔════╝██║ ██║
|
|
7
|
+
██║ ███████║██████╔╝ ██║ ██║ ██║ ██║ ██║ ██║
|
|
8
|
+
██║ ██╔══██║██╔══██╗ ██║ ██║ ██║ ██║ ██║ ██║
|
|
9
|
+
╚██████╗██║ ██║██║ ██║ ██║ ╚██████╔╝ ╚██████╗███████╗██║
|
|
10
|
+
╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚══════╝╚═╝
|
|
11
|
+
`;
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
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 () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.promptForConfirmation = promptForConfirmation;
|
|
37
|
+
const readline = __importStar(require("readline"));
|
|
38
|
+
/**
|
|
39
|
+
* Prompt the user for confirmation by typing a specific word
|
|
40
|
+
* @param message The message to display before the prompt
|
|
41
|
+
* @param expectedInput The exact string the user must type (case-sensitive)
|
|
42
|
+
* @returns Promise that resolves to true if user entered correct input, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
async function promptForConfirmation(message, expectedInput) {
|
|
45
|
+
// Check if we're in an interactive terminal
|
|
46
|
+
if (!process.stdin.isTTY) {
|
|
47
|
+
// Non-interactive mode - cannot prompt
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
const rl = readline.createInterface({
|
|
52
|
+
input: process.stdin,
|
|
53
|
+
output: process.stdout
|
|
54
|
+
});
|
|
55
|
+
// Handle Ctrl+C gracefully
|
|
56
|
+
rl.on('SIGINT', () => {
|
|
57
|
+
console.log('\n'); // New line after ^C
|
|
58
|
+
rl.close();
|
|
59
|
+
resolve(false);
|
|
60
|
+
});
|
|
61
|
+
rl.question(message, (answer) => {
|
|
62
|
+
rl.close();
|
|
63
|
+
const trimmedAnswer = answer.trim();
|
|
64
|
+
resolve(trimmedAnswer === expectedInput);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Schedule expression parser for different data warehouse providers
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseScheduleExpression = parseScheduleExpression;
|
|
7
|
+
const DAYS_OF_WEEK_MAP = {
|
|
8
|
+
'sunday': 0,
|
|
9
|
+
'sun': 0,
|
|
10
|
+
'monday': 1,
|
|
11
|
+
'mon': 1,
|
|
12
|
+
'tuesday': 2,
|
|
13
|
+
'tue': 2,
|
|
14
|
+
'wednesday': 3,
|
|
15
|
+
'wed': 3,
|
|
16
|
+
'thursday': 4,
|
|
17
|
+
'thu': 4,
|
|
18
|
+
'friday': 5,
|
|
19
|
+
'fri': 5,
|
|
20
|
+
'saturday': 6,
|
|
21
|
+
'sat': 6,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Parse schedule expression based on provider type
|
|
25
|
+
*/
|
|
26
|
+
function parseScheduleExpression(expression, provider) {
|
|
27
|
+
const normalizedProvider = provider.toLowerCase();
|
|
28
|
+
if (normalizedProvider === 'bigquery' || normalizedProvider === 'bq' || normalizedProvider.includes('carto')) {
|
|
29
|
+
return parseNaturalLanguage(expression);
|
|
30
|
+
}
|
|
31
|
+
else if (normalizedProvider === 'snowflake' || normalizedProvider === 'sf' ||
|
|
32
|
+
normalizedProvider === 'postgres' || normalizedProvider === 'postgresql' ||
|
|
33
|
+
normalizedProvider === 'redshift' || normalizedProvider === 'rs') {
|
|
34
|
+
return parseCron(expression);
|
|
35
|
+
}
|
|
36
|
+
else if (normalizedProvider === 'databricks' || normalizedProvider === 'databricksrest' || normalizedProvider === 'db') {
|
|
37
|
+
return parseQuartzCron(expression);
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`Unsupported provider: ${provider}`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse natural language schedule expressions (BigQuery/CARTO DW)
|
|
43
|
+
*/
|
|
44
|
+
function parseNaturalLanguage(expr) {
|
|
45
|
+
const normalized = expr.toLowerCase().trim();
|
|
46
|
+
// Pattern: "every day HH:MM"
|
|
47
|
+
const dailyPattern = /^every\s+day\s+(\d{1,2}):(\d{2})$/;
|
|
48
|
+
const dailyMatch = normalized.match(dailyPattern);
|
|
49
|
+
if (dailyMatch) {
|
|
50
|
+
const hour = parseInt(dailyMatch[1], 10);
|
|
51
|
+
const minute = parseInt(dailyMatch[2], 10);
|
|
52
|
+
return {
|
|
53
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
|
|
54
|
+
frequency: 4,
|
|
55
|
+
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
56
|
+
daysOfMonth: [],
|
|
57
|
+
expression: expr,
|
|
58
|
+
repeatInterval: 1
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Pattern: "every (monday|tuesday|...) HH:MM"
|
|
62
|
+
const weeklyPattern = /^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday|mon|tue|wed|thu|fri|sat|sun)\s+(\d{1,2}):(\d{2})$/;
|
|
63
|
+
const weeklyMatch = normalized.match(weeklyPattern);
|
|
64
|
+
if (weeklyMatch) {
|
|
65
|
+
const dayName = weeklyMatch[1];
|
|
66
|
+
const dayOfWeek = DAYS_OF_WEEK_MAP[dayName];
|
|
67
|
+
const hour = parseInt(weeklyMatch[2], 10);
|
|
68
|
+
const minute = parseInt(weeklyMatch[3], 10);
|
|
69
|
+
return {
|
|
70
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
|
|
71
|
+
frequency: 4,
|
|
72
|
+
daysOfWeek: [dayOfWeek],
|
|
73
|
+
daysOfMonth: [],
|
|
74
|
+
expression: expr,
|
|
75
|
+
repeatInterval: 1
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Pattern: "every N hours" or "every N hour"
|
|
79
|
+
const hourlyPattern = /^every\s+(\d+)\s+hours?$/;
|
|
80
|
+
const hourlyMatch = normalized.match(hourlyPattern);
|
|
81
|
+
if (hourlyMatch) {
|
|
82
|
+
const interval = parseInt(hourlyMatch[1], 10);
|
|
83
|
+
return {
|
|
84
|
+
time: "00:00",
|
|
85
|
+
frequency: 4,
|
|
86
|
+
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
87
|
+
daysOfMonth: [],
|
|
88
|
+
expression: expr,
|
|
89
|
+
repeatInterval: interval
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Pattern: "every hour"
|
|
93
|
+
if (normalized === 'every hour') {
|
|
94
|
+
return {
|
|
95
|
+
time: "00:00",
|
|
96
|
+
frequency: 4,
|
|
97
|
+
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
98
|
+
daysOfMonth: [],
|
|
99
|
+
expression: expr,
|
|
100
|
+
repeatInterval: 1
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Pattern: "N of month HH:MM" or "N,M,O of month HH:MM"
|
|
104
|
+
const monthlyPattern = /^(\d+(?:,\d+)*)\s+of\s+month\s+(\d{1,2}):(\d{2})$/;
|
|
105
|
+
const monthlyMatch = normalized.match(monthlyPattern);
|
|
106
|
+
if (monthlyMatch) {
|
|
107
|
+
const days = monthlyMatch[1].split(',').map(d => parseInt(d, 10));
|
|
108
|
+
const hour = parseInt(monthlyMatch[2], 10);
|
|
109
|
+
const minute = parseInt(monthlyMatch[3], 10);
|
|
110
|
+
return {
|
|
111
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
|
|
112
|
+
frequency: 4,
|
|
113
|
+
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
114
|
+
daysOfMonth: days,
|
|
115
|
+
expression: expr,
|
|
116
|
+
repeatInterval: 1
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Pattern: "Nth weekday of month HH:MM" (e.g., "1st monday of month 09:00")
|
|
120
|
+
const ordinalWeekdayPattern = /^(\d+(?:st|nd|rd|th)?)\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday|mon|tue|wed|thu|fri|sat|sun)\s+of\s+month\s+(\d{1,2}):(\d{2})$/;
|
|
121
|
+
const ordinalWeekdayMatch = normalized.match(ordinalWeekdayPattern);
|
|
122
|
+
if (ordinalWeekdayMatch) {
|
|
123
|
+
const dayName = ordinalWeekdayMatch[2];
|
|
124
|
+
const dayOfWeek = DAYS_OF_WEEK_MAP[dayName];
|
|
125
|
+
const hour = parseInt(ordinalWeekdayMatch[3], 10);
|
|
126
|
+
const minute = parseInt(ordinalWeekdayMatch[4], 10);
|
|
127
|
+
return {
|
|
128
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
|
|
129
|
+
frequency: 4,
|
|
130
|
+
daysOfWeek: [dayOfWeek],
|
|
131
|
+
daysOfMonth: [],
|
|
132
|
+
expression: expr,
|
|
133
|
+
repeatInterval: 1
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// For any other complex BigQuery format, return a default structure
|
|
137
|
+
// Extract time if present
|
|
138
|
+
const timeMatch = normalized.match(/(\d{1,2}):(\d{2})/);
|
|
139
|
+
if (timeMatch) {
|
|
140
|
+
const hour = parseInt(timeMatch[1], 10);
|
|
141
|
+
const minute = parseInt(timeMatch[2], 10);
|
|
142
|
+
return {
|
|
143
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
|
|
144
|
+
frequency: 4,
|
|
145
|
+
daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
|
|
146
|
+
daysOfMonth: [],
|
|
147
|
+
expression: expr,
|
|
148
|
+
repeatInterval: 1
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
throw new Error(`Invalid BigQuery/CARTO schedule expression: ${expr}. Expected formats: "every day HH:MM", "every monday HH:MM", "every N hours", "N of month HH:MM"`);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parse standard cron expression (Snowflake/PostgreSQL/Redshift)
|
|
155
|
+
* Format: minute hour day-of-month month day-of-week
|
|
156
|
+
*/
|
|
157
|
+
function parseCron(expr) {
|
|
158
|
+
const parts = expr.trim().split(/\s+/);
|
|
159
|
+
if (parts.length < 5) {
|
|
160
|
+
throw new Error(`Invalid cron expression: ${expr}. Expected format: "M H D M W"`);
|
|
161
|
+
}
|
|
162
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
163
|
+
// Parse time
|
|
164
|
+
const hourNum = parseInt(hour, 10);
|
|
165
|
+
const minuteNum = parseInt(minute, 10);
|
|
166
|
+
if (isNaN(hourNum) || isNaN(minuteNum)) {
|
|
167
|
+
throw new Error(`Invalid time in cron expression: ${expr}`);
|
|
168
|
+
}
|
|
169
|
+
const time = `${hourNum.toString().padStart(2, '0')}:${minuteNum.toString().padStart(2, '0')}`;
|
|
170
|
+
// Parse days of week (0=Sunday, 7=Sunday)
|
|
171
|
+
let daysOfWeek = [];
|
|
172
|
+
if (dayOfWeek === '*') {
|
|
173
|
+
daysOfWeek = [0, 1, 2, 3, 4, 5, 6];
|
|
174
|
+
}
|
|
175
|
+
else if (dayOfWeek.includes(',')) {
|
|
176
|
+
daysOfWeek = dayOfWeek.split(',').map(d => {
|
|
177
|
+
const num = parseInt(d, 10);
|
|
178
|
+
return num === 7 ? 0 : num; // Convert 7 to 0 (Sunday)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if (dayOfWeek.includes('*/')) {
|
|
182
|
+
// Every N days - treat as all days
|
|
183
|
+
daysOfWeek = [0, 1, 2, 3, 4, 5, 6];
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const num = parseInt(dayOfWeek, 10);
|
|
187
|
+
daysOfWeek = [num === 7 ? 0 : num];
|
|
188
|
+
}
|
|
189
|
+
// Parse days of month
|
|
190
|
+
let daysOfMonth = [];
|
|
191
|
+
if (dayOfMonth !== '*' && !dayOfMonth.includes('/')) {
|
|
192
|
+
if (dayOfMonth.includes(',')) {
|
|
193
|
+
daysOfMonth = dayOfMonth.split(',').map(d => parseInt(d, 10));
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
daysOfMonth = [parseInt(dayOfMonth, 10)];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Detect interval schedules (every N hours)
|
|
200
|
+
let repeatInterval = 1;
|
|
201
|
+
if (hour.includes('*/')) {
|
|
202
|
+
const match = hour.match(/\*\/(\d+)/);
|
|
203
|
+
if (match) {
|
|
204
|
+
repeatInterval = parseInt(match[1], 10);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
time,
|
|
209
|
+
frequency: 4,
|
|
210
|
+
daysOfWeek,
|
|
211
|
+
daysOfMonth,
|
|
212
|
+
expression: expr,
|
|
213
|
+
repeatInterval
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Parse Quartz cron expression (Databricks)
|
|
218
|
+
* Format: second minute hour day-of-month month day-of-week [year]
|
|
219
|
+
*/
|
|
220
|
+
function parseQuartzCron(expr) {
|
|
221
|
+
const parts = expr.trim().split(/\s+/);
|
|
222
|
+
if (parts.length < 6) {
|
|
223
|
+
throw new Error(`Invalid Quartz cron expression: ${expr}. Expected format: "S M H D M W [Y]"`);
|
|
224
|
+
}
|
|
225
|
+
const [second, minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
226
|
+
// Parse time
|
|
227
|
+
const hourNum = parseInt(hour, 10);
|
|
228
|
+
const minuteNum = parseInt(minute, 10);
|
|
229
|
+
if (isNaN(hourNum) || isNaN(minuteNum)) {
|
|
230
|
+
throw new Error(`Invalid time in Quartz cron expression: ${expr}`);
|
|
231
|
+
}
|
|
232
|
+
const time = `${hourNum.toString().padStart(2, '0')}:${minuteNum.toString().padStart(2, '0')}`;
|
|
233
|
+
// Parse days of week (1=Sunday in Quartz, or MON/TUE/etc)
|
|
234
|
+
let daysOfWeek = [];
|
|
235
|
+
if (dayOfWeek === '?' || dayOfWeek === '*') {
|
|
236
|
+
daysOfWeek = [0, 1, 2, 3, 4, 5, 6];
|
|
237
|
+
}
|
|
238
|
+
else if (/^[A-Z]{3}$/.test(dayOfWeek.toUpperCase())) {
|
|
239
|
+
// Named day (MON, TUE, etc)
|
|
240
|
+
const dayName = dayOfWeek.toLowerCase();
|
|
241
|
+
const dayNum = DAYS_OF_WEEK_MAP[dayName];
|
|
242
|
+
if (dayNum !== undefined) {
|
|
243
|
+
daysOfWeek = [dayNum];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (dayOfWeek.includes(',')) {
|
|
247
|
+
daysOfWeek = dayOfWeek.split(',').map(d => {
|
|
248
|
+
if (/^[A-Z]{3}$/i.test(d)) {
|
|
249
|
+
return DAYS_OF_WEEK_MAP[d.toLowerCase()];
|
|
250
|
+
}
|
|
251
|
+
const num = parseInt(d, 10);
|
|
252
|
+
return num === 1 ? 0 : num - 1; // Quartz: 1=Sunday, convert to 0=Sunday
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
const num = parseInt(dayOfWeek, 10);
|
|
257
|
+
if (!isNaN(num)) {
|
|
258
|
+
daysOfWeek = [num === 1 ? 0 : num - 1];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Parse days of month
|
|
262
|
+
let daysOfMonth = [];
|
|
263
|
+
if (dayOfMonth !== '?' && dayOfMonth !== '*' && !dayOfMonth.includes('/')) {
|
|
264
|
+
if (dayOfMonth.includes(',')) {
|
|
265
|
+
daysOfMonth = dayOfMonth.split(',').map(d => parseInt(d, 10));
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
daysOfMonth = [parseInt(dayOfMonth, 10)];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Detect interval schedules
|
|
272
|
+
let repeatInterval = 1;
|
|
273
|
+
if (hour.includes('*/')) {
|
|
274
|
+
const match = hour.match(/\*\/(\d+)/);
|
|
275
|
+
if (match) {
|
|
276
|
+
repeatInterval = parseInt(match[1], 10);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
time,
|
|
281
|
+
frequency: 4,
|
|
282
|
+
daysOfWeek,
|
|
283
|
+
daysOfMonth,
|
|
284
|
+
expression: expr,
|
|
285
|
+
repeatInterval
|
|
286
|
+
};
|
|
287
|
+
}
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Config } from '@jest/types';
|
|
2
|
+
|
|
3
|
+
const config: Config.InitialOptions = {
|
|
4
|
+
preset: 'ts-jest',
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
roots: ['<rootDir>/__tests__'],
|
|
7
|
+
testRegex: '/__tests__/.*\\.(spec|test)\\.ts$',
|
|
8
|
+
moduleFileExtensions: ['ts', 'js', 'json'],
|
|
9
|
+
collectCoverage: true,
|
|
10
|
+
coverageDirectory: 'coverage',
|
|
11
|
+
coverageReporters: ['text', 'text-summary', 'lcov'],
|
|
12
|
+
collectCoverageFrom: [
|
|
13
|
+
'src/**/*.ts',
|
|
14
|
+
'!src/logo.ts',
|
|
15
|
+
'!src/index.ts',
|
|
16
|
+
'!src/commands/**/*.ts', // Commands tested via integration tests with mocks
|
|
17
|
+
'!src/prompt.ts' // Interactive prompts not unit-testable
|
|
18
|
+
],
|
|
19
|
+
coverageThreshold: {
|
|
20
|
+
global: {
|
|
21
|
+
// Raised thresholds after comprehensive unit test coverage
|
|
22
|
+
statements: 75,
|
|
23
|
+
branches: 70,
|
|
24
|
+
functions: 70,
|
|
25
|
+
lines: 75
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
setupFilesAfterEnv: ['<rootDir>/__tests__/setup.ts'],
|
|
29
|
+
testPathIgnorePatterns: [
|
|
30
|
+
'<rootDir>/node_modules/',
|
|
31
|
+
'<rootDir>/__tests__/e2e/',
|
|
32
|
+
'<rootDir>/__tests__/fixtures/',
|
|
33
|
+
'<rootDir>/__tests__/mocks/'
|
|
34
|
+
],
|
|
35
|
+
transform: {
|
|
36
|
+
'\\.ts$': 'ts-jest'
|
|
37
|
+
},
|
|
38
|
+
clearMocks: true,
|
|
39
|
+
// Increase timeout for integration tests
|
|
40
|
+
testTimeout: 10000
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default config;
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "carto-cli",
|
|
3
|
+
"version": "0.1.0-rc.1",
|
|
4
|
+
"description": "CARTO CLI - Geospatial Cloud Native Platform Admin Tool",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"carto": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"bundle": "ncc build dist/index.js -o bundle && cp bundle/index.js bundle/carto",
|
|
12
|
+
"watch": "ncc build src/index.ts -o bundle --watch && mv bundle/index.js bundle/carto",
|
|
13
|
+
"pkg": "pkg bundle/carto -t node18-macos-x64,node18-linux-x64,node18-win-x64 -o bin/carto",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"dev": "npm run build && node dist/index.js",
|
|
16
|
+
"build:all": "npm run build && npm run bundle && npm run pkg",
|
|
17
|
+
"test": "jest --config jest.config.ts",
|
|
18
|
+
"test:watch": "jest --config jest.config.ts --watch",
|
|
19
|
+
"test:unit": "jest --config jest.config.ts __tests__/unit",
|
|
20
|
+
"test:integration": "jest --config jest.config.ts __tests__/integration",
|
|
21
|
+
"test:coverage": "jest --config jest.config.ts --coverage",
|
|
22
|
+
"bun:dev": "bun run src/index.ts",
|
|
23
|
+
"bun:bundle": "bun build src/index.ts --outfile bun-bundle/carto.js --target node",
|
|
24
|
+
"bun:compile": "bun build src/index.ts --compile --outfile bun-bin/carto",
|
|
25
|
+
"bun:compile:all": "bun build src/index.ts --compile --outfile bun-bin/carto-macos && bun build src/index.ts --compile --target=bun-linux-x64 --outfile bun-bin/carto-linux && bun build src/index.ts --compile --target=bun-windows-x64 --outfile bun-bin/carto-windows.exe"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"carto",
|
|
29
|
+
"cli",
|
|
30
|
+
"geospatial",
|
|
31
|
+
"admin"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "ISC",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@types/js-yaml": "^4.0.9",
|
|
37
|
+
"js-yaml": "^4.1.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/jest": "^30.0.0",
|
|
41
|
+
"@types/node": "^24.7.0",
|
|
42
|
+
"@vercel/ncc": "^0.38.4",
|
|
43
|
+
"jest": "^30.2.0",
|
|
44
|
+
"memfs": "^4.51.1",
|
|
45
|
+
"pkg": "^5.8.1",
|
|
46
|
+
"ts-jest": "^29.4.6",
|
|
47
|
+
"ts-node": "^10.9.2",
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
},
|
|
50
|
+
"overrides": {
|
|
51
|
+
"node-gyp": "^11.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|