frg-data-diff 2.0.0 → 2.1.0

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,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generatePgViewsDiffSql = generatePgViewsDiffSql;
4
+ const pg_views_1 = require("../db/pg-views");
5
+ const identifiers_1 = require("../shared/identifiers");
6
+ async function generatePgViewsDiffSql(sourcePool, destPool, options) {
7
+ reportProgress(options.onProgress, "PostgreSQL views: resolving view patterns");
8
+ const { views } = await (0, pg_views_1.resolvePgViewPatterns)(sourcePool, destPool, options.schema, options.views, options.excludeViews);
9
+ reportProgress(options.onProgress, `PostgreSQL views: comparing ${views.length} view(s)`);
10
+ const sourceClient = await sourcePool.connect();
11
+ const destClient = await destPool.connect();
12
+ let sql = `-- PostgreSQL Views Diff\n`;
13
+ sql += `-- Generated automatically\n\n`;
14
+ try {
15
+ reportProgress(options.onProgress, "PostgreSQL views: fetching view definitions from source");
16
+ const sourceViews = await (0, pg_views_1.fetchPgViews)(sourceClient, options.schema, views, {
17
+ onViewStart: (viewName, viewPosition, totalViews) => {
18
+ reportProgress(options.onProgress, `[pg-views source ${viewPosition}/${totalViews}] ${options.schema}.${viewName}: fetching definition`);
19
+ },
20
+ });
21
+ reportProgress(options.onProgress, "PostgreSQL views: fetching view definitions from destination");
22
+ const destViews = await (0, pg_views_1.fetchPgViews)(destClient, options.schema, views, {
23
+ onViewStart: (viewName, viewPosition, totalViews) => {
24
+ reportProgress(options.onProgress, `[pg-views dest ${viewPosition}/${totalViews}] ${options.schema}.${viewName}: fetching definition`);
25
+ },
26
+ });
27
+ const sourceViewsMap = new Map(sourceViews.map((view) => [view.viewName, view]));
28
+ const destViewsMap = new Map(destViews.map((view) => [view.viewName, view]));
29
+ const work = buildPgViewDiffWork(views, sourceViewsMap, destViewsMap, options);
30
+ if (work.viewsToDrop.length === 0 && work.viewsToCreate.length === 0) {
31
+ reportProgress(options.onProgress, "PostgreSQL views: no differences found");
32
+ sql += `-- No differences found.\n`;
33
+ return sql;
34
+ }
35
+ reportProgress(options.onProgress, "PostgreSQL views: generating SQL script");
36
+ if (work.viewsToDrop.length > 0) {
37
+ sql += `-- Drop removed or incompatible views\n`;
38
+ for (const view of work.viewsToDrop) {
39
+ sql += `${buildDropViewStatement(view)}\n`;
40
+ }
41
+ sql += `\n`;
42
+ }
43
+ if (work.viewsToCreate.length > 0) {
44
+ sql += `-- Create or replace source views\n`;
45
+ for (const view of work.viewsToCreate) {
46
+ sql += `${buildCreateViewStatement(view)}\n\n`;
47
+ }
48
+ }
49
+ }
50
+ finally {
51
+ sourceClient.release();
52
+ destClient.release();
53
+ }
54
+ return sql;
55
+ }
56
+ function buildPgViewDiffWork(views, sourceViewsMap, destViewsMap, options) {
57
+ const viewsToDrop = [];
58
+ const viewsToCreate = [];
59
+ for (const [viewIndex, viewName] of views.entries()) {
60
+ const progressLabel = formatPgViewsProgressLabel(viewIndex + 1, views.length, options.schema, viewName);
61
+ const sourceView = sourceViewsMap.get(viewName);
62
+ const destView = destViewsMap.get(viewName);
63
+ reportProgress(options.onProgress, `${progressLabel}: comparing view`);
64
+ if (sourceView && !destView) {
65
+ viewsToCreate.push(sourceView);
66
+ reportProgress(options.onProgress, `${progressLabel}: view to create`);
67
+ continue;
68
+ }
69
+ if (!sourceView && destView) {
70
+ viewsToDrop.push(destView);
71
+ reportProgress(options.onProgress, `${progressLabel}: view to drop`);
72
+ continue;
73
+ }
74
+ if (!sourceView || !destView) {
75
+ reportProgress(options.onProgress, `${progressLabel}: no view metadata`);
76
+ continue;
77
+ }
78
+ if (pgViewsAreEqual(sourceView, destView)) {
79
+ reportProgress(options.onProgress, `${progressLabel}: no changes`);
80
+ continue;
81
+ }
82
+ if (requiresDropBeforeCreate(sourceView, destView)) {
83
+ viewsToDrop.push(destView);
84
+ }
85
+ viewsToCreate.push(sourceView);
86
+ reportProgress(options.onProgress, `${progressLabel}: view definition changed`);
87
+ }
88
+ return { viewsToDrop, viewsToCreate };
89
+ }
90
+ function pgViewsAreEqual(sourceView, destView) {
91
+ if (sourceView.viewType !== destView.viewType) {
92
+ return false;
93
+ }
94
+ return (normalizeViewDefinition(sourceView.viewDefinition) ===
95
+ normalizeViewDefinition(destView.viewDefinition));
96
+ }
97
+ function requiresDropBeforeCreate(sourceView, destView) {
98
+ if (sourceView.viewType !== destView.viewType) {
99
+ return true;
100
+ }
101
+ return sourceView.viewType === "materialized_view";
102
+ }
103
+ function buildDropViewStatement(view) {
104
+ return `DROP ${buildViewObjectKeyword(view)} IF EXISTS ${quoteQualifiedView(view)};`;
105
+ }
106
+ function buildCreateViewStatement(view) {
107
+ const definition = normalizeViewDefinition(view.viewDefinition);
108
+ if (view.viewType === "materialized_view") {
109
+ return `CREATE MATERIALIZED VIEW ${quoteQualifiedView(view)} AS\n${definition};`;
110
+ }
111
+ return `CREATE OR REPLACE VIEW ${quoteQualifiedView(view)} AS\n${definition};`;
112
+ }
113
+ function buildViewObjectKeyword(view) {
114
+ if (view.viewType === "materialized_view") {
115
+ return "MATERIALIZED VIEW";
116
+ }
117
+ return "VIEW";
118
+ }
119
+ function quoteQualifiedView(view) {
120
+ return `${(0, identifiers_1.quoteIdentifier)(view.viewSchema)}.${(0, identifiers_1.quoteIdentifier)(view.viewName)}`;
121
+ }
122
+ function normalizeViewDefinition(definition) {
123
+ return definition.trim().replace(/;+$/, "").trim();
124
+ }
125
+ function formatPgViewsProgressLabel(viewPosition, totalViews, schema, viewName) {
126
+ return `[pg-views ${viewPosition}/${totalViews}] ${schema}.${viewName}`;
127
+ }
128
+ function reportProgress(callback, message) {
129
+ if (callback) {
130
+ callback(message);
131
+ }
132
+ }
133
+ //# sourceMappingURL=pg-views-diff.js.map
@@ -68,7 +68,7 @@ async function generateSchemaDiff(sourcePool, destPool, options) {
68
68
  destClient.release();
69
69
  }
