@rebasepro/server-postgresql 0.0.1-canary.4f204c2 → 0.0.1-canary.629af03

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.
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Introspection logic — pure functions and the pipeline that transforms
3
+ * raw PostgreSQL metadata into Rebase collection definition files.
4
+ *
5
+ * This module contains NO side-effects: no fs writes, no pg.Client creation,
6
+ * no process.exit. It is imported by introspect-db.ts (the CLI entry-point)
7
+ * and consumed directly by tests.
8
+ */
9
+ export interface TableRow {
10
+ table_name: string;
11
+ }
12
+ export interface TableColumn {
13
+ table_name: string;
14
+ column_name: string;
15
+ data_type: string;
16
+ udt_name: string;
17
+ is_nullable: string;
18
+ column_default: string | null;
19
+ }
20
+ export interface EnumValue {
21
+ enum_name: string;
22
+ enum_value: string;
23
+ sort_order: number;
24
+ }
25
+ export interface PrimaryKeyRow {
26
+ table_name: string;
27
+ column_name: string;
28
+ }
29
+ export interface ForeignKeyRow {
30
+ table_name: string;
31
+ column_name: string;
32
+ foreign_table_name: string;
33
+ foreign_column_name: string;
34
+ }
35
+ export interface TableMeta {
36
+ name: string;
37
+ columns: TableColumn[];
38
+ pks: string[];
39
+ fks: ForeignKeyRow[];
40
+ }
41
+ export declare function singularize(word: string): string;
42
+ /**
43
+ * Convert a snake_case name to a human-readable Title Case label.
44
+ * e.g. "created_at" -> "Created At", "customer_id" -> "Customer Id"
45
+ */
46
+ export declare function humanize(snakeName: string): string;
47
+ /**
48
+ * Convert a snake_case table name to a camelCase + "Collection" variable name.
49
+ * e.g. "company_token" -> "companyTokenCollection"
50
+ */
51
+ export declare function toCollectionVarName(tableName: string): string;
52
+ export declare function getIconForTable(tableName: string): string;
53
+ /**
54
+ * Map a PostgreSQL data type to a Rebase property type.
55
+ */
56
+ export declare function mapPgType(dataType: string): string;
57
+ export declare function buildEnumMap(enumValues: EnumValue[]): Map<string, string[]>;
58
+ export declare function buildTablesMap(tables: TableRow[], columns: TableColumn[], pks: PrimaryKeyRow[], fks: ForeignKeyRow[]): Map<string, TableMeta>;
59
+ export declare function identifyJoinTables(tablesMap: Map<string, TableMeta>): Set<string>;
60
+ export interface GeneratedFile {
61
+ tableName: string;
62
+ fileName: string;
63
+ content: string;
64
+ }
65
+ /**
66
+ * Generate the full TypeScript file content for a single collection.
67
+ * Pure function — no I/O.
68
+ */
69
+ export declare function generateCollectionFile(tableName: string, meta: TableMeta, allFks: ForeignKeyRow[], joinTables: Set<string>, tablesMap: Map<string, TableMeta>, enumMap: Map<string, string[]>): string;
70
+ /**
71
+ * Generate the content for an index.ts file that re-exports all collections.
72
+ */
73
+ export declare function generateIndexContent(fileNames: string[]): string;
74
+ /**
75
+ * Merge new exports into existing index.ts content.
76
+ * Returns the merged content string.
77
+ */
78
+ export declare function mergeIndexContent(existingContent: string, newFileNames: string[]): string;
79
+ /**
80
+ * Safely extract the host portion of a database URL for logging.
81
+ */
82
+ export declare function safeHostFromUrl(url: string): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/server-postgresql",
3
3
  "type": "module",
4
- "version": "0.0.1-canary.4f204c2",
4
+ "version": "0.0.1-canary.629af03",
5
5
  "description": "PostgreSQL data source backend implementation for Rebase with Drizzle ORM",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -60,13 +60,14 @@
