@rebasepro/server-postgresql 0.0.1-canary.629af03 → 0.0.1-canary.94dff14
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/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.
|
|
4
|
+
"version": "0.0.1-canary.94dff14",
|
|
5
5
|
"description": "PostgreSQL data source backend implementation for Rebase with Drizzle ORM",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"drizzle-orm": "^0.44.4",
|
|
65
65
|
"execa": "^4.1.0",
|
|
66
66
|
"pg": "^8.11.3",
|
|
67
|
-
"@rebasepro/
|
|
68
|
-
"@rebasepro/
|
|
69
|
-
"@rebasepro/
|
|
70
|
-
"@rebasepro/
|
|
67
|
+
"@rebasepro/common": "0.0.1-canary.94dff14",
|
|
68
|
+
"@rebasepro/utils": "0.0.1-canary.94dff14",
|
|
69
|
+
"@rebasepro/server-core": "0.0.1-canary.94dff14",
|
|
70
|
+
"@rebasepro/types": "0.0.1-canary.94dff14"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@types/jest": "^29.5.14",
|
|
@@ -159,7 +159,7 @@ export function mapPgType(dataType: string): string {
|
|
|
159
159
|
if (dt === "interval") return "string";
|
|
160
160
|
|
|
161
161
|
// Array types MUST be checked before numeric ("_int4" contains "int")
|
|
162
|
-
if (dt === "array" || dt.startsWith("_")) return "
|
|
162
|
+
if (dt === "array" || dt.startsWith("_")) return "array";
|
|
163
163
|
|
|
164
164
|
// Numeric types
|
|
165
165
|
if (
|
|
@@ -183,7 +183,7 @@ export function mapPgType(dataType: string): string {
|
|
|
183
183
|
if (dt.includes("time") || dt.includes("date")) return "date";
|
|
184
184
|
|
|
185
185
|
// JSON
|
|
186
|
-
if (dt === "json" || dt === "jsonb") return "
|
|
186
|
+
if (dt === "json" || dt === "jsonb") return "map";
|
|
187
187
|
|
|
188
188
|
// Binary
|
|
189
189
|
if (dt === "bytea") return "string";
|
|
@@ -321,6 +321,20 @@ export function generateCollectionFile(
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
// Array/Map heuristics
|
|
325
|
+
if (propType === "array") {
|
|
326
|
+
let innerType = "string";
|
|
327
|
+
if (col.udt_name.startsWith("_")) {
|
|
328
|
+
const baseType = col.udt_name.substring(1);
|
|
329
|
+
// Simple recursive check or hardcoded for inner type:
|
|
330
|
+
// We'll just call mapPgType on the baseType
|
|
331
|
+
innerType = mapPgType(baseType);
|
|
332
|
+
}
|
|
333
|
+
extra = `\n of: { type: "${innerType}" },`;
|
|
334
|
+
} else if (propType === "map") {
|
|
335
|
+
extra = `\n keyValue: true,`;
|
|
336
|
+
}
|
|
337
|
+
|
|
324
338
|
// String sub-type heuristics (skip if already handled as enum)
|
|
325
339
|
if (propType === "string" && !isEnumColumn) {
|
|
326
340
|
if (colNameLower.includes("image") || colNameLower.includes("avatar") || colNameLower.includes("photo") || colNameLower.includes("logo") || colNameLower.includes("cover")) {
|
|
@@ -509,11 +523,14 @@ export default ${tableName}Collection;
|
|
|
509
523
|
*/
|
|
510
524
|
export function generateIndexContent(fileNames: string[]): string {
|
|
511
525
|
const sorted = [...fileNames].sort();
|
|
512
|
-
let
|
|
526
|
+
let imports = "";
|
|
527
|
+
let arrayElements = "";
|
|
513
528
|
for (const f of sorted) {
|
|
514
|
-
|
|
529
|
+
const varName = toCollectionVarName(f);
|
|
530
|
+
imports += `import ${varName} from "./${f}";\n`;
|
|
531
|
+
arrayElements += ` ${varName},\n`;
|
|
515
532
|
}
|
|
516
|
-
return
|
|
533
|
+
return `${imports}\nexport const collections = [\n${arrayElements}];\n`;
|
|
517
534
|
}
|
|
518
535
|
|
|
519
536
|
/**
|
|
@@ -521,17 +538,50 @@ export function generateIndexContent(fileNames: string[]): string {
|
|
|
521
538
|
* Returns the merged content string.
|
|
522
539
|
*/
|
|
523
540
|
export function mergeIndexContent(existingContent: string, newFileNames: string[]): string {
|
|
524
|
-
const
|
|
525
|
-
[...existingContent.matchAll(/
|
|
541
|
+
const existingImports = new Set(
|
|
542
|
+
[...existingContent.matchAll(/import\s+([a-zA-Z0-9_]+)\s+from\s+"\.\/([^"]+)"/g)].map((m) => m[2])
|
|
526
543
|
);
|
|
527
544
|
const sorted = [...newFileNames].sort();
|
|
528
|
-
|
|
545
|
+
|
|
546
|
+
let newImports = "";
|
|
547
|
+
let newElements = "";
|
|
548
|
+
|
|
529
549
|
for (const f of sorted) {
|
|
530
|
-
if (!
|
|
531
|
-
|
|
550
|
+
if (!existingImports.has(f)) {
|
|
551
|
+
const varName = toCollectionVarName(f);
|
|
552
|
+
newImports += `import ${varName} from "./${f}";\n`;
|
|
553
|
+
newElements += ` ${varName},\n`;
|
|
532
554
|
}
|
|
533
555
|
}
|
|
534
|
-
|
|
556
|
+
|
|
557
|
+
if (!newImports) return existingContent;
|
|
558
|
+
|
|
559
|
+
// Simple injection logic:
|
|
560
|
+
// Add new imports below the last import or at the top
|
|
561
|
+
const importRegex = /import\s+.*?;/g;
|
|
562
|
+
let lastImportMatch;
|
|
563
|
+
let match;
|
|
564
|
+
while ((match = importRegex.exec(existingContent)) !== null) {
|
|
565
|
+
lastImportMatch = match;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
let contentWithImports = existingContent;
|
|
569
|
+
if (lastImportMatch) {
|
|
570
|
+
const pos = lastImportMatch.index + lastImportMatch[0].length;
|
|
571
|
+
contentWithImports = existingContent.slice(0, pos) + "\n" + newImports.trimEnd() + existingContent.slice(pos);
|
|
572
|
+
} else {
|
|
573
|
+
contentWithImports = newImports + "\n" + existingContent;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Inject into the `collections = [...]` array
|
|
577
|
+
const arrayRegex = /export\s+const\s+collections\s*=\s*\[([\s\S]*?)\];/;
|
|
578
|
+
return contentWithImports.replace(arrayRegex, (fullMatch, arrayContent) => {
|
|
579
|
+
let mergedArray = arrayContent.trimEnd();
|
|
580
|
+
if (mergedArray && !mergedArray.endsWith(",")) mergedArray += ",";
|
|
581
|
+
if (mergedArray) mergedArray += "\n";
|
|
582
|
+
mergedArray += newElements.trimEnd();
|
|
583
|
+
return `export const collections = [\n ${mergedArray.trim()}\n];`;
|
|
584
|
+
});
|
|
535
585
|
}
|
|
536
586
|
|
|
537
587
|
/**
|
|
@@ -49,7 +49,7 @@ describe("generateCollectionFile", () => {
|
|
|
49
49
|
expect(result).toContain('type: "number"');
|
|
50
50
|
expect(result).toContain('type: "boolean"');
|
|
51
51
|
expect(result).toContain('type: "date"');
|
|
52
|
-
expect(result).toContain('type: "
|
|
52
|
+
expect(result).toContain('type: "map"');
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
it("skips FK columns from properties (they become relations)", () => {
|
|
@@ -190,14 +190,14 @@ describe("mapPgType", () => {
|
|
|
190
190
|
expect(mapPgType(t)).toBe("date");
|
|
191
191
|
}
|
|
192
192
|
});
|
|
193
|
-
it("maps JSON types to
|
|
194
|
-
expect(mapPgType("json")).toBe("
|
|
195
|
-
expect(mapPgType("jsonb")).toBe("
|
|
193
|
+
it("maps JSON types to map", () => {
|
|
194
|
+
expect(mapPgType("json")).toBe("map");
|
|
195
|
+
expect(mapPgType("jsonb")).toBe("map");
|
|
196
196
|
});
|
|
197
|
-
it("maps ARRAY and underscore-prefixed types to
|
|
198
|
-
expect(mapPgType("ARRAY")).toBe("
|
|
199
|
-
expect(mapPgType("_int4")).toBe("
|
|
200
|
-
expect(mapPgType("_text")).toBe("
|
|
197
|
+
it("maps ARRAY and underscore-prefixed types to array", () => {
|
|
198
|
+
expect(mapPgType("ARRAY")).toBe("array");
|
|
199
|
+
expect(mapPgType("_int4")).toBe("array");
|
|
200
|
+
expect(mapPgType("_text")).toBe("array");
|
|
201
201
|
});
|
|
202
202
|
it("maps string-like types to string", () => {
|
|
203
203
|
for (const t of ["text", "varchar", "character varying", "char", "character", "uuid", "bytea", "inet", "cidr", "macaddr", "macaddr8", "interval"]) {
|
|
@@ -350,9 +350,12 @@ describe("generateIndexContent", () => {
|
|
|
350
350
|
expect(lines[2]).toContain("zebra");
|
|
351
351
|
});
|
|
352
352
|
|
|
353
|
-
it("
|
|
353
|
+
it("generates import statements and collections array", () => {
|
|
354
354
|
const result = generateIndexContent(["users"]);
|
|
355
|
-
expect(result).
|
|
355
|
+
expect(result).toContain('import usersCollection from "./users";');
|
|
356
|
+
expect(result).toContain('export const collections = [');
|
|
357
|
+
expect(result).toContain(' usersCollection,');
|
|
358
|
+
expect(result).toContain('];');
|
|
356
359
|
});
|
|
357
360
|
});
|
|
358
361
|
|
|
@@ -361,16 +364,16 @@ describe("generateIndexContent", () => {
|
|
|
361
364
|
// ═══════════════════════════════════════════════════════════════════════
|
|
362
365
|
describe("mergeIndexContent", () => {
|
|
363
366
|
it("adds new exports without duplicating existing ones", () => {
|
|
364
|
-
const existing = '
|
|
367
|
+
const existing = 'import usersCollection from "./users";\n\nexport const collections = [\n usersCollection,\n];\n';
|
|
365
368
|
const result = mergeIndexContent(existing, ["users", "posts"]);
|
|
366
|
-
expect(result.match(/users
|
|
367
|
-
expect(result).toContain('
|
|
368
|
-
|
|
369
|
-
expect(result
|
|
369
|
+
expect(result.match(/import usersCollection from ".\/users";/g)!.length).toBe(1);
|
|
370
|
+
expect(result).toContain('import postsCollection from "./posts";');
|
|
371
|
+
expect(result).toContain('usersCollection,');
|
|
372
|
+
expect(result).toContain('postsCollection,');
|
|
370
373
|
});
|
|
371
374
|
|
|
372
375
|
it("returns existing content trimmed + newline when no new files", () => {
|
|
373
|
-
const existing = '
|
|
376
|
+
const existing = 'import aCollection from "./a";\n\nexport const collections = [\n aCollection,\n];\n';
|
|
374
377
|
const result = mergeIndexContent(existing, ["a"]);
|
|
375
378
|
expect(result.trim()).toBe(existing.trim());
|
|
376
379
|
});
|