70
70
  return {
71
- format: "postgres-schema-diff-json/v1",
71
+ format: "frg-schema-diff-json/v1",
72
72
  generatedAt: new Date().toISOString(),
73
73
  source: { schema: options.schema },
74
74
  dest: { schema: options.schema },
@@ -518,7 +518,7 @@ declare const schemaTableDiffSchema: z.ZodObject<{
518
518
  } | null;
519
519
  }>;
520
520
  export declare const schemaDiffJsonSchema: z.ZodObject<{
521
- format: z.ZodLiteral<"postgres-schema-diff-json/v1">;
521
+ format: z.ZodLiteral<"frg-schema-diff-json/v1">;
522
522
  generatedAt: z.ZodString;
523
523
  source: z.ZodObject<{
524
524
  schema: z.ZodString;
@@ -911,7 +911,7 @@ export declare const schemaDiffJsonSchema: z.ZodObject<{
911
911
  tables: string[];
912
912
  excludedTables: string[];
913
913
  };
914
- format: "postgres-schema-diff-json/v1";
914
+ format: "frg-schema-diff-json/v1";
915
915
  generatedAt: string;
916
916
  source: {
917
917
  schema: string;
@@ -996,7 +996,7 @@ export declare const schemaDiffJsonSchema: z.ZodObject<{
996
996
  tables: string[];
997
997
  excludedTables: string[];
998
998
  };
999
- format: "postgres-schema-diff-json/v1";
999
+ format: "frg-schema-diff-json/v1";
1000
1000
  generatedAt: string;
1001
1001
  source: {
1002
1002
  schema: string;
@@ -48,7 +48,7 @@ const schemaDiffSummarySchema = zod_1.z.object({
48
48
  primaryKeysToChange: zod_1.z.number().int(),
49
49
  });
50
50
  exports.schemaDiffJsonSchema = zod_1.z.object({
51
- format: zod_1.z.literal("postgres-schema-diff-json/v1"),
51
+ format: zod_1.z.literal("frg-schema-diff-json/v1"),
52
52
  generatedAt: zod_1.z.string(),
53
53
  source: zod_1.z.object({ schema: zod_1.z.string() }),
54
54
  dest: zod_1.z.object({ schema: zod_1.z.string() }),
@@ -83,6 +83,11 @@ async function promptForGeneratorOptions(defaults, promptFn, dependencies = {})
83
83
  const pgTriggersOutput = await promptConfigString("PostgreSQL triggers output file", defaults.pgTriggersOutput, ask, env, envrcPath, {}, onEnvrcWrite);
84
84
  const generatePgTriggers = await promptBoolean("Generate a PostgreSQL triggers and functions diff? (SQL script)", defaults.generatePgTriggers ?? true, ask, env, envrcPath, onEnvrcWrite);
85
85
  console.log("");
86
+ const pgViews = await promptOptionalList('PostgreSQL views to compare (comma-separated, "*" supported; blank for all)', defaults.pgViews, ask, env, envrcPath, onEnvrcWrite);
87
+ const pgViewsExclude = await promptOptionalList('PostgreSQL views to exclude (comma-separated, "*" supported)', defaults.pgViewsExclude, ask, env, envrcPath, onEnvrcWrite);
88
+ const pgViewsOutput = await promptConfigString("PostgreSQL views output file", defaults.pgViewsOutput, ask, env, envrcPath, {}, onEnvrcWrite);
89
+ const generatePgViews = await promptBoolean("Generate a PostgreSQL views diff? (SQL script)", defaults.generatePgViews ?? true, ask, env, envrcPath, onEnvrcWrite);
90
+ console.log("");
86
91
  const pretty = await promptBoolean("Pretty-print JSON", defaults.pretty, ask, env, envrcPath, onEnvrcWrite);
87
92
  return {
88
93
  sourcePgHost,
@@ -104,15 +109,19 @@ async function promptForGeneratorOptions(defaults, promptFn, dependencies = {})
104
109
  schemaDiffExcludeTables,
105
110
  pgTriggersTables,
106
111
  pgTriggersExcludeTables,
112
+ pgViews,
113
+ pgViewsExclude,
107
114
  ignoreColumns,
108
115
  includeDeletes,
109
116
  skipMissingPk,
110
117
  output,
111
118
  schemaDiffOutput,
112
119
  pgTriggersOutput,
120
+ pgViewsOutput,
113
121
  pretty,
114
122
  generateSql,
115
123
  generatePgTriggers,
124
+ generatePgViews,
116
125
  };
117
126
  }
118
127
  finally {
@@ -0,0 +1,4 @@
1
+ -- PostgreSQL Triggers and Functions Diff
2
+ -- Generated automatically
3
+
4
+ -- No differences found.
@@ -0,0 +1,4 @@
1
+ -- PostgreSQL Views Diff
2
+ -- Generated automatically
3
+
4
+ -- No differences found.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frg-data-diff",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Safe PostgreSQL data diff and apply tooling. Compare data between two PostgreSQL databases and apply changes safely.",
5
5
  "bin": "./dist/cli/root.js",
6
6
  "scripts": {