@c15t/cli 0.0.1-rc.24 → 1.0.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/README.md +93 -0
- package/dist/actions/get-config/config-extraction.d.ts +37 -0
- package/dist/actions/get-config/config-extraction.d.ts.map +1 -0
- package/dist/actions/get-config/config-validation.d.ts +7 -0
- package/dist/actions/get-config/config-validation.d.ts.map +1 -0
- package/dist/actions/get-config/constants.d.ts +13 -0
- package/dist/actions/get-config/constants.d.ts.map +1 -0
- package/dist/actions/get-config/directory-search.d.ts +6 -0
- package/dist/actions/get-config/directory-search.d.ts.map +1 -0
- package/dist/actions/get-config/jiti-options.d.ts +9 -0
- package/dist/actions/get-config/jiti-options.d.ts.map +1 -0
- package/dist/actions/get-config.d.ts +13 -0
- package/dist/actions/get-config.d.ts.map +1 -0
- package/dist/actions/load-config-and-onboard.d.ts +9 -0
- package/dist/actions/load-config-and-onboard.d.ts.map +1 -0
- package/dist/actions/show-help-menu.d.ts +11 -0
- package/dist/actions/show-help-menu.d.ts.map +1 -0
- package/dist/commands/generate/actions/handle-existing-file.d.ts +7 -0
- package/dist/commands/generate/actions/handle-existing-file.d.ts.map +1 -0
- package/dist/commands/generate/actions/handle-new-file.d.ts +7 -0
- package/dist/commands/generate/actions/handle-new-file.d.ts.map +1 -0
- package/dist/commands/generate/actions/perform-write-action.d.ts +6 -0
- package/dist/commands/generate/actions/perform-write-action.d.ts.map +1 -0
- package/dist/commands/generate/generators/drizzle.d.ts.map +1 -0
- package/dist/{generators → commands/generate/generators}/index.d.ts +2 -1
- package/dist/commands/generate/generators/index.d.ts.map +1 -0
- package/dist/commands/generate/generators/kysely.d.ts.map +1 -0
- package/dist/commands/generate/generators/prisma.d.ts.map +1 -0
- package/dist/commands/generate/generators/types.d.ts.map +1 -0
- package/dist/commands/generate/schema.d.ts +10 -0
- package/dist/commands/generate/schema.d.ts.map +1 -0
- package/dist/commands/generate/setup.d.ts +13 -0
- package/dist/commands/generate/setup.d.ts.map +1 -0
- package/dist/commands/generate/write.d.ts +8 -0
- package/dist/commands/generate/write.d.ts.map +1 -0
- package/dist/commands/generate.d.ts +5 -3
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/migrate/execute.d.ts +7 -0
- package/dist/commands/migrate/execute.d.ts.map +1 -0
- package/dist/commands/migrate/plan.d.ts +12 -0
- package/dist/commands/migrate/plan.d.ts.map +1 -0
- package/dist/commands/migrate/setup.d.ts +12 -0
- package/dist/commands/migrate/setup.d.ts.map +1 -0
- package/dist/commands/migrate.d.ts +2 -3
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/components/intro.d.ts +9 -0
- package/dist/components/intro.d.ts.map +1 -0
- package/dist/context/config-management.d.ts +20 -0
- package/dist/context/config-management.d.ts.map +1 -0
- package/dist/context/creator.d.ts +11 -0
- package/dist/context/creator.d.ts.map +1 -0
- package/dist/context/error-handlers.d.ts +18 -0
- package/dist/context/error-handlers.d.ts.map +1 -0
- package/dist/context/file-system.d.ts +11 -0
- package/dist/context/file-system.d.ts.map +1 -0
- package/dist/context/parser.d.ts +11 -0
- package/dist/context/parser.d.ts.map +1 -0
- package/dist/context/types.d.ts +54 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/user-interaction.d.ts +14 -0
- package/dist/context/user-interaction.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1883 -746
- package/dist/onboarding/dependencies.d.ts +20 -0
- package/dist/onboarding/dependencies.d.ts.map +1 -0
- package/dist/onboarding/detection.d.ts +33 -0
- package/dist/onboarding/detection.d.ts.map +1 -0
- package/dist/onboarding/index.d.ts +11 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/storage-modes/c15t-mode.d.ts +22 -0
- package/dist/onboarding/storage-modes/c15t-mode.d.ts.map +1 -0
- package/dist/onboarding/storage-modes/custom-mode.d.ts +18 -0
- package/dist/onboarding/storage-modes/custom-mode.d.ts.map +1 -0
- package/dist/onboarding/storage-modes/index.d.ts +5 -0
- package/dist/onboarding/storage-modes/index.d.ts.map +1 -0
- package/dist/onboarding/storage-modes/offline-mode.d.ts +19 -0
- package/dist/onboarding/storage-modes/offline-mode.d.ts.map +1 -0
- package/dist/onboarding/storage-modes/self-hosted-mode.d.ts +22 -0
- package/dist/onboarding/storage-modes/self-hosted-mode.d.ts.map +1 -0
- package/dist/onboarding/templates.d.ts +30 -0
- package/dist/onboarding/templates.d.ts.map +1 -0
- package/dist/onboarding.d.ts +15 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +29 -2
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/telemetry.d.ts +140 -0
- package/dist/utils/telemetry.d.ts.map +1 -0
- package/package.json +13 -11
- package/dist/commands/secret.d.ts +0 -3
- package/dist/commands/secret.d.ts.map +0 -1
- package/dist/generators/drizzle.d.ts.map +0 -1
- package/dist/generators/index.d.ts.map +0 -1
- package/dist/generators/kysely.d.ts.map +0 -1
- package/dist/generators/prisma.d.ts.map +0 -1
- package/dist/generators/types.d.ts.map +0 -1
- package/dist/utils/add-svelte-kit-env-modules.d.ts +0 -4
- package/dist/utils/add-svelte-kit-env-modules.d.ts.map +0 -1
- package/dist/utils/get-config.d.ts +0 -11
- package/dist/utils/get-config.d.ts.map +0 -1
- package/dist/utils/get-package-info.d.ts +0 -2
- package/dist/utils/get-package-info.d.ts.map +0 -1
- /package/dist/{generators → commands/generate/generators}/drizzle.d.ts +0 -0
- /package/dist/{generators → commands/generate/generators}/kysely.d.ts +0 -0
- /package/dist/{generators → commands/generate/generators}/prisma.d.ts +0 -0
- /package/dist/{generators → commands/generate/generators}/types.d.ts +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,424 +1,83 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__ from "@clack/prompts";
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import * as __WEBPACK_EXTERNAL_MODULE_open__ from "open";
|
|
5
|
+
import * as __WEBPACK_EXTERNAL_MODULE_picocolors__ from "picocolors";
|
|
4
6
|
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__ from "node:fs/promises";
|
|
5
7
|
import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
|
|
6
|
-
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_db_adapters_cee37d0f__ from "@c15t/backend/pkgs/db-adapters";
|
|
7
|
-
import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
|
|
8
|
-
import * as __WEBPACK_EXTERNAL_MODULE_prompts__ from "prompts";
|
|
9
|
-
import * as __WEBPACK_EXTERNAL_MODULE_yocto_spinner_579f0326__ from "yocto-spinner";
|
|
10
|
-
import * as __WEBPACK_EXTERNAL_MODULE_zod__ from "zod";
|
|
11
|
-
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_logger_44a195c6__ from "@c15t/backend/pkgs/logger";
|
|
12
|
-
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_schema_4fae43f5__ from "@c15t/backend/schema";
|
|
13
|
-
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_migrations_80b6e3bd__ from "@c15t/backend/pkgs/migrations";
|
|
14
|
-
import * as __WEBPACK_EXTERNAL_MODULE__mrleebo_prisma_ast_c5b328aa__ from "@mrleebo/prisma-ast";
|
|
15
|
-
import * as __WEBPACK_EXTERNAL_MODULE__babel_preset_react_76cf724d__ from "@babel/preset-react";
|
|
16
|
-
import * as __WEBPACK_EXTERNAL_MODULE__babel_preset_typescript_a7789c85__ from "@babel/preset-typescript";
|
|
17
|
-
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_results_3ca2b89f__ from "@c15t/backend/pkgs/results";
|
|
18
8
|
import * as __WEBPACK_EXTERNAL_MODULE_c12__ from "c12";
|
|
19
|
-
import "
|
|
9
|
+
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_logger_44a195c6__ from "@c15t/backend/pkgs/logger";
|
|
20
10
|
import * as __WEBPACK_EXTERNAL_MODULE_node_crypto_9ba42079__ from "node:crypto";
|
|
11
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__ from "node:os";
|
|
12
|
+
import * as __WEBPACK_EXTERNAL_MODULE_posthog_node_1b07bdf4__ from "posthog-node";
|
|
13
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__ from "node:child_process";
|
|
14
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_events_0a6aefe7__ from "node:events";
|
|
15
|
+
import * as __WEBPACK_EXTERNAL_MODULE_package_manager_detector_detect_94d6a9ae__ from "package-manager-detector/detect";
|
|
16
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
|
|
17
|
+
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_db_adapters_cee37d0f__ from "@c15t/backend/pkgs/db-adapters";
|
|
18
|
+
import * as __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_migrations_80b6e3bd__ from "@c15t/backend/pkgs/migrations";
|
|
19
|
+
import * as __WEBPACK_EXTERNAL_MODULE_figlet__ from "figlet";
|
|
21
20
|
import * as __WEBPACK_EXTERNAL_MODULE_fs_extra_ce68a66b__ from "fs-extra";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const filePath = file || './auth-schema.ts';
|
|
34
|
-
const databaseType = adapter.options?.provider;
|
|
35
|
-
const usePlural = adapter.options?.usePlural;
|
|
36
|
-
const timestampAndBoolean = 'sqlite' !== databaseType ? 'timestamp, boolean' : '';
|
|
37
|
-
const int = 'mysql' === databaseType ? 'int' : 'integer';
|
|
38
|
-
const hasBigint = Object.values(tables).some((table)=>Object.values(table.fields).some((field)=>'bigint' in field && field.bigint));
|
|
39
|
-
const bigint = 'sqlite' !== databaseType ? 'bigint' : '';
|
|
40
|
-
const text = 'mysql' === databaseType ? 'varchar, text' : 'text';
|
|
41
|
-
const jsonType = [
|
|
42
|
-
'mysql',
|
|
43
|
-
'pg'
|
|
44
|
-
].includes(databaseType || '') ? ', json' : '';
|
|
45
|
-
let code = `import { ${databaseType}Table, ${text}, ${int}${hasBigint ? `, ${bigint}` : ''}, ${timestampAndBoolean}${jsonType} } from "drizzle-orm/${databaseType}-core";`;
|
|
46
|
-
const fileExist = (0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(filePath);
|
|
47
|
-
let isFirstTable = true;
|
|
48
|
-
for(const table in tables)if (Object.prototype.hasOwnProperty.call(tables, table)) {
|
|
49
|
-
const tableDefinition = tables[table];
|
|
50
|
-
if (!tableDefinition) continue;
|
|
51
|
-
let modelName = usePlural ? `${tableDefinition.modelName}s` : tableDefinition.modelName;
|
|
52
|
-
if (!modelName) modelName = table;
|
|
53
|
-
const fields = tableDefinition.fields;
|
|
54
|
-
function getMySQLStringType(field, name) {
|
|
55
|
-
if (field.unique) return `varchar('${name}', { length: 255 })`;
|
|
56
|
-
if (field.references) return `varchar('${name}', { length: 36 })`;
|
|
57
|
-
return `text('${name}')`;
|
|
58
|
-
}
|
|
59
|
-
function getType(fieldName, field) {
|
|
60
|
-
const snakeCaseName = convertToSnakeCase(fieldName);
|
|
61
|
-
const type = field.type;
|
|
62
|
-
const typeMap = {
|
|
63
|
-
string: {
|
|
64
|
-
sqlite: `text('${snakeCaseName}')`,
|
|
65
|
-
pg: `text('${snakeCaseName}')`,
|
|
66
|
-
mysql: getMySQLStringType(field, snakeCaseName)
|
|
67
|
-
},
|
|
68
|
-
boolean: {
|
|
69
|
-
sqlite: `integer('${snakeCaseName}', { mode: 'boolean' })`,
|
|
70
|
-
pg: `boolean('${snakeCaseName}')`,
|
|
71
|
-
mysql: `boolean('${snakeCaseName}')`
|
|
72
|
-
},
|
|
73
|
-
number: {
|
|
74
|
-
sqlite: `integer('${snakeCaseName}')`,
|
|
75
|
-
pg: 'bigint' in field && field.bigint ? `bigint('${snakeCaseName}', { mode: 'number' })` : `integer('${snakeCaseName}')`,
|
|
76
|
-
mysql: 'bigint' in field && field.bigint ? `bigint('${snakeCaseName}', { mode: 'number' })` : `int('${snakeCaseName}')`
|
|
77
|
-
},
|
|
78
|
-
date: {
|
|
79
|
-
sqlite: `integer('${snakeCaseName}', { mode: 'timestamp' })`,
|
|
80
|
-
pg: `timestamp('${snakeCaseName}')`,
|
|
81
|
-
mysql: `timestamp('${snakeCaseName}')`
|
|
82
|
-
},
|
|
83
|
-
json: {
|
|
84
|
-
sqlite: `text('${snakeCaseName}')`,
|
|
85
|
-
pg: `json('${snakeCaseName}')`,
|
|
86
|
-
mysql: `json('${snakeCaseName}')`
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
if (!typeMap[type]) return `text('${snakeCaseName}')`;
|
|
90
|
-
const dbType = databaseType && [
|
|
91
|
-
'sqlite',
|
|
92
|
-
'pg',
|
|
93
|
-
'mysql'
|
|
94
|
-
].includes(databaseType) ? databaseType : 'sqlite';
|
|
95
|
-
return typeMap[type][dbType];
|
|
96
|
-
}
|
|
97
|
-
const id = 'mysql' === databaseType ? 'varchar("id", { length: 36 }).primaryKey()' : 'text("id").primaryKey()';
|
|
98
|
-
const tableNameForSQL = convertToSnakeCase(modelName);
|
|
99
|
-
if (isFirstTable) {
|
|
100
|
-
code += '\n\n';
|
|
101
|
-
isFirstTable = false;
|
|
102
|
-
} else code += '\n\n';
|
|
103
|
-
const fieldDefinitions = Object.keys(fields).map((field)=>{
|
|
104
|
-
if (Object.prototype.hasOwnProperty.call(fields, field)) {
|
|
105
|
-
const attr = fields[field];
|
|
106
|
-
if (!attr) return '';
|
|
107
|
-
return ` ${field}: ${getType(field, attr)}${attr.required ? '.notNull()' : ''}${attr.unique ? '.unique()' : ''}${attr.references ? `.references(()=> ${usePlural ? `${attr.references.model}s` : attr.references.model}.${attr.references.field}, { onDelete: 'cascade' })` : ''}`;
|
|
108
|
-
}
|
|
109
|
-
return '';
|
|
110
|
-
}).filter(Boolean).join(',\n');
|
|
111
|
-
const schema = [
|
|
112
|
-
`export const ${modelName} = ${databaseType}Table("${tableNameForSQL}", {`,
|
|
113
|
-
` id: ${id},`,
|
|
114
|
-
fieldDefinitions,
|
|
115
|
-
'});'
|
|
116
|
-
].join('\n');
|
|
117
|
-
code += schema;
|
|
21
|
+
function isC15TOptions(obj) {
|
|
22
|
+
return 'object' == typeof obj && null !== obj && 'appName' in obj;
|
|
23
|
+
}
|
|
24
|
+
function isClientOptions(obj) {
|
|
25
|
+
return 'object' == typeof obj && null !== obj && ('mode' in obj || 'backendURL' in obj);
|
|
26
|
+
}
|
|
27
|
+
function tryGetFunctionResult(fn) {
|
|
28
|
+
if ('function' == typeof fn) try {
|
|
29
|
+
return fn();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.warn('Error executing config function:', error);
|
|
118
32
|
}
|
|
119
|
-
return
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
const REFERENCES_REGEX = /\breferences\b/gi;
|
|
130
|
-
const UNIQUE_REGEX = /\bunique\b/gi;
|
|
131
|
-
const CREATE_TABLE_KEYWORD_REGEX = /\bcreate\s+table\b/gi;
|
|
132
|
-
const CREATE_INDEX_KEYWORD_REGEX = /\bcreate\s+index\b/gi;
|
|
133
|
-
const ALTER_TABLE_REGEX = /\balter\s+table\b/gi;
|
|
134
|
-
const INSERT_INTO_REGEX = /\binsert\s+into\b/gi;
|
|
135
|
-
const UPDATE_REGEX = /\bupdate\b/gi;
|
|
136
|
-
const DELETE_FROM_REGEX = /\bdelete\s+from\b/gi;
|
|
137
|
-
const SELECT_REGEX = /\bselect\b/gi;
|
|
138
|
-
const FROM_REGEX = /\bfrom\b/gi;
|
|
139
|
-
const WHERE_REGEX = /\bwhere\b/gi;
|
|
140
|
-
const JOIN_REGEX = /\bjoin\b/gi;
|
|
141
|
-
const ON_REGEX = /\bon\b/gi;
|
|
142
|
-
const AND_REGEX = /\band\b/gi;
|
|
143
|
-
const OR_REGEX = /\bor\b/gi;
|
|
144
|
-
const BOOLEAN_FIELD_REGEX = /("is[A-Z][a-zA-Z0-9]*")\s+integer/g;
|
|
145
|
-
const DATE_FIELD_REGEX = /("(?:created|updated|expires)At")\s+date/gi;
|
|
146
|
-
const TEXT_FIELD_REGEX = /("(?:name|code|description|id)")\s+text/gi;
|
|
147
|
-
const JSON_FIELD_REGEX = /("(?:metadata|config|data|settings|options|preferences|attributes)")\s+text/gi;
|
|
148
|
-
function formatSQL(sql, databaseType = 'sqlite', options) {
|
|
149
|
-
const dbType = 'pg' === databaseType ? 'postgresql' : databaseType;
|
|
150
|
-
const statements = sql.split(';').filter((stmt)=>stmt.trim());
|
|
151
|
-
const rollbackStatements = [];
|
|
152
|
-
const formattedStatements = statements.map((statement)=>{
|
|
153
|
-
const trimmedStmt = statement.trim().toLowerCase();
|
|
154
|
-
if (trimmedStmt.startsWith('create table')) {
|
|
155
|
-
const match = statement.match(CREATE_TABLE_REGEX);
|
|
156
|
-
if (match) {
|
|
157
|
-
const [_, tableName, columnsStr] = match;
|
|
158
|
-
if (!columnsStr) return `${statement.trim()};`;
|
|
159
|
-
rollbackStatements.unshift(`DROP TABLE IF EXISTS "${tableName}"`);
|
|
160
|
-
const columns = columnsStr.split(',').map((col)=>col.trim());
|
|
161
|
-
const formattedColumns = columns.map((col)=>{
|
|
162
|
-
let formattedCol = col.replace(NOT_NULL_REGEX, 'NOT NULL').replace(PRIMARY_KEY_REGEX, 'PRIMARY KEY').replace(REFERENCES_REGEX, 'REFERENCES').replace(UNIQUE_REGEX, 'UNIQUE');
|
|
163
|
-
if ('postgresql' === dbType) formattedCol = formattedCol.replace(BOOLEAN_FIELD_REGEX, '$1 boolean').replace(DATE_FIELD_REGEX, '$1 timestamp with time zone').replace(TEXT_FIELD_REGEX, '$1 varchar(255)').replace(JSON_FIELD_REGEX, '$1 jsonb');
|
|
164
|
-
else if ('mysql' === dbType) formattedCol = formattedCol.replace(BOOLEAN_FIELD_REGEX, '$1 TINYINT(1)').replace(DATE_FIELD_REGEX, '$1 DATETIME').replace(TEXT_FIELD_REGEX, '$1 VARCHAR(255)').replace(JSON_FIELD_REGEX, '$1 JSON');
|
|
165
|
-
else if ('sqlite' === dbType) formattedCol = formattedCol.replace(JSON_FIELD_REGEX, '$1 text -- stored as JSON');
|
|
166
|
-
return formattedCol;
|
|
167
|
-
}).map((col)=>` ${col}`).join(',\n');
|
|
168
|
-
return `CREATE TABLE IF NOT EXISTS "${tableName}" (\n${formattedColumns}\n);`;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (trimmedStmt.startsWith('create index')) {
|
|
172
|
-
const indexMatch = statement.match(CREATE_INDEX_REGEX);
|
|
173
|
-
if (indexMatch) {
|
|
174
|
-
const [_, indexName] = indexMatch;
|
|
175
|
-
rollbackStatements.unshift(`DROP INDEX IF EXISTS "${indexName}"`);
|
|
176
|
-
return `CREATE INDEX IF NOT EXISTS "${indexName}" ${statement.substring(statement.toLowerCase().indexOf('on')).trim()};`;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return `${statement.trim().replace(CREATE_TABLE_KEYWORD_REGEX, 'CREATE TABLE').replace(CREATE_INDEX_KEYWORD_REGEX, 'CREATE INDEX').replace(ALTER_TABLE_REGEX, 'ALTER TABLE').replace(INSERT_INTO_REGEX, 'INSERT INTO').replace(UPDATE_REGEX, 'UPDATE').replace(DELETE_FROM_REGEX, 'DELETE FROM').replace(SELECT_REGEX, 'SELECT').replace(FROM_REGEX, 'FROM').replace(WHERE_REGEX, 'WHERE').replace(JOIN_REGEX, 'JOIN').replace(ON_REGEX, 'ON').replace(AND_REGEX, 'AND').replace(OR_REGEX, 'OR')};`;
|
|
180
|
-
}).join('\n\n');
|
|
181
|
-
const useTransactions = 'd1' !== dbType;
|
|
182
|
-
let transactionStart = '';
|
|
183
|
-
if (useTransactions) transactionStart = 'mysql' === dbType ? 'START TRANSACTION;' : 'BEGIN;';
|
|
184
|
-
const transactionEnd = useTransactions ? 'COMMIT;' : '';
|
|
185
|
-
const timestamp = options?.timestamp || new Date().toISOString();
|
|
186
|
-
return `-- Migration generated by C15T (${timestamp})
|
|
187
|
-
-- Database type: ${dbType}
|
|
188
|
-
-- Description: Automatically generated schema migration
|
|
189
|
-
--
|
|
190
|
-
-- Wrapped in a transaction for atomicity
|
|
191
|
-
-- To roll back this migration, use the ROLLBACK section below
|
|
192
|
-
|
|
193
|
-
${transactionStart}
|
|
194
|
-
-- MIGRATION
|
|
195
|
-
${formattedStatements}
|
|
196
|
-
${transactionEnd}
|
|
197
|
-
|
|
198
|
-
-- ROLLBACK
|
|
199
|
-
-- Uncomment the section below to roll back this migration
|
|
200
|
-
/*
|
|
201
|
-
${transactionStart}
|
|
202
|
-
|
|
203
|
-
${rollbackStatements.join(';\n\n')};\n
|
|
204
|
-
${transactionEnd}
|
|
205
|
-
*/`;
|
|
206
|
-
}
|
|
207
|
-
const generateMigrations = async ({ options, file, adapter })=>{
|
|
208
|
-
const { compileMigrations } = await (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_migrations_80b6e3bd__.getMigrations)(options);
|
|
209
|
-
const migrations = await compileMigrations();
|
|
210
|
-
let databaseType = 'sqlite';
|
|
211
|
-
if (adapter?.options?.provider) databaseType = adapter.options.provider;
|
|
212
|
-
else {
|
|
213
|
-
const dbOptions = options.database?.options;
|
|
214
|
-
if (dbOptions?.provider) databaseType = dbOptions.provider;
|
|
215
|
-
}
|
|
216
|
-
const isTest = 'test' === process.env.NODE_ENV || file?.includes('test');
|
|
217
|
-
const testTimestamp = options?._testTimestamp;
|
|
218
|
-
const formatOptions = {
|
|
219
|
-
timestamp: testTimestamp || (isTest ? '2023-01-01T00:00:00.000Z' : void 0)
|
|
220
|
-
};
|
|
221
|
-
const formattedMigrations = formatSQL(migrations, databaseType, formatOptions);
|
|
222
|
-
const generatedFileName = file || `./c15t_migrations/${Date.now()}_create_tables.sql`;
|
|
223
|
-
return {
|
|
224
|
-
code: formattedMigrations,
|
|
225
|
-
fileName: generatedFileName
|
|
226
|
-
};
|
|
227
|
-
};
|
|
228
|
-
function capitalizeFirstLetter(str) {
|
|
229
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
230
|
-
}
|
|
231
|
-
const generatePrismaSchema = async ({ adapter, options, file })=>{
|
|
232
|
-
const provider = adapter.options?.provider || 'postgresql';
|
|
233
|
-
const tables = (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_schema_4fae43f5__.getConsentTables)(options);
|
|
234
|
-
const filePath = file || './prisma/schema.prisma';
|
|
235
|
-
const schemaPrismaExist = (0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), filePath));
|
|
236
|
-
let schemaPrisma = '';
|
|
237
|
-
schemaPrisma = schemaPrismaExist ? await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), filePath), 'utf-8') : getNewPrisma(provider);
|
|
238
|
-
const manyToManyRelations = new Map();
|
|
239
|
-
for(const table in tables)if (Object.hasOwn(tables, table)) {
|
|
240
|
-
const fields = tables[table]?.fields;
|
|
241
|
-
for(const field in fields)if (Object.hasOwn(fields, field)) {
|
|
242
|
-
const attr = fields[field];
|
|
243
|
-
if (attr?.references) {
|
|
244
|
-
const referencedModel = capitalizeFirstLetter(attr.references.model);
|
|
245
|
-
if (!manyToManyRelations.has(referencedModel)) manyToManyRelations.set(referencedModel, new Set());
|
|
246
|
-
manyToManyRelations.get(referencedModel)?.add(capitalizeFirstLetter(table));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function extractOptionsFromConfig(config) {
|
|
36
|
+
if (config.c15tConfig && isClientOptions(config.c15tConfig)) return config.c15tConfig;
|
|
37
|
+
if (config.c15tOptions && isClientOptions(config.c15tOptions)) return config.c15tOptions;
|
|
38
|
+
if (isClientOptions(config)) return config;
|
|
39
|
+
if (isC15TOptions(config.c15t)) return config.c15t;
|
|
40
|
+
if ('function' == typeof config.c15t) {
|
|
41
|
+
const result = tryGetFunctionResult(config.c15t);
|
|
42
|
+
if (isC15TOptions(result)) return result;
|
|
249
43
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
else builder.model(modelName).field('id', 'String').attribute('id');
|
|
275
|
-
for(const field in fields)if (Object.hasOwn(fields, field)) {
|
|
276
|
-
const attr = fields[field];
|
|
277
|
-
const existingField = builder.findByType('field', {
|
|
278
|
-
name: field,
|
|
279
|
-
within: prismaModel?.properties
|
|
280
|
-
});
|
|
281
|
-
if (existingField) continue;
|
|
282
|
-
if (!attr) continue;
|
|
283
|
-
builder.model(modelName).field(field, getPrismaType(attr.type, !attr?.required, attr?.bigint || false));
|
|
284
|
-
if (attr.unique) builder.model(modelName).blockAttribute(`unique([${field}])`);
|
|
285
|
-
if (attr.references) builder.model(modelName).field(`${attr.references.model.toLowerCase()}`, capitalizeFirstLetter(attr.references.model)).attribute(`relation(fields: [${field}], references: [${attr.references.field}], onDelete: Cascade)`);
|
|
286
|
-
if (!attr.unique && !attr.references && 'mysql' === provider && 'string' === attr.type) builder.model(modelName).field(field).attribute('db.Text');
|
|
287
|
-
}
|
|
288
|
-
if (originalTable && originalTable !== modelName) {
|
|
289
|
-
const hasMapAttribute = builder.findByType('attribute', {
|
|
290
|
-
name: 'map',
|
|
291
|
-
within: prismaModel?.properties
|
|
292
|
-
});
|
|
293
|
-
if (!hasMapAttribute) builder.model(modelName).blockAttribute('map', originalTable);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
for (const [referencedModel, relatedModels] of manyToManyRelations.entries())for (const relatedModel of relatedModels){
|
|
297
|
-
const fieldName = `${relatedModel.toLowerCase()}s`;
|
|
298
|
-
const model = builder.findByType('model', {
|
|
299
|
-
name: referencedModel
|
|
300
|
-
});
|
|
301
|
-
if (model) {
|
|
302
|
-
const existingField = builder.findByType('field', {
|
|
303
|
-
name: fieldName,
|
|
304
|
-
within: model.properties
|
|
305
|
-
});
|
|
306
|
-
if (!existingField) builder.model(referencedModel).field(fieldName, `${relatedModel}[]`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
return {
|
|
311
|
-
code: schema.trim() === schemaPrisma.trim() ? '' : schema,
|
|
312
|
-
fileName: filePath
|
|
313
|
-
};
|
|
314
|
-
};
|
|
315
|
-
const getNewPrisma = (provider)=>`generator client {
|
|
316
|
-
provider = "prisma-client-js"
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
datasource db {
|
|
320
|
-
provider = "${provider}"
|
|
321
|
-
url = ${'sqlite' === provider ? '"file:./dev.db"' : 'env("DATABASE_URL")'}
|
|
322
|
-
}`;
|
|
323
|
-
const adapters = {
|
|
324
|
-
prisma: generatePrismaSchema,
|
|
325
|
-
drizzle: generateDrizzleSchema,
|
|
326
|
-
kysely: generateMigrations
|
|
327
|
-
};
|
|
328
|
-
const getGenerator = (opts)=>{
|
|
329
|
-
const adapter = opts.adapter;
|
|
330
|
-
const generator = adapter.id in adapters ? adapters[adapter.id] : null;
|
|
331
|
-
if (!generator) {
|
|
332
|
-
utils_logger.error(`${adapter.id} is not supported.`);
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
335
|
-
return generator(opts);
|
|
336
|
-
};
|
|
337
|
-
function addSvelteKitEnvModules(aliases) {
|
|
338
|
-
aliases['$env/dynamic/private'] = createDataUriModule(createDynamicEnvModule());
|
|
339
|
-
aliases['$env/dynamic/public'] = createDataUriModule(createDynamicEnvModule());
|
|
340
|
-
aliases['$env/static/private'] = createDataUriModule(createStaticEnvModule(filterPrivateEnv('PUBLIC_', '')));
|
|
341
|
-
aliases['$env/static/public'] = createDataUriModule(createStaticEnvModule(filterPublicEnv('PUBLIC_', '')));
|
|
342
|
-
}
|
|
343
|
-
function createDataUriModule(module) {
|
|
344
|
-
return `data:text/javascript;charset=utf-8,${encodeURIComponent(module)}`;
|
|
345
|
-
}
|
|
346
|
-
function createStaticEnvModule(env) {
|
|
347
|
-
const declarations = Object.keys(env).filter((k)=>validIdentifier.test(k) && !reserved.has(k)).map((k)=>`export const ${k} = ${JSON.stringify(env[k])};`);
|
|
348
|
-
return `
|
|
349
|
-
${declarations.join('\n')}
|
|
350
|
-
// jiti dirty hack: .unknown
|
|
351
|
-
`;
|
|
352
|
-
}
|
|
353
|
-
function createDynamicEnvModule() {
|
|
354
|
-
return `
|
|
355
|
-
export const env = process.env;
|
|
356
|
-
// jiti dirty hack: .unknown
|
|
357
|
-
`;
|
|
358
|
-
}
|
|
359
|
-
function filterPrivateEnv(publicPrefix, privatePrefix) {
|
|
360
|
-
return Object.fromEntries(Object.entries(process.env).filter(([k])=>k.startsWith(privatePrefix) && ('' === publicPrefix || !k.startsWith(publicPrefix))));
|
|
361
|
-
}
|
|
362
|
-
function filterPublicEnv(publicPrefix, privatePrefix) {
|
|
363
|
-
return Object.fromEntries(Object.entries(process.env).filter(([k])=>k.startsWith(publicPrefix) && ('' === privatePrefix || !k.startsWith(privatePrefix))));
|
|
364
|
-
}
|
|
365
|
-
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
366
|
-
const reserved = new Set([
|
|
367
|
-
'do',
|
|
368
|
-
'if',
|
|
369
|
-
'in',
|
|
370
|
-
'for',
|
|
371
|
-
'let',
|
|
372
|
-
'new',
|
|
373
|
-
'try',
|
|
374
|
-
'var',
|
|
375
|
-
'case',
|
|
376
|
-
'else',
|
|
377
|
-
'enum',
|
|
378
|
-
'eval',
|
|
379
|
-
'null',
|
|
380
|
-
'this',
|
|
381
|
-
'true',
|
|
382
|
-
'void',
|
|
383
|
-
'with',
|
|
384
|
-
'await',
|
|
385
|
-
'break',
|
|
386
|
-
'catch',
|
|
387
|
-
'class',
|
|
388
|
-
'const',
|
|
389
|
-
'false',
|
|
390
|
-
'super',
|
|
391
|
-
'throw',
|
|
392
|
-
'while',
|
|
393
|
-
'yield',
|
|
394
|
-
'delete',
|
|
395
|
-
'export',
|
|
396
|
-
'import',
|
|
397
|
-
'public',
|
|
398
|
-
'return',
|
|
399
|
-
'static',
|
|
400
|
-
'switch',
|
|
401
|
-
'typeof',
|
|
402
|
-
'default',
|
|
403
|
-
'extends',
|
|
404
|
-
'finally',
|
|
405
|
-
'package',
|
|
406
|
-
'private',
|
|
407
|
-
'continue',
|
|
408
|
-
'debugger',
|
|
409
|
-
'function',
|
|
410
|
-
'arguments',
|
|
411
|
-
'interface',
|
|
412
|
-
'protected',
|
|
413
|
-
'implements',
|
|
414
|
-
'instanceof'
|
|
415
|
-
]);
|
|
44
|
+
if (isC15TOptions(config.default)) return config.default;
|
|
45
|
+
if ('function' == typeof config.default) {
|
|
46
|
+
const result = tryGetFunctionResult(config.default);
|
|
47
|
+
if (isC15TOptions(result)) return result;
|
|
48
|
+
}
|
|
49
|
+
if (isC15TOptions(config.c15tInstance)) return config.c15tInstance;
|
|
50
|
+
if ('function' == typeof config.c15tInstance) {
|
|
51
|
+
const result = tryGetFunctionResult(config.c15tInstance);
|
|
52
|
+
if (isC15TOptions(result)) return result;
|
|
53
|
+
}
|
|
54
|
+
if (isC15TOptions(config.consent)) return config.consent;
|
|
55
|
+
if ('function' == typeof config.consent) {
|
|
56
|
+
const result = tryGetFunctionResult(config.consent);
|
|
57
|
+
if (isC15TOptions(result)) return result;
|
|
58
|
+
}
|
|
59
|
+
if ('object' == typeof config.c15t && null !== config.c15t && isC15TOptions(config.c15t.options)) return config.c15t.options;
|
|
60
|
+
if ('object' == typeof config.default && null !== config.default && isC15TOptions(config.default.options)) return config.default.options;
|
|
61
|
+
if ('object' == typeof config.c15tInstance && null !== config.c15tInstance && isC15TOptions(config.c15tInstance.options)) return config.c15tInstance.options;
|
|
62
|
+
if ('object' == typeof config.instance && null !== config.instance && isC15TOptions(config.instance.options)) return config.instance.options;
|
|
63
|
+
if ('object' == typeof config.consent && null !== config.consent && isC15TOptions(config.consent.options)) return config.consent.options;
|
|
64
|
+
if ('object' == typeof config.config && null !== config.config && isC15TOptions(config.config.options)) return config.config.options;
|
|
65
|
+
console.debug('No valid configuration found in any of the expected locations');
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
416
68
|
const configFileNames = [
|
|
69
|
+
'c15t.config',
|
|
70
|
+
'c15t.backend',
|
|
417
71
|
'c15t',
|
|
72
|
+
'c15t.client',
|
|
73
|
+
'consent.config',
|
|
74
|
+
'consent.backend',
|
|
418
75
|
'consent',
|
|
76
|
+
'cmp.config',
|
|
77
|
+
'cmp.backend',
|
|
419
78
|
'cmp'
|
|
420
79
|
];
|
|
421
|
-
const
|
|
80
|
+
const constants_extensions = [
|
|
422
81
|
'.js',
|
|
423
82
|
'.jsx',
|
|
424
83
|
'.ts',
|
|
@@ -436,7 +95,7 @@ const extensions = [
|
|
|
436
95
|
'.server.ts',
|
|
437
96
|
'.server.tsx'
|
|
438
97
|
];
|
|
439
|
-
let possiblePaths = configFileNames.flatMap((name)=>
|
|
98
|
+
let possiblePaths = configFileNames.flatMap((name)=>constants_extensions.map((ext)=>`${name}${ext}`));
|
|
440
99
|
const directories = [
|
|
441
100
|
'',
|
|
442
101
|
'lib/server/',
|
|
@@ -448,65 +107,9 @@ const directories = [
|
|
|
448
107
|
'app/'
|
|
449
108
|
];
|
|
450
109
|
possiblePaths = directories.flatMap((dir)=>possiblePaths.map((file)=>`${dir}${file}`));
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
'apps/*'
|
|
454
|
-
];
|
|
455
|
-
function stripJsonComments(jsonString) {
|
|
456
|
-
return jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g)=>g ? '' : m).replace(/,(?=\s*[}\]])/g, '');
|
|
457
|
-
}
|
|
458
|
-
function getPathAliases(cwd) {
|
|
459
|
-
const tsConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'tsconfig.json');
|
|
460
|
-
if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(tsConfigPath)) {
|
|
461
|
-
const jsConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'jsconfig.json');
|
|
462
|
-
if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(jsConfigPath)) return null;
|
|
463
|
-
return extractAliasesFromConfigFile(jsConfigPath, cwd);
|
|
464
|
-
}
|
|
465
|
-
return extractAliasesFromConfigFile(tsConfigPath, cwd);
|
|
466
|
-
}
|
|
467
|
-
function extractAliasesFromConfigFile(configPath, cwd) {
|
|
468
|
-
try {
|
|
469
|
-
const configContent = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(configPath, 'utf8');
|
|
470
|
-
const strippedConfigContent = stripJsonComments(configContent);
|
|
471
|
-
const config = JSON.parse(strippedConfigContent);
|
|
472
|
-
const { paths = {}, baseUrl = '.' } = config.compilerOptions || {};
|
|
473
|
-
const result = {};
|
|
474
|
-
const obj = Object.entries(paths);
|
|
475
|
-
for (const [alias, aliasPaths] of obj)for (const aliasedPath of aliasPaths){
|
|
476
|
-
const resolvedBaseUrl = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, baseUrl);
|
|
477
|
-
const finalAlias = '*' === alias.slice(-1) ? alias.slice(0, -1) : alias;
|
|
478
|
-
const finalAliasedPath = '*' === aliasedPath.slice(-1) ? aliasedPath.slice(0, -1) : aliasedPath;
|
|
479
|
-
result[finalAlias || ''] = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(resolvedBaseUrl, finalAliasedPath);
|
|
480
|
-
}
|
|
481
|
-
addSvelteKitEnvModules(result);
|
|
482
|
-
return result;
|
|
483
|
-
} catch (error) {
|
|
484
|
-
utils_logger.warn(`Error parsing config file ${configPath}`, error);
|
|
485
|
-
return null;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
const jitiOptions = (cwd)=>{
|
|
489
|
-
const alias = getPathAliases(cwd) || {};
|
|
110
|
+
const jitiOptions = (context, cwd)=>{
|
|
111
|
+
const alias = context.config.getPathAliases(cwd) || {};
|
|
490
112
|
return {
|
|
491
|
-
transformOptions: {
|
|
492
|
-
babel: {
|
|
493
|
-
presets: [
|
|
494
|
-
[
|
|
495
|
-
__WEBPACK_EXTERNAL_MODULE__babel_preset_typescript_a7789c85__["default"],
|
|
496
|
-
{
|
|
497
|
-
isTSX: true,
|
|
498
|
-
allExtensions: true
|
|
499
|
-
}
|
|
500
|
-
],
|
|
501
|
-
[
|
|
502
|
-
__WEBPACK_EXTERNAL_MODULE__babel_preset_react_76cf724d__["default"],
|
|
503
|
-
{
|
|
504
|
-
runtime: 'automatic'
|
|
505
|
-
}
|
|
506
|
-
]
|
|
507
|
-
]
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
113
|
extensions: [
|
|
511
114
|
'.ts',
|
|
512
115
|
'.tsx',
|
|
@@ -520,332 +123,1866 @@ const jitiOptions = (cwd)=>{
|
|
|
520
123
|
alias
|
|
521
124
|
};
|
|
522
125
|
};
|
|
523
|
-
function
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
126
|
+
async function getConfig(contextOrOptions) {
|
|
127
|
+
const context = 'logger' in contextOrOptions ? contextOrOptions : {
|
|
128
|
+
...contextOrOptions,
|
|
129
|
+
logger: {
|
|
130
|
+
debug: console.debug,
|
|
131
|
+
info: console.info,
|
|
132
|
+
warn: console.warn,
|
|
133
|
+
error: console.error
|
|
134
|
+
},
|
|
135
|
+
flags: {
|
|
136
|
+
config: contextOrOptions.configPath
|
|
137
|
+
},
|
|
138
|
+
error: {
|
|
139
|
+
handleError: (error)=>{
|
|
140
|
+
console.error('Error loading configuration:', error);
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const { cwd, logger, flags } = context;
|
|
146
|
+
const configPath = flags.config;
|
|
147
|
+
let foundConfigPath = null;
|
|
148
|
+
try {
|
|
149
|
+
let options = null;
|
|
150
|
+
const customJitiOptions = jitiOptions(context, cwd);
|
|
151
|
+
if (configPath) {
|
|
152
|
+
foundConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(cwd, configPath);
|
|
153
|
+
logger.debug(`Using explicitly provided config path: ${foundConfigPath}`);
|
|
154
|
+
} else {
|
|
155
|
+
const prioritizedDirs = [
|
|
156
|
+
cwd,
|
|
157
|
+
__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'packages/cli')
|
|
158
|
+
];
|
|
159
|
+
const primaryName = 'c15t.config';
|
|
160
|
+
const extensions = [
|
|
161
|
+
'.ts',
|
|
162
|
+
'.js',
|
|
163
|
+
'.mjs'
|
|
164
|
+
];
|
|
165
|
+
for (const dir of prioritizedDirs){
|
|
166
|
+
for (const ext of extensions){
|
|
167
|
+
const checkPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(dir, `${primaryName}${ext}`);
|
|
168
|
+
try {
|
|
169
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(checkPath);
|
|
170
|
+
foundConfigPath = checkPath;
|
|
171
|
+
logger.debug(`Found config via manual check: ${foundConfigPath}`);
|
|
172
|
+
break;
|
|
173
|
+
} catch {}
|
|
174
|
+
}
|
|
175
|
+
if (foundConfigPath) break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (foundConfigPath) try {
|
|
179
|
+
logger.debug(`Loading configuration from resolved path: ${foundConfigPath}`);
|
|
180
|
+
const result = await (0, __WEBPACK_EXTERNAL_MODULE_c12__.loadConfig)({
|
|
181
|
+
configFile: foundConfigPath,
|
|
182
|
+
jitiOptions: customJitiOptions
|
|
183
|
+
});
|
|
184
|
+
logger.debug('Raw config loading result:', result);
|
|
185
|
+
if (result.config) {
|
|
186
|
+
logger.debug('Trying to extract config from result.config');
|
|
187
|
+
options = extractOptionsFromConfig(result.config);
|
|
188
|
+
}
|
|
189
|
+
if (options) {
|
|
190
|
+
logger.debug('Extracted config:', options);
|
|
191
|
+
if (isC15TOptions(options) || isClientOptions(options)) {
|
|
192
|
+
logger.debug('Configuration validated successfully.');
|
|
193
|
+
return options;
|
|
194
|
+
}
|
|
195
|
+
logger.debug('Loaded config does not match expected schema');
|
|
196
|
+
} else logger.debug('No configuration extracted from loaded file');
|
|
197
|
+
logger.debug('Raw loaded configuration:', result);
|
|
198
|
+
return null;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
logger.debug('Error loading config from explicit path:', error);
|
|
536
201
|
try {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
202
|
+
logger.debug(`Trying to require module directly: ${foundConfigPath}`);
|
|
203
|
+
const importedModule = await import(foundConfigPath);
|
|
204
|
+
logger.debug('Directly imported module:', importedModule);
|
|
205
|
+
const extracted = extractOptionsFromConfig(importedModule);
|
|
206
|
+
if (extracted && (isC15TOptions(extracted) || isClientOptions(extracted))) {
|
|
207
|
+
logger.debug('Found valid config through direct import');
|
|
208
|
+
return extracted;
|
|
542
209
|
}
|
|
543
|
-
} catch
|
|
210
|
+
} catch (importError) {
|
|
211
|
+
logger.debug('Error importing module directly:', importError);
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
544
214
|
}
|
|
545
|
-
|
|
546
|
-
|
|
215
|
+
return options;
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if ('error' in context && context.error && 'function' == typeof context.error.handleError) return context.error.handleError(error, 'Error loading configuration');
|
|
218
|
+
console.error('Error loading configuration:', error);
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
547
221
|
}
|
|
548
|
-
function
|
|
549
|
-
|
|
550
|
-
|
|
222
|
+
function showHelpMenu(context, version, commands, flags) {
|
|
223
|
+
const { logger } = context;
|
|
224
|
+
logger.debug('Displaying help menu using command and flag structures.');
|
|
225
|
+
const commandLines = commands.map((cmd)=>` ${cmd.name.padEnd(10)} ${cmd.description}`).join('\n');
|
|
226
|
+
const optionLines = flags.map((flag)=>{
|
|
227
|
+
const names = flag.names.join(', ');
|
|
228
|
+
const valuePlaceholder = flag.expectsValue ? ' <value>' : '';
|
|
229
|
+
return ` ${(names + valuePlaceholder).padEnd(20)} ${flag.description}`;
|
|
230
|
+
}).join('\n');
|
|
231
|
+
const helpContent = `c15t CLI version ${version}
|
|
232
|
+
|
|
233
|
+
Available Commands:
|
|
234
|
+
${commandLines}
|
|
235
|
+
|
|
236
|
+
Options:
|
|
237
|
+
${optionLines}
|
|
238
|
+
|
|
239
|
+
Run a command directly (e.g., ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('c15t generate')}) or select one interactively when no command is provided.
|
|
240
|
+
|
|
241
|
+
For more help, visit: https://c15t.dev`;
|
|
242
|
+
logger.debug('Help menu content generated.');
|
|
243
|
+
logger.note(helpContent, 'Usage');
|
|
551
244
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
245
|
+
const validLogLevels = [
|
|
246
|
+
'error',
|
|
247
|
+
'warn',
|
|
248
|
+
'info',
|
|
249
|
+
'debug'
|
|
250
|
+
];
|
|
251
|
+
const formatArgs = (args)=>{
|
|
252
|
+
if (0 === args.length) return '';
|
|
253
|
+
return `\n${args.map((arg)=>` - ${JSON.stringify(arg, null, 2)}`).join('\n')}`;
|
|
254
|
+
};
|
|
255
|
+
const formatLogMessage = (logLevel, message, args = [])=>{
|
|
256
|
+
const messageStr = 'string' == typeof message ? message : String(message);
|
|
257
|
+
const formattedArgs = formatArgs(args);
|
|
258
|
+
switch(logLevel){
|
|
259
|
+
case 'error':
|
|
260
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgRed(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].black(' error '))} ${messageStr}${formattedArgs}`;
|
|
261
|
+
case 'warn':
|
|
262
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgYellow(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].black(' warning '))} ${messageStr}${formattedArgs}`;
|
|
263
|
+
case 'info':
|
|
264
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgGreen(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].black(' info '))} ${messageStr}${formattedArgs}`;
|
|
265
|
+
case 'debug':
|
|
266
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgBlack(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].white(' debug '))} ${messageStr}${formattedArgs}`;
|
|
267
|
+
case 'success':
|
|
268
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgGreen(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].white(' success '))} ${messageStr}${formattedArgs}`;
|
|
269
|
+
case 'failed':
|
|
270
|
+
return `${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bgRed(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].white(' failed '))} ${messageStr}${formattedArgs}`;
|
|
271
|
+
default:
|
|
272
|
+
{
|
|
273
|
+
const levelStr = logLevel;
|
|
274
|
+
return `[${levelStr.toUpperCase()}] ${messageStr}${formattedArgs}`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const logMessage = (logLevel, message, ...args)=>{
|
|
279
|
+
const formattedMessage = formatLogMessage(logLevel, message, args);
|
|
280
|
+
switch(logLevel){
|
|
281
|
+
case 'error':
|
|
282
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.error(formattedMessage);
|
|
283
|
+
break;
|
|
284
|
+
case 'warn':
|
|
285
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.warn(formattedMessage);
|
|
286
|
+
break;
|
|
287
|
+
case 'info':
|
|
288
|
+
case 'debug':
|
|
289
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.info(formattedMessage);
|
|
290
|
+
break;
|
|
291
|
+
case 'success':
|
|
292
|
+
case 'failed':
|
|
293
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.outro(formattedMessage);
|
|
294
|
+
break;
|
|
295
|
+
default:
|
|
296
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.message(formattedMessage);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
const createCliLogger = (level)=>{
|
|
300
|
+
const baseLogger = (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_logger_44a195c6__.createLogger)({
|
|
301
|
+
level,
|
|
302
|
+
appName: 'c15t',
|
|
303
|
+
log: (logLevel, message, ...args)=>{
|
|
304
|
+
logMessage(logLevel, message, ...args);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
const extendedLogger = baseLogger;
|
|
308
|
+
extendedLogger.message = (message)=>{
|
|
309
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.message(message);
|
|
310
|
+
};
|
|
311
|
+
extendedLogger.note = (message, ...args)=>{
|
|
312
|
+
const messageStr = 'string' == typeof message ? message : String(message);
|
|
313
|
+
const title = args.length > 0 && 'string' == typeof args[0] ? args[0] : void 0;
|
|
314
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.note(messageStr, title, {
|
|
315
|
+
format: (line)=>line
|
|
316
|
+
});
|
|
317
|
+
};
|
|
318
|
+
extendedLogger.success = (message, ...args)=>{
|
|
319
|
+
logMessage('success', message, ...args);
|
|
320
|
+
};
|
|
321
|
+
extendedLogger.failed = (message, ...args)=>{
|
|
322
|
+
logMessage('failed', message, ...args);
|
|
323
|
+
};
|
|
324
|
+
extendedLogger.outro = (message)=>{
|
|
325
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.outro(message);
|
|
326
|
+
};
|
|
327
|
+
return extendedLogger;
|
|
328
|
+
};
|
|
329
|
+
const TELEMETRY_DISABLED_ENV = 'C15T_TELEMETRY_DISABLED';
|
|
330
|
+
var telemetry_TelemetryEventName = /*#__PURE__*/ function(TelemetryEventName) {
|
|
331
|
+
TelemetryEventName["CLI_INVOKED"] = "cli.invoked";
|
|
332
|
+
TelemetryEventName["CLI_COMPLETED"] = "cli.completed";
|
|
333
|
+
TelemetryEventName["CLI_EXITED"] = "cli.exited";
|
|
334
|
+
TelemetryEventName["CLI_ENVIRONMENT_DETECTED"] = "cli.environment_detected";
|
|
335
|
+
TelemetryEventName["COMMAND_EXECUTED"] = "command.executed";
|
|
336
|
+
TelemetryEventName["COMMAND_SUCCEEDED"] = "command.succeeded";
|
|
337
|
+
TelemetryEventName["COMMAND_FAILED"] = "command.failed";
|
|
338
|
+
TelemetryEventName["COMMAND_UNKNOWN"] = "command.unknown";
|
|
339
|
+
TelemetryEventName["INTERACTIVE_MENU_OPENED"] = "ui.menu.opened";
|
|
340
|
+
TelemetryEventName["INTERACTIVE_MENU_EXITED"] = "ui.menu.exited";
|
|
341
|
+
TelemetryEventName["CONFIG_LOADED"] = "config.loaded";
|
|
342
|
+
TelemetryEventName["CONFIG_ERROR"] = "config.error";
|
|
343
|
+
TelemetryEventName["CONFIG_UPDATED"] = "config.updated";
|
|
344
|
+
TelemetryEventName["HELP_DISPLAYED"] = "help.displayed";
|
|
345
|
+
TelemetryEventName["VERSION_DISPLAYED"] = "version.displayed";
|
|
346
|
+
TelemetryEventName["ONBOARDING_STARTED"] = "onboarding.started";
|
|
347
|
+
TelemetryEventName["ONBOARDING_COMPLETED"] = "onboarding.completed";
|
|
348
|
+
TelemetryEventName["ONBOARDING_EXITED"] = "onboarding.exited";
|
|
349
|
+
TelemetryEventName["ONBOARDING_STORAGE_MODE_SELECTED"] = "onboarding.storage_mode_selected";
|
|
350
|
+
TelemetryEventName["ONBOARDING_C15T_MODE_CONFIGURED"] = "onboarding.c15t_mode_configured";
|
|
351
|
+
TelemetryEventName["ONBOARDING_OFFLINE_MODE_CONFIGURED"] = "onboarding.offline_mode_configured";
|
|
352
|
+
TelemetryEventName["ONBOARDING_SELF_HOSTED_CONFIGURED"] = "onboarding.self_hosted_configured";
|
|
353
|
+
TelemetryEventName["ONBOARDING_CUSTOM_MODE_CONFIGURED"] = "onboarding.custom_mode_configured";
|
|
354
|
+
TelemetryEventName["ONBOARDING_DEPENDENCIES_CHOICE"] = "onboarding.dependencies_choice";
|
|
355
|
+
TelemetryEventName["ONBOARDING_DEPENDENCIES_INSTALLED"] = "onboarding.dependencies_installed";
|
|
356
|
+
TelemetryEventName["ONBOARDING_GITHUB_STAR"] = "onboarding.github_star";
|
|
357
|
+
TelemetryEventName["ERROR_OCCURRED"] = "error.occurred";
|
|
358
|
+
TelemetryEventName["MIGRATION_STARTED"] = "migration.started";
|
|
359
|
+
TelemetryEventName["MIGRATION_PLANNED"] = "migration.planned";
|
|
360
|
+
TelemetryEventName["MIGRATION_EXECUTED"] = "migration.executed";
|
|
361
|
+
TelemetryEventName["MIGRATION_COMPLETED"] = "migration.completed";
|
|
362
|
+
TelemetryEventName["MIGRATION_FAILED"] = "migration.failed";
|
|
363
|
+
TelemetryEventName["GENERATE_STARTED"] = "generate.started";
|
|
364
|
+
TelemetryEventName["GENERATE_COMPLETED"] = "generate.completed";
|
|
365
|
+
TelemetryEventName["GENERATE_FAILED"] = "generate.failed";
|
|
366
|
+
return TelemetryEventName;
|
|
367
|
+
}({});
|
|
368
|
+
class Telemetry {
|
|
369
|
+
client = null;
|
|
370
|
+
disabled;
|
|
371
|
+
defaultProperties;
|
|
372
|
+
distinctId;
|
|
373
|
+
apiKey = '';
|
|
374
|
+
constructor(options){
|
|
375
|
+
const envDisabled = '1' === process.env[TELEMETRY_DISABLED_ENV] || process.env[TELEMETRY_DISABLED_ENV]?.toLowerCase() === 'true';
|
|
376
|
+
const hasValidApiKey = !!(this.apiKey && '' !== this.apiKey.trim());
|
|
377
|
+
this.disabled = options?.disabled ?? envDisabled ?? !hasValidApiKey;
|
|
378
|
+
this.defaultProperties = options?.defaultProperties ?? {};
|
|
379
|
+
this.distinctId = this.generateAnonymousId();
|
|
380
|
+
if (this.disabled) {
|
|
381
|
+
if (!hasValidApiKey) console.debug('Telemetry disabled: No API key provided');
|
|
382
|
+
} else this.initClient(options?.client);
|
|
383
|
+
}
|
|
384
|
+
trackEvent(eventName, properties = {}) {
|
|
385
|
+
if (this.disabled || !this.client) return;
|
|
386
|
+
const safeProperties = {};
|
|
387
|
+
for (const [key, value] of Object.entries(properties))if ('config' !== key && void 0 !== value) safeProperties[key] = value;
|
|
388
|
+
this.client.capture({
|
|
389
|
+
distinctId: this.distinctId,
|
|
390
|
+
event: eventName,
|
|
391
|
+
properties: {
|
|
392
|
+
...this.defaultProperties,
|
|
393
|
+
...safeProperties,
|
|
394
|
+
timestamp: new Date().toISOString()
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
trackCommand(command, args = [], flags = {}) {
|
|
399
|
+
if (this.disabled || !this.client) return;
|
|
400
|
+
const safeFlags = {};
|
|
401
|
+
for (const [key, value] of Object.entries(flags))if ('config' !== key && void 0 !== value) safeFlags[key] = value;
|
|
402
|
+
this.trackEvent("command.executed", {
|
|
403
|
+
command,
|
|
404
|
+
args: args.join(' '),
|
|
405
|
+
flagsData: JSON.stringify(safeFlags)
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
trackError(error, command) {
|
|
409
|
+
if (this.disabled || !this.client) return;
|
|
410
|
+
this.trackEvent("error.occurred", {
|
|
411
|
+
command,
|
|
412
|
+
error: error.message,
|
|
413
|
+
errorName: error.name,
|
|
414
|
+
stack: 'development' === process.env.NODE_ENV ? error.stack : void 0
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
setLogLevel(level) {
|
|
418
|
+
if (this.client && 'debug' === level) this.client.debug(true);
|
|
419
|
+
}
|
|
420
|
+
disable() {
|
|
421
|
+
this.disabled = true;
|
|
422
|
+
}
|
|
423
|
+
enable() {
|
|
424
|
+
this.disabled = false;
|
|
425
|
+
if (!this.client) this.initClient();
|
|
426
|
+
}
|
|
427
|
+
isDisabled() {
|
|
428
|
+
return this.disabled;
|
|
429
|
+
}
|
|
430
|
+
async shutdown() {
|
|
431
|
+
if (this.client) {
|
|
432
|
+
await this.client.shutdown();
|
|
433
|
+
this.client = null;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
initClient(customClient) {
|
|
437
|
+
if (customClient) this.client = customClient;
|
|
438
|
+
else {
|
|
439
|
+
if (!this.apiKey || '' === this.apiKey.trim()) {
|
|
440
|
+
this.disabled = true;
|
|
441
|
+
console.debug('Telemetry disabled: No API key provided');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
559
444
|
try {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
category: 'CONFIG_FILE_NOT_FOUND'
|
|
445
|
+
this.client = new __WEBPACK_EXTERNAL_MODULE_posthog_node_1b07bdf4__.PostHog(this.apiKey, {
|
|
446
|
+
host: 'https://eu.i.posthog.com',
|
|
447
|
+
flushInterval: 0
|
|
564
448
|
});
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
dotenv: true,
|
|
569
|
-
jitiOptions: jitiOptions(cwd)
|
|
570
|
-
});
|
|
571
|
-
configFile = extractOptionsFromConfig(config);
|
|
572
|
-
if (!configFile) throw new __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_results_3ca2b89f__.DoubleTieError(`Found config file at ${resolvedPath} but couldn't extract c15t options.\nMake sure you're exporting c15t with one of these patterns:\n- export const c15t = c15tInstance({...})\n- export const consent = c15tInstance({...})\n- export const c15tInstance = c15tInstance({...})\n- export default c15tInstance({...})`, {
|
|
573
|
-
code: 'CONFIG_FILE_LOAD_ERROR',
|
|
574
|
-
status: 500,
|
|
575
|
-
category: 'CONFIG_FILE_LOAD_ERROR'
|
|
576
|
-
});
|
|
577
|
-
} catch (e) {
|
|
578
|
-
if (__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(resolvedPath)) {
|
|
579
|
-
failedImports.push(resolvedPath);
|
|
580
|
-
if (e instanceof __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_results_3ca2b89f__.DoubleTieError) throw e;
|
|
581
|
-
throw new __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_results_3ca2b89f__.DoubleTieError(`Config file found at ${resolvedPath} but failed to load.\nThis usually happens because of import problems:\n- Check for invalid import paths\n- Ensure all dependencies are installed\n- Verify path aliases in tsconfig.json\n\nError details: ${e instanceof Error ? e.message : String(e)}`, {
|
|
582
|
-
code: 'CONFIG_FILE_LOAD_ERROR',
|
|
583
|
-
status: 500,
|
|
584
|
-
category: 'CONFIG_FILE_LOAD_ERROR',
|
|
585
|
-
cause: e instanceof Error ? e : new Error(String(e))
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
throw e;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
this.disabled = true;
|
|
451
|
+
console.debug('Telemetry disabled due to initialization error:', error);
|
|
589
452
|
}
|
|
590
453
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
454
|
+
}
|
|
455
|
+
generateAnonymousId() {
|
|
456
|
+
const machineId = __WEBPACK_EXTERNAL_MODULE_node_crypto_9ba42079__["default"].createHash('sha256').update(__WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__["default"].hostname() + __WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__["default"].platform() + __WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__["default"].arch() + __WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__["default"].totalmem()).digest('hex');
|
|
457
|
+
return machineId;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function createTelemetry(options) {
|
|
461
|
+
return new Telemetry(options);
|
|
462
|
+
}
|
|
463
|
+
async function addAndInstallDependenciesViaPM(projectRoot, dependencies, packageManager) {
|
|
464
|
+
const depsToAdd = dependencies.map((dep)=>`${dep}`);
|
|
465
|
+
if (0 === depsToAdd.length) return;
|
|
466
|
+
let command = '';
|
|
467
|
+
let args = [];
|
|
468
|
+
switch(packageManager){
|
|
469
|
+
case 'npm':
|
|
470
|
+
command = 'npm';
|
|
471
|
+
args = [
|
|
472
|
+
'install',
|
|
473
|
+
...depsToAdd
|
|
594
474
|
];
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
475
|
+
break;
|
|
476
|
+
case 'yarn':
|
|
477
|
+
command = 'yarn';
|
|
478
|
+
args = [
|
|
479
|
+
'add',
|
|
480
|
+
...depsToAdd
|
|
481
|
+
];
|
|
482
|
+
break;
|
|
483
|
+
case 'pnpm':
|
|
484
|
+
command = 'pnpm';
|
|
485
|
+
args = [
|
|
486
|
+
'add',
|
|
487
|
+
...depsToAdd
|
|
488
|
+
];
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
throw new Error(`Unsupported package manager for dependency addition: ${packageManager}`);
|
|
492
|
+
}
|
|
493
|
+
const child = (0, __WEBPACK_EXTERNAL_MODULE_node_child_process_27f17141__.spawn)(command, args, {
|
|
494
|
+
cwd: projectRoot,
|
|
495
|
+
stdio: 'inherit'
|
|
496
|
+
});
|
|
497
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_node_events_0a6aefe7__.once)(child, 'exit');
|
|
498
|
+
}
|
|
499
|
+
function getManualInstallCommand(dependencies, packageManager) {
|
|
500
|
+
const depsToAdd = dependencies.map((dep)=>`${dep}`);
|
|
501
|
+
switch(packageManager){
|
|
502
|
+
case 'npm':
|
|
503
|
+
return `npm install ${depsToAdd.join(' ')}`;
|
|
504
|
+
case 'yarn':
|
|
505
|
+
return `yarn add ${depsToAdd.join(' ')}`;
|
|
506
|
+
case 'pnpm':
|
|
507
|
+
return `pnpm add ${depsToAdd.join(' ')}`;
|
|
508
|
+
default:
|
|
509
|
+
return `npm install ${depsToAdd.join(' ')}`;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
async function detectFramework(projectRoot) {
|
|
513
|
+
try {
|
|
514
|
+
const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'package.json');
|
|
515
|
+
const packageJson = JSON.parse(await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(packageJsonPath, 'utf-8'));
|
|
516
|
+
const deps = {
|
|
517
|
+
...packageJson.dependencies,
|
|
518
|
+
...packageJson.devDependencies
|
|
519
|
+
};
|
|
520
|
+
const hasReact = 'react' in deps;
|
|
521
|
+
let framework = null;
|
|
522
|
+
if ('next' in deps) framework = 'Next.js';
|
|
523
|
+
else if ('@remix-run/react' in deps) framework = 'Remix';
|
|
524
|
+
else if ('@vitejs/plugin-react' in deps || '@vitejs/plugin-react-swc' in deps) framework = 'Vite + React';
|
|
525
|
+
else if ('gatsby' in deps) framework = 'Gatsby';
|
|
526
|
+
else if (hasReact) framework = 'React';
|
|
527
|
+
return {
|
|
528
|
+
framework,
|
|
529
|
+
hasReact
|
|
530
|
+
};
|
|
531
|
+
} catch (error) {
|
|
532
|
+
return {
|
|
533
|
+
framework: null,
|
|
534
|
+
hasReact: false
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async function detectProjectRoot(cwd) {
|
|
539
|
+
let projectRoot = cwd;
|
|
540
|
+
try {
|
|
541
|
+
let prevDir = '';
|
|
542
|
+
while(projectRoot !== prevDir)try {
|
|
543
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'package.json'));
|
|
544
|
+
break;
|
|
545
|
+
} catch {
|
|
546
|
+
prevDir = projectRoot;
|
|
547
|
+
projectRoot = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].dirname(projectRoot);
|
|
626
548
|
}
|
|
627
|
-
if (
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
549
|
+
if (projectRoot === prevDir) throw new Error('Could not find project root (no package.json found)');
|
|
550
|
+
return projectRoot;
|
|
551
|
+
} catch {
|
|
552
|
+
return cwd;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
async function detectPackageManager(projectRoot) {
|
|
556
|
+
try {
|
|
557
|
+
const result = await (0, __WEBPACK_EXTERNAL_MODULE_package_manager_detector_detect_94d6a9ae__.detect)({
|
|
558
|
+
cwd: projectRoot
|
|
559
|
+
});
|
|
560
|
+
let detectedPm = null;
|
|
561
|
+
if ('string' == typeof result) detectedPm = result;
|
|
562
|
+
else if (result && 'object' == typeof result) {
|
|
563
|
+
if ('name' in result && 'string' == typeof result.name) detectedPm = result.name;
|
|
564
|
+
else if ('pm' in result && 'string' == typeof result.pm) detectedPm = result.pm;
|
|
565
|
+
}
|
|
566
|
+
if (detectedPm && ('npm' === detectedPm || 'yarn' === detectedPm || 'pnpm' === detectedPm)) return detectedPm;
|
|
567
|
+
let detectedValueStr = String(result);
|
|
568
|
+
if (result && 'object' == typeof result) detectedValueStr = JSON.stringify(result);
|
|
569
|
+
throw new Error(`Could not reliably detect package manager (detected: ${detectedValueStr}).`);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.warn(`Automatic package manager detection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
572
|
+
const selectedPackageManager = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.select({
|
|
573
|
+
message: 'Please select your package manager:',
|
|
574
|
+
options: [
|
|
575
|
+
{
|
|
576
|
+
value: 'npm',
|
|
577
|
+
label: 'npm'
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
value: 'yarn',
|
|
581
|
+
label: 'yarn'
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
value: 'pnpm',
|
|
585
|
+
label: 'pnpm'
|
|
638
586
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
587
|
+
],
|
|
588
|
+
initialValue: 'npm'
|
|
589
|
+
});
|
|
590
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(selectedPackageManager)) {
|
|
591
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.warn('Package manager selection cancelled. Exiting.');
|
|
592
|
+
process.exit(0);
|
|
593
|
+
}
|
|
594
|
+
return selectedPackageManager;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
function generateClientConfigContent(mode, backendURL, useEnvFile) {
|
|
598
|
+
let configContent = '';
|
|
599
|
+
const validModes = [
|
|
600
|
+
'c15t',
|
|
601
|
+
'offline',
|
|
602
|
+
'custom'
|
|
603
|
+
];
|
|
604
|
+
if (!validModes.includes(mode)) throw new Error(`Invalid mode: ${mode}. Valid modes are: ${validModes.join(', ')}`);
|
|
605
|
+
switch(mode){
|
|
606
|
+
case 'c15t':
|
|
607
|
+
configContent = `// c15t Client Configuration
|
|
608
|
+
import type { ConsentManagerOptions } from '@c15t/react';
|
|
609
|
+
|
|
610
|
+
export const c15tConfig = {
|
|
611
|
+
// Using hosted c15t (consent.io) or self-hosted instance
|
|
612
|
+
mode: 'c15t',
|
|
613
|
+
backendURL: ${useEnvFile ? 'process.env.NEXT_PUBLIC_C15T_URL' : `'${backendURL || 'https://your-instance.c15t.dev'}'`},
|
|
614
|
+
|
|
615
|
+
// Optional: Add callback functions for various events
|
|
616
|
+
callbacks: {
|
|
617
|
+
onConsentSet: (response) => {
|
|
618
|
+
console.log('Consent has been saved');
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
} satisfies ConsentManagerOptions;
|
|
622
|
+
|
|
623
|
+
// Use in your app layout:
|
|
624
|
+
// <ConsentManagerProvider options={c15tConfig}>
|
|
625
|
+
// {children}
|
|
626
|
+
// <CookieBanner />
|
|
627
|
+
// <ConsentManagerDialog />
|
|
628
|
+
// </ConsentManagerProvider>
|
|
629
|
+
`;
|
|
630
|
+
break;
|
|
631
|
+
case 'offline':
|
|
632
|
+
configContent = `// c15t Client Configuration
|
|
633
|
+
import type { ConsentManagerOptions } from '@c15t/react';
|
|
634
|
+
|
|
635
|
+
export const c15tConfig = {
|
|
636
|
+
// Using offline mode for browser-based storage
|
|
637
|
+
mode: 'offline',
|
|
638
|
+
|
|
639
|
+
// Optional: Add callback functions for various events
|
|
640
|
+
callbacks: {
|
|
641
|
+
onConsentSet: (response) => {
|
|
642
|
+
console.log('Consent has been saved locally');
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
} satisfies ConsentManagerOptions;
|
|
646
|
+
|
|
647
|
+
// Use in your app layout:
|
|
648
|
+
// <ConsentManagerProvider options={c15tConfig}>
|
|
649
|
+
// {children}
|
|
650
|
+
// <CookieBanner />
|
|
651
|
+
// <ConsentManagerDialog />
|
|
652
|
+
// </ConsentManagerProvider>
|
|
653
|
+
`;
|
|
654
|
+
break;
|
|
655
|
+
case 'custom':
|
|
656
|
+
configContent = `// c15t Client Configuration
|
|
657
|
+
import type { ConsentManagerOptions } from '@c15t/react';
|
|
658
|
+
import { createCustomHandlers } from './consent-handlers';
|
|
659
|
+
|
|
660
|
+
export const c15tConfig = {
|
|
661
|
+
// Using custom mode for complete control
|
|
662
|
+
mode: 'custom',
|
|
663
|
+
endpointHandlers: createCustomHandlers(),
|
|
664
|
+
|
|
665
|
+
// Optional: Add callback functions for various events
|
|
666
|
+
callbacks: {
|
|
667
|
+
onConsentSet: (response) => {
|
|
668
|
+
console.log('Consent has been saved');
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
} satisfies ConsentManagerOptions;
|
|
672
|
+
|
|
673
|
+
// Use in your app layout:
|
|
674
|
+
// <ConsentManagerProvider options={c15tConfig}>
|
|
675
|
+
// {children}
|
|
676
|
+
// <CookieBanner />
|
|
677
|
+
// <ConsentManagerDialog />
|
|
678
|
+
// </ConsentManagerProvider>
|
|
679
|
+
|
|
680
|
+
// Don't forget to implement your custom handlers in consent-handlers.ts!
|
|
681
|
+
`;
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
return configContent;
|
|
685
|
+
}
|
|
686
|
+
function generateBackendConfigContent(adapterChoice, connectionString, filePath) {
|
|
687
|
+
let adapterImport = '';
|
|
688
|
+
let adapterConfig = '';
|
|
689
|
+
switch(adapterChoice){
|
|
690
|
+
case 'kysely-postgres':
|
|
691
|
+
adapterImport = `import { kyselyAdapter } from '@c15t/backend/db/adapters/kysely';\nimport { PostgresDialect } from 'kysely';\nimport { Pool } from 'pg';`;
|
|
692
|
+
adapterConfig = `kyselyAdapter({
|
|
693
|
+
dialect: new PostgresDialect({
|
|
694
|
+
pool: new Pool({
|
|
695
|
+
connectionString: ${connectionString ? `"${connectionString}"` : 'process.env.DATABASE_URL || "postgresql://user:password@host:port/db"'}
|
|
696
|
+
})
|
|
697
|
+
})
|
|
698
|
+
})`;
|
|
699
|
+
break;
|
|
700
|
+
case 'kysely-sqlite':
|
|
701
|
+
adapterImport = `import { kyselyAdapter } from '@c15t/backend/db/adapters/kysely';\nimport { SqliteDialect } from 'kysely';\nimport Database from 'better-sqlite3';`;
|
|
702
|
+
adapterConfig = `kyselyAdapter({
|
|
703
|
+
dialect: new SqliteDialect({
|
|
704
|
+
database: new Database("${filePath || './db.sqlite'}")
|
|
705
|
+
})
|
|
706
|
+
})`;
|
|
707
|
+
break;
|
|
708
|
+
default:
|
|
709
|
+
adapterImport = "import { memoryAdapter } from '@c15t/backend/db/adapters/memory';";
|
|
710
|
+
adapterConfig = 'memoryAdapter({})';
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
return `// c15t Backend Configuration
|
|
714
|
+
// Generated by c15t CLI onboarding
|
|
715
|
+
|
|
648
716
|
import { c15tInstance } from '@c15t/backend';
|
|
717
|
+
${adapterImport}
|
|
718
|
+
|
|
719
|
+
// WARNING: Database connection strings often contain sensitive credentials.
|
|
720
|
+
// Consider using environment variables instead of hardcoding these values.
|
|
649
721
|
|
|
650
|
-
|
|
651
|
-
|
|
722
|
+
// Define your c15t instance
|
|
723
|
+
const instance = c15tInstance({
|
|
724
|
+
appName: 'Your App Name',
|
|
652
725
|
basePath: '/api/c15t',
|
|
653
|
-
|
|
726
|
+
database: ${adapterConfig},
|
|
727
|
+
trustedOrigins: ['http://localhost:3000'],
|
|
654
728
|
});
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
729
|
+
|
|
730
|
+
export default instance;
|
|
731
|
+
`;
|
|
732
|
+
}
|
|
733
|
+
function generateEnvFileContent(backendURL) {
|
|
734
|
+
return `# c15t Configuration
|
|
735
|
+
# Note: This URL is public and can be safely committed to version control
|
|
736
|
+
NEXT_PUBLIC_C15T_URL=${backendURL}
|
|
737
|
+
`;
|
|
738
|
+
}
|
|
739
|
+
async function setupC15tMode(context, projectRoot, spinner, initialBackendURL, handleCancel) {
|
|
740
|
+
const { logger, cwd } = context;
|
|
741
|
+
const needsAccount = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
742
|
+
message: 'Do you need to create a consent.io account?',
|
|
743
|
+
initialValue: true
|
|
744
|
+
});
|
|
745
|
+
if (handleCancel?.(needsAccount)) throw new Error('Setup cancelled');
|
|
746
|
+
if (needsAccount) {
|
|
747
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.note(`We'll open your browser to create a consent.io account and set up your instance.\nFollow these steps:\n1. Sign up for a consent.io account\n2. Create a new instance in the dashboard\n3. Configure your trusted origins (domains that can connect)\n4. Copy the provided backendURL (e.g., https://your-instance.c15t.dev)`, 'consent.io Setup');
|
|
748
|
+
const shouldOpen = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
749
|
+
message: 'Open browser to sign up for consent.io?',
|
|
750
|
+
initialValue: true
|
|
751
|
+
});
|
|
752
|
+
if (handleCancel?.(shouldOpen)) throw new Error('Setup cancelled');
|
|
753
|
+
if (shouldOpen) try {
|
|
754
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_open__["default"])('https://consent.io/dashboard/register?ref=cli');
|
|
755
|
+
const enterPressed = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.text({
|
|
756
|
+
message: 'Press Enter once you have created your instance and have the backendURL'
|
|
660
757
|
});
|
|
758
|
+
if (handleCancel?.(enterPressed)) throw new Error('Setup cancelled');
|
|
759
|
+
} catch (error) {
|
|
760
|
+
logger.warn('Failed to open browser automatically. Please visit https://consent.io/dashboard/register manually.');
|
|
661
761
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
762
|
+
}
|
|
763
|
+
const backendURLSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.text({
|
|
764
|
+
message: 'Enter your consent.io instance URL:',
|
|
765
|
+
placeholder: 'https://your-instance.c15t.dev',
|
|
766
|
+
initialValue: initialBackendURL,
|
|
767
|
+
validate: (value)=>{
|
|
768
|
+
if (!value || '' === value) return 'URL is required';
|
|
769
|
+
try {
|
|
770
|
+
const url = new URL(value);
|
|
771
|
+
if (!url.hostname.endsWith('.c15t.dev')) return 'Please enter a valid *.c15t.dev URL';
|
|
772
|
+
} catch {
|
|
773
|
+
return 'Please enter a valid URL';
|
|
774
|
+
}
|
|
667
775
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
776
|
+
});
|
|
777
|
+
if (handleCancel?.(backendURLSelection)) throw new Error('Setup cancelled');
|
|
778
|
+
if (!backendURLSelection || '' === backendURLSelection) {
|
|
779
|
+
logger.error('A valid consent.io URL is required');
|
|
780
|
+
throw new Error('A valid consent.io URL is required');
|
|
781
|
+
}
|
|
782
|
+
const backendURL = backendURLSelection;
|
|
783
|
+
const useEnvFileSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
784
|
+
message: 'Store the backendURL in a .env file? (Recommended, URL is public)',
|
|
785
|
+
initialValue: true
|
|
786
|
+
});
|
|
787
|
+
if (handleCancel?.(useEnvFileSelection)) throw new Error('Setup cancelled');
|
|
788
|
+
const useEnvFile = useEnvFileSelection;
|
|
789
|
+
const clientConfigContent = generateClientConfigContent('c15t', backendURL, useEnvFile);
|
|
790
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.config.ts');
|
|
791
|
+
spinner.start('Creating client configuration file...');
|
|
792
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(configPath, clientConfigContent);
|
|
793
|
+
spinner.stop(formatLogMessage('info', `Client configuration created: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath))}`));
|
|
794
|
+
if (useEnvFile) {
|
|
795
|
+
const envPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, '.env.local');
|
|
796
|
+
const envExamplePath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, '.env.example');
|
|
797
|
+
spinner.start('Creating environment files...');
|
|
798
|
+
const envContent = generateEnvFileContent(backendURL);
|
|
799
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(envPath, envContent);
|
|
800
|
+
logger.info(` - Created environment file: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, envPath))}`);
|
|
801
|
+
const envExampleContent = '# c15t Configuration\nNEXT_PUBLIC_C15T_URL=https://your-instance.c15t.dev\n';
|
|
802
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(envExamplePath, envExampleContent);
|
|
803
|
+
logger.info(` - Created example env file: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, envExamplePath))}`);
|
|
804
|
+
spinner.stop(formatLogMessage('info', 'Environment files created.'));
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
clientConfigContent,
|
|
808
|
+
backendURL,
|
|
809
|
+
usingEnvFile: useEnvFile
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
async function setupCustomMode(context, projectRoot, spinner) {
|
|
813
|
+
const { logger, cwd } = context;
|
|
814
|
+
const clientConfigContent = generateClientConfigContent('custom');
|
|
815
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.config.ts');
|
|
816
|
+
spinner.start('Creating client configuration file...');
|
|
817
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(configPath, clientConfigContent);
|
|
818
|
+
spinner.stop(formatLogMessage('info', `Client configuration created: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath))}`));
|
|
819
|
+
logger.info(`Remember to implement custom endpoint handlers (see ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath))}).`);
|
|
820
|
+
return {
|
|
821
|
+
clientConfigContent
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
async function setupOfflineMode(context, projectRoot, spinner, handleCancel) {
|
|
825
|
+
const { logger, cwd } = context;
|
|
826
|
+
const clientConfigContent = generateClientConfigContent('offline', void 0, false);
|
|
827
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.config.ts');
|
|
828
|
+
spinner.start('Creating client configuration file...');
|
|
829
|
+
try {
|
|
830
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(configPath, clientConfigContent);
|
|
831
|
+
spinner.stop(formatLogMessage('info', `Client configuration created: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath))}`));
|
|
832
|
+
} catch (error) {
|
|
833
|
+
spinner.stop(formatLogMessage('error', `Failed to create configuration file: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
834
|
+
throw error;
|
|
835
|
+
} finally{}
|
|
836
|
+
return {
|
|
837
|
+
clientConfigContent
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
async function setupSelfHostedMode(context, projectRoot, spinner, handleCancel) {
|
|
841
|
+
const { logger, cwd } = context;
|
|
842
|
+
let backendConfigContent = null;
|
|
843
|
+
const dependencies = [
|
|
844
|
+
'@c15t/backend'
|
|
845
|
+
];
|
|
846
|
+
const setupBackendSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
847
|
+
message: 'Set up the backend configuration now?',
|
|
848
|
+
initialValue: true
|
|
849
|
+
});
|
|
850
|
+
if (handleCancel?.(setupBackendSelection)) throw new Error('Setup cancelled');
|
|
851
|
+
const setupBackend = setupBackendSelection;
|
|
852
|
+
let adapterChoice = 'memory';
|
|
853
|
+
if (setupBackend) {
|
|
854
|
+
const adapterSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.select({
|
|
855
|
+
message: 'Choose a database adapter:',
|
|
856
|
+
initialValue: 'kysely-sqlite',
|
|
857
|
+
options: [
|
|
858
|
+
{
|
|
859
|
+
value: 'kysely-sqlite',
|
|
860
|
+
label: 'Kysely (SQLite)',
|
|
861
|
+
hint: 'Simple setups/local dev'
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
value: 'kysely-postgres',
|
|
865
|
+
label: 'Kysely (PostgreSQL)',
|
|
866
|
+
hint: 'Production'
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
value: 'memory',
|
|
870
|
+
label: 'Memory',
|
|
871
|
+
hint: 'Testing/development only'
|
|
872
|
+
}
|
|
873
|
+
]
|
|
874
|
+
});
|
|
875
|
+
if (handleCancel?.(adapterSelection)) throw new Error('Setup cancelled');
|
|
876
|
+
adapterChoice = adapterSelection;
|
|
877
|
+
let connectionString;
|
|
878
|
+
let dbPath;
|
|
879
|
+
if ('kysely-postgres' === adapterChoice) {
|
|
880
|
+
const connectionStringSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.text({
|
|
881
|
+
message: 'Enter PostgreSQL connection string:',
|
|
882
|
+
placeholder: 'postgresql://user:pass@host:port/db'
|
|
883
|
+
});
|
|
884
|
+
if (handleCancel?.(connectionStringSelection)) throw new Error('Setup cancelled');
|
|
885
|
+
if (!connectionStringSelection || '' === connectionStringSelection) {
|
|
886
|
+
logger.error('A valid PostgreSQL connection string is required');
|
|
887
|
+
throw new Error('A valid PostgreSQL connection string is required');
|
|
888
|
+
}
|
|
889
|
+
connectionString = connectionStringSelection;
|
|
890
|
+
} else if ('kysely-sqlite' === adapterChoice) {
|
|
891
|
+
const dbPathSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.text({
|
|
892
|
+
message: 'Enter path for SQLite database file:',
|
|
893
|
+
placeholder: './db.sqlite',
|
|
894
|
+
initialValue: './db.sqlite'
|
|
895
|
+
});
|
|
896
|
+
if (handleCancel?.(dbPathSelection)) throw new Error('Setup cancelled');
|
|
897
|
+
if (!dbPathSelection || '' === dbPathSelection) {
|
|
898
|
+
logger.error('A valid database path is required');
|
|
899
|
+
throw new Error('A valid database path is required');
|
|
900
|
+
}
|
|
901
|
+
dbPath = dbPathSelection;
|
|
902
|
+
}
|
|
903
|
+
backendConfigContent = generateBackendConfigContent(adapterChoice, connectionString, dbPath);
|
|
904
|
+
const backendConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.backend.ts');
|
|
905
|
+
spinner.start('Creating backend configuration file...');
|
|
906
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(backendConfigPath, backendConfigContent);
|
|
907
|
+
spinner.stop(formatLogMessage('info', `Backend configuration created: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, backendConfigPath))}`));
|
|
908
|
+
}
|
|
909
|
+
const clientConfigContent = generateClientConfigContent('c15t', '/api/c15t', false);
|
|
910
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.config.ts');
|
|
911
|
+
spinner.start('Creating client configuration file...');
|
|
912
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(configPath, clientConfigContent);
|
|
913
|
+
spinner.stop(formatLogMessage('info', `Client configuration created: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath))}`));
|
|
914
|
+
return {
|
|
915
|
+
clientConfigContent,
|
|
916
|
+
backendConfigContent,
|
|
917
|
+
dependencies,
|
|
918
|
+
adapterChoice
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
async function startOnboarding(context, existingConfig) {
|
|
922
|
+
const { logger, cwd, telemetry } = context;
|
|
923
|
+
const handleCancel = (value)=>{
|
|
924
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(value)) {
|
|
925
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_EXITED, {
|
|
926
|
+
reason: 'user_cancelled',
|
|
927
|
+
stage: 'setup'
|
|
928
|
+
});
|
|
929
|
+
context.error.handleCancel('Configuration cancelled.');
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
return false;
|
|
933
|
+
};
|
|
934
|
+
const isUpdate = !!existingConfig;
|
|
935
|
+
logger.info(isUpdate ? 'Starting configuration update...' : 'Starting onboarding process...');
|
|
936
|
+
telemetry.trackEvent(isUpdate ? telemetry_TelemetryEventName.CONFIG_UPDATED : telemetry_TelemetryEventName.ONBOARDING_STARTED, {
|
|
937
|
+
isUpdate
|
|
938
|
+
});
|
|
939
|
+
logger.note(isUpdate ? "Let's update your c15t configuration." : `Welcome to c15t! Let's set up your consent management configuration.\nFirst, we'll help you choose the best storage approach for your needs.`, isUpdate ? 'Update Configuration' : 'First time setup');
|
|
940
|
+
const projectRoot = await detectProjectRoot(cwd);
|
|
941
|
+
if (projectRoot !== cwd) logger.debug(`Project root identified: ${projectRoot}`);
|
|
942
|
+
else logger.warn('Could not determine project root, using current directory');
|
|
943
|
+
const s = __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.spinner();
|
|
944
|
+
let spinnerActive = false;
|
|
945
|
+
try {
|
|
946
|
+
const packageManager = await detectPackageManager(projectRoot);
|
|
947
|
+
const { framework, hasReact } = await detectFramework(projectRoot);
|
|
948
|
+
logger.debug(`Detected package manager: ${packageManager}`);
|
|
949
|
+
if (framework) logger.debug(`Detected framework: ${framework}`);
|
|
950
|
+
logger.debug(`React detected: ${hasReact}`);
|
|
951
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CLI_ENVIRONMENT_DETECTED, {
|
|
952
|
+
packageManager,
|
|
953
|
+
framework: framework || 'unknown',
|
|
954
|
+
hasReact
|
|
955
|
+
});
|
|
956
|
+
let initialStorageMode;
|
|
957
|
+
if (isUpdate && existingConfig && 'mode' in existingConfig) {
|
|
958
|
+
if (isClientOptions(existingConfig)) initialStorageMode = existingConfig.mode;
|
|
959
|
+
else if (isC15TOptions(existingConfig)) initialStorageMode = 'c15t';
|
|
960
|
+
}
|
|
961
|
+
let storageModeSelection;
|
|
962
|
+
try {
|
|
963
|
+
storageModeSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.select({
|
|
964
|
+
message: isUpdate ? `Select storage mode (current: ${initialStorageMode || 'unknown'}):` : 'How would you like to store consent decisions?',
|
|
965
|
+
initialValue: initialStorageMode || 'c15t',
|
|
966
|
+
options: [
|
|
967
|
+
{
|
|
968
|
+
value: 'c15t',
|
|
969
|
+
label: 'Hosted c15t (consent.io)',
|
|
970
|
+
hint: 'Recommended: Fully managed service'
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
value: 'offline',
|
|
974
|
+
label: 'Offline Mode',
|
|
975
|
+
hint: 'Store in browser, no backend needed'
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
value: 'self-hosted',
|
|
979
|
+
label: 'Self-Hosted',
|
|
980
|
+
hint: 'Run your own c15t backend'
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
value: 'custom',
|
|
984
|
+
label: 'Custom Implementation',
|
|
985
|
+
hint: 'Full control over storage logic'
|
|
986
|
+
}
|
|
987
|
+
]
|
|
988
|
+
});
|
|
989
|
+
} catch (error) {
|
|
990
|
+
logger.error('Error selecting storage mode:', error);
|
|
991
|
+
throw error;
|
|
992
|
+
}
|
|
993
|
+
if (handleCancel(storageModeSelection)) return;
|
|
994
|
+
const storageMode = storageModeSelection;
|
|
995
|
+
logger.debug(`Selected storage mode: ${storageMode}`);
|
|
996
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_STORAGE_MODE_SELECTED, {
|
|
997
|
+
storageMode,
|
|
998
|
+
isUpdate
|
|
999
|
+
});
|
|
1000
|
+
const dependenciesToAdd = [];
|
|
1001
|
+
let installDepsConfirmed = false;
|
|
1002
|
+
let ranInstall = false;
|
|
1003
|
+
if (hasReact) dependenciesToAdd.push('@c15t/react');
|
|
1004
|
+
else {
|
|
1005
|
+
dependenciesToAdd.push('c15t');
|
|
1006
|
+
if (null === framework) logger.note(`No React framework detected, installing base c15t package.\nIf you're using React, you might need to manually install @c15t/react instead.`, formatLogMessage('warn', 'Package Selection'));
|
|
1007
|
+
}
|
|
1008
|
+
if ('c15t' === storageMode) {
|
|
1009
|
+
let initialBackendURL;
|
|
1010
|
+
if (isUpdate && existingConfig && isClientOptions(existingConfig) && existingConfig.backendURL) initialBackendURL = existingConfig.backendURL;
|
|
1011
|
+
const c15tResult = await setupC15tMode(context, projectRoot, s, initialBackendURL, handleCancel);
|
|
1012
|
+
c15tResult.clientConfigContent;
|
|
1013
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_C15T_MODE_CONFIGURED, {
|
|
1014
|
+
usingEnvFile: c15tResult.usingEnvFile,
|
|
1015
|
+
hasInitialBackendURL: !!initialBackendURL
|
|
1016
|
+
});
|
|
1017
|
+
} else if ('offline' === storageMode) {
|
|
1018
|
+
const offlineResult = await setupOfflineMode(context, projectRoot, s, handleCancel);
|
|
1019
|
+
offlineResult.clientConfigContent;
|
|
1020
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_OFFLINE_MODE_CONFIGURED, {});
|
|
1021
|
+
} else if ('self-hosted' === storageMode) {
|
|
1022
|
+
const selfHostedResult = await setupSelfHostedMode(context, projectRoot, s, handleCancel);
|
|
1023
|
+
selfHostedResult.clientConfigContent;
|
|
1024
|
+
selfHostedResult.backendConfigContent;
|
|
1025
|
+
dependenciesToAdd.push(...selfHostedResult.dependencies);
|
|
1026
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_SELF_HOSTED_CONFIGURED, {
|
|
1027
|
+
databaseType: selfHostedResult.adapterChoice,
|
|
1028
|
+
dependencies: selfHostedResult.dependencies.join(',')
|
|
1029
|
+
});
|
|
1030
|
+
} else if ('custom' === storageMode) {
|
|
1031
|
+
const customResult = await setupCustomMode(context, projectRoot, s);
|
|
1032
|
+
customResult.clientConfigContent;
|
|
1033
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_CUSTOM_MODE_CONFIGURED, {});
|
|
1034
|
+
}
|
|
1035
|
+
let addDeps = false;
|
|
1036
|
+
if (dependenciesToAdd.length > 0) {
|
|
1037
|
+
const depsString = dependenciesToAdd.map((d)=>__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(d)).join(', ');
|
|
1038
|
+
const addDepsSelection = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
1039
|
+
message: `${isUpdate ? 'Update' : 'Add'} required dependencies using ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(packageManager)}? (${depsString})`,
|
|
1040
|
+
initialValue: true
|
|
1041
|
+
});
|
|
1042
|
+
if (handleCancel(addDepsSelection)) return;
|
|
1043
|
+
addDeps = addDepsSelection;
|
|
1044
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_DEPENDENCIES_CHOICE, {
|
|
1045
|
+
confirmed: addDeps,
|
|
1046
|
+
dependencies: dependenciesToAdd.join(','),
|
|
1047
|
+
packageManager
|
|
1048
|
+
});
|
|
1049
|
+
if (addDeps) {
|
|
1050
|
+
installDepsConfirmed = true;
|
|
1051
|
+
s.start(`Running ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(packageManager)} to add and install dependencies... (this might take a moment)`);
|
|
1052
|
+
spinnerActive = true;
|
|
1053
|
+
try {
|
|
1054
|
+
await addAndInstallDependenciesViaPM(projectRoot, dependenciesToAdd, packageManager);
|
|
1055
|
+
s.stop(`✅ Dependencies installed: ${dependenciesToAdd.map((d)=>__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(d)).join(', ')}`);
|
|
1056
|
+
spinnerActive = false;
|
|
1057
|
+
ranInstall = true;
|
|
1058
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_DEPENDENCIES_INSTALLED, {
|
|
1059
|
+
success: true,
|
|
1060
|
+
dependencies: dependenciesToAdd.join(','),
|
|
1061
|
+
packageManager
|
|
1062
|
+
});
|
|
1063
|
+
} catch (installError) {
|
|
1064
|
+
s.stop(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].yellow('⚠️ Dependency installation failed.'));
|
|
1065
|
+
spinnerActive = false;
|
|
1066
|
+
logger.error('Installation Error:', installError);
|
|
1067
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_DEPENDENCIES_INSTALLED, {
|
|
1068
|
+
success: false,
|
|
1069
|
+
error: installError instanceof Error ? installError.message : String(installError),
|
|
1070
|
+
dependencies: dependenciesToAdd.join(','),
|
|
1071
|
+
packageManager
|
|
1072
|
+
});
|
|
1073
|
+
const pmCommand = getManualInstallCommand(dependenciesToAdd, packageManager);
|
|
1074
|
+
logger.info(`Please try running '${pmCommand}' manually in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, projectRoot))}.`);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.step('Configuration Complete! Next Steps:');
|
|
1079
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.config.ts');
|
|
1080
|
+
const backendConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, 'c15t.backend.ts');
|
|
1081
|
+
const relativeConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, configPath);
|
|
1082
|
+
const importPath = `./${relativeConfigPath.replace(/\\/g, '/').replace(/\.(ts|js|tsx|jsx)$/, '')}`;
|
|
1083
|
+
const importStatement = __WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(`import { c15tConfig } from '${importPath}';`);
|
|
1084
|
+
switch(storageMode){
|
|
1085
|
+
case 'c15t':
|
|
1086
|
+
{
|
|
1087
|
+
let steps = '1. Ensure your consent.io instance is configured (trusted origins etc).\n';
|
|
1088
|
+
try {
|
|
1089
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, '.env.local'));
|
|
1090
|
+
steps += ` 2. Verify ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('NEXT_PUBLIC_C15T_URL')} in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(projectRoot, '.env.local')))}.\n`;
|
|
1091
|
+
} catch {
|
|
1092
|
+
steps += ` 2. Verify ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('backendURL')} in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(relativeConfigPath)}.\n`;
|
|
1093
|
+
}
|
|
1094
|
+
steps += ` 3. Import and use configuration in your app: ${importStatement}`;
|
|
1095
|
+
logger.info(steps);
|
|
1096
|
+
break;
|
|
1097
|
+
}
|
|
1098
|
+
case 'offline':
|
|
1099
|
+
logger.info(`1. Import and use configuration in your app: ${importStatement}`);
|
|
1100
|
+
break;
|
|
1101
|
+
case 'self-hosted':
|
|
1102
|
+
{
|
|
1103
|
+
let steps = '';
|
|
1104
|
+
try {
|
|
1105
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(backendConfigPath);
|
|
1106
|
+
steps += `1. Configure database connection in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].relative(cwd, backendConfigPath))}.\n`;
|
|
1107
|
+
steps += ' 2. Set up API routes using the exported backend instance.\n';
|
|
1108
|
+
} catch {
|
|
1109
|
+
steps += '1. Set up your c15t backend instance and API routes.\n';
|
|
1110
|
+
}
|
|
1111
|
+
steps += ` 3. Ensure ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('backendURL')} in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(relativeConfigPath)} points to your API.\n`;
|
|
1112
|
+
steps += ` 4. Import and use client configuration: ${importStatement}`;
|
|
1113
|
+
logger.info(steps);
|
|
1114
|
+
break;
|
|
1115
|
+
}
|
|
1116
|
+
case 'custom':
|
|
1117
|
+
{
|
|
1118
|
+
const steps = `1. Implement your custom endpoint handlers (referenced in ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(relativeConfigPath)}).\n 2. Import and use configuration in your app: ${importStatement}`;
|
|
1119
|
+
logger.info(steps);
|
|
1120
|
+
break;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if (installDepsConfirmed && !ranInstall) logger.info(` - ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].yellow('Dependency installation failed.')} Please check errors and install manually.`);
|
|
1124
|
+
else if (!addDeps && dependenciesToAdd.length > 0) {
|
|
1125
|
+
const pmCommand = getManualInstallCommand(dependenciesToAdd, packageManager);
|
|
1126
|
+
logger.warn(` - Run ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan(pmCommand)} to install required dependencies.`);
|
|
1127
|
+
}
|
|
1128
|
+
logger.note(`${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bold('✨ Setup complete!')} Your c15t configuration is ready to use. \n
|
|
1129
|
+
|
|
1130
|
+
We're building c15t as an ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bold('open source')} project to make consent management more accessible.
|
|
1131
|
+
If you find this useful, we'd really appreciate a GitHub star - it helps others discover the project!`, '🎉 Thanks for using c15t');
|
|
1132
|
+
const shouldOpenGithub = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
1133
|
+
message: 'Would you like to star c15t on GitHub now?',
|
|
1134
|
+
initialValue: true
|
|
1135
|
+
});
|
|
1136
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(shouldOpenGithub)) {
|
|
1137
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_GITHUB_STAR, {
|
|
1138
|
+
action: 'cancelled'
|
|
1139
|
+
});
|
|
1140
|
+
return context.error.handleCancel('GitHub star prompt cancelled. Exiting onboarding.');
|
|
1141
|
+
}
|
|
1142
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_GITHUB_STAR, {
|
|
1143
|
+
action: shouldOpenGithub ? 'opened_browser' : 'declined'
|
|
1144
|
+
});
|
|
1145
|
+
if (shouldOpenGithub) try {
|
|
1146
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.note('Your support helps us continue improving c15t.\nThank you for being part of our community!', '⭐ Star Us on GitHub');
|
|
1147
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_open__["default"])('https://github.com/c15t/c15t');
|
|
1148
|
+
logger.success('GitHub repository opened. Thank you for your support!');
|
|
1149
|
+
} catch (error) {
|
|
1150
|
+
logger.debug('Failed to open browser:', error);
|
|
1151
|
+
logger.info(`You can star us later by visiting: ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('https://github.com/c15t/c15t')}`);
|
|
675
1152
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
1153
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_COMPLETED, {
|
|
1154
|
+
success: true,
|
|
1155
|
+
storageMode,
|
|
1156
|
+
installDependencies: ranInstall
|
|
1157
|
+
});
|
|
1158
|
+
logger.success('🚀 Setup completed successfully!');
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
if (spinnerActive) s.stop(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].red('Onboarding failed.'));
|
|
1161
|
+
if (!__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(error)) {
|
|
1162
|
+
logger.error('An unexpected error occurred during onboarding:', error);
|
|
1163
|
+
if (error instanceof Error && error.message) logger.error(`Error details: ${error.message}`);
|
|
1164
|
+
logger.failed('Onboarding process could not be completed.');
|
|
1165
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_COMPLETED, {
|
|
1166
|
+
success: false,
|
|
1167
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1168
|
+
});
|
|
679
1169
|
}
|
|
680
|
-
process.exit(1);
|
|
681
1170
|
}
|
|
682
1171
|
}
|
|
683
|
-
async function
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
y: __WEBPACK_EXTERNAL_MODULE_zod__.z.boolean().optional()
|
|
689
|
-
}).parse(opts);
|
|
690
|
-
const cwd = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(options.cwd);
|
|
1172
|
+
async function setupGenerateEnvironment(context) {
|
|
1173
|
+
const { logger, flags, cwd, error, telemetry } = context;
|
|
1174
|
+
logger.debug('Setting up generate environment...');
|
|
1175
|
+
logger.debug('Context flags:', flags);
|
|
1176
|
+
logger.debug(`Context CWD: ${cwd}`);
|
|
691
1177
|
if (!(0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(cwd)) {
|
|
692
|
-
|
|
693
|
-
|
|
1178
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1179
|
+
error: `Directory ${cwd} does not exist`,
|
|
1180
|
+
stage: 'setup'
|
|
1181
|
+
});
|
|
1182
|
+
return error.handleError(new Error(`The directory "${cwd}" does not exist`), 'Generate setup failed');
|
|
694
1183
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
1184
|
+
logger.debug('Attempting to load configuration...');
|
|
1185
|
+
const config = await context.config.loadConfig();
|
|
1186
|
+
if (!config) {
|
|
1187
|
+
logger.debug('No config found during setup, generate command will handle onboarding.');
|
|
1188
|
+
try {
|
|
1189
|
+
const memAdapter = await (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_db_adapters_cee37d0f__.getAdapter)({
|
|
1190
|
+
appName: 'temp-for-setup',
|
|
1191
|
+
database: {
|
|
1192
|
+
adapter: 'memory'
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
return {
|
|
1196
|
+
config: null,
|
|
1197
|
+
adapter: memAdapter
|
|
1198
|
+
};
|
|
1199
|
+
} catch (adapterError) {
|
|
1200
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1201
|
+
error: adapterError instanceof Error ? adapterError.message : String(adapterError),
|
|
1202
|
+
stage: 'adapter_initialization'
|
|
1203
|
+
});
|
|
1204
|
+
return error.handleError(adapterError, 'Failed to initialize default memory adapter');
|
|
1205
|
+
}
|
|
716
1206
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
1207
|
+
logger.debug('Config loaded, initializing adapter...');
|
|
1208
|
+
let adapter;
|
|
1209
|
+
try {
|
|
1210
|
+
adapter = await (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_db_adapters_cee37d0f__.getAdapter)(config);
|
|
1211
|
+
logger.debug('Adapter initialized successfully');
|
|
1212
|
+
} catch (e) {
|
|
1213
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1214
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1215
|
+
stage: 'adapter_initialization_with_config'
|
|
1216
|
+
});
|
|
1217
|
+
return error.handleError(e, 'Failed to initialize database adapter');
|
|
1218
|
+
}
|
|
1219
|
+
if (!adapter) {
|
|
1220
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1221
|
+
error: 'Adapter initialization returned undefined',
|
|
1222
|
+
stage: 'adapter_initialization_check'
|
|
1223
|
+
});
|
|
1224
|
+
return error.handleError(new Error('Adapter initialization returned undefined'), 'Database adapter could not be initialized');
|
|
1225
|
+
}
|
|
1226
|
+
logger.debug('Environment setup complete');
|
|
1227
|
+
return {
|
|
1228
|
+
config,
|
|
1229
|
+
adapter
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
async function generate(context) {
|
|
1233
|
+
const { logger, error, telemetry } = context;
|
|
1234
|
+
logger.debug('Starting generate command...');
|
|
1235
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_STARTED, {});
|
|
1236
|
+
const setupResult = await setupGenerateEnvironment(context);
|
|
1237
|
+
let { config, adapter } = setupResult;
|
|
1238
|
+
if (config) {
|
|
1239
|
+
let currentMode = 'unknown';
|
|
1240
|
+
if (isClientOptions(config)) {
|
|
1241
|
+
if (config.mode) currentMode = config.mode;
|
|
1242
|
+
} else if (isC15TOptions(config)) currentMode = 'backend';
|
|
1243
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CONFIG_LOADED, {
|
|
1244
|
+
type: currentMode,
|
|
1245
|
+
exists: true
|
|
1246
|
+
});
|
|
1247
|
+
const shouldUpdate = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
1248
|
+
message: formatLogMessage('warn', `A c15t configuration already exists. Would you like to update it before generating? (${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].dim(`Current mode: ${currentMode}`)})`),
|
|
1249
|
+
initialValue: false
|
|
1250
|
+
});
|
|
1251
|
+
if (!shouldUpdate) {
|
|
1252
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_COMPLETED, {
|
|
1253
|
+
success: false,
|
|
1254
|
+
reason: 'user_cancelled'
|
|
724
1255
|
});
|
|
725
|
-
|
|
1256
|
+
return error.handleCancel('Operation cancelled.');
|
|
726
1257
|
}
|
|
727
|
-
if (
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
1258
|
+
if (shouldUpdate) {
|
|
1259
|
+
await startOnboarding(context, config);
|
|
1260
|
+
logger.debug('Reloading configuration after update...');
|
|
1261
|
+
const postUpdateResult = await setupGenerateEnvironment(context);
|
|
1262
|
+
if (!postUpdateResult.config) {
|
|
1263
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1264
|
+
error: 'Failed to load configuration after update'
|
|
1265
|
+
});
|
|
1266
|
+
return error.handleError(new Error('Failed to load configuration after update.'), 'Configuration Error');
|
|
1267
|
+
}
|
|
1268
|
+
config = postUpdateResult.config;
|
|
1269
|
+
postUpdateResult.adapter;
|
|
1270
|
+
logger.info('Configuration updated successfully.');
|
|
1271
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_COMPLETED, {
|
|
1272
|
+
success: true,
|
|
1273
|
+
configUpdated: true
|
|
731
1274
|
});
|
|
732
|
-
if (schema.overwrite) await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, schema.fileName), schema.code);
|
|
733
|
-
else await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].appendFile(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, schema.fileName), schema.code);
|
|
734
|
-
utils_logger.success(`🚀 Schema was ${schema.overwrite ? 'overwritten' : 'appended'} successfully!`);
|
|
735
|
-
process.exit(0);
|
|
736
1275
|
} else {
|
|
737
|
-
|
|
738
|
-
|
|
1276
|
+
logger.debug('Proceeding with existing configuration.');
|
|
1277
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_COMPLETED, {
|
|
1278
|
+
success: true,
|
|
1279
|
+
configUpdated: false
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
} else {
|
|
1283
|
+
logger.info('No configuration found.');
|
|
1284
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CONFIG_LOADED, {
|
|
1285
|
+
exists: false
|
|
1286
|
+
});
|
|
1287
|
+
const shouldOnboard = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
1288
|
+
message: 'No c15t configuration found. Would you like to create one now?',
|
|
1289
|
+
initialValue: true
|
|
1290
|
+
});
|
|
1291
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(shouldOnboard) || !shouldOnboard) {
|
|
1292
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_COMPLETED, {
|
|
1293
|
+
success: false,
|
|
1294
|
+
reason: 'onboarding_declined'
|
|
1295
|
+
});
|
|
1296
|
+
return error.handleCancel('Configuration setup cancelled.');
|
|
1297
|
+
}
|
|
1298
|
+
await startOnboarding(context);
|
|
1299
|
+
logger.debug('Reloading configuration after onboarding...');
|
|
1300
|
+
const postOnboardResult = await setupGenerateEnvironment(context);
|
|
1301
|
+
if (!postOnboardResult.config) {
|
|
1302
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_FAILED, {
|
|
1303
|
+
error: 'Failed to load configuration even after onboarding'
|
|
1304
|
+
});
|
|
1305
|
+
return error.handleError(new Error('Failed to load configuration even after onboarding.'), 'Configuration Error');
|
|
739
1306
|
}
|
|
1307
|
+
config = postOnboardResult.config;
|
|
1308
|
+
postOnboardResult.adapter;
|
|
1309
|
+
logger.info('New configuration loaded successfully.');
|
|
1310
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.GENERATE_COMPLETED, {
|
|
1311
|
+
success: true,
|
|
1312
|
+
newConfigCreated: true
|
|
1313
|
+
});
|
|
740
1314
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
1315
|
+
}
|
|
1316
|
+
async function executeMigrations(context, runMigrationsFn) {
|
|
1317
|
+
const { logger, telemetry } = context;
|
|
1318
|
+
logger.info('Executing migrations...');
|
|
1319
|
+
const s = __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.spinner();
|
|
1320
|
+
s.start('Running migrations...');
|
|
1321
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_EXECUTED, {
|
|
1322
|
+
status: 'started'
|
|
1323
|
+
});
|
|
1324
|
+
try {
|
|
1325
|
+
await runMigrationsFn();
|
|
1326
|
+
s.stop('Migrations completed successfully!');
|
|
1327
|
+
logger.success('🚀 Database migrated successfully');
|
|
1328
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_EXECUTED, {
|
|
1329
|
+
status: 'completed'
|
|
1330
|
+
});
|
|
1331
|
+
} catch (error) {
|
|
1332
|
+
logger.error('Migration failed.');
|
|
1333
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_EXECUTED, {
|
|
1334
|
+
status: 'failed',
|
|
1335
|
+
error: error instanceof Error ? error.message : String(error)
|
|
747
1336
|
});
|
|
748
|
-
|
|
1337
|
+
context.error.handleError(error, 'Error running migrations');
|
|
749
1338
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
1339
|
+
}
|
|
1340
|
+
async function planMigrations(context, config, skipConfirmation) {
|
|
1341
|
+
const { logger } = context;
|
|
1342
|
+
logger.info('Planning migrations...');
|
|
1343
|
+
logger.debug('Config:', config);
|
|
1344
|
+
logger.debug(`Skip confirmation: ${skipConfirmation}`);
|
|
1345
|
+
const s = __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.spinner();
|
|
1346
|
+
s.start('Preparing migration plan...');
|
|
1347
|
+
let migrationData;
|
|
1348
|
+
try {
|
|
1349
|
+
migrationData = await (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_migrations_80b6e3bd__.getMigrations)(config);
|
|
1350
|
+
logger.debug('Migration data:', migrationData);
|
|
1351
|
+
} catch (err) {
|
|
1352
|
+
s.stop('Migration preparation failed.');
|
|
1353
|
+
if (err instanceof Error) logger.error(err.message);
|
|
1354
|
+
else logger.error(String(err));
|
|
1355
|
+
logger.failed('Migration planning failed');
|
|
1356
|
+
return {
|
|
1357
|
+
shouldRun: false,
|
|
1358
|
+
runMigrationsFn: null
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
if (!migrationData) {
|
|
1362
|
+
s.stop('Could not retrieve migration data.');
|
|
1363
|
+
logger.failed('Migration planning failed');
|
|
1364
|
+
return {
|
|
1365
|
+
shouldRun: false,
|
|
1366
|
+
runMigrationsFn: null
|
|
1367
|
+
};
|
|
753
1368
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
1369
|
+
const { toBeAdded, toBeCreated, runMigrations } = migrationData;
|
|
1370
|
+
logger.debug('Migrations to be added:', toBeAdded);
|
|
1371
|
+
logger.debug('Migrations to be created:', toBeCreated);
|
|
1372
|
+
if (!toBeAdded.length && !toBeCreated.length) {
|
|
1373
|
+
s.stop('No migrations needed.');
|
|
1374
|
+
logger.info('🚀 Database is up to date');
|
|
1375
|
+
return {
|
|
1376
|
+
shouldRun: false,
|
|
1377
|
+
runMigrationsFn: null
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
s.stop('Migration plan prepared.');
|
|
1381
|
+
logger.info('🔑 The following migrations will be applied:');
|
|
1382
|
+
for (const table of [
|
|
1383
|
+
...toBeCreated,
|
|
1384
|
+
...toBeAdded
|
|
1385
|
+
]){
|
|
1386
|
+
const fields = Object.keys(table.fields).join(', ');
|
|
1387
|
+
const tableName = table.table;
|
|
1388
|
+
logger.info(` + Table ${tableName}: Add fields [${fields}]`);
|
|
1389
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.message(` ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyan('+')} Table ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].yellow(tableName)}: Add fields [${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].green(fields)}]`);
|
|
1390
|
+
}
|
|
1391
|
+
__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.message('');
|
|
1392
|
+
let shouldMigrate = skipConfirmation;
|
|
1393
|
+
if (!shouldMigrate) {
|
|
1394
|
+
shouldMigrate = await context.confirm('Apply these migrations to the database?', false);
|
|
1395
|
+
logger.debug(`User confirmation: ${shouldMigrate}`);
|
|
1396
|
+
}
|
|
1397
|
+
if (!shouldMigrate) {
|
|
1398
|
+
logger.failed('Migration cancelled');
|
|
1399
|
+
return {
|
|
1400
|
+
shouldRun: false,
|
|
1401
|
+
runMigrationsFn: null
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
logger.debug('Proceeding with migration execution');
|
|
1405
|
+
return {
|
|
1406
|
+
shouldRun: true,
|
|
1407
|
+
runMigrationsFn: runMigrations
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
async function loadConfigAndOnboard(context) {
|
|
1411
|
+
const { logger } = context;
|
|
1412
|
+
logger.debug('Checking for existing configuration...');
|
|
1413
|
+
let config;
|
|
1414
|
+
try {
|
|
1415
|
+
config = await context.config.loadConfig();
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
return context.error.handleError(error, 'Unexpected error during configuration loading');
|
|
1418
|
+
}
|
|
1419
|
+
if (!config) {
|
|
1420
|
+
logger.info('No config found, starting onboarding.');
|
|
1421
|
+
await startOnboarding(context);
|
|
1422
|
+
logger.debug('Exiting after triggering onboarding.');
|
|
1423
|
+
process.exit(0);
|
|
1424
|
+
}
|
|
1425
|
+
logger.debug('Configuration loaded successfully.');
|
|
1426
|
+
return config;
|
|
1427
|
+
}
|
|
1428
|
+
function validateAdapterIsKysely(context, adapter) {
|
|
1429
|
+
const { logger, error } = context;
|
|
1430
|
+
logger.debug('Validating adapter:', adapter);
|
|
1431
|
+
if (!adapter || 'kysely' !== adapter.id) {
|
|
1432
|
+
let message = 'Invalid or unsupported database configuration for migrate. Migrate command only works with built-in Kysely adapter.';
|
|
1433
|
+
if (adapter?.id === 'prisma') message = "The migrate command only works with the built-in Kysely adapter. For Prisma, run `npx @c15t/cli generate` to create the schema, then use Prisma's migrate or push to apply it.";
|
|
1434
|
+
else if (adapter?.id === 'drizzle') message = "The migrate command only works with the built-in Kysely adapter. For Drizzle, run `npx @c15t/cli generate` to create the schema, then use Drizzle's migrate or push to apply it.";
|
|
1435
|
+
error.handleError(new Error('Adapter validation failed: Not using Kysely'), message);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
async function setupEnvironment(context) {
|
|
1439
|
+
const { logger, flags, cwd, error } = context;
|
|
1440
|
+
logger.info('Setting up migration environment...');
|
|
1441
|
+
logger.debug('Flags:', flags);
|
|
1442
|
+
logger.debug(`Working directory: ${cwd}`);
|
|
1443
|
+
if (!(0, __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__.existsSync)(cwd)) return error.handleError(new Error(`The directory "${cwd}" does not exist`), 'Migration setup failed');
|
|
1444
|
+
const config = await loadConfigAndOnboard(context);
|
|
1445
|
+
logger.debug('Config loaded:', config);
|
|
1446
|
+
let adapter;
|
|
1447
|
+
try {
|
|
1448
|
+
logger.debug('Initializing database adapter...');
|
|
1449
|
+
adapter = await (0, __WEBPACK_EXTERNAL_MODULE__c15t_backend_pkgs_db_adapters_cee37d0f__.getAdapter)(config);
|
|
1450
|
+
logger.debug('Adapter initialized:', adapter);
|
|
1451
|
+
} catch (e) {
|
|
1452
|
+
return error.handleError(e, 'Failed to initialize database adapter');
|
|
1453
|
+
}
|
|
1454
|
+
validateAdapterIsKysely(context, adapter);
|
|
1455
|
+
logger.info('✅ Environment setup complete');
|
|
1456
|
+
return {
|
|
1457
|
+
config,
|
|
1458
|
+
adapter: adapter
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
async function migrate(context) {
|
|
1462
|
+
const { logger, flags, telemetry } = context;
|
|
1463
|
+
logger.info('Starting migration process...');
|
|
1464
|
+
logger.debug('Context:', context);
|
|
1465
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_STARTED, {
|
|
1466
|
+
skipConfirmation: true === flags.y
|
|
1467
|
+
});
|
|
1468
|
+
const skipConfirmation = flags.y;
|
|
1469
|
+
try {
|
|
1470
|
+
const { config } = await setupEnvironment(context);
|
|
1471
|
+
const planResult = await planMigrations(context, config, skipConfirmation);
|
|
1472
|
+
logger.debug('Plan result:', planResult);
|
|
1473
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_PLANNED, {
|
|
1474
|
+
shouldRun: planResult.shouldRun,
|
|
1475
|
+
hasMigrations: !!planResult.runMigrationsFn
|
|
758
1476
|
});
|
|
1477
|
+
if (planResult.shouldRun && planResult.runMigrationsFn) {
|
|
1478
|
+
await executeMigrations(context, planResult.runMigrationsFn);
|
|
1479
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_COMPLETED, {
|
|
1480
|
+
success: true
|
|
1481
|
+
});
|
|
1482
|
+
} else {
|
|
1483
|
+
logger.debug('Skipping migration execution based on plan result');
|
|
1484
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_COMPLETED, {
|
|
1485
|
+
success: true,
|
|
1486
|
+
reason: planResult.shouldRun ? 'no_migrations_needed' : 'user_cancelled'
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.MIGRATION_FAILED, {
|
|
1491
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1492
|
+
});
|
|
1493
|
+
context.error.handleError(error, 'An unexpected error occurred during the migration process');
|
|
759
1494
|
}
|
|
760
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(options.output || __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, schema.fileName), schema.code);
|
|
761
|
-
utils_logger.success('🚀 Schema was generated successfully!');
|
|
762
|
-
process.exit(0);
|
|
763
1495
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
1496
|
+
async function displayIntro(context, version) {
|
|
1497
|
+
const { logger } = context;
|
|
1498
|
+
logger.info(`${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bold('Welcome!')} Let's get you set up.`);
|
|
1499
|
+
logger.message('');
|
|
1500
|
+
let figletText = 'c15t';
|
|
1501
|
+
try {
|
|
1502
|
+
figletText = await new Promise((resolve)=>{
|
|
1503
|
+
__WEBPACK_EXTERNAL_MODULE_figlet__["default"].text('c15t', {
|
|
1504
|
+
font: 'Nancyj-Improved',
|
|
1505
|
+
horizontalLayout: 'default',
|
|
1506
|
+
verticalLayout: 'default',
|
|
1507
|
+
width: 80,
|
|
1508
|
+
whitespaceBreak: true
|
|
1509
|
+
}, (err, data)=>{
|
|
1510
|
+
if (err) {
|
|
1511
|
+
logger.debug('Failed to generate figlet text');
|
|
1512
|
+
resolve('c15t');
|
|
1513
|
+
} else resolve(data || 'c15t');
|
|
1514
|
+
});
|
|
1515
|
+
});
|
|
1516
|
+
} catch (error) {
|
|
1517
|
+
logger.debug('Error generating figlet text', error);
|
|
775
1518
|
}
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
|
|
1519
|
+
const customColor = {
|
|
1520
|
+
teal10: (text)=>`\x1b[38;2;10;80;70m${text}\x1b[0m`,
|
|
1521
|
+
teal20: (text)=>`\x1b[38;2;15;100;90m${text}\x1b[0m`,
|
|
1522
|
+
teal30: (text)=>`\x1b[38;2;20;120;105m${text}\x1b[0m`,
|
|
1523
|
+
teal40: (text)=>`\x1b[38;2;25;150;130m${text}\x1b[0m`,
|
|
1524
|
+
teal50: (text)=>`\x1b[38;2;30;170;150m${text}\x1b[0m`,
|
|
1525
|
+
teal75: (text)=>`\x1b[38;2;34;211;187m${text}\x1b[0m`,
|
|
1526
|
+
teal90: (text)=>`\x1b[38;2;45;225;205m${text}\x1b[0m`,
|
|
1527
|
+
teal100: (text)=>`\x1b[38;2;65;235;220m${text}\x1b[0m`
|
|
1528
|
+
};
|
|
1529
|
+
const lines = figletText.split('\n');
|
|
1530
|
+
const coloredLines = lines.map((line, index)=>{
|
|
1531
|
+
const position = index / (lines.length - 1);
|
|
1532
|
+
if (position < 0.1) return customColor.teal10(line);
|
|
1533
|
+
if (position < 0.2) return customColor.teal20(line);
|
|
1534
|
+
if (position < 0.3) return customColor.teal30(line);
|
|
1535
|
+
if (position < 0.4) return customColor.teal40(line);
|
|
1536
|
+
if (position < 0.5) return customColor.teal50(line);
|
|
1537
|
+
if (position < 0.65) return customColor.teal75(line);
|
|
1538
|
+
if (position < 0.8) return customColor.teal90(line);
|
|
1539
|
+
return customColor.teal100(line);
|
|
779
1540
|
});
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1541
|
+
logger.message(coloredLines.join('\n'));
|
|
1542
|
+
}
|
|
1543
|
+
function createConfigManagement(context) {
|
|
1544
|
+
const { logger, error } = context;
|
|
1545
|
+
return {
|
|
1546
|
+
loadConfig: async ()=>{
|
|
1547
|
+
logger.debug('Attempting to load configuration...');
|
|
1548
|
+
try {
|
|
1549
|
+
const configResult = await getConfig(context);
|
|
1550
|
+
const config = configResult ?? null;
|
|
1551
|
+
logger.debug('Config loading result:', config);
|
|
1552
|
+
if (config) logger.debug('Configuration loaded successfully.');
|
|
1553
|
+
else logger.debug('No configuration found.');
|
|
1554
|
+
return config;
|
|
1555
|
+
} catch (err) {
|
|
1556
|
+
return error.handleError(err, 'Error loading configuration');
|
|
1557
|
+
}
|
|
1558
|
+
},
|
|
1559
|
+
requireConfig: async ()=>{
|
|
1560
|
+
const config = await context.config.loadConfig();
|
|
1561
|
+
if (!config) return error.handleError(new Error('Configuration required but not found'), 'Missing required configuration');
|
|
1562
|
+
return config;
|
|
1563
|
+
},
|
|
1564
|
+
getPathAliases: (configDir)=>{
|
|
1565
|
+
const cwd = configDir || context.cwd;
|
|
1566
|
+
const tsConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'tsconfig.json');
|
|
1567
|
+
const jsConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'jsconfig.json');
|
|
1568
|
+
const configPath = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(tsConfigPath) ? tsConfigPath : __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(jsConfigPath) ? jsConfigPath : null;
|
|
1569
|
+
if (!configPath) return null;
|
|
1570
|
+
try {
|
|
1571
|
+
return extractAliasesFromConfigFile(context, configPath, cwd);
|
|
1572
|
+
} catch (extractError) {
|
|
1573
|
+
logger.warn(`Error extracting path aliases from ${configPath}:`, extractError);
|
|
1574
|
+
return null;
|
|
1575
|
+
}
|
|
790
1576
|
}
|
|
791
|
-
|
|
792
|
-
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
function stripJsonComments(jsonString) {
|
|
1580
|
+
return jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g)=>g ? '' : m).replace(/,(?=\s*[}\]])/g, '');
|
|
1581
|
+
}
|
|
1582
|
+
function extractAliasesFromConfigFile(context, configPath, cwd) {
|
|
1583
|
+
try {
|
|
1584
|
+
const configContent = __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(configPath, 'utf8');
|
|
1585
|
+
const strippedConfigContent = stripJsonComments(configContent);
|
|
1586
|
+
const config = JSON.parse(strippedConfigContent);
|
|
1587
|
+
const { paths = {}, baseUrl = '.' } = config.compilerOptions || {};
|
|
1588
|
+
const result = {};
|
|
1589
|
+
const obj = Object.entries(paths);
|
|
1590
|
+
for (const [alias, aliasPaths] of obj)for (const aliasedPath of aliasPaths){
|
|
1591
|
+
const resolvedBaseUrl = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, baseUrl);
|
|
1592
|
+
const finalAlias = '*' === alias.slice(-1) ? alias.slice(0, -1) : alias;
|
|
1593
|
+
const finalAliasedPath = '*' === aliasedPath.slice(-1) ? aliasedPath.slice(0, -1) : aliasedPath;
|
|
1594
|
+
result[finalAlias || ''] = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(resolvedBaseUrl, finalAliasedPath);
|
|
1595
|
+
}
|
|
1596
|
+
if (hasSvelteKit(cwd)) addSvelteKitEnvModules(result);
|
|
1597
|
+
return result;
|
|
1598
|
+
} catch (error) {
|
|
1599
|
+
context.logger.warn(`Error parsing config file ${configPath}`, error);
|
|
1600
|
+
return null;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
function hasSvelteKit(cwd) {
|
|
1604
|
+
try {
|
|
1605
|
+
const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'package.json');
|
|
1606
|
+
if (!__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].existsSync(packageJsonPath)) return false;
|
|
1607
|
+
const packageJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].readFileSync(packageJsonPath, 'utf8'));
|
|
1608
|
+
const deps = {
|
|
1609
|
+
...packageJson.dependencies,
|
|
1610
|
+
...packageJson.devDependencies
|
|
1611
|
+
};
|
|
1612
|
+
return '@sveltejs/kit' in deps;
|
|
1613
|
+
} catch (error) {
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function addSvelteKitEnvModules(aliases) {
|
|
1618
|
+
aliases['$app/'] = '$app/';
|
|
1619
|
+
aliases['$lib/'] = '$lib/';
|
|
1620
|
+
aliases['$env/'] = '$env/';
|
|
1621
|
+
aliases['$service-worker'] = '$service-worker';
|
|
1622
|
+
}
|
|
1623
|
+
function createErrorHandlers(context) {
|
|
1624
|
+
const { logger } = context;
|
|
1625
|
+
return {
|
|
1626
|
+
handleError: (error, message)=>{
|
|
1627
|
+
logger.error(message, error);
|
|
1628
|
+
if (error instanceof Error) logger.error(error.message);
|
|
1629
|
+
else logger.error(String(error));
|
|
1630
|
+
logger.failed(`${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].red('Operation failed unexpectedly.')}`);
|
|
1631
|
+
process.exit(1);
|
|
1632
|
+
},
|
|
1633
|
+
handleCancel: (message = 'Operation cancelled.')=>{
|
|
1634
|
+
logger.debug(`Handling cancellation: ${message}`);
|
|
1635
|
+
logger.failed(message);
|
|
793
1636
|
process.exit(0);
|
|
794
1637
|
}
|
|
795
|
-
|
|
796
|
-
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
function createFileSystem(context) {
|
|
1641
|
+
const { logger, cwd } = context;
|
|
1642
|
+
return {
|
|
1643
|
+
getPackageInfo: ()=>{
|
|
1644
|
+
logger.debug('Reading package.json');
|
|
1645
|
+
const packageJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(cwd, 'package.json');
|
|
1646
|
+
logger.debug(`package.json path: ${packageJsonPath}`);
|
|
1647
|
+
try {
|
|
1648
|
+
const packageInfo = __WEBPACK_EXTERNAL_MODULE_fs_extra_ce68a66b__["default"].readJSONSync(packageJsonPath);
|
|
1649
|
+
logger.debug('Successfully read package.json');
|
|
1650
|
+
return {
|
|
1651
|
+
name: packageInfo?.name || 'unknown',
|
|
1652
|
+
version: packageInfo?.version || 'unknown',
|
|
1653
|
+
...packageInfo
|
|
1654
|
+
};
|
|
1655
|
+
} catch (error) {
|
|
1656
|
+
logger.error(`Error reading package.json at ${packageJsonPath}:`, error);
|
|
1657
|
+
return {
|
|
1658
|
+
name: 'unknown',
|
|
1659
|
+
version: 'unknown'
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
const globalFlags = [
|
|
1666
|
+
{
|
|
1667
|
+
names: [
|
|
1668
|
+
'--help',
|
|
1669
|
+
'-h'
|
|
1670
|
+
],
|
|
1671
|
+
description: 'Show this help message.',
|
|
1672
|
+
type: 'special',
|
|
1673
|
+
expectsValue: false
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
names: [
|
|
1677
|
+
'--version',
|
|
1678
|
+
'-v'
|
|
1679
|
+
],
|
|
1680
|
+
description: 'Show the CLI version.',
|
|
1681
|
+
type: 'special',
|
|
1682
|
+
expectsValue: false
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
names: [
|
|
1686
|
+
'--logger'
|
|
1687
|
+
],
|
|
1688
|
+
description: 'Set log level (fatal, error, warn, info, debug).',
|
|
1689
|
+
type: 'string',
|
|
1690
|
+
expectsValue: true
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
names: [
|
|
1694
|
+
'--config'
|
|
1695
|
+
],
|
|
1696
|
+
description: 'Specify path to configuration file.',
|
|
1697
|
+
type: 'string',
|
|
1698
|
+
expectsValue: true
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
names: [
|
|
1702
|
+
'-y'
|
|
1703
|
+
],
|
|
1704
|
+
description: 'Skip confirmation prompts (use with caution).',
|
|
1705
|
+
type: 'boolean',
|
|
1706
|
+
expectsValue: false
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
names: [
|
|
1710
|
+
'--no-telemetry'
|
|
1711
|
+
],
|
|
1712
|
+
description: 'Disable telemetry data collection.',
|
|
1713
|
+
type: 'boolean',
|
|
1714
|
+
expectsValue: false
|
|
1715
|
+
}
|
|
1716
|
+
];
|
|
1717
|
+
function parseCliArgs(rawArgs, commands) {
|
|
1718
|
+
const parsedFlags = {};
|
|
1719
|
+
const potentialCommandArgsAndUndefined = [];
|
|
1720
|
+
let commandName;
|
|
1721
|
+
const commandArgs = [];
|
|
1722
|
+
for (const flag of globalFlags){
|
|
1723
|
+
const primaryName = flag.names[0]?.replace(/^--/, '').replace(/^-/, '');
|
|
1724
|
+
if (primaryName) parsedFlags[primaryName] = 'boolean' === flag.type ? false : void 0;
|
|
1725
|
+
}
|
|
1726
|
+
for(let i = 0; i < rawArgs.length; i++){
|
|
1727
|
+
const arg = rawArgs[i];
|
|
1728
|
+
if ('string' != typeof arg) continue;
|
|
1729
|
+
let argIsFlagOrValue = false;
|
|
1730
|
+
for (const flag of globalFlags)if (flag.names.includes(arg)) {
|
|
1731
|
+
const primaryName = flag.names[0]?.replace(/^--/, '').replace(/^-/, '');
|
|
1732
|
+
if (primaryName) {
|
|
1733
|
+
argIsFlagOrValue = true;
|
|
1734
|
+
if ('boolean' === flag.type) parsedFlags[primaryName] = true;
|
|
1735
|
+
else if (flag.expectsValue) {
|
|
1736
|
+
const nextArg = rawArgs[i + 1];
|
|
1737
|
+
if (nextArg && !nextArg.startsWith('-')) {
|
|
1738
|
+
parsedFlags[primaryName] = nextArg;
|
|
1739
|
+
i++;
|
|
1740
|
+
} else __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.log.warn(formatLogMessage('warn', `Flag ${arg} expects a value, but none was found or the next item is a flag.`));
|
|
1741
|
+
} else parsedFlags[primaryName] = true;
|
|
1742
|
+
}
|
|
1743
|
+
break;
|
|
1744
|
+
}
|
|
1745
|
+
if (!argIsFlagOrValue) potentialCommandArgsAndUndefined.push(arg);
|
|
797
1746
|
}
|
|
798
|
-
const
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
1747
|
+
const potentialCommandArgs = potentialCommandArgsAndUndefined.filter((arg)=>'string' == typeof arg);
|
|
1748
|
+
commandName = potentialCommandArgs.find((arg)=>commands.some((cmd)=>cmd.name === arg));
|
|
1749
|
+
for (const arg of potentialCommandArgs)if (arg !== commandName) commandArgs.push(arg);
|
|
1750
|
+
return {
|
|
1751
|
+
commandName,
|
|
1752
|
+
commandArgs,
|
|
1753
|
+
parsedFlags
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
function createUserInteraction(context) {
|
|
1757
|
+
const { logger, error } = context;
|
|
1758
|
+
return {
|
|
1759
|
+
confirm: async (message, initialValue)=>{
|
|
1760
|
+
logger.debug(`Confirm action: "${message}", Initial: ${initialValue}`);
|
|
1761
|
+
const confirmed = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.confirm({
|
|
1762
|
+
message,
|
|
1763
|
+
initialValue
|
|
1764
|
+
});
|
|
1765
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(confirmed)) {
|
|
1766
|
+
error.handleCancel();
|
|
1767
|
+
return false;
|
|
1768
|
+
}
|
|
1769
|
+
logger.debug(`Confirmation result: ${confirmed}`);
|
|
1770
|
+
return confirmed;
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
function createCliContext(rawArgs, cwd, commands) {
|
|
1775
|
+
const { commandName, commandArgs, parsedFlags } = parseCliArgs(rawArgs, commands);
|
|
1776
|
+
let desiredLogLevel = 'info';
|
|
1777
|
+
const levelArg = parsedFlags.logger;
|
|
1778
|
+
if ('string' == typeof levelArg) if (validLogLevels.includes(levelArg)) desiredLogLevel = levelArg;
|
|
1779
|
+
else console.warn(`[CLI Setup] Invalid log level '${levelArg}' provided via --logger. Using default 'info'.`);
|
|
1780
|
+
else if (true === levelArg) console.warn("[CLI Setup] --logger flag found but no level specified. Using default 'info'.");
|
|
1781
|
+
const logger = createCliLogger(desiredLogLevel);
|
|
1782
|
+
logger.debug(`Logger initialized with level: ${desiredLogLevel}`);
|
|
1783
|
+
const baseContext = {
|
|
1784
|
+
logger,
|
|
1785
|
+
flags: parsedFlags,
|
|
1786
|
+
commandName,
|
|
1787
|
+
commandArgs,
|
|
1788
|
+
cwd
|
|
1789
|
+
};
|
|
1790
|
+
const context = baseContext;
|
|
1791
|
+
context.error = createErrorHandlers(context);
|
|
1792
|
+
const userInteraction = createUserInteraction(context);
|
|
1793
|
+
context.confirm = userInteraction.confirm;
|
|
1794
|
+
context.config = createConfigManagement(context);
|
|
1795
|
+
context.fs = createFileSystem(context);
|
|
1796
|
+
const telemetryDisabled = true === parsedFlags['no-telemetry'];
|
|
1797
|
+
context.telemetry = createTelemetry({
|
|
1798
|
+
disabled: telemetryDisabled,
|
|
1799
|
+
defaultProperties: {
|
|
1800
|
+
cliVersion: context.fs.getPackageInfo().version
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
context.telemetry.setLogLevel(desiredLogLevel);
|
|
1804
|
+
if (telemetryDisabled) logger.debug('Telemetry is disabled by user preference');
|
|
1805
|
+
else logger.debug('Telemetry initialized');
|
|
1806
|
+
logger.debug('CLI context fully initialized with all utilities');
|
|
1807
|
+
return context;
|
|
1808
|
+
}
|
|
1809
|
+
const src_commands = [
|
|
1810
|
+
{
|
|
1811
|
+
name: 'generate',
|
|
1812
|
+
label: 'generate',
|
|
1813
|
+
hint: 'Generate schema/code',
|
|
1814
|
+
description: 'Generate schema/code based on your c15t config.',
|
|
1815
|
+
action: (context)=>generate(context)
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
name: 'migrate',
|
|
1819
|
+
label: 'migrate',
|
|
1820
|
+
hint: 'Run database migrations',
|
|
1821
|
+
description: 'Run database migrations based on your c15t config.',
|
|
1822
|
+
action: (context)=>migrate(context)
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
name: 'github',
|
|
1826
|
+
label: 'Github',
|
|
1827
|
+
hint: 'Star us on GitHub',
|
|
1828
|
+
description: 'Open our GitHub repository to give us a star.',
|
|
1829
|
+
action: async (context)=>{
|
|
1830
|
+
const { logger } = context;
|
|
1831
|
+
logger.note(`We're building c15t as an ${__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].bold('open source')} project to make consent management more accessible.\nIf you find this useful, we'd really appreciate a GitHub star - it helps others discover the project!`, '⭐ Star Us on GitHub');
|
|
1832
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_open__["default"])('https://github.com/c15t/c15t');
|
|
1833
|
+
logger.success('Thank you for your support!');
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1836
|
+
{
|
|
1837
|
+
name: 'docs',
|
|
1838
|
+
label: 'c15t docs',
|
|
1839
|
+
hint: 'Open documentation',
|
|
1840
|
+
description: 'Open the c15t documentation in your browser.',
|
|
1841
|
+
action: async (context)=>{
|
|
1842
|
+
const { logger } = context;
|
|
1843
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_open__["default"])('https://c15t.com/docs?ref=cli');
|
|
1844
|
+
logger.success('Documentation opened in your browser.');
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
];
|
|
1848
|
+
async function main() {
|
|
1849
|
+
const rawArgs = process.argv.slice(2);
|
|
1850
|
+
const cwd = process.cwd();
|
|
1851
|
+
const context = createCliContext(rawArgs, cwd, src_commands);
|
|
1852
|
+
const { logger, flags, commandName, commandArgs, error, telemetry } = context;
|
|
1853
|
+
const packageInfo = context.fs.getPackageInfo();
|
|
1854
|
+
const version = packageInfo.version;
|
|
1855
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CLI_INVOKED, {
|
|
1856
|
+
version,
|
|
1857
|
+
nodeVersion: process.version,
|
|
1858
|
+
platform: process.platform
|
|
1859
|
+
});
|
|
1860
|
+
if (flags.version) {
|
|
1861
|
+
logger.debug('Version flag detected');
|
|
1862
|
+
logger.message(`c15t CLI version ${version}`);
|
|
1863
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.VERSION_DISPLAYED, {
|
|
1864
|
+
version
|
|
1865
|
+
});
|
|
1866
|
+
await telemetry.shutdown();
|
|
805
1867
|
process.exit(0);
|
|
806
1868
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
if (!migrate) {
|
|
815
|
-
const response = await (0, __WEBPACK_EXTERNAL_MODULE_prompts__["default"])({
|
|
816
|
-
type: 'confirm',
|
|
817
|
-
name: 'migrate',
|
|
818
|
-
message: 'Are you sure you want to run these migrations?',
|
|
819
|
-
initial: false
|
|
820
|
-
});
|
|
821
|
-
migrate = response.migrate;
|
|
822
|
-
}
|
|
823
|
-
if (!migrate) {
|
|
824
|
-
utils_logger.info('Migration cancelled.');
|
|
1869
|
+
if (flags.help) {
|
|
1870
|
+
logger.debug('Help flag detected. Displaying help and exiting.');
|
|
1871
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.HELP_DISPLAYED, {
|
|
1872
|
+
version
|
|
1873
|
+
});
|
|
1874
|
+
showHelpMenu(context, version, src_commands, globalFlags);
|
|
1875
|
+
await telemetry.shutdown();
|
|
825
1876
|
process.exit(0);
|
|
826
1877
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1878
|
+
logger.debug('Raw process arguments:', process.argv);
|
|
1879
|
+
logger.debug('Parsed command name:', commandName);
|
|
1880
|
+
logger.debug('Parsed command args:', commandArgs);
|
|
1881
|
+
logger.debug('Parsed global flags:', flags);
|
|
1882
|
+
await displayIntro(context, version);
|
|
1883
|
+
logger.debug(`Current working directory: ${cwd}`);
|
|
1884
|
+
logger.debug(`Config path flag: ${flags.config}`);
|
|
1885
|
+
let clientConfig;
|
|
1886
|
+
let backendConfig;
|
|
1887
|
+
try {
|
|
1888
|
+
const loadedConfig = await getConfig(context);
|
|
1889
|
+
if (loadedConfig) if (isClientOptions(loadedConfig)) clientConfig = loadedConfig;
|
|
1890
|
+
else if (isC15TOptions(loadedConfig)) backendConfig = loadedConfig;
|
|
1891
|
+
else logger.warn('Loaded configuration is of an unknown type.');
|
|
1892
|
+
if (loadedConfig) telemetry.trackEvent(telemetry_TelemetryEventName.CONFIG_LOADED, {
|
|
1893
|
+
configType: clientConfig ? 'client' : backendConfig ? 'backend' : 'unknown',
|
|
1894
|
+
hasBackend: Boolean(backendConfig)
|
|
1895
|
+
});
|
|
1896
|
+
} catch (loadError) {
|
|
1897
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CONFIG_ERROR, {
|
|
1898
|
+
error: loadError instanceof Error ? loadError.message : String(loadError)
|
|
1899
|
+
});
|
|
1900
|
+
return error.handleError(loadError, 'An unexpected error occurred during configuration loading');
|
|
1901
|
+
}
|
|
1902
|
+
if (!clientConfig) {
|
|
1903
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.ONBOARDING_STARTED, {});
|
|
1904
|
+
await startOnboarding(context);
|
|
1905
|
+
await telemetry.shutdown();
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1908
|
+
const coloredConsentIo = __WEBPACK_EXTERNAL_MODULE_picocolors__["default"].cyanBright('consent.io');
|
|
1909
|
+
const backendStatus = backendConfig ? 'Backend configuration loaded' : `Using ${coloredConsentIo} for your c15t deployment`;
|
|
1910
|
+
logger.info(`Client configuration successfully loaded and validated \n ${backendStatus}`);
|
|
1911
|
+
logger.debug('Client config details:', clientConfig);
|
|
1912
|
+
if (backendConfig) logger.debug('Backend config details:', backendConfig);
|
|
1913
|
+
try {
|
|
1914
|
+
if (commandName) {
|
|
1915
|
+
const command = src_commands.find((cmd)=>cmd.name === commandName);
|
|
1916
|
+
if (command) {
|
|
1917
|
+
logger.info(`Executing command: ${command.name}`);
|
|
1918
|
+
telemetry.trackCommand(command.name, commandArgs, flags);
|
|
1919
|
+
await command.action(context);
|
|
1920
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.COMMAND_SUCCEEDED, {
|
|
1921
|
+
command: command.name,
|
|
1922
|
+
executionTime: Date.now() - performance.now()
|
|
1923
|
+
});
|
|
1924
|
+
} else {
|
|
1925
|
+
logger.error(`Unknown command: ${commandName}`);
|
|
1926
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.COMMAND_UNKNOWN, {
|
|
1927
|
+
unknownCommand: commandName
|
|
1928
|
+
});
|
|
1929
|
+
logger.info('Run c15t --help to see available commands.');
|
|
1930
|
+
await telemetry.shutdown();
|
|
1931
|
+
process.exit(1);
|
|
1932
|
+
}
|
|
1933
|
+
} else {
|
|
1934
|
+
logger.debug('No command specified, entering interactive selection.');
|
|
1935
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.INTERACTIVE_MENU_OPENED, {});
|
|
1936
|
+
const promptOptions = src_commands.map((cmd)=>({
|
|
1937
|
+
value: cmd.name,
|
|
1938
|
+
label: cmd.label,
|
|
1939
|
+
hint: cmd.hint
|
|
1940
|
+
}));
|
|
1941
|
+
promptOptions.push({
|
|
1942
|
+
value: 'exit',
|
|
1943
|
+
label: 'exit',
|
|
1944
|
+
hint: 'Close the CLI'
|
|
1945
|
+
});
|
|
1946
|
+
const selectedCommandName = await __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.select({
|
|
1947
|
+
message: formatLogMessage('info', 'Which command would you like to run?'),
|
|
1948
|
+
options: promptOptions
|
|
1949
|
+
});
|
|
1950
|
+
if (__WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(selectedCommandName) || 'exit' === selectedCommandName) {
|
|
1951
|
+
logger.debug('Interactive selection cancelled or exit chosen.');
|
|
1952
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.INTERACTIVE_MENU_EXITED, {
|
|
1953
|
+
action: __WEBPACK_EXTERNAL_MODULE__clack_prompts_3cae1695__.isCancel(selectedCommandName) ? 'cancelled' : 'exit'
|
|
1954
|
+
});
|
|
1955
|
+
context.error.handleCancel('Operation cancelled.');
|
|
1956
|
+
} else {
|
|
1957
|
+
const selectedCommand = src_commands.find((cmd)=>cmd.name === selectedCommandName);
|
|
1958
|
+
if (selectedCommand) {
|
|
1959
|
+
logger.debug(`User selected command: ${selectedCommand.name}`);
|
|
1960
|
+
telemetry.trackCommand(selectedCommand.name, [], flags);
|
|
1961
|
+
await selectedCommand.action(context);
|
|
1962
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.COMMAND_SUCCEEDED, {
|
|
1963
|
+
command: selectedCommand.name,
|
|
1964
|
+
executionTime: Date.now() - performance.now()
|
|
1965
|
+
});
|
|
1966
|
+
} else {
|
|
1967
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.COMMAND_UNKNOWN, {
|
|
1968
|
+
unknownCommand: String(selectedCommandName)
|
|
1969
|
+
});
|
|
1970
|
+
error.handleError(new Error(`Command '${selectedCommandName}' not found`), 'An internal error occurred');
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
logger.debug('Command execution completed');
|
|
1975
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.CLI_COMPLETED, {
|
|
1976
|
+
success: true
|
|
1977
|
+
});
|
|
1978
|
+
} catch (executionError) {
|
|
1979
|
+
telemetry.trackEvent(telemetry_TelemetryEventName.COMMAND_FAILED, {
|
|
1980
|
+
command: commandName,
|
|
1981
|
+
error: executionError instanceof Error ? executionError.message : String(executionError)
|
|
1982
|
+
});
|
|
1983
|
+
error.handleError(executionError, 'An unexpected error occurred during command execution');
|
|
1984
|
+
}
|
|
1985
|
+
await telemetry.shutdown();
|
|
850
1986
|
}
|
|
851
1987
|
main();
|
|
1988
|
+
export { main };
|