@tostudy-ai/cli 0.11.0 → 0.11.2
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/bin/cli.js +0 -0
- package/dist/cli.js +466 -106
- package/dist/cli.js.map +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +16 -15
package/dist/cli.js
CHANGED
|
@@ -104,7 +104,7 @@ var require_picocolors = __commonJS({
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
// ../../node_modules/@parisgroup-ai/logger/dist/logger.base-
|
|
107
|
+
// ../../node_modules/@parisgroup-ai/logger/dist/logger.base-CG4i4G4l.mjs
|
|
108
108
|
function formatJson(entry) {
|
|
109
109
|
const { timestamp: timestamp2, level, message, service, environment, context, data, error: error49 } = entry;
|
|
110
110
|
const output3 = {
|
|
@@ -284,8 +284,8 @@ function extractErrorInfo(error49, includeStack) {
|
|
|
284
284
|
return info;
|
|
285
285
|
}
|
|
286
286
|
var import_picocolors, LOG_LEVELS, LEVEL_COLORS, LEVEL_WIDTH, SENSITIVE_FIELDS, sanitize, BaseLogger;
|
|
287
|
-
var
|
|
288
|
-
"../../node_modules/@parisgroup-ai/logger/dist/logger.base-
|
|
287
|
+
var init_logger_base_CG4i4G4l = __esm({
|
|
288
|
+
"../../node_modules/@parisgroup-ai/logger/dist/logger.base-CG4i4G4l.mjs"() {
|
|
289
289
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
290
290
|
LOG_LEVELS = {
|
|
291
291
|
trace: 0,
|
|
@@ -541,7 +541,7 @@ var init_logger_base_CHajMTDD = __esm({
|
|
|
541
541
|
}
|
|
542
542
|
});
|
|
543
543
|
|
|
544
|
-
// ../../node_modules/@parisgroup-ai/logger/dist/index.
|
|
544
|
+
// ../../node_modules/@parisgroup-ai/logger/dist/index.mjs
|
|
545
545
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
546
546
|
import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
547
547
|
import { join } from "node:path";
|
|
@@ -610,8 +610,8 @@ function createLogger(module, options) {
|
|
|
610
610
|
}
|
|
611
611
|
var asyncLocalStorage, ConsoleTransport, FileTransport, HttpTransport, SINGLETON_KEY, Logger, logger;
|
|
612
612
|
var init_dist = __esm({
|
|
613
|
-
"../../node_modules/@parisgroup-ai/logger/dist/index.
|
|
614
|
-
|
|
613
|
+
"../../node_modules/@parisgroup-ai/logger/dist/index.mjs"() {
|
|
614
|
+
init_logger_base_CG4i4G4l();
|
|
615
615
|
asyncLocalStorage = new AsyncLocalStorage();
|
|
616
616
|
ConsoleTransport = class {
|
|
617
617
|
log(entry, formatted) {
|
|
@@ -859,6 +859,21 @@ function createHttpProvider(apiUrl, token2) {
|
|
|
859
859
|
const res = await apiFetch(`${base}/courses`, token2);
|
|
860
860
|
return res.courses;
|
|
861
861
|
},
|
|
862
|
+
listCreatorCourses: async (filters) => {
|
|
863
|
+
const params = new URLSearchParams();
|
|
864
|
+
params.append("status", filters.status || "all");
|
|
865
|
+
if (filters.search) params.append("search", filters.search);
|
|
866
|
+
if (filters.sortBy) params.append("sortBy", filters.sortBy);
|
|
867
|
+
if (filters.sortOrder) params.append("sortOrder", filters.sortOrder);
|
|
868
|
+
if (filters.limit) params.append("limit", filters.limit.toString());
|
|
869
|
+
if (filters.offset) params.append("offset", filters.offset.toString());
|
|
870
|
+
if (filters.projectId) params.append("projectId", filters.projectId);
|
|
871
|
+
const res = await apiFetch(
|
|
872
|
+
`${base}/creator-courses?${params.toString()}`,
|
|
873
|
+
token2
|
|
874
|
+
);
|
|
875
|
+
return res.courses;
|
|
876
|
+
},
|
|
862
877
|
select: async (_userId, courseId) => {
|
|
863
878
|
const res = await apiFetch(`${base}/courses/select`, token2, {
|
|
864
879
|
method: "POST",
|
|
@@ -1265,12 +1280,16 @@ function formatCourseList(courses3) {
|
|
|
1265
1280
|
month: "short",
|
|
1266
1281
|
day: "numeric"
|
|
1267
1282
|
}) : null;
|
|
1268
|
-
|
|
1283
|
+
const archivedBadge = course.status === "archived" ? " [ARQUIVADO]" : "";
|
|
1284
|
+
lines.push(` ${idx + 1}. ${course.title}${archivedBadge}`);
|
|
1269
1285
|
lines.push(` ${bar}`);
|
|
1270
1286
|
lines.push(` Professor: ${course.creatorName}`);
|
|
1271
1287
|
if (enrolledDate) {
|
|
1272
1288
|
lines.push(` Inscrito em: ${enrolledDate}`);
|
|
1273
1289
|
}
|
|
1290
|
+
if (course.status === "archived") {
|
|
1291
|
+
lines.push(` \u26A0 Arquivado \u2014 somente leitura (use \`tostudy lesson\`)`);
|
|
1292
|
+
}
|
|
1274
1293
|
lines.push("");
|
|
1275
1294
|
});
|
|
1276
1295
|
lines.push("\u2192 tostudy select <n\xFAmero> para ativar um curso");
|
|
@@ -1291,10 +1310,19 @@ function formatProgress(data) {
|
|
|
1291
1310
|
`Li\xE7\xF5es conclu\xEDdas: ${data.completedLessons}`,
|
|
1292
1311
|
`Tempo restante estimado: ~${data.estimatedMinutesRemaining} min`,
|
|
1293
1312
|
"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
1294
|
-
""
|
|
1295
|
-
"\u2192 tostudy next para avan\xE7ar para a pr\xF3xima li\xE7\xE3o",
|
|
1296
|
-
"\u2192 tostudy lesson para ver o conte\xFAdo da li\xE7\xE3o atual"
|
|
1313
|
+
""
|
|
1297
1314
|
];
|
|
1315
|
+
if (data.isArchived) {
|
|
1316
|
+
lines.push(
|
|
1317
|
+
"\u26A0 Curso arquivado \u2014 somente leitura.",
|
|
1318
|
+
"\u2192 tostudy lesson para reler o conte\xFAdo j\xE1 estudado"
|
|
1319
|
+
);
|
|
1320
|
+
} else {
|
|
1321
|
+
lines.push(
|
|
1322
|
+
"\u2192 tostudy next para avan\xE7ar para a pr\xF3xima li\xE7\xE3o",
|
|
1323
|
+
"\u2192 tostudy lesson para ver o conte\xFAdo da li\xE7\xE3o atual"
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1298
1326
|
return lines.join("\n");
|
|
1299
1327
|
}
|
|
1300
1328
|
function formatLesson(data) {
|
|
@@ -2303,7 +2331,9 @@ var init_errors_pt_br = __esm({
|
|
|
2303
2331
|
vaultNotFound: "\u274C Vault n\xE3o encontrado. Execute 'tostudy vault init' primeiro.\n",
|
|
2304
2332
|
logoutSuccess: "\n Deslogado com sucesso.\n",
|
|
2305
2333
|
workspaceCommandDescription: "Gerenciar workspace de estudo local",
|
|
2306
|
-
workspaceSetupDescription: "Criar estrutura do workspace para o curso ativo"
|
|
2334
|
+
workspaceSetupDescription: "Criar estrutura do workspace para o curso ativo",
|
|
2335
|
+
insufficientCredits: "\u274C Voc\xEA est\xE1 sem cr\xE9ditos. Cada resposta do tutor de IA consome cr\xE9ditos para cobrir o processamento. Recarregue em https://tostudy.ai/student/credits para continuar de onde parou.\n",
|
|
2336
|
+
courseArchived: "Este curso foi arquivado e est\xE1 dispon\xEDvel somente para leitura.\nUse `tostudy lesson` para revisar o conte\xFAdo j\xE1 estudado.\n"
|
|
2307
2337
|
};
|
|
2308
2338
|
}
|
|
2309
2339
|
});
|
|
@@ -2320,7 +2350,9 @@ var init_errors_en_us = __esm({
|
|
|
2320
2350
|
vaultNotFound: "\u274C Vault not found. Run 'tostudy vault init' first.\n",
|
|
2321
2351
|
logoutSuccess: "\n Logged out successfully.\n",
|
|
2322
2352
|
workspaceCommandDescription: "Manage local study workspace",
|
|
2323
|
-
workspaceSetupDescription: "Create the workspace structure for the active course"
|
|
2353
|
+
workspaceSetupDescription: "Create the workspace structure for the active course",
|
|
2354
|
+
insufficientCredits: "\u274C You're out of credits. Every reply from the AI tutor uses credits to cover processing. Top up at https://tostudy.ai/student/credits to continue from where you stopped.\n",
|
|
2355
|
+
courseArchived: "This course has been archived and is available for reading only.\nUse `tostudy lesson` to review the content you've already studied.\n"
|
|
2324
2356
|
};
|
|
2325
2357
|
}
|
|
2326
2358
|
});
|
|
@@ -2348,6 +2380,14 @@ function resolveLocale() {
|
|
|
2348
2380
|
function getErrors(locale) {
|
|
2349
2381
|
return BUNDLES[locale ?? resolveLocale()];
|
|
2350
2382
|
}
|
|
2383
|
+
function isInsufficientCreditsError(err) {
|
|
2384
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2385
|
+
return msg.includes("INSUFFICIENT_CREDITS");
|
|
2386
|
+
}
|
|
2387
|
+
function isCourseArchivedError(err) {
|
|
2388
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2389
|
+
return msg.includes("COURSE_ARCHIVED");
|
|
2390
|
+
}
|
|
2351
2391
|
var BUNDLES, _cachedLocale;
|
|
2352
2392
|
var init_errors = __esm({
|
|
2353
2393
|
"src/errors/index.ts"() {
|
|
@@ -2544,7 +2584,7 @@ var CLI_VERSION;
|
|
|
2544
2584
|
var init_version = __esm({
|
|
2545
2585
|
"src/version.ts"() {
|
|
2546
2586
|
"use strict";
|
|
2547
|
-
CLI_VERSION = true ? "0.11.
|
|
2587
|
+
CLI_VERSION = true ? "0.11.2" : "0.7.1";
|
|
2548
2588
|
}
|
|
2549
2589
|
});
|
|
2550
2590
|
|
|
@@ -2947,16 +2987,24 @@ var init_courses2 = __esm({
|
|
|
2947
2987
|
init_guards();
|
|
2948
2988
|
init_formatter();
|
|
2949
2989
|
logger4 = createLogger("cli:courses");
|
|
2950
|
-
coursesCommand = new Command5("courses").description("List your enrolled courses with progress").option("--json", "Output structured JSON").action(async (opts) => {
|
|
2990
|
+
coursesCommand = new Command5("courses").description("List your enrolled courses with progress").option("--json", "Output structured JSON").option("--mine", "List only your own courses, including drafts").action(async (opts) => {
|
|
2951
2991
|
try {
|
|
2952
2992
|
const session = await requireSession();
|
|
2953
2993
|
const data = createHttpProvider(session.apiUrl, session.token);
|
|
2954
2994
|
const deps = { data, logger: logger4 };
|
|
2955
|
-
|
|
2995
|
+
let coursesToList;
|
|
2996
|
+
if (opts.mine) {
|
|
2997
|
+
coursesToList = await data.courses.listCreatorCourses({
|
|
2998
|
+
userId: session.userId,
|
|
2999
|
+
status: "all"
|
|
3000
|
+
});
|
|
3001
|
+
} else {
|
|
3002
|
+
coursesToList = await listCourses({ userId: session.userId }, deps);
|
|
3003
|
+
}
|
|
2956
3004
|
if (opts.json) {
|
|
2957
|
-
output(
|
|
3005
|
+
output(coursesToList, { json: true });
|
|
2958
3006
|
} else {
|
|
2959
|
-
output(formatCourseList(
|
|
3007
|
+
output(formatCourseList(coursesToList), { json: false });
|
|
2960
3008
|
}
|
|
2961
3009
|
} catch (err) {
|
|
2962
3010
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -28729,6 +28777,12 @@ var init_users = __esm({
|
|
|
28729
28777
|
// Stripe Integration
|
|
28730
28778
|
stripeCustomerId: varchar("stripe_customer_id", { length: 255 }),
|
|
28731
28779
|
// Stripe Customer ID (cus_xxx) for payment method reuse
|
|
28780
|
+
// Paris Group integration: server-to-server provisioning attribution.
|
|
28781
|
+
// Set by `POST /api/internal/v1/cohort-enrollments` so the same paris
|
|
28782
|
+
// participant maps idempotently to a single tostudy user, and outbound
|
|
28783
|
+
// webhooks can scope themselves to `provisioning_source='paris-immersion'`.
|
|
28784
|
+
provisioningSource: text("provisioning_source"),
|
|
28785
|
+
externalUserId: text("external_user_id"),
|
|
28732
28786
|
metadata: jsonb("metadata").$type().default({}),
|
|
28733
28787
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
28734
28788
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
|
|
@@ -28747,7 +28801,12 @@ var init_users = __esm({
|
|
|
28747
28801
|
// FEAT-754: Portfolio index for public portfolio queries
|
|
28748
28802
|
portfolioEnabledIdx: index("users_portfolio_enabled_idx").on(table.portfolioEnabled),
|
|
28749
28803
|
// Admin analytics: date-range queries on users.createdAt (gte/lte)
|
|
28750
|
-
createdAtIdx: index("users_created_at_idx").on(table.createdAt)
|
|
28804
|
+
createdAtIdx: index("users_created_at_idx").on(table.createdAt),
|
|
28805
|
+
// Paris Group integration: composite lookup for idempotent provisioning.
|
|
28806
|
+
externalIdIdx: index("idx_users_external_id").on(
|
|
28807
|
+
table.provisioningSource,
|
|
28808
|
+
table.externalUserId
|
|
28809
|
+
)
|
|
28751
28810
|
})
|
|
28752
28811
|
);
|
|
28753
28812
|
}
|
|
@@ -28888,6 +28947,8 @@ var init_user_preferences = __esm({
|
|
|
28888
28947
|
emailNewReplies: boolean("email_new_replies").default(true).notNull(),
|
|
28889
28948
|
/** Whether user wants push notifications for mentorship (via MCP) */
|
|
28890
28949
|
pushMentoria: boolean("push_mentoria").default(true).notNull(),
|
|
28950
|
+
// i18n nickname pilot column (dogfooding)
|
|
28951
|
+
nicknameI18n: jsonb("nickname_i18n").$type(),
|
|
28891
28952
|
// Timestamps
|
|
28892
28953
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
28893
28954
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
@@ -29071,6 +29132,20 @@ var init_course_categories = __esm({
|
|
|
29071
29132
|
}
|
|
29072
29133
|
});
|
|
29073
29134
|
|
|
29135
|
+
// ../../packages/database/src/schema/course-visibility.ts
|
|
29136
|
+
var courseVisibilityEnum;
|
|
29137
|
+
var init_course_visibility = __esm({
|
|
29138
|
+
"../../packages/database/src/schema/course-visibility.ts"() {
|
|
29139
|
+
"use strict";
|
|
29140
|
+
init_pg_core();
|
|
29141
|
+
courseVisibilityEnum = pgEnum("course_visibility", [
|
|
29142
|
+
"public",
|
|
29143
|
+
"unlisted",
|
|
29144
|
+
"private_allowlist"
|
|
29145
|
+
]);
|
|
29146
|
+
}
|
|
29147
|
+
});
|
|
29148
|
+
|
|
29074
29149
|
// ../../packages/database/src/schema/courses.ts
|
|
29075
29150
|
var courseStatusEnum, courseFormatEnum, courseLevelEnum, creatorReviewStatusEnum, studyChannelEnum, courses;
|
|
29076
29151
|
var init_courses3 = __esm({
|
|
@@ -29079,6 +29154,7 @@ var init_courses3 = __esm({
|
|
|
29079
29154
|
init_pg_core();
|
|
29080
29155
|
init_users();
|
|
29081
29156
|
init_course_categories();
|
|
29157
|
+
init_course_visibility();
|
|
29082
29158
|
courseStatusEnum = pgEnum("course_status", [
|
|
29083
29159
|
"draft",
|
|
29084
29160
|
"pending_review",
|
|
@@ -29111,6 +29187,7 @@ var init_courses3 = __esm({
|
|
|
29111
29187
|
type: varchar("type", { length: 50 }),
|
|
29112
29188
|
// "self-paced" | "with-mentorship"
|
|
29113
29189
|
status: courseStatusEnum("status").default("draft"),
|
|
29190
|
+
visibility: courseVisibilityEnum("visibility").default("public").notNull(),
|
|
29114
29191
|
featured: boolean("featured").default(false).notNull(),
|
|
29115
29192
|
verified: boolean("verified").default(false).notNull(),
|
|
29116
29193
|
isEssential: boolean("is_essential").default(false).notNull(),
|
|
@@ -29206,7 +29283,20 @@ var init_courses3 = __esm({
|
|
|
29206
29283
|
// Widened to 800 in BUG-1346 (GH #382) — `deriveCertificateSummary` can
|
|
29207
29284
|
// return up to 203 chars (truncated + "..."), and AI-path edge cases
|
|
29208
29285
|
// exceeded varchar(200) silently. 800 covers worst observed (~660) + buffer.
|
|
29209
|
-
certificateSummary: varchar("certificate_summary", { length: 800 })
|
|
29286
|
+
certificateSummary: varchar("certificate_summary", { length: 800 }),
|
|
29287
|
+
/**
|
|
29288
|
+
* paris-immersion onboarding gate: true quando o curso foi endossado
|
|
29289
|
+
* pela equipe Paris para ser servido como onboarding de turmas. Default
|
|
29290
|
+
* false. NÃO afeta o marketplace ou a publicação normal — apenas o
|
|
29291
|
+
* endpoint `/api/internal/v1/courses?tag=paris-onboarding&endorsed=true`
|
|
29292
|
+
* filtra por este campo.
|
|
29293
|
+
*
|
|
29294
|
+
* Auto-marcado true quando o creator está em `paris_authorized_creators`
|
|
29295
|
+
* E o curso tem `tags` contendo 'paris-onboarding' (ver application/paris-endorsement.ts).
|
|
29296
|
+
* Admins paris-immersion podem endossar manualmente via
|
|
29297
|
+
* POST /api/internal/v1/courses/:slug/endorse.
|
|
29298
|
+
*/
|
|
29299
|
+
parisEndorsed: boolean("paris_endorsed").default(false).notNull()
|
|
29210
29300
|
},
|
|
29211
29301
|
(table) => ({
|
|
29212
29302
|
creatorIdIdx: index("courses_creator_id_idx").on(table.creatorId),
|
|
@@ -29233,6 +29323,8 @@ var init_courses3 = __esm({
|
|
|
29233
29323
|
// B-tree for FIFO ordering
|
|
29234
29324
|
statusSubmittedIdx: index("courses_status_submitted_idx").on(table.status, table.submittedAt),
|
|
29235
29325
|
// Composite for queue queries
|
|
29326
|
+
visibilityIdx: index("courses_visibility_idx").on(table.visibility),
|
|
29327
|
+
statusVisibilityIdx: index("courses_status_visibility_idx").on(table.status, table.visibility),
|
|
29236
29328
|
// Course completeness tracking index
|
|
29237
29329
|
completenessStatusIdx: index("courses_completeness_status_idx").on(table.completenessStatus),
|
|
29238
29330
|
// Verified Seal Quality System - Indexes for quality metrics filtering
|
|
@@ -29770,6 +29862,9 @@ var init_badges = __esm({
|
|
|
29770
29862
|
// Link to specific module (for module badges)
|
|
29771
29863
|
isEssentialBadge: boolean("is_essential_badge").default(false).notNull(),
|
|
29772
29864
|
// Flag for essential course badges
|
|
29865
|
+
// i18n dynamic translation pilot columns (Expand pattern)
|
|
29866
|
+
nameI18n: jsonb("name_i18n").$type(),
|
|
29867
|
+
descriptionI18n: jsonb("description_i18n").$type(),
|
|
29773
29868
|
// Display
|
|
29774
29869
|
order: integer("order").notNull().default(0),
|
|
29775
29870
|
// Display order
|
|
@@ -30203,6 +30298,34 @@ var init_course_reports = __esm({
|
|
|
30203
30298
|
}
|
|
30204
30299
|
});
|
|
30205
30300
|
|
|
30301
|
+
// ../../packages/database/src/schema/cohorts.ts
|
|
30302
|
+
var cohorts;
|
|
30303
|
+
var init_cohorts = __esm({
|
|
30304
|
+
"../../packages/database/src/schema/cohorts.ts"() {
|
|
30305
|
+
"use strict";
|
|
30306
|
+
init_pg_core();
|
|
30307
|
+
cohorts = pgTable(
|
|
30308
|
+
"cohorts",
|
|
30309
|
+
{
|
|
30310
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
30311
|
+
slug: text("slug").notNull().unique(),
|
|
30312
|
+
name: text("name").notNull(),
|
|
30313
|
+
/** e.g. "paris-immersion" — namespace for the external system that owns this cohort. */
|
|
30314
|
+
source: text("source").notNull(),
|
|
30315
|
+
/** Stable identifier in the source system (e.g. immersion slug). */
|
|
30316
|
+
sourceExternalId: text("source_external_id").notNull(),
|
|
30317
|
+
startsAt: timestamp("starts_at", { withTimezone: true }).notNull(),
|
|
30318
|
+
endsAt: timestamp("ends_at", { withTimezone: true }).notNull(),
|
|
30319
|
+
metadata: jsonb("metadata").$type().notNull().default({}),
|
|
30320
|
+
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
|
|
30321
|
+
},
|
|
30322
|
+
(table) => ({
|
|
30323
|
+
sourceIdx: index("idx_cohorts_source").on(table.source, table.sourceExternalId)
|
|
30324
|
+
})
|
|
30325
|
+
);
|
|
30326
|
+
}
|
|
30327
|
+
});
|
|
30328
|
+
|
|
30206
30329
|
// ../../packages/database/src/schema/enrollments.ts
|
|
30207
30330
|
var enrollmentStatusEnum, enrollmentSourceEnum, exerciseEntryLevelEnum, EXERCISE_ENTRY_LEVELS, enrollments;
|
|
30208
30331
|
var init_enrollments = __esm({
|
|
@@ -30211,6 +30334,7 @@ var init_enrollments = __esm({
|
|
|
30211
30334
|
init_pg_core();
|
|
30212
30335
|
init_users();
|
|
30213
30336
|
init_courses3();
|
|
30337
|
+
init_cohorts();
|
|
30214
30338
|
enrollmentStatusEnum = pgEnum("enrollment_status", [
|
|
30215
30339
|
"active",
|
|
30216
30340
|
"preview",
|
|
@@ -30264,6 +30388,10 @@ var init_enrollments = __esm({
|
|
|
30264
30388
|
// adjusts via the `enrollments.setExerciseLevel` mutation.
|
|
30265
30389
|
entryLevel: exerciseEntryLevelEnum("entry_level").notNull().default("L4"),
|
|
30266
30390
|
currentLevel: exerciseEntryLevelEnum("current_level").notNull().default("L4"),
|
|
30391
|
+
// Paris Group integration: links a provisioned enrollment to its cohort.
|
|
30392
|
+
// Set when tostudy provisions an account via `POST /api/internal/v1/cohort-enrollments`.
|
|
30393
|
+
// Nullable for non-cohort enrollments (self-enrollment, subscriptions, etc.).
|
|
30394
|
+
cohortId: uuid("cohort_id").references(() => cohorts.id, { onDelete: "set null" }),
|
|
30267
30395
|
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
|
30268
30396
|
metadata: jsonb("metadata").$type().default({})
|
|
30269
30397
|
},
|
|
@@ -30282,7 +30410,9 @@ var init_enrollments = __esm({
|
|
|
30282
30410
|
courseCurrentLevelIdx: index("enrollments_course_current_level_idx").on(
|
|
30283
30411
|
table.courseId,
|
|
30284
30412
|
table.currentLevel
|
|
30285
|
-
)
|
|
30413
|
+
),
|
|
30414
|
+
// Paris Group integration: partial index for cohort lookups.
|
|
30415
|
+
cohortIdIdx: index("idx_enrollments_cohort_id").on(table.cohortId)
|
|
30286
30416
|
})
|
|
30287
30417
|
);
|
|
30288
30418
|
}
|
|
@@ -30443,6 +30573,29 @@ var init_course_index = __esm({
|
|
|
30443
30573
|
}
|
|
30444
30574
|
});
|
|
30445
30575
|
|
|
30576
|
+
// ../../packages/database/src/schema/paris-authorized-creators.ts
|
|
30577
|
+
var parisAuthorizedCreators;
|
|
30578
|
+
var init_paris_authorized_creators = __esm({
|
|
30579
|
+
"../../packages/database/src/schema/paris-authorized-creators.ts"() {
|
|
30580
|
+
"use strict";
|
|
30581
|
+
init_pg_core();
|
|
30582
|
+
init_users();
|
|
30583
|
+
parisAuthorizedCreators = pgTable(
|
|
30584
|
+
"paris_authorized_creators",
|
|
30585
|
+
{
|
|
30586
|
+
userId: uuid("user_id").primaryKey().references(() => users.id, { onDelete: "cascade" }),
|
|
30587
|
+
/** Quem aprovou (admin Paris). NULL se setado via seed/SQL direto. */
|
|
30588
|
+
authorizedBy: uuid("authorized_by").references(() => users.id, { onDelete: "set null" }),
|
|
30589
|
+
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
30590
|
+
notes: text("notes")
|
|
30591
|
+
},
|
|
30592
|
+
(table) => ({
|
|
30593
|
+
authorizedByIdx: index("idx_paris_authorized_creators_authorized_by").on(table.authorizedBy)
|
|
30594
|
+
})
|
|
30595
|
+
);
|
|
30596
|
+
}
|
|
30597
|
+
});
|
|
30598
|
+
|
|
30446
30599
|
// ../../packages/database/src/schema/enrollment-channel-changes.ts
|
|
30447
30600
|
var enrollmentChannelChanges;
|
|
30448
30601
|
var init_enrollment_channel_changes = __esm({
|
|
@@ -33693,6 +33846,8 @@ var init_mentorship_services = __esm({
|
|
|
33693
33846
|
// 30, 45, 60, 90
|
|
33694
33847
|
priceCents: integer("price_cents").notNull(),
|
|
33695
33848
|
// min 5000 for 1:1, 3000 for group/workshop
|
|
33849
|
+
currency: varchar("currency", { length: 3 }).notNull().default("BRL"),
|
|
33850
|
+
// ISO 4217 uppercase; Phase 1 threads through DTOs
|
|
33696
33851
|
priceCredits: integer("price_credits"),
|
|
33697
33852
|
// nullable during migration, NOT NULL after Phase 3
|
|
33698
33853
|
maxParticipants: integer("max_participants").default(1).notNull(),
|
|
@@ -33943,37 +34098,50 @@ var init_mentorship_packages = __esm({
|
|
|
33943
34098
|
init_users();
|
|
33944
34099
|
init_mentorship_services();
|
|
33945
34100
|
init_zod();
|
|
33946
|
-
mentorshipPackages2 = pgTable(
|
|
33947
|
-
|
|
33948
|
-
|
|
33949
|
-
|
|
33950
|
-
|
|
33951
|
-
|
|
33952
|
-
|
|
33953
|
-
|
|
33954
|
-
|
|
33955
|
-
|
|
33956
|
-
|
|
33957
|
-
|
|
33958
|
-
|
|
33959
|
-
|
|
33960
|
-
|
|
33961
|
-
|
|
33962
|
-
|
|
33963
|
-
|
|
33964
|
-
|
|
33965
|
-
|
|
33966
|
-
|
|
33967
|
-
|
|
33968
|
-
|
|
33969
|
-
|
|
33970
|
-
|
|
33971
|
-
|
|
33972
|
-
|
|
33973
|
-
|
|
33974
|
-
|
|
33975
|
-
|
|
33976
|
-
|
|
34101
|
+
mentorshipPackages2 = pgTable(
|
|
34102
|
+
"mentorship_packages",
|
|
34103
|
+
{
|
|
34104
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
34105
|
+
mentorId: uuid("mentor_id").references(() => users.id, { onDelete: "cascade" }).notNull(),
|
|
34106
|
+
serviceId: uuid("service_id").references(() => mentorshipServices2.id, { onDelete: "cascade" }).notNull(),
|
|
34107
|
+
// Package configuration
|
|
34108
|
+
numSessions: integer("num_sessions").notNull(),
|
|
34109
|
+
// 4, 8, or 12 (enforced by check constraint)
|
|
34110
|
+
discountPercent: integer("discount_percent").notNull().default(0),
|
|
34111
|
+
// 0-50 (enforced by check constraint)
|
|
34112
|
+
validityMonths: integer("validity_months").notNull().default(6),
|
|
34113
|
+
// 3, 6, or 12
|
|
34114
|
+
// Calculated prices (stored for consistency and to avoid recalculation issues)
|
|
34115
|
+
pricePerSessionCents: integer("price_per_session_cents").notNull(),
|
|
34116
|
+
// Price per session after discount
|
|
34117
|
+
totalPriceCents: integer("total_price_cents").notNull(),
|
|
34118
|
+
// Total package price
|
|
34119
|
+
currency: varchar("currency", { length: 3 }).notNull().default("BRL"),
|
|
34120
|
+
// ISO 4217 uppercase; Phase 2 threads through DTOs (derived from service.currency)
|
|
34121
|
+
// Status
|
|
34122
|
+
isActive: boolean("is_active").notNull().default(true),
|
|
34123
|
+
// Timestamps
|
|
34124
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
34125
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
34126
|
+
},
|
|
34127
|
+
(table) => ({
|
|
34128
|
+
mentorIdIdx: index("mentorship_packages_mentor_id_idx").on(table.mentorId),
|
|
34129
|
+
serviceIdIdx: index("mentorship_packages_service_id_idx").on(table.serviceId),
|
|
34130
|
+
isActiveIdx: index("mentorship_packages_is_active_idx").on(table.isActive),
|
|
34131
|
+
mentorServiceActiveIdx: index("mentorship_packages_mentor_service_active_idx").on(
|
|
34132
|
+
table.mentorId,
|
|
34133
|
+
table.serviceId,
|
|
34134
|
+
table.isActive
|
|
34135
|
+
),
|
|
34136
|
+
// Check constraints for business rules
|
|
34137
|
+
numSessionsCheck: check("num_sessions_check", sql`${table.numSessions} IN (4, 8, 12)`),
|
|
34138
|
+
discountPercentCheck: check(
|
|
34139
|
+
"discount_percent_check",
|
|
34140
|
+
sql`${table.discountPercent} >= 0 AND ${table.discountPercent} <= 50`
|
|
34141
|
+
),
|
|
34142
|
+
validityMonthsCheck: check("validity_months_check", sql`${table.validityMonths} IN (3, 6, 12)`)
|
|
34143
|
+
})
|
|
34144
|
+
);
|
|
33977
34145
|
PACKAGE_SESSION_OPTIONS = [4, 8, 12];
|
|
33978
34146
|
PACKAGE_VALIDITY_OPTIONS = [3, 6, 12];
|
|
33979
34147
|
MAX_DISCOUNT_PERCENT = 50;
|
|
@@ -34207,7 +34375,7 @@ var init_mentorship_transactions = __esm({
|
|
|
34207
34375
|
transactionType: mentorshipTransactionTypeEnum("transaction_type").default("session").notNull(),
|
|
34208
34376
|
packageId: uuid("package_id").references(() => mentorshipPackages2.id, { onDelete: "set null" }),
|
|
34209
34377
|
serviceId: uuid("service_id").references(() => mentorshipServices2.id, { onDelete: "set null" }),
|
|
34210
|
-
// Financial amounts in cents
|
|
34378
|
+
// Financial amounts in cents - Story 19.3: Split tracking
|
|
34211
34379
|
grossAmountCents: integer("gross_amount_cents").notNull(),
|
|
34212
34380
|
// Original price before discount
|
|
34213
34381
|
discountCents: integer("discount_cents").default(0).notNull(),
|
|
@@ -34216,6 +34384,8 @@ var init_mentorship_transactions = __esm({
|
|
|
34216
34384
|
// 15% of net amount
|
|
34217
34385
|
mentorPayoutCents: integer("mentor_payout_cents").notNull(),
|
|
34218
34386
|
// 85% of net amount (netAmountCents)
|
|
34387
|
+
currency: varchar("currency", { length: 3 }).notNull().default("BRL"),
|
|
34388
|
+
// ISO 4217 uppercase; Phase 3 threads through DTOs (derived from package.currency / service.currency)
|
|
34219
34389
|
// Transaction status
|
|
34220
34390
|
status: mentorshipTransactionStatusEnum("status").default("pending").notNull(),
|
|
34221
34391
|
// Stripe integration
|
|
@@ -34462,53 +34632,66 @@ var init_transactions = __esm({
|
|
|
34462
34632
|
init_pg_core();
|
|
34463
34633
|
init_courses3();
|
|
34464
34634
|
init_users();
|
|
34465
|
-
transactions2 = pgTable(
|
|
34466
|
-
|
|
34467
|
-
|
|
34468
|
-
|
|
34469
|
-
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
|
|
34473
|
-
|
|
34474
|
-
|
|
34475
|
-
|
|
34476
|
-
|
|
34477
|
-
|
|
34478
|
-
|
|
34479
|
-
|
|
34480
|
-
|
|
34481
|
-
|
|
34482
|
-
|
|
34483
|
-
|
|
34484
|
-
|
|
34485
|
-
|
|
34486
|
-
|
|
34487
|
-
|
|
34488
|
-
|
|
34489
|
-
|
|
34490
|
-
|
|
34491
|
-
|
|
34492
|
-
|
|
34493
|
-
|
|
34494
|
-
|
|
34495
|
-
|
|
34496
|
-
|
|
34497
|
-
|
|
34498
|
-
|
|
34499
|
-
|
|
34500
|
-
|
|
34501
|
-
|
|
34502
|
-
|
|
34503
|
-
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
|
|
34507
|
-
|
|
34508
|
-
|
|
34509
|
-
|
|
34510
|
-
|
|
34511
|
-
|
|
34635
|
+
transactions2 = pgTable(
|
|
34636
|
+
"transactions",
|
|
34637
|
+
{
|
|
34638
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
34639
|
+
// Stripe references
|
|
34640
|
+
stripePaymentIntentId: varchar("stripe_payment_intent_id", { length: 255 }).notNull().unique(),
|
|
34641
|
+
stripeTransferId: varchar("stripe_transfer_id", { length: 255 }),
|
|
34642
|
+
// Stripe Transfer ID (if separate transfer)
|
|
34643
|
+
// Foreign keys
|
|
34644
|
+
courseId: uuid("course_id").notNull().references(() => courses.id, { onDelete: "restrict" }),
|
|
34645
|
+
creatorId: uuid("creator_id").notNull().references(() => users.id, { onDelete: "restrict" }),
|
|
34646
|
+
studentId: uuid("student_id").notNull().references(() => users.id, { onDelete: "restrict" }),
|
|
34647
|
+
// Financial details (all amounts in cents)
|
|
34648
|
+
amount: integer("amount").notNull(),
|
|
34649
|
+
// Total amount charged
|
|
34650
|
+
currency: varchar("currency", { length: 3 }).notNull().default("BRL"),
|
|
34651
|
+
// ISO 4217 uppercase; seeded from Stripe charge.currency on webhook insert
|
|
34652
|
+
platformFee: integer("platform_fee").notNull(),
|
|
34653
|
+
// Amount kept by platform
|
|
34654
|
+
creatorPayout: integer("creator_payout").notNull(),
|
|
34655
|
+
// Amount transferred to creator
|
|
34656
|
+
stripeFee: integer("stripe_fee"),
|
|
34657
|
+
// Stripe processing fee (nullable, updated from webhook)
|
|
34658
|
+
netPlatformRevenue: integer("net_platform_revenue"),
|
|
34659
|
+
// platformFee - stripeFee
|
|
34660
|
+
// Transaction metadata
|
|
34661
|
+
type: varchar("type", { length: 20 }).notNull(),
|
|
34662
|
+
// 'mentoria' or 'self-paced'
|
|
34663
|
+
paymentMethod: varchar("payment_method", { length: 50 }),
|
|
34664
|
+
// 'card' or 'pix'
|
|
34665
|
+
status: varchar("status", { length: 20 }).notNull().default("pending"),
|
|
34666
|
+
// 'pending', 'succeeded', 'failed', 'refunded'
|
|
34667
|
+
// Timestamps
|
|
34668
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
34669
|
+
processedAt: timestamp("processed_at"),
|
|
34670
|
+
refundedAt: timestamp("refunded_at"),
|
|
34671
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
|
|
34672
|
+
},
|
|
34673
|
+
(table) => ({
|
|
34674
|
+
// Indexes for fast lookups
|
|
34675
|
+
stripePaymentIntentIdIdx: index("transactions_stripe_payment_intent_id_idx").on(
|
|
34676
|
+
table.stripePaymentIntentId
|
|
34677
|
+
),
|
|
34678
|
+
creatorIdIdx: index("transactions_creator_id_idx").on(table.creatorId),
|
|
34679
|
+
studentIdIdx: index("transactions_student_id_idx").on(table.studentId),
|
|
34680
|
+
statusIdx: index("transactions_status_idx").on(table.status),
|
|
34681
|
+
paymentMethodIdx: index("transactions_payment_method_idx").on(table.paymentMethod),
|
|
34682
|
+
// For PIX analytics
|
|
34683
|
+
createdAtIdx: index("transactions_created_at_idx").on(table.createdAt),
|
|
34684
|
+
// For analytics queries
|
|
34685
|
+
refundedAtIdx: index("transactions_refunded_at_idx").on(table.refundedAt),
|
|
34686
|
+
// Issue #4: Database Index Gaps - Composite index for refund lookups
|
|
34687
|
+
refundLookupIdx: index("transactions_refund_lookup_idx").on(
|
|
34688
|
+
table.courseId,
|
|
34689
|
+
table.studentId,
|
|
34690
|
+
table.status,
|
|
34691
|
+
table.createdAt
|
|
34692
|
+
)
|
|
34693
|
+
})
|
|
34694
|
+
);
|
|
34512
34695
|
}
|
|
34513
34696
|
});
|
|
34514
34697
|
|
|
@@ -36827,7 +37010,16 @@ var init_security_audit_log = __esm({
|
|
|
36827
37010
|
"admin.impersonate_start",
|
|
36828
37011
|
"admin.impersonate_end",
|
|
36829
37012
|
"admin.config_change",
|
|
36830
|
-
"admin.student_progress_reset"
|
|
37013
|
+
"admin.student_progress_reset",
|
|
37014
|
+
// Paris integration events (PR #575)
|
|
37015
|
+
"account.claimed_by_external",
|
|
37016
|
+
"account.claim_denied_by_policy",
|
|
37017
|
+
"user.created_by_external",
|
|
37018
|
+
"authorized_creator.added",
|
|
37019
|
+
"authorized_creator.add_attempt_unknown_user",
|
|
37020
|
+
"authorized_creator.removed",
|
|
37021
|
+
"course.paris_endorsed",
|
|
37022
|
+
"course.paris_endorsement_revoked"
|
|
36831
37023
|
]);
|
|
36832
37024
|
securityEventResultEnum = pgEnum("security_event_result", [
|
|
36833
37025
|
"success",
|
|
@@ -36936,7 +37128,7 @@ var init_credit_movement_audit_log = __esm({
|
|
|
36936
37128
|
});
|
|
36937
37129
|
|
|
36938
37130
|
// ../../packages/database/src/schema/marketing.ts
|
|
36939
|
-
var testimonialStatusEnum, marketingContentTypeEnum, creatorTestimonials2, marketingContent2, newsletterSubscribers, contactSubmissions;
|
|
37131
|
+
var testimonialStatusEnum, testimonialPlacementEnum, marketingContentTypeEnum, creatorTestimonials2, marketingContent2, newsletterSubscribers, contactSubmissions;
|
|
36940
37132
|
var init_marketing = __esm({
|
|
36941
37133
|
"../../packages/database/src/schema/marketing.ts"() {
|
|
36942
37134
|
"use strict";
|
|
@@ -36947,6 +37139,11 @@ var init_marketing = __esm({
|
|
|
36947
37139
|
"published",
|
|
36948
37140
|
"archived"
|
|
36949
37141
|
]);
|
|
37142
|
+
testimonialPlacementEnum = pgEnum("testimonial_placement", [
|
|
37143
|
+
"homepage",
|
|
37144
|
+
"creators",
|
|
37145
|
+
"both"
|
|
37146
|
+
]);
|
|
36950
37147
|
marketingContentTypeEnum = pgEnum("marketing_content_type", [
|
|
36951
37148
|
"text",
|
|
36952
37149
|
// Simple text content
|
|
@@ -36981,6 +37178,7 @@ var init_marketing = __esm({
|
|
|
36981
37178
|
featured: boolean("featured").default(false).notNull(),
|
|
36982
37179
|
// Show in carousel
|
|
36983
37180
|
displayOrder: integer("display_order").default(0).notNull(),
|
|
37181
|
+
placement: testimonialPlacementEnum("placement").default("creators").notNull(),
|
|
36984
37182
|
// Localization support (null = applies to all locales)
|
|
36985
37183
|
locale: varchar("locale", { length: 10 }),
|
|
36986
37184
|
// Metadata
|
|
@@ -36993,7 +37191,8 @@ var init_marketing = __esm({
|
|
|
36993
37191
|
statusIdx: index("creator_testimonials_status_idx").on(table.status),
|
|
36994
37192
|
featuredIdx: index("creator_testimonials_featured_idx").on(table.featured),
|
|
36995
37193
|
displayOrderIdx: index("creator_testimonials_display_order_idx").on(table.displayOrder),
|
|
36996
|
-
localeIdx: index("creator_testimonials_locale_idx").on(table.locale)
|
|
37194
|
+
localeIdx: index("creator_testimonials_locale_idx").on(table.locale),
|
|
37195
|
+
placementIdx: index("creator_testimonials_placement_idx").on(table.placement)
|
|
36997
37196
|
})
|
|
36998
37197
|
);
|
|
36999
37198
|
marketingContent2 = pgTable(
|
|
@@ -40896,6 +41095,75 @@ var init_brainstorm_knowledge_bases = __esm({
|
|
|
40896
41095
|
}
|
|
40897
41096
|
});
|
|
40898
41097
|
|
|
41098
|
+
// ../../packages/database/src/schema/course-allowlist.ts
|
|
41099
|
+
var courseAllowlist;
|
|
41100
|
+
var init_course_allowlist = __esm({
|
|
41101
|
+
"../../packages/database/src/schema/course-allowlist.ts"() {
|
|
41102
|
+
"use strict";
|
|
41103
|
+
init_pg_core();
|
|
41104
|
+
init_courses3();
|
|
41105
|
+
init_users();
|
|
41106
|
+
courseAllowlist = pgTable(
|
|
41107
|
+
"course_allowlist",
|
|
41108
|
+
{
|
|
41109
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
41110
|
+
courseId: uuid("course_id").references(() => courses.id, { onDelete: "cascade" }).notNull(),
|
|
41111
|
+
email: varchar("email", { length: 255 }).notNull(),
|
|
41112
|
+
userId: uuid("user_id").references(() => users.id, { onDelete: "cascade" }),
|
|
41113
|
+
invitedBy: uuid("invited_by").references(() => users.id, {
|
|
41114
|
+
onDelete: "set null"
|
|
41115
|
+
}),
|
|
41116
|
+
invitedAt: timestamp("invited_at", { withTimezone: true }).defaultNow().notNull(),
|
|
41117
|
+
resolvedAt: timestamp("resolved_at", { withTimezone: true })
|
|
41118
|
+
},
|
|
41119
|
+
(table) => ({
|
|
41120
|
+
courseEmailUnique: uniqueIndex("course_allowlist_course_email_unique").on(
|
|
41121
|
+
table.courseId,
|
|
41122
|
+
table.email
|
|
41123
|
+
),
|
|
41124
|
+
courseIdIdx: index("course_allowlist_course_id_idx").on(table.courseId)
|
|
41125
|
+
// partial indexes (user_id IS NOT NULL / IS NULL) are created via raw SQL in the migration — see drizzle-kit $N gotcha in packages/database/AGENTS.md
|
|
41126
|
+
})
|
|
41127
|
+
);
|
|
41128
|
+
}
|
|
41129
|
+
});
|
|
41130
|
+
|
|
41131
|
+
// ../../packages/database/src/schema/idempotency.ts
|
|
41132
|
+
var pgBackendIdempotencyKeys;
|
|
41133
|
+
var init_idempotency = __esm({
|
|
41134
|
+
"../../packages/database/src/schema/idempotency.ts"() {
|
|
41135
|
+
"use strict";
|
|
41136
|
+
init_drizzle_orm();
|
|
41137
|
+
init_pg_core();
|
|
41138
|
+
pgBackendIdempotencyKeys = pgTable(
|
|
41139
|
+
"pg_backend_idempotency_keys",
|
|
41140
|
+
{
|
|
41141
|
+
reservationId: uuid("reservation_id").primaryKey().defaultRandom(),
|
|
41142
|
+
idempotencyKey: text("idempotency_key").notNull(),
|
|
41143
|
+
resource: text("resource").notNull(),
|
|
41144
|
+
operation: text("operation").notNull(),
|
|
41145
|
+
fingerprint: text("fingerprint").notNull(),
|
|
41146
|
+
scopeKey: text("scope_key"),
|
|
41147
|
+
status: text("status").notNull(),
|
|
41148
|
+
response: jsonb("response"),
|
|
41149
|
+
reservedAt: timestamp("reserved_at", { withTimezone: true }).notNull().defaultNow(),
|
|
41150
|
+
committedAt: timestamp("committed_at", { withTimezone: true }),
|
|
41151
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull()
|
|
41152
|
+
},
|
|
41153
|
+
(t) => [
|
|
41154
|
+
uniqueIndex("pg_backend_idempotency_unique").on(
|
|
41155
|
+
t.idempotencyKey,
|
|
41156
|
+
t.resource,
|
|
41157
|
+
t.operation,
|
|
41158
|
+
sql`COALESCE(${t.scopeKey}, '')`
|
|
41159
|
+
),
|
|
41160
|
+
index("pg_backend_idempotency_expires").on(t.expiresAt),
|
|
41161
|
+
index("pg_backend_idempotency_pending").on(t.status, t.reservedAt)
|
|
41162
|
+
]
|
|
41163
|
+
);
|
|
41164
|
+
}
|
|
41165
|
+
});
|
|
41166
|
+
|
|
40899
41167
|
// ../../packages/database/src/schema/index.ts
|
|
40900
41168
|
var schema_exports = {};
|
|
40901
41169
|
__export(schema_exports, {
|
|
@@ -40943,6 +41211,7 @@ __export(schema_exports, {
|
|
|
40943
41211
|
challengeType: () => challengeType,
|
|
40944
41212
|
challenges: () => challenges,
|
|
40945
41213
|
challengesRelations: () => challengesRelations,
|
|
41214
|
+
cohorts: () => cohorts,
|
|
40946
41215
|
communityComments: () => communityComments2,
|
|
40947
41216
|
communityCommentsRelations: () => communityCommentsRelations2,
|
|
40948
41217
|
communityLikes: () => communityLikes2,
|
|
@@ -40968,6 +41237,7 @@ __export(schema_exports, {
|
|
|
40968
41237
|
couponUsagesRelations: () => couponUsagesRelations2,
|
|
40969
41238
|
coupons: () => coupons2,
|
|
40970
41239
|
couponsRelations: () => couponsRelations2,
|
|
41240
|
+
courseAllowlist: () => courseAllowlist,
|
|
40971
41241
|
courseAssets: () => courseAssets,
|
|
40972
41242
|
courseAssetsRelations: () => courseAssetsRelations,
|
|
40973
41243
|
courseCategories: () => courseCategories,
|
|
@@ -41000,6 +41270,7 @@ __export(schema_exports, {
|
|
|
41000
41270
|
courseValidations: () => courseValidations,
|
|
41001
41271
|
courseVideoPrompts: () => courseVideoPrompts,
|
|
41002
41272
|
courseVideoPromptsRelations: () => courseVideoPromptsRelations,
|
|
41273
|
+
courseVisibilityEnum: () => courseVisibilityEnum,
|
|
41003
41274
|
courses: () => courses,
|
|
41004
41275
|
coursesRelations: () => coursesRelations2,
|
|
41005
41276
|
creatorApplications: () => creatorApplications2,
|
|
@@ -41158,6 +41429,7 @@ __export(schema_exports, {
|
|
|
41158
41429
|
onboardingAnalytics: () => onboardingAnalytics2,
|
|
41159
41430
|
onboardingAnalyticsRelations: () => onboardingAnalyticsRelations2,
|
|
41160
41431
|
optimizerRoleEnum: () => optimizerRoleEnum,
|
|
41432
|
+
parisAuthorizedCreators: () => parisAuthorizedCreators,
|
|
41161
41433
|
parseSettingValue: () => parseSettingValue,
|
|
41162
41434
|
participantStatusEnum: () => participantStatusEnum,
|
|
41163
41435
|
pathCourses: () => pathCourses2,
|
|
@@ -41177,6 +41449,7 @@ __export(schema_exports, {
|
|
|
41177
41449
|
payoutWithdrawals: () => payoutWithdrawals,
|
|
41178
41450
|
payouts: () => payouts2,
|
|
41179
41451
|
payoutsRelations: () => payoutsRelations2,
|
|
41452
|
+
pgBackendIdempotencyKeys: () => pgBackendIdempotencyKeys,
|
|
41180
41453
|
pixKeyTypeEnum: () => pixKeyTypeEnum,
|
|
41181
41454
|
platformConfig: () => platformConfig,
|
|
41182
41455
|
platformFeeTypeEnum: () => platformFeeTypeEnum,
|
|
@@ -41308,6 +41581,7 @@ __export(schema_exports, {
|
|
|
41308
41581
|
syncLogsRelations: () => syncLogsRelations2,
|
|
41309
41582
|
systemConfigs: () => systemConfigs,
|
|
41310
41583
|
systemConfigsRelations: () => systemConfigsRelations,
|
|
41584
|
+
testimonialPlacementEnum: () => testimonialPlacementEnum,
|
|
41311
41585
|
testimonialStatusEnum: () => testimonialStatusEnum,
|
|
41312
41586
|
threadStatusEnum: () => threadStatusEnum,
|
|
41313
41587
|
toneEnum: () => toneEnum,
|
|
@@ -41367,6 +41641,8 @@ var init_schema3 = __esm({
|
|
|
41367
41641
|
"use strict";
|
|
41368
41642
|
init_auth_index();
|
|
41369
41643
|
init_course_index();
|
|
41644
|
+
init_cohorts();
|
|
41645
|
+
init_paris_authorized_creators();
|
|
41370
41646
|
init_enrollment_channel_changes();
|
|
41371
41647
|
init_badges();
|
|
41372
41648
|
init_user_badges();
|
|
@@ -41457,6 +41733,9 @@ var init_schema3 = __esm({
|
|
|
41457
41733
|
init_announcements();
|
|
41458
41734
|
init_creator_brainstorm();
|
|
41459
41735
|
init_brainstorm_knowledge_bases();
|
|
41736
|
+
init_course_visibility();
|
|
41737
|
+
init_course_allowlist();
|
|
41738
|
+
init_idempotency();
|
|
41460
41739
|
}
|
|
41461
41740
|
});
|
|
41462
41741
|
|
|
@@ -41469,6 +41748,14 @@ var init_check_module_unlocked = __esm({
|
|
|
41469
41748
|
}
|
|
41470
41749
|
});
|
|
41471
41750
|
|
|
41751
|
+
// ../../packages/database/src/utils/courses-filter.ts
|
|
41752
|
+
var init_courses_filter = __esm({
|
|
41753
|
+
"../../packages/database/src/utils/courses-filter.ts"() {
|
|
41754
|
+
"use strict";
|
|
41755
|
+
init_courses3();
|
|
41756
|
+
}
|
|
41757
|
+
});
|
|
41758
|
+
|
|
41472
41759
|
// ../../packages/database/src/utils/date-helpers.ts
|
|
41473
41760
|
var init_date_helpers = __esm({
|
|
41474
41761
|
"../../packages/database/src/utils/date-helpers.ts"() {
|
|
@@ -41494,6 +41781,7 @@ var init_src4 = __esm({
|
|
|
41494
41781
|
init_schema3();
|
|
41495
41782
|
init_schema3();
|
|
41496
41783
|
init_check_module_unlocked();
|
|
41784
|
+
init_courses_filter();
|
|
41497
41785
|
init_date_helpers();
|
|
41498
41786
|
init_lessons();
|
|
41499
41787
|
init_mentorship_services();
|
|
@@ -41791,6 +42079,10 @@ async function runStart(opts, deps = defaultDeps3) {
|
|
|
41791
42079
|
process.stderr.write("Acesse tostudy.ai para estudar este curso pelo ChatStudy.\n");
|
|
41792
42080
|
process.exit(1);
|
|
41793
42081
|
}
|
|
42082
|
+
if (isCourseArchivedError(err)) {
|
|
42083
|
+
deps.stderrWrite(getErrors().courseArchived);
|
|
42084
|
+
process.exit(1);
|
|
42085
|
+
}
|
|
41794
42086
|
const msg = err instanceof Error ? err.message : String(err);
|
|
41795
42087
|
deps.error(msg);
|
|
41796
42088
|
}
|
|
@@ -41807,6 +42099,7 @@ var init_start = __esm({
|
|
|
41807
42099
|
init_workspace_state();
|
|
41808
42100
|
init_status();
|
|
41809
42101
|
init_formatter();
|
|
42102
|
+
init_errors();
|
|
41810
42103
|
logger9 = createLogger("cli:start");
|
|
41811
42104
|
defaultDeps3 = {
|
|
41812
42105
|
requireSession,
|
|
@@ -41842,6 +42135,7 @@ var init_start_next = __esm({
|
|
|
41842
42135
|
init_course_state();
|
|
41843
42136
|
init_workspace_state();
|
|
41844
42137
|
init_formatter();
|
|
42138
|
+
init_errors();
|
|
41845
42139
|
logger10 = createLogger("cli:start-next");
|
|
41846
42140
|
startNextCommand = new Command9("start-next").description("Transition to the next module after completing the current one").option("--json", "Output structured JSON").action(async (opts) => {
|
|
41847
42141
|
try {
|
|
@@ -41869,6 +42163,10 @@ var init_start_next = __esm({
|
|
|
41869
42163
|
process.stderr.write("\u2192 tostudy courses para ver outros cursos\n");
|
|
41870
42164
|
process.exit(0);
|
|
41871
42165
|
}
|
|
42166
|
+
if (isCourseArchivedError(err)) {
|
|
42167
|
+
process.stderr.write(getErrors().courseArchived);
|
|
42168
|
+
process.exit(1);
|
|
42169
|
+
}
|
|
41872
42170
|
const msg = err instanceof Error ? err.message : String(err);
|
|
41873
42171
|
if (opts.json) jsonError(msg);
|
|
41874
42172
|
error(msg);
|
|
@@ -41890,6 +42188,7 @@ var init_next = __esm({
|
|
|
41890
42188
|
init_course_state();
|
|
41891
42189
|
init_workspace_state();
|
|
41892
42190
|
init_formatter();
|
|
42191
|
+
init_errors();
|
|
41893
42192
|
logger11 = createLogger("cli:next");
|
|
41894
42193
|
nextCommand = new Command10("next").description("Advance to the next lesson in the active course").option("--json", "Output structured JSON").action(async (opts) => {
|
|
41895
42194
|
try {
|
|
@@ -41915,6 +42214,12 @@ var init_next = __esm({
|
|
|
41915
42214
|
output(formatLesson(lessonData), { json: false });
|
|
41916
42215
|
}
|
|
41917
42216
|
} catch (err) {
|
|
42217
|
+
if (isCourseArchivedError(err)) {
|
|
42218
|
+
const friendly = getErrors().courseArchived;
|
|
42219
|
+
if (opts.json) jsonError("course_archived", { message: friendly });
|
|
42220
|
+
process.stderr.write(friendly);
|
|
42221
|
+
process.exit(1);
|
|
42222
|
+
}
|
|
41918
42223
|
if (err instanceof CliApiError) {
|
|
41919
42224
|
if (err.status === 403 && err.message === "CHANNEL_MISMATCH") {
|
|
41920
42225
|
process.stderr.write("Este curso n\xE3o est\xE1 dispon\xEDvel via CLI.\n");
|
|
@@ -41991,13 +42296,18 @@ var init_lesson = __esm({
|
|
|
41991
42296
|
"use strict";
|
|
41992
42297
|
init_src();
|
|
41993
42298
|
init_lessons2();
|
|
42299
|
+
init_courses();
|
|
41994
42300
|
init_http();
|
|
41995
42301
|
init_guards();
|
|
41996
42302
|
init_course_state();
|
|
41997
42303
|
init_formatter();
|
|
41998
42304
|
init_resolve();
|
|
42305
|
+
init_errors();
|
|
41999
42306
|
logger12 = createLogger("cli:lesson");
|
|
42000
|
-
lessonCommand = new Command11("lesson").description("Show the content of the current lesson").option("--json", "Output structured JSON").
|
|
42307
|
+
lessonCommand = new Command11("lesson").description("Show the content of the current lesson").option("--json", "Output structured JSON").option(
|
|
42308
|
+
"--read <lessonId>",
|
|
42309
|
+
"Read a specific lesson by id (works on archived / read-only courses)"
|
|
42310
|
+
).action(async (opts) => {
|
|
42001
42311
|
try {
|
|
42002
42312
|
const session = await requireSession();
|
|
42003
42313
|
const activeCourse = await requireActiveCourse();
|
|
@@ -42005,10 +42315,21 @@ var init_lesson = __esm({
|
|
|
42005
42315
|
if (driftWarning) process.stderr.write(driftWarning + "\n");
|
|
42006
42316
|
const data = createHttpProvider(session.apiUrl, session.token);
|
|
42007
42317
|
const deps = { data, logger: logger12 };
|
|
42008
|
-
|
|
42318
|
+
let lessonId = opts.read ?? activeCourse.currentLessonId;
|
|
42009
42319
|
if (!lessonId) {
|
|
42010
|
-
|
|
42011
|
-
|
|
42320
|
+
try {
|
|
42321
|
+
const prog = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
|
|
42322
|
+
lessonId = prog.currentLesson?.id || void 0;
|
|
42323
|
+
if (prog.isArchived) {
|
|
42324
|
+
process.stderr.write("\u2139 Curso arquivado \u2014 modo leitura.\n");
|
|
42325
|
+
}
|
|
42326
|
+
} catch {
|
|
42327
|
+
}
|
|
42328
|
+
}
|
|
42329
|
+
if (!lessonId) {
|
|
42330
|
+
if (opts.json)
|
|
42331
|
+
jsonError("no_active_lesson", { message: "Nenhuma li\xE7\xE3o encontrada para leitura" });
|
|
42332
|
+
error("Nenhuma li\xE7\xE3o encontrada para leitura. Rode: tostudy start ou tostudy next");
|
|
42012
42333
|
}
|
|
42013
42334
|
const content = await getContent({ lessonId, enrollmentId: activeCourse.enrollmentId }, deps);
|
|
42014
42335
|
if (opts.json) {
|
|
@@ -42029,6 +42350,12 @@ var init_lesson = __esm({
|
|
|
42029
42350
|
}
|
|
42030
42351
|
}
|
|
42031
42352
|
} catch (err) {
|
|
42353
|
+
if (isInsufficientCreditsError(err)) {
|
|
42354
|
+
const friendly = getErrors().insufficientCredits;
|
|
42355
|
+
if (opts.json) jsonError("insufficient_credits", { message: friendly });
|
|
42356
|
+
error(friendly);
|
|
42357
|
+
return;
|
|
42358
|
+
}
|
|
42032
42359
|
const msg = err instanceof Error ? err.message : String(err);
|
|
42033
42360
|
if (opts.json) jsonError(msg);
|
|
42034
42361
|
error(msg);
|
|
@@ -42049,6 +42376,7 @@ var init_hint = __esm({
|
|
|
42049
42376
|
init_guards();
|
|
42050
42377
|
init_course_state();
|
|
42051
42378
|
init_formatter();
|
|
42379
|
+
init_errors();
|
|
42052
42380
|
logger13 = createLogger("cli:hint");
|
|
42053
42381
|
hintCommand = new Command12("hint").description("Get a progressive hint for the current exercise").option("--json", "Output structured JSON").action(async (opts) => {
|
|
42054
42382
|
try {
|
|
@@ -42068,6 +42396,18 @@ var init_hint = __esm({
|
|
|
42068
42396
|
output(formatHint(hint), { json: false });
|
|
42069
42397
|
}
|
|
42070
42398
|
} catch (err) {
|
|
42399
|
+
if (isCourseArchivedError(err)) {
|
|
42400
|
+
const friendly = getErrors().courseArchived;
|
|
42401
|
+
if (opts.json) jsonError("course_archived", { message: friendly });
|
|
42402
|
+
error(friendly);
|
|
42403
|
+
return;
|
|
42404
|
+
}
|
|
42405
|
+
if (isInsufficientCreditsError(err)) {
|
|
42406
|
+
const friendly = getErrors().insufficientCredits;
|
|
42407
|
+
if (opts.json) jsonError("insufficient_credits", { message: friendly });
|
|
42408
|
+
error(friendly);
|
|
42409
|
+
return;
|
|
42410
|
+
}
|
|
42071
42411
|
const msg = err instanceof Error ? err.message : String(err);
|
|
42072
42412
|
if (opts.json) jsonError(msg);
|
|
42073
42413
|
error(msg);
|
|
@@ -42404,6 +42744,7 @@ var init_validate = __esm({
|
|
|
42404
42744
|
init_course_state();
|
|
42405
42745
|
init_formatter();
|
|
42406
42746
|
init_init_template();
|
|
42747
|
+
init_errors();
|
|
42407
42748
|
logger14 = createLogger("cli:validate");
|
|
42408
42749
|
validateCommand = new Command13("validate").description("Validate your solution for the current exercise").argument("[file]", "Path to the solution file to read").option("--stdin", "Read solution from stdin instead of a file").option("--json", "Output structured JSON").action(async (file2, opts) => {
|
|
42409
42750
|
try {
|
|
@@ -42485,6 +42826,18 @@ var init_validate = __esm({
|
|
|
42485
42826
|
}
|
|
42486
42827
|
process.exit(result.passed ? 0 : 1);
|
|
42487
42828
|
} catch (err) {
|
|
42829
|
+
if (isCourseArchivedError(err)) {
|
|
42830
|
+
const friendly = getErrors().courseArchived;
|
|
42831
|
+
if (opts.json) jsonError("course_archived", { message: friendly });
|
|
42832
|
+
error(friendly);
|
|
42833
|
+
return;
|
|
42834
|
+
}
|
|
42835
|
+
if (isInsufficientCreditsError(err)) {
|
|
42836
|
+
const friendly = getErrors().insufficientCredits;
|
|
42837
|
+
if (opts.json) jsonError("insufficient_credits", { message: friendly });
|
|
42838
|
+
error(friendly);
|
|
42839
|
+
return;
|
|
42840
|
+
}
|
|
42488
42841
|
const msg = err instanceof Error ? err.message : String(err);
|
|
42489
42842
|
if (opts.json) jsonError(msg);
|
|
42490
42843
|
error(msg);
|
|
@@ -44286,6 +44639,7 @@ var init_theory = __esm({
|
|
|
44286
44639
|
init_src();
|
|
44287
44640
|
init_guards();
|
|
44288
44641
|
init_formatter();
|
|
44642
|
+
init_errors();
|
|
44289
44643
|
logger27 = createLogger("cli:theory");
|
|
44290
44644
|
EXERCISE_LEVELS2 = ["L0", "L1", "L2", "L3", "L4"];
|
|
44291
44645
|
theoryCommand = new Command28("theory").description("Request more theory on the current lesson (escape hatch)").option("--focus <text>", "Optional focus area in PT-BR (max 500 chars)").option("--level <L0|L1|L2|L3|L4>", "Override current exercise level (otherwise auto-detect)").option("--lesson <uuid>", "Override lesson ID (defaults to current workspace lesson)").option("--json", "Output structured JSON").action(async (opts) => {
|
|
@@ -44352,6 +44706,12 @@ var init_theory = __esm({
|
|
|
44352
44706
|
output(formatMoreTheory(data), { json: false });
|
|
44353
44707
|
}
|
|
44354
44708
|
} catch (err) {
|
|
44709
|
+
if (isInsufficientCreditsError(err)) {
|
|
44710
|
+
const friendly = getErrors().insufficientCredits;
|
|
44711
|
+
if (opts.json) jsonError("insufficient_credits", { message: friendly });
|
|
44712
|
+
error(friendly);
|
|
44713
|
+
return;
|
|
44714
|
+
}
|
|
44355
44715
|
const msg = err instanceof Error ? err.message : String(err);
|
|
44356
44716
|
if (opts.json) jsonError("unexpected_error", { message: msg });
|
|
44357
44717
|
error(msg);
|