@pgpmjs/bundle 0.12.2 → 0.13.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.
package/esm/transpile.js CHANGED
@@ -1,8 +1,26 @@
1
1
  import { parsePgpmHeader, renameInHeader, writePgpmScript } from '@pgpmjs/ast/files/sql/header';
2
2
  import { hashString } from '@pgpmjs/ast';
3
- import { renameInPlanContent } from '@pgpmjs/ast';
3
+ import { generatePlanFileContent, parsePlanContent, renameInPlanContent } from '@pgpmjs/ast';
4
4
  import { mapScripts } from '@pgpmjs/traverse';
5
5
  import { computeBundleDigest, computeChangeDigest } from './create';
6
+ /**
7
+ * Drop excluded changes from a plan's text and prune references to them from
8
+ * the surviving changes' dependency brackets, re-serializing the plan. Tags on
9
+ * excluded changes are dropped with them.
10
+ */
11
+ function removeChangesFromPlan(plan, excluded) {
12
+ const parsed = parsePlanContent(plan);
13
+ if (!parsed.data)
14
+ return plan;
15
+ const changes = parsed.data.changes
16
+ .filter(change => !excluded.has(change.name))
17
+ .map(change => ({
18
+ ...change,
19
+ dependencies: change.dependencies.filter(dep => !excluded.has(dep))
20
+ }));
21
+ const tags = (parsed.data.tags ?? []).filter(tag => !excluded.has(tag.change));
22
+ return generatePlanFileContent({ ...parsed.data, changes, tags });
23
+ }
6
24
  function renameProjectInPlan(plan, from, to) {
7
25
  return plan
8
26
  .split('\n')
@@ -67,10 +85,15 @@ function transpileScriptSql(script, changeName, renames, options) {
67
85
  */
68
86
  export function transpileBundle(bundle, options = {}) {
69
87
  const renameChange = options.renameChange ?? ((name) => name);
88
+ const excludeChange = options.excludeChange ?? (() => false);
70
89
  const renames = buildRenames(bundle.manifest.deployOrder, renameChange);
71
- const changes = bundle.changes.map(change => {
90
+ const changes = bundle.changes
91
+ .filter(change => !excludeChange(change.name))
92
+ .map(change => {
72
93
  const name = renames.get(change.name) ?? change.name;
73
- const dependencies = change.dependencies.map(dep => renames.get(dep) ?? dep);
94
+ const dependencies = change.dependencies
95
+ .filter(dep => !excludeChange(dep))
96
+ .map(dep => renames.get(dep) ?? dep);
74
97
  const { deploy, revert, verify } = mapScripts(change, script => transpileScriptSql(script, change.name, renames, options));
75
98
  const digest = computeChangeDigest(name, {
76
99
  deploy: deploy?.digest,
@@ -80,6 +103,13 @@ export function transpileBundle(bundle, options = {}) {
80
103
  return { name, dependencies, deploy, revert, verify, digest };
81
104
  });
82
105
  let plan = renames.size > 0 ? renameInPlanContent(bundle.plan, renames) : bundle.plan;
106
+ // Excluded changes are matched by source name; they are never renamed (the
107
+ // caller leaves excluded changes' identity intact), so prune the plan by the
108
+ // source names, after any survivor renames have been applied above.
109
+ const excluded = new Set(bundle.manifest.deployOrder.filter(excludeChange));
110
+ if (excluded.size > 0) {
111
+ plan = removeChangesFromPlan(plan, excluded);
112
+ }
83
113
  const moduleName = options.renameModule ?? bundle.manifest.name;
84
114
  if (options.renameModule && options.renameModule !== bundle.manifest.name) {
85
115
  plan = renameProjectInPlan(plan, bundle.manifest.name, options.renameModule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pgpmjs/bundle",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "PGPM migration bundle — the portable, content-addressed artifact layer (create/io/verify/transpile/diff/reconcile)",
6
6
  "main": "index.js",
@@ -40,8 +40,8 @@
40
40
  "makage": "^0.3.0"
41
41
  },
42
42
  "dependencies": {
43
- "@pgpmjs/ast": "^0.9.4",
44
- "@pgpmjs/traverse": "^0.9.4"
43
+ "@pgpmjs/ast": "^0.10.0",
44
+ "@pgpmjs/traverse": "^0.10.0"
45
45
  },
46
- "gitHead": "2832d5632d11eb22e1437df773706ac6a99175fe"
46
+ "gitHead": "622be766e8b1d5762b6f0536699d59f745a34c0c"
47
47
  }
package/transpile.d.ts CHANGED
@@ -40,6 +40,20 @@ export interface TranspileBundleOptions extends CreateBundleOptions {
40
40
  * dependency references land on the instance instead of the source.
41
41
  */
42
42
  renameModule?: string;
43
+ /**
44
+ * Select changes to drop from the transpiled bundle entirely (return `true`
45
+ * to exclude). Excluded changes are removed from the change list, deploy
46
+ * order, and plan, and their name is pruned from every surviving change's
47
+ * dependencies (plan brackets included).
48
+ *
49
+ * This is the mechanism behind subsystem exclusion in apply: an excluded
50
+ * subsystem is genuinely absent from the artifact rather than emitted as an
51
+ * empty script. Empty tombstones are indistinguishable by content, so they
52
+ * collide on the deploy ledger's `(package, script_hash)` uniqueness — a
53
+ * dropped change has no script to hash. Cascade safety (no survivor still
54
+ * references a dropped object) is the caller's responsibility.
55
+ */
56
+ excludeChange?: (name: string) => boolean;
43
57
  }
44
58
  /**
45
59
  * Transpile a {@link MigrationBundle} into a new namespace, producing a fresh
package/transpile.js CHANGED
@@ -6,6 +6,24 @@ const ast_1 = require("@pgpmjs/ast");
6
6
  const ast_2 = require("@pgpmjs/ast");
7
7
  const traverse_1 = require("@pgpmjs/traverse");
8
8
  const create_1 = require("./create");
9
+ /**
10
+ * Drop excluded changes from a plan's text and prune references to them from
11
+ * the surviving changes' dependency brackets, re-serializing the plan. Tags on
12
+ * excluded changes are dropped with them.
13
+ */
14
+ function removeChangesFromPlan(plan, excluded) {
15
+ const parsed = (0, ast_2.parsePlanContent)(plan);
16
+ if (!parsed.data)
17
+ return plan;
18
+ const changes = parsed.data.changes
19
+ .filter(change => !excluded.has(change.name))
20
+ .map(change => ({
21
+ ...change,
22
+ dependencies: change.dependencies.filter(dep => !excluded.has(dep))
23
+ }));
24
+ const tags = (parsed.data.tags ?? []).filter(tag => !excluded.has(tag.change));
25
+ return (0, ast_2.generatePlanFileContent)({ ...parsed.data, changes, tags });
26
+ }
9
27
  function renameProjectInPlan(plan, from, to) {
10
28
  return plan
11
29
  .split('\n')
@@ -70,10 +88,15 @@ function transpileScriptSql(script, changeName, renames, options) {
70
88
  */
71
89
  function transpileBundle(bundle, options = {}) {
72
90
  const renameChange = options.renameChange ?? ((name) => name);
91
+ const excludeChange = options.excludeChange ?? (() => false);
73
92
  const renames = buildRenames(bundle.manifest.deployOrder, renameChange);
74
- const changes = bundle.changes.map(change => {
93
+ const changes = bundle.changes
94
+ .filter(change => !excludeChange(change.name))
95
+ .map(change => {
75
96
  const name = renames.get(change.name) ?? change.name;
76
- const dependencies = change.dependencies.map(dep => renames.get(dep) ?? dep);
97
+ const dependencies = change.dependencies
98
+ .filter(dep => !excludeChange(dep))
99
+ .map(dep => renames.get(dep) ?? dep);
77
100
  const { deploy, revert, verify } = (0, traverse_1.mapScripts)(change, script => transpileScriptSql(script, change.name, renames, options));
78
101
  const digest = (0, create_1.computeChangeDigest)(name, {
79
102
  deploy: deploy?.digest,
@@ -83,6 +106,13 @@ function transpileBundle(bundle, options = {}) {
83
106
  return { name, dependencies, deploy, revert, verify, digest };
84
107
  });
85
108
  let plan = renames.size > 0 ? (0, ast_2.renameInPlanContent)(bundle.plan, renames) : bundle.plan;
109
+ // Excluded changes are matched by source name; they are never renamed (the
110
+ // caller leaves excluded changes' identity intact), so prune the plan by the
111
+ // source names, after any survivor renames have been applied above.
112
+ const excluded = new Set(bundle.manifest.deployOrder.filter(excludeChange));
113
+ if (excluded.size > 0) {
114
+ plan = removeChangesFromPlan(plan, excluded);
115
+ }
86
116
  const moduleName = options.renameModule ?? bundle.manifest.name;
87
117
  if (options.renameModule && options.renameModule !== bundle.manifest.name) {
88
118
  plan = renameProjectInPlan(plan, bundle.manifest.name, options.renameModule);