ugly-app 0.1.158 → 0.1.159

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.
@@ -1 +1 @@
1
- {"version":3,"file":"migrateToPostgres.d.ts","sourceRoot":"","sources":["../../src/cli/migrateToPostgres.ts"],"names":[],"mappings":"AAKA,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqF1D"}
1
+ {"version":3,"file":"migrateToPostgres.d.ts","sourceRoot":"","sources":["../../src/cli/migrateToPostgres.ts"],"names":[],"mappings":"AA8EA,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC1D"}
@@ -2,6 +2,54 @@ import { MongoClient } from 'mongodb';
2
2
  import { initPostgres, query, stopPostgres } from '../server/Postgres.js';
3
3
  import { ensureTable } from '../server/PostgresSchema.js';
4
4
  import { computeEnvVars, readUglyAppConfig } from './uglyappConfig.js';
5
+ const BATCH_SIZE = 2000;
6
+ const PARALLEL_COLLECTIONS = 4;
7
+ function toDate(v) {
8
+ return v instanceof Date ? v : typeof v === 'number' ? new Date(v) : new Date();
9
+ }
10
+ async function migrateCollection(db, name) {
11
+ await ensureTable(name);
12
+ const count = await db.collection(name).countDocuments();
13
+ if (count === 0) {
14
+ console.log(`[migrate] ${name}: 0 documents`);
15
+ return;
16
+ }
17
+ console.log(`[migrate] ${name}: ${count} documents`);
18
+ let inserted = 0;
19
+ let batch = [];
20
+ const cursor = db.collection(name).find({});
21
+ for await (const doc of cursor) {
22
+ batch.push(doc);
23
+ if (batch.length >= BATCH_SIZE) {
24
+ await insertBatch(name, batch);
25
+ inserted += batch.length;
26
+ batch = [];
27
+ }
28
+ }
29
+ if (batch.length > 0) {
30
+ await insertBatch(name, batch);
31
+ inserted += batch.length;
32
+ }
33
+ console.log(`[migrate] ${name}: ${inserted} inserted`);
34
+ }
35
+ async function insertBatch(name, batch) {
36
+ const valuePlaceholders = [];
37
+ const values = [];
38
+ let paramIdx = 1;
39
+ for (const doc of batch) {
40
+ const id = String(doc._id);
41
+ const { _id, version, created, updated, ...data } = doc;
42
+ valuePlaceholders.push(`($${paramIdx}, $${paramIdx + 1}, $${paramIdx + 2}, $${paramIdx + 3}, $${paramIdx + 4})`);
43
+ values.push(id, JSON.stringify(data).replace(/\\u0000/g, ''), toDate(created), toDate(updated), version ?? 1);
44
+ paramIdx += 5;
45
+ }
46
+ await query(`INSERT INTO "${name}" (_id, data, created, updated, version)
47
+ VALUES ${valuePlaceholders.join(', ')}
48
+ ON CONFLICT (_id) DO UPDATE SET
49
+ data = EXCLUDED.data,
50
+ updated = EXCLUDED.updated,
51
+ version = EXCLUDED.version`, values);
52
+ }
5
53
  export async function runMigrateToPostgres() {
6
54
  const config = readUglyAppConfig(process.cwd());
7
55
  if (config) {
@@ -24,37 +72,10 @@ export async function runMigrateToPostgres() {
24
72
  .map((c) => c.name)
25
73
  .filter((name) => !name.startsWith('system.'));
26
74
  console.log(`[migrate] Found ${collectionNames.length} collections: ${collectionNames.join(', ')}`);
27
- for (const name of collectionNames) {
28
- await ensureTable(name);
29
- const docs = await db.collection(name).find({}).toArray();
30
- console.log(`[migrate] ${name}: ${docs.length} documents`);
31
- if (docs.length === 0)
32
- continue;
33
- const BATCH_SIZE = 500;
34
- let inserted = 0;
35
- for (let i = 0; i < docs.length; i += BATCH_SIZE) {
36
- const batch = docs.slice(i, i + BATCH_SIZE);
37
- const valuePlaceholders = [];
38
- const values = [];
39
- let paramIdx = 1;
40
- for (const doc of batch) {
41
- const id = String(doc._id);
42
- const { _id, version, created, updated, ...data } = doc;
43
- const toDate = (v) => v instanceof Date ? v : typeof v === 'number' ? new Date(v) : new Date();
44
- valuePlaceholders.push(`($${paramIdx}, $${paramIdx + 1}, $${paramIdx + 2}, $${paramIdx + 3}, $${paramIdx + 4})`);
45
- values.push(id, JSON.stringify(data).replace(/\\u0000/g, ''), toDate(created), toDate(updated), version ?? 1);
46
- paramIdx += 5;
47
- }
48
- await query(`INSERT INTO "${name}" (_id, data, created, updated, version)
49
- VALUES ${valuePlaceholders.join(', ')}
50
- ON CONFLICT (_id) DO UPDATE SET
51
- data = EXCLUDED.data,
52
- updated = EXCLUDED.updated,
53
- version = EXCLUDED.version`, values);
54
- inserted += batch.length;
55
- }
56
- const pgCount = await query(`SELECT COUNT(*) as count FROM "${name}"`);
57
- console.log(`[migrate] ${name}: ${inserted} inserted, ${pgCount.rows[0].count} in PostgreSQL`);
75
+ // Process collections in parallel batches
76
+ for (let i = 0; i < collectionNames.length; i += PARALLEL_COLLECTIONS) {
77
+ const chunk = collectionNames.slice(i, i + PARALLEL_COLLECTIONS);
78
+ await Promise.all(chunk.map((name) => migrateCollection(db, name)));
58
79
  }
59
80
  console.log('[migrate] Done.');
60
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrateToPostgres.js","sourceRoot":"","sources":["../../src/cli/migrateToPostgres.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migrateToPostgres.js","sourceRoot":"","sources":["../../src/cli/migrateToPostgres.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.158";
1
+ export declare const CLI_VERSION = "0.1.159";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.158";
2
+ export const CLI_VERSION = "0.1.159";
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.158",
3
+ "version": "0.1.159",
4
4
  "type": "module",
5
5
  "main": "./dist/server/index.js",
6
6
  "exports": {
@@ -3,6 +3,79 @@ import { initPostgres, query, stopPostgres } from '../server/Postgres.js';
3
3
  import { ensureTable } from '../server/PostgresSchema.js';
4
4
  import { computeEnvVars, readUglyAppConfig } from './uglyappConfig.js';
5
5
 
6
+ const BATCH_SIZE = 2000;
7
+ const PARALLEL_COLLECTIONS = 4;
8
+
9
+ function toDate(v: unknown): Date {
10
+ return v instanceof Date ? v : typeof v === 'number' ? new Date(v) : new Date();
11
+ }
12
+
13
+ async function migrateCollection(
14
+ db: ReturnType<MongoClient['db']>,
15
+ name: string,
16
+ ): Promise<void> {
17
+ await ensureTable(name);
18
+
19
+ const count = await db.collection(name).countDocuments();
20
+ if (count === 0) {
21
+ console.log(`[migrate] ${name}: 0 documents`);
22
+ return;
23
+ }
24
+
25
+ console.log(`[migrate] ${name}: ${count} documents`);
26
+ let inserted = 0;
27
+ let batch: Record<string, unknown>[] = [];
28
+
29
+ const cursor = db.collection(name).find({});
30
+ for await (const doc of cursor) {
31
+ batch.push(doc as Record<string, unknown>);
32
+ if (batch.length >= BATCH_SIZE) {
33
+ await insertBatch(name, batch);
34
+ inserted += batch.length;
35
+ batch = [];
36
+ }
37
+ }
38
+
39
+ if (batch.length > 0) {
40
+ await insertBatch(name, batch);
41
+ inserted += batch.length;
42
+ }
43
+
44
+ console.log(`[migrate] ${name}: ${inserted} inserted`);
45
+ }
46
+
47
+ async function insertBatch(name: string, batch: Record<string, unknown>[]): Promise<void> {
48
+ const valuePlaceholders: string[] = [];
49
+ const values: unknown[] = [];
50
+ let paramIdx = 1;
51
+
52
+ for (const doc of batch) {
53
+ const id = String(doc._id);
54
+ const { _id, version, created, updated, ...data } = doc;
55
+ valuePlaceholders.push(
56
+ `($${paramIdx}, $${paramIdx + 1}, $${paramIdx + 2}, $${paramIdx + 3}, $${paramIdx + 4})`,
57
+ );
58
+ values.push(
59
+ id,
60
+ JSON.stringify(data).replace(/\\u0000/g, ''),
61
+ toDate(created),
62
+ toDate(updated),
63
+ version ?? 1,
64
+ );
65
+ paramIdx += 5;
66
+ }
67
+
68
+ await query(
69
+ `INSERT INTO "${name}" (_id, data, created, updated, version)
70
+ VALUES ${valuePlaceholders.join(', ')}
71
+ ON CONFLICT (_id) DO UPDATE SET
72
+ data = EXCLUDED.data,
73
+ updated = EXCLUDED.updated,
74
+ version = EXCLUDED.version`,
75
+ values,
76
+ );
77
+ }
78
+
6
79
  export async function runMigrateToPostgres(): Promise<void> {
7
80
  const config = readUglyAppConfig(process.cwd());
8
81
  if (config) {
@@ -29,58 +102,10 @@ export async function runMigrateToPostgres(): Promise<void> {
29
102
 
30
103
  console.log(`[migrate] Found ${collectionNames.length} collections: ${collectionNames.join(', ')}`);
31
104
 
32
- for (const name of collectionNames) {
33
- await ensureTable(name);
34
-
35
- const docs = await db.collection(name).find({}).toArray();
36
- console.log(`[migrate] ${name}: ${docs.length} documents`);
37
-
38
- if (docs.length === 0) continue;
39
-
40
- const BATCH_SIZE = 500;
41
- let inserted = 0;
42
-
43
- for (let i = 0; i < docs.length; i += BATCH_SIZE) {
44
- const batch = docs.slice(i, i + BATCH_SIZE);
45
- const valuePlaceholders: string[] = [];
46
- const values: unknown[] = [];
47
- let paramIdx = 1;
48
-
49
- for (const doc of batch) {
50
- const id = String(doc._id);
51
- const { _id, version, created, updated, ...data } = doc as Record<string, unknown>;
52
- const toDate = (v: unknown): Date =>
53
- v instanceof Date ? v : typeof v === 'number' ? new Date(v) : new Date();
54
- valuePlaceholders.push(
55
- `($${paramIdx}, $${paramIdx + 1}, $${paramIdx + 2}, $${paramIdx + 3}, $${paramIdx + 4})`,
56
- );
57
- values.push(
58
- id,
59
- JSON.stringify(data).replace(/\\u0000/g, ''),
60
- toDate(created),
61
- toDate(updated),
62
- version ?? 1,
63
- );
64
- paramIdx += 5;
65
- }
66
-
67
- await query(
68
- `INSERT INTO "${name}" (_id, data, created, updated, version)
69
- VALUES ${valuePlaceholders.join(', ')}
70
- ON CONFLICT (_id) DO UPDATE SET
71
- data = EXCLUDED.data,
72
- updated = EXCLUDED.updated,
73
- version = EXCLUDED.version`,
74
- values,
75
- );
76
-
77
- inserted += batch.length;
78
- }
79
-
80
- const pgCount = await query<{ count: string }>(
81
- `SELECT COUNT(*) as count FROM "${name}"`,
82
- );
83
- console.log(`[migrate] ${name}: ${inserted} inserted, ${pgCount.rows[0].count} in PostgreSQL`);
105
+ // Process collections in parallel batches
106
+ for (let i = 0; i < collectionNames.length; i += PARALLEL_COLLECTIONS) {
107
+ const chunk = collectionNames.slice(i, i + PARALLEL_COLLECTIONS);
108
+ await Promise.all(chunk.map((name) => migrateCollection(db, name)));
84
109
  }
85
110
 
86
111
  console.log('[migrate] Done.');
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.158";
2
+ export const CLI_VERSION = "0.1.159";