60
60
  "dependencies": {
61
61
  "arg": "^5.0.2",
62
62
  "chalk": "^4.1.2",
63
+ "chokidar": "5.0.0",
63
64
  "drizzle-orm": "^0.44.4",
64
65
  "execa": "^4.1.0",
65
66
  "pg": "^8.11.3",
66
- "@rebasepro/common": "0.0.1-canary.4f204c2",
67
- "@rebasepro/server-core": "0.0.1-canary.4f204c2",
68
- "@rebasepro/types": "0.0.1-canary.4f204c2",
69
- "@rebasepro/utils": "0.0.1-canary.4f204c2"
67
+ "@rebasepro/server-core": "0.0.1-canary.629af03",
68
+ "@rebasepro/types": "0.0.1-canary.629af03",
69
+ "@rebasepro/utils": "0.0.1-canary.629af03",
70
+ "@rebasepro/common": "0.0.1-canary.629af03"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@types/jest": "^29.5.14",
package/src/cli.ts CHANGED
@@ -408,9 +408,16 @@ async function runDrizzleKit(action: string, _rawArgs: string[]): Promise<void>
408
408
 
409
409
  const interactive = ["generate", "push"].includes(action);
410
410
 
411
+ // For push: always use --strict (prompts before destructive ops) and --verbose
412
+ // (shows all SQL). This ensures unmapped tables are never silently dropped.
413
+ const drizzleKitArgs = [action];
414
+ if (action === "push") {
415
+ drizzleKitArgs.push("--strict", "--verbose");
416
+ }
417
+
411
418
  try {
412
419
  if (interactive) {
413
- await execa(drizzleKitBin, [action], {
420
+ await execa(drizzleKitBin, drizzleKitArgs, {
414
421
  cwd: process.cwd(),
415
422
  stdio: "inherit",
416
423
  env
@@ -527,6 +534,57 @@ async function schemaCommand(subcommand: string, rawArgs: string[]): Promise<voi
527
534
  console.error(chalk.red(`✗ Failed to run schema generator: ${err instanceof Error ? err.message : String(err)}`));
528
535
  process.exit(1);
529
536
  }
537
+ } else if (subcommand === "introspect") {
538
+ const argsList = arg(
539
+ {
540
+ "--output": String,
541
+ "--force": Boolean,
542
+ "--schema": String,
543
+ "-o": "--output",
544
+ "-f": "--force"
545
+ },
546
+ {
547
+ argv: rawArgs.slice(2),
548
+ permissive: true
549
+ }
550
+ );
551
+
552
+ const introspectScript = path.join(__dirname, "schema", "introspect-db.ts");
553
+ if (!fs.existsSync(introspectScript)) {
554
+ console.error(chalk.red(`✗ Could not find introspect-db.ts at ${introspectScript}`));
555
+ process.exit(1);
556
+ }
557
+
558
+ const tsxBin = resolveLocalBin("tsx");
559
+ if (!tsxBin) {
560
+ console.error(chalk.red("✗ Could not find tsx binary."));
561
+ process.exit(1);
562
+ }
563
+
564
+ const outputPath = argsList["--output"] || path.join("config", "collections");
565
+
566
+ console.log("");
567
+ console.log(chalk.bold(" 🔍 Rebase Schema Introspector"));
568
+ console.log("");
569
+
570
+ const cmdParts = [
571
+ tsxBin,
572
+ introspectScript,
573
+ `--output=${outputPath}`,
574
+ ...(argsList["--force"] ? ["--force"] : []),
575
+ ...(argsList["--schema"] ? [`--schema=${argsList["--schema"]}`] : [])
576
+ ];
577
+
578
+ try {
579
+ await execa(cmdParts[0], cmdParts.slice(1), {
580
+ cwd: process.cwd(),
581
+ stdio: "inherit",
582
+ env: { ...process.env as Record<string, string> }
583
+ });
584
+ } catch (err: unknown) {
585
+ console.error(chalk.red(`✗ Failed to run schema introspector: ${err instanceof Error ? err.message : String(err)}`));
586
+ process.exit(1);
587
+ }
530
588
  } else {
531
589
  console.error(chalk.red("Unknown schema command."));
532
590
  process.exit(1);