@pagepocket/cli 0.11.0 → 0.11.1

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.
Files changed (48) hide show
  1. package/dist/commands/archive.js +67 -105
  2. package/dist/commands/plugin/add.js +19 -25
  3. package/dist/commands/plugin/doctor.js +22 -28
  4. package/dist/commands/plugin/ls.js +16 -22
  5. package/dist/commands/plugin/prune.js +13 -19
  6. package/dist/commands/plugin/remove.js +16 -22
  7. package/dist/commands/plugin/set.js +13 -19
  8. package/dist/commands/plugin/uninstall.js +29 -35
  9. package/dist/commands/plugin/update.js +22 -28
  10. package/dist/commands/strategy/add.js +14 -20
  11. package/dist/commands/strategy/doctor.js +11 -17
  12. package/dist/commands/strategy/ls.js +9 -12
  13. package/dist/commands/strategy/pin.js +10 -16
  14. package/dist/commands/strategy/remove.js +10 -16
  15. package/dist/commands/strategy/update.js +21 -27
  16. package/dist/commands/view.js +36 -42
  17. package/dist/index.js +9 -7
  18. package/dist/lib/filename.js +1 -5
  19. package/dist/services/config-service.js +24 -30
  20. package/dist/services/load-configured-plugins.js +8 -12
  21. package/dist/services/plugin-installer.js +6 -12
  22. package/dist/services/plugin-store.js +27 -68
  23. package/dist/services/strategy/builtin-strategy-registry.js +11 -20
  24. package/dist/services/strategy/strategy-analyze.js +10 -18
  25. package/dist/services/strategy/strategy-config.js +8 -15
  26. package/dist/services/strategy/strategy-fetch.js +11 -18
  27. package/dist/services/strategy/strategy-io.js +15 -25
  28. package/dist/services/strategy/strategy-normalize.js +4 -8
  29. package/dist/services/strategy/strategy-pack-read.js +10 -17
  30. package/dist/services/strategy/strategy-pack-store.js +12 -18
  31. package/dist/services/strategy/strategy-service.js +79 -83
  32. package/dist/services/strategy/types.js +1 -2
  33. package/dist/services/units/unit-store.js +16 -20
  34. package/dist/services/units/unit-validate.js +20 -5
  35. package/dist/services/user-packages/parse-pinned-spec.js +5 -11
  36. package/dist/services/user-packages/user-package-installer.js +4 -9
  37. package/dist/services/user-packages/user-package-store.js +19 -57
  38. package/dist/stages/prepare-output.js +6 -13
  39. package/dist/units/network-observer-unit.js +7 -10
  40. package/dist/utils/array.js +1 -5
  41. package/dist/utils/normalize-argv.js +3 -8
  42. package/dist/utils/parse-json.js +1 -5
  43. package/dist/utils/parse-plugin-options.js +1 -5
  44. package/dist/utils/parse-plugin-spec.js +5 -11
  45. package/dist/utils/validate-plugin-default-export.js +1 -5
  46. package/dist/utils/with-spinner.js +3 -10
  47. package/dist/view.js +12 -19
  48. package/package.json +12 -11
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.normalizeStrategyUnits = void 0;
4
- const parse_pinned_spec_1 = require("../user-packages/parse-pinned-spec");
1
+ import { parsePinnedSpec } from "../user-packages/parse-pinned-spec.js";
5
2
  const isRecord = (value) => {
6
3
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7
4
  };
@@ -23,7 +20,7 @@ const isJsonValue = (value) => {
23
20
  };
24
21
  const normalizeUnitSpec = (spec, idx) => {
25
22
  if (typeof spec === "string") {
26
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
23
+ const pinned = parsePinnedSpec(spec);
27
24
  return { ref: pinned.spec, args: [] };
28
25
  }
29
26
  if (!isRecord(spec)) {
@@ -33,7 +30,7 @@ const normalizeUnitSpec = (spec, idx) => {
33
30
  if (typeof ref !== "string") {
34
31
  throw new Error(`Invalid unit ref at index ${idx}`);
35
32
  }
36
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(ref);
33
+ const pinned = parsePinnedSpec(ref);
37
34
  const argsRaw = spec.args;
38
35
  const args = typeof argsRaw === "undefined" ? [] : argsRaw;
39
36
  if (!Array.isArray(args)) {
@@ -44,8 +41,7 @@ const normalizeUnitSpec = (spec, idx) => {
44
41
  }
45
42
  return { ref: pinned.spec, args };
46
43
  };
47
- const normalizeStrategyUnits = (strategy) => {
44
+ export const normalizeStrategyUnits = (strategy) => {
48
45
  const units = strategy.pipeline.units;
49
46
  return units.map((spec, idx) => normalizeUnitSpec(spec, idx));
50
47
  };
51
- exports.normalizeStrategyUnits = normalizeStrategyUnits;
@@ -1,12 +1,6 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.readStrategiesFromPackRoot = void 0;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- const parse_json_1 = require("../../utils/parse-json");
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { parseJson } from "../../utils/parse-json.js";
10
4
  const isRecord = (value) => {
11
5
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
12
6
  };
@@ -29,19 +23,19 @@ const isStrategyFile = (value) => {
29
23
  }
30
24
  return true;
31
25
  };
32
- const readStrategiesFromPackRoot = (packRoot) => {
33
- const strategiesDir = node_path_1.default.join(packRoot, "strategies");
34
- if (!node_fs_1.default.existsSync(strategiesDir)) {
26
+ export const readStrategiesFromPackRoot = (packRoot) => {
27
+ const strategiesDir = path.join(packRoot, "strategies");
28
+ if (!fs.existsSync(strategiesDir)) {
35
29
  return [];
36
30
  }
37
- const fileNames = node_fs_1.default
31
+ const fileNames = fs
38
32
  .readdirSync(strategiesDir)
39
33
  .filter((f) => f.endsWith(".strategy.json"))
40
34
  .sort((a, b) => a.localeCompare(b));
41
35
  return fileNames.map((fileName) => {
42
- const filePath = node_path_1.default.join(strategiesDir, fileName);
43
- const text = node_fs_1.default.readFileSync(filePath, "utf8");
44
- const parsed = (0, parse_json_1.parseJson)(text);
36
+ const filePath = path.join(strategiesDir, fileName);
37
+ const text = fs.readFileSync(filePath, "utf8");
38
+ const parsed = parseJson(text);
45
39
  if (!parsed.ok) {
46
40
  throw parsed.error;
47
41
  }
@@ -51,4 +45,3 @@ const readStrategiesFromPackRoot = (packRoot) => {
51
45
  return parsed.value;
52
46
  });
53
47
  };
54
- exports.readStrategiesFromPackRoot = readStrategiesFromPackRoot;
@@ -1,19 +1,14 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.StrategyPackStore = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- const user_package_installer_1 = require("../user-packages/user-package-installer");
9
- const user_package_installer_2 = require("../user-packages/user-package-installer");
10
- const parse_pinned_spec_1 = require("../user-packages/parse-pinned-spec");
11
- const user_package_store_1 = require("../user-packages/user-package-store");
1
+ import path from "node:path";
2
+ import { installPinnedPackage } from "../user-packages/user-package-installer.js";
3
+ import { updatePackageToLatest } from "../user-packages/user-package-installer.js";
4
+ import { parsePinnedSpec } from "../user-packages/parse-pinned-spec.js";
5
+ import { UserPackageStore } from "../user-packages/user-package-store.js";
12
6
  const STRATEGY_PACKS_KIND = "strategy-packs";
13
7
  const STRATEGY_PACKS_PACKAGE_JSON_NAME = "pagepocket-user-strategy-packs";
14
- class StrategyPackStore {
8
+ export class StrategyPackStore {
9
+ store;
15
10
  constructor(configService) {
16
- this.store = new user_package_store_1.UserPackageStore(configService, STRATEGY_PACKS_KIND);
11
+ this.store = new UserPackageStore(configService, STRATEGY_PACKS_KIND);
17
12
  }
18
13
  getInstallDir() {
19
14
  return this.store.getInstallDir();
@@ -22,15 +17,15 @@ class StrategyPackStore {
22
17
  return this.store.readInstalledDependencyVersions(STRATEGY_PACKS_PACKAGE_JSON_NAME);
23
18
  }
24
19
  installPinned(spec) {
25
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
26
- (0, user_package_installer_1.installPinnedPackage)(this.store, {
20
+ const pinned = parsePinnedSpec(spec);
21
+ installPinnedPackage(this.store, {
27
22
  packageJsonName: STRATEGY_PACKS_PACKAGE_JSON_NAME,
28
23
  packageSpec: pinned.spec
29
24
  });
30
25
  return pinned;
31
26
  }
32
27
  updateToLatest(packageName) {
33
- (0, user_package_installer_2.updatePackageToLatest)(this.store, {
28
+ updatePackageToLatest(this.store, {
34
29
  packageJsonName: STRATEGY_PACKS_PACKAGE_JSON_NAME,
35
30
  packageName
36
31
  });
@@ -39,7 +34,6 @@ class StrategyPackStore {
39
34
  this.store.ensureInstallDirPackageJson(STRATEGY_PACKS_PACKAGE_JSON_NAME);
40
35
  const req = this.store.createRequire(STRATEGY_PACKS_PACKAGE_JSON_NAME);
41
36
  const pkgJsonPath = req.resolve(`${packageName}/package.json`);
42
- return node_path_1.default.dirname(pkgJsonPath);
37
+ return path.dirname(pkgJsonPath);
43
38
  }
44
39
  }
45
- exports.StrategyPackStore = StrategyPackStore;
@@ -1,42 +1,39 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.StrategyService = void 0;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const config_service_1 = require("../config-service");
9
- const parse_pinned_spec_1 = require("../user-packages/parse-pinned-spec");
10
- const unit_store_1 = require("../units/unit-store");
11
- const array_1 = require("../../utils/array");
12
- const strategy_analyze_1 = require("./strategy-analyze");
13
- const strategy_config_1 = require("./strategy-config");
14
- const strategy_fetch_1 = require("./strategy-fetch");
15
- const strategy_io_1 = require("./strategy-io");
16
- const strategy_normalize_1 = require("./strategy-normalize");
17
- const strategy_pack_read_1 = require("./strategy-pack-read");
18
- const strategy_pack_store_1 = require("./strategy-pack-store");
19
- class StrategyService {
20
- constructor(configService = new config_service_1.ConfigService()) {
1
+ import fs from "node:fs";
2
+ import { ConfigService } from "../config-service.js";
3
+ import { parsePinnedSpec } from "../user-packages/parse-pinned-spec.js";
4
+ import { UnitStore } from "../units/unit-store.js";
5
+ import { uniq } from "../../utils/array.js";
6
+ import { collectWantedVersions, computeConflicts, computeDrift, ensureNoInstalledVersionConflicts } from "./strategy-analyze.js";
7
+ import { listStrategyNamesFromConfig, requireStrategyInstalled, withStrategyInConfig, withoutStrategyInConfig } from "./strategy-config.js";
8
+ import { fetchStrategyFile } from "./strategy-fetch.js";
9
+ import { getStrategyPath, getStrategiesDir, readStrategyFile, writeJsonAtomic } from "./strategy-io.js";
10
+ import { normalizeStrategyUnits } from "./strategy-normalize.js";
11
+ import { readStrategiesFromPackRoot } from "./strategy-pack-read.js";
12
+ import { StrategyPackStore } from "./strategy-pack-store.js";
13
+ export class StrategyService {
14
+ configService;
15
+ unitStore;
16
+ packStore;
17
+ constructor(configService = new ConfigService()) {
21
18
  this.configService = configService;
22
- this.unitStore = new unit_store_1.UnitStore(configService);
23
- this.packStore = new strategy_pack_store_1.StrategyPackStore(configService);
19
+ this.unitStore = new UnitStore(configService);
20
+ this.packStore = new StrategyPackStore(configService);
24
21
  }
25
22
  ensureConfigFileExists() {
26
23
  return this.configService.ensureConfigFileExists();
27
24
  }
28
25
  getStrategiesDir() {
29
- return (0, strategy_io_1.getStrategiesDir)(this.configService);
26
+ return getStrategiesDir(this.configService);
30
27
  }
31
28
  getStrategyPath(name) {
32
- return (0, strategy_io_1.getStrategyPath)(this.configService, name);
29
+ return getStrategyPath(this.configService, name);
33
30
  }
34
31
  readStrategy(name) {
35
- return (0, strategy_io_1.readStrategyFile)(this.getStrategyPath(name));
32
+ return readStrategyFile(this.getStrategyPath(name));
36
33
  }
37
34
  listInstalledStrategyNames() {
38
35
  const config = this.configService.readConfigOrDefault();
39
- return (0, strategy_config_1.listStrategyNamesFromConfig)(config);
36
+ return listStrategyNamesFromConfig(config);
40
37
  }
41
38
  async addStrategy(input) {
42
39
  this.configService.ensureConfigFileExists();
@@ -44,7 +41,7 @@ class StrategyService {
44
41
  const sourceTrimmed = input.source.trim();
45
42
  const isPinnedNpm = (() => {
46
43
  try {
47
- (0, parse_pinned_spec_1.parsePinnedSpec)(sourceTrimmed);
44
+ parsePinnedSpec(sourceTrimmed);
48
45
  return true;
49
46
  }
50
47
  catch {
@@ -54,29 +51,29 @@ class StrategyService {
54
51
  if (isPinnedNpm) {
55
52
  const pinned = this.packStore.installPinned(sourceTrimmed);
56
53
  const packRoot = this.packStore.resolvePackRoot(pinned.name);
57
- const strategies = (0, strategy_pack_read_1.readStrategiesFromPackRoot)(packRoot);
54
+ const strategies = readStrategiesFromPackRoot(packRoot);
58
55
  if (strategies.length === 0) {
59
56
  throw new Error(`No *.strategy.json found in package: ${pinned.spec}`);
60
57
  }
61
- const allUnits = strategies.flatMap((s) => (0, strategy_normalize_1.normalizeStrategyUnits)(s));
62
- const refs = (0, array_1.uniq)(allUnits.map((u) => u.ref));
63
- (0, strategy_analyze_1.ensureNoInstalledVersionConflicts)(this.unitStore.readInstalledDependencyVersions(), refs);
58
+ const allUnits = strategies.flatMap((s) => normalizeStrategyUnits(s));
59
+ const refs = uniq(allUnits.map((u) => u.ref));
60
+ ensureNoInstalledVersionConflicts(this.unitStore.readInstalledDependencyVersions(), refs);
64
61
  refs.forEach((ref) => this.unitStore.installPinned(ref));
65
62
  const installedStrategies = [];
66
63
  strategies.forEach((strategy) => {
67
64
  const name = strategy.name;
68
65
  const strategyPath = this.getStrategyPath(name);
69
- if (!input.force && node_fs_1.default.existsSync(strategyPath)) {
66
+ if (!input.force && fs.existsSync(strategyPath)) {
70
67
  return;
71
68
  }
72
69
  const toWrite = {
73
70
  ...strategy,
74
71
  source: { type: "npm", value: pinned.spec }
75
72
  };
76
- (0, strategy_io_1.writeJsonAtomic)(strategyPath, toWrite);
73
+ writeJsonAtomic(strategyPath, toWrite);
77
74
  installedStrategies.push(name);
78
75
  });
79
- const nextConfig = installedStrategies.reduce((acc, s) => (0, strategy_config_1.withStrategyInConfig)(acc, s), config);
76
+ const nextConfig = installedStrategies.reduce((acc, s) => withStrategyInConfig(acc, s), config);
80
77
  const existing = nextConfig.strategyPacks ?? [];
81
78
  const filtered = existing.filter((x) => {
82
79
  if (typeof x === "string") {
@@ -94,60 +91,60 @@ class StrategyService {
94
91
  this.configService.writeConfig({ ...nextConfig, strategyPacks });
95
92
  return { installedRefs: refs, installedStrategies };
96
93
  }
97
- const { strategy, source } = await (0, strategy_fetch_1.fetchStrategyFile)(sourceTrimmed);
98
- const normalizedUnits = (0, strategy_normalize_1.normalizeStrategyUnits)(strategy);
99
- const refs = (0, array_1.uniq)(normalizedUnits.map((u) => u.ref));
94
+ const { strategy, source } = await fetchStrategyFile(sourceTrimmed);
95
+ const normalizedUnits = normalizeStrategyUnits(strategy);
96
+ const refs = uniq(normalizedUnits.map((u) => u.ref));
100
97
  const strategyPath = this.getStrategyPath(strategy.name);
101
- if (!input.force && node_fs_1.default.existsSync(strategyPath)) {
98
+ if (!input.force && fs.existsSync(strategyPath)) {
102
99
  throw new Error(`Strategy already exists: ${strategy.name}`);
103
100
  }
104
- (0, strategy_analyze_1.ensureNoInstalledVersionConflicts)(this.unitStore.readInstalledDependencyVersions(), refs);
101
+ ensureNoInstalledVersionConflicts(this.unitStore.readInstalledDependencyVersions(), refs);
105
102
  refs.forEach((ref) => this.unitStore.installPinned(ref));
106
103
  const toWrite = {
107
104
  ...strategy,
108
105
  source
109
106
  };
110
- (0, strategy_io_1.writeJsonAtomic)(strategyPath, toWrite);
111
- this.configService.writeConfig((0, strategy_config_1.withStrategyInConfig)(config, strategy.name));
107
+ writeJsonAtomic(strategyPath, toWrite);
108
+ this.configService.writeConfig(withStrategyInConfig(config, strategy.name));
112
109
  return { installedRefs: refs, installedStrategies: [strategy.name] };
113
110
  }
114
111
  removeStrategy(name) {
115
112
  this.configService.ensureConfigFileExists();
116
113
  const config = this.configService.readConfigOrDefault();
117
- (0, strategy_config_1.requireStrategyInstalled)(config, name);
114
+ requireStrategyInstalled(config, name);
118
115
  const strategyPath = this.getStrategyPath(name);
119
- if (node_fs_1.default.existsSync(strategyPath)) {
120
- node_fs_1.default.rmSync(strategyPath);
116
+ if (fs.existsSync(strategyPath)) {
117
+ fs.rmSync(strategyPath);
121
118
  }
122
- this.configService.writeConfig((0, strategy_config_1.withoutStrategyInConfig)(config, name));
119
+ this.configService.writeConfig(withoutStrategyInConfig(config, name));
123
120
  }
124
121
  async updateStrategy(name, opts) {
125
122
  this.configService.ensureConfigFileExists();
126
123
  const config = this.configService.readConfigOrDefault();
127
- const names = name ? [name] : (0, strategy_config_1.listStrategyNamesFromConfig)(config);
124
+ const names = name ? [name] : listStrategyNamesFromConfig(config);
128
125
  if (names.length === 0) {
129
126
  return;
130
127
  }
131
128
  const installed = this.unitStore.readInstalledDependencyVersions();
132
129
  if (opts?.packageOnly) {
133
- const packageNames = (0, array_1.uniq)(names
134
- .flatMap((n) => (0, strategy_normalize_1.normalizeStrategyUnits)(this.readStrategy(n)).map((u) => (0, parse_pinned_spec_1.parsePinnedSpec)(u.ref).name))
130
+ const packageNames = uniq(names
131
+ .flatMap((n) => normalizeStrategyUnits(this.readStrategy(n)).map((u) => parsePinnedSpec(u.ref).name))
135
132
  .filter((x) => x.trim().length > 0));
136
133
  packageNames.forEach((pkg) => {
137
134
  this.unitStore.updateToLatest(pkg);
138
135
  });
139
136
  const afterInstalled = this.unitStore.readInstalledDependencyVersions();
140
- const afterStrategies = (0, strategy_config_1.listStrategyNamesFromConfig)(config).map((n) => ({
137
+ const afterStrategies = listStrategyNamesFromConfig(config).map((n) => ({
141
138
  name: n,
142
- units: (0, strategy_normalize_1.normalizeStrategyUnits)(this.readStrategy(n))
139
+ units: normalizeStrategyUnits(this.readStrategy(n))
143
140
  }));
144
- const wanted = (0, strategy_analyze_1.collectWantedVersions)(afterStrategies);
145
- const conflicts = (0, strategy_analyze_1.computeConflicts)(wanted);
141
+ const wanted = collectWantedVersions(afterStrategies);
142
+ const conflicts = computeConflicts(wanted);
146
143
  if (conflicts.length > 0) {
147
144
  throw new Error(`Strategy version conflicts detected (${conflicts.length}). Run 'pp strategy doctor' for details.`);
148
145
  }
149
146
  const drift = afterStrategies
150
- .map((s) => (0, strategy_analyze_1.computeDrift)({ strategyName: s.name, units: s.units, installed: afterInstalled }))
147
+ .map((s) => computeDrift({ strategyName: s.name, units: s.units, installed: afterInstalled }))
151
148
  .filter((d) => d.items.length > 0);
152
149
  if (drift.length > 0) {
153
150
  throw new Error("Strategy drift detected after --package-only update. Run 'pp strategy doctor'.");
@@ -166,23 +163,23 @@ class StrategyService {
166
163
  npmPacksToUpdate.add(src.value);
167
164
  continue;
168
165
  }
169
- const fetched = await (0, strategy_fetch_1.fetchStrategyFile)(src.value);
166
+ const fetched = await fetchStrategyFile(src.value);
170
167
  if (fetched.strategy.name !== n) {
171
168
  throw new Error(`Strategy name mismatch while updating ${n}: got ${fetched.strategy.name}`);
172
169
  }
173
170
  const file = { ...fetched.strategy, source: fetched.source };
174
- const units = (0, strategy_normalize_1.normalizeStrategyUnits)(file);
171
+ const units = normalizeStrategyUnits(file);
175
172
  nextStrategies.push({ name: n, file, units });
176
173
  }
177
174
  if (npmPacksToUpdate.size > 0) {
178
175
  const specs = [...npmPacksToUpdate];
179
176
  specs.forEach((spec) => {
180
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
177
+ const pinned = parsePinnedSpec(spec);
181
178
  this.packStore.updateToLatest(pinned.name);
182
179
  });
183
180
  const installedPackVersions = this.packStore.readInstalledDependencyVersions();
184
181
  const updatedSpecs = specs.map((spec) => {
185
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
182
+ const pinned = parsePinnedSpec(spec);
186
183
  const v = installedPackVersions[pinned.name];
187
184
  if (!v) {
188
185
  throw new Error(`Strategy pack not installed after update: ${pinned.name}`);
@@ -191,16 +188,16 @@ class StrategyService {
191
188
  });
192
189
  const updatedFiles = [];
193
190
  updatedSpecs.forEach((spec) => {
194
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
191
+ const pinned = parsePinnedSpec(spec);
195
192
  const root = this.packStore.resolvePackRoot(pinned.name);
196
- const files = (0, strategy_pack_read_1.readStrategiesFromPackRoot)(root).map((f) => ({
193
+ const files = readStrategiesFromPackRoot(root).map((f) => ({
197
194
  ...f,
198
195
  source: { type: "npm", value: spec }
199
196
  }));
200
197
  updatedFiles.push(...files);
201
198
  });
202
199
  updatedFiles.forEach((file) => {
203
- const units = (0, strategy_normalize_1.normalizeStrategyUnits)(file);
200
+ const units = normalizeStrategyUnits(file);
204
201
  nextStrategies.push({ name: file.name, file, units });
205
202
  });
206
203
  const nextConfig = this.configService.readConfigOrDefault();
@@ -209,48 +206,48 @@ class StrategyService {
209
206
  if (typeof x === "string") {
210
207
  return x.trim().length > 0;
211
208
  }
212
- return !updatedSpecs.some((spec) => (0, parse_pinned_spec_1.parsePinnedSpec)(spec).name === x.name);
209
+ return !updatedSpecs.some((spec) => parsePinnedSpec(spec).name === x.name);
213
210
  });
214
211
  const packsNext = [
215
212
  ...filtered,
216
213
  ...updatedSpecs.map((spec) => {
217
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(spec);
214
+ const pinned = parsePinnedSpec(spec);
218
215
  return { name: pinned.name, spec: pinned.spec };
219
216
  })
220
217
  ];
221
218
  this.configService.writeConfig({ ...nextConfig, strategyPacks: packsNext });
222
219
  }
223
- const allOtherNames = (0, strategy_config_1.listStrategyNamesFromConfig)(config).filter((n) => !names.includes(n));
220
+ const allOtherNames = listStrategyNamesFromConfig(config).filter((n) => !names.includes(n));
224
221
  const otherStrategies = allOtherNames.map((n) => ({
225
222
  name: n,
226
- units: (0, strategy_normalize_1.normalizeStrategyUnits)(this.readStrategy(n))
223
+ units: normalizeStrategyUnits(this.readStrategy(n))
227
224
  }));
228
- const wanted = (0, strategy_analyze_1.collectWantedVersions)([
225
+ const wanted = collectWantedVersions([
229
226
  ...otherStrategies,
230
227
  ...nextStrategies.map((s) => ({ name: s.name, units: s.units }))
231
228
  ]);
232
- const conflicts = (0, strategy_analyze_1.computeConflicts)(wanted);
229
+ const conflicts = computeConflicts(wanted);
233
230
  if (conflicts.length > 0) {
234
231
  throw new Error(`Strategy version conflicts detected (${conflicts.length}). Run 'pp strategy doctor' for details.`);
235
232
  }
236
- const refs = (0, array_1.uniq)(nextStrategies.flatMap((s) => s.units.map((u) => u.ref)));
237
- (0, strategy_analyze_1.ensureNoInstalledVersionConflicts)(installed, refs);
233
+ const refs = uniq(nextStrategies.flatMap((s) => s.units.map((u) => u.ref)));
234
+ ensureNoInstalledVersionConflicts(installed, refs);
238
235
  refs.forEach((ref) => {
239
236
  this.unitStore.installPinned(ref);
240
237
  });
241
238
  nextStrategies.forEach((s) => {
242
- (0, strategy_io_1.writeJsonAtomic)(this.getStrategyPath(s.name), s.file);
239
+ writeJsonAtomic(this.getStrategyPath(s.name), s.file);
243
240
  });
244
241
  }
245
242
  pinStrategy(name) {
246
243
  this.configService.ensureConfigFileExists();
247
244
  const config = this.configService.readConfigOrDefault();
248
- (0, strategy_config_1.requireStrategyInstalled)(config, name);
245
+ requireStrategyInstalled(config, name);
249
246
  const file = this.readStrategy(name);
250
- const units = (0, strategy_normalize_1.normalizeStrategyUnits)(file);
247
+ const units = normalizeStrategyUnits(file);
251
248
  const installed = this.unitStore.readInstalledDependencyVersions();
252
249
  const pinnedUnits = units.map((u) => {
253
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(u.ref);
250
+ const pinned = parsePinnedSpec(u.ref);
254
251
  const v = installed[pinned.name];
255
252
  if (!v) {
256
253
  throw new Error(`Unit package is not installed: ${pinned.name}`);
@@ -258,17 +255,17 @@ class StrategyService {
258
255
  const nextRef = `${pinned.name}@${v}`;
259
256
  return u.args.length === 0 ? nextRef : { ref: nextRef, args: u.args };
260
257
  });
261
- const others = (0, strategy_config_1.listStrategyNamesFromConfig)(config)
258
+ const others = listStrategyNamesFromConfig(config)
262
259
  .filter((n) => n !== name)
263
- .map((n) => ({ name: n, units: (0, strategy_normalize_1.normalizeStrategyUnits)(this.readStrategy(n)) }));
264
- const nextWanted = (0, strategy_analyze_1.collectWantedVersions)([
260
+ .map((n) => ({ name: n, units: normalizeStrategyUnits(this.readStrategy(n)) }));
261
+ const nextWanted = collectWantedVersions([
265
262
  ...others,
266
263
  {
267
264
  name,
268
265
  units: pinnedUnits.map((x) => typeof x === "string" ? { ref: x, args: [] } : { ref: x.ref, args: x.args ?? [] })
269
266
  }
270
267
  ]);
271
- const conflicts = (0, strategy_analyze_1.computeConflicts)(nextWanted);
268
+ const conflicts = computeConflicts(nextWanted);
272
269
  if (conflicts.length > 0) {
273
270
  throw new Error(`Strategy version conflicts detected (${conflicts.length}). Run 'pp strategy doctor' for details.`);
274
271
  }
@@ -279,23 +276,22 @@ class StrategyService {
279
276
  units: pinnedUnits
280
277
  }
281
278
  };
282
- (0, strategy_io_1.writeJsonAtomic)(this.getStrategyPath(name), nextFile);
279
+ writeJsonAtomic(this.getStrategyPath(name), nextFile);
283
280
  }
284
281
  doctor() {
285
282
  this.configService.ensureConfigFileExists();
286
283
  const config = this.configService.readConfigOrDefault();
287
- const names = (0, strategy_config_1.listStrategyNamesFromConfig)(config);
284
+ const names = listStrategyNamesFromConfig(config);
288
285
  const installed = this.unitStore.readInstalledDependencyVersions();
289
286
  const strategies = names.map((n) => ({
290
287
  name: n,
291
- units: (0, strategy_normalize_1.normalizeStrategyUnits)(this.readStrategy(n))
288
+ units: normalizeStrategyUnits(this.readStrategy(n))
292
289
  }));
293
- const wanted = (0, strategy_analyze_1.collectWantedVersions)(strategies);
294
- const conflicts = (0, strategy_analyze_1.computeConflicts)(wanted);
290
+ const wanted = collectWantedVersions(strategies);
291
+ const conflicts = computeConflicts(wanted);
295
292
  const drift = strategies
296
- .map((s) => (0, strategy_analyze_1.computeDrift)({ strategyName: s.name, units: s.units, installed }))
293
+ .map((s) => computeDrift({ strategyName: s.name, units: s.units, installed }))
297
294
  .filter((d) => d.items.length > 0);
298
295
  return { conflicts, drift };
299
296
  }
300
297
  }
301
- exports.StrategyService = StrategyService;
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,15 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UnitStore = void 0;
4
- const user_package_installer_1 = require("../user-packages/user-package-installer");
5
- const parse_pinned_spec_1 = require("../user-packages/parse-pinned-spec");
6
- const user_package_store_1 = require("../user-packages/user-package-store");
7
- const unit_validate_1 = require("./unit-validate");
1
+ import { installPinnedPackage, updatePackageToLatest } from "../user-packages/user-package-installer.js";
2
+ import { parsePinnedSpec } from "../user-packages/parse-pinned-spec.js";
3
+ import { UserPackageStore } from "../user-packages/user-package-store.js";
4
+ import { isUnitLike, resolveUnitConstructor } from "./unit-validate.js";
8
5
  const UNITS_KIND = "units";
9
6
  const UNITS_PACKAGE_JSON_NAME = "pagepocket-user-units";
10
- class UnitStore {
7
+ export class UnitStore {
8
+ store;
11
9
  constructor(configService) {
12
- this.store = new user_package_store_1.UserPackageStore(configService, UNITS_KIND);
10
+ this.store = new UserPackageStore(configService, UNITS_KIND);
13
11
  }
14
12
  getInstallDir() {
15
13
  return this.store.getInstallDir();
@@ -21,14 +19,14 @@ class UnitStore {
21
19
  return this.store.readInstalledPackageMeta(UNITS_PACKAGE_JSON_NAME, packageName);
22
20
  }
23
21
  installPinned(ref) {
24
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(ref);
25
- (0, user_package_installer_1.installPinnedPackage)(this.store, {
22
+ const pinned = parsePinnedSpec(ref);
23
+ installPinnedPackage(this.store, {
26
24
  packageJsonName: UNITS_PACKAGE_JSON_NAME,
27
25
  packageSpec: pinned.spec
28
26
  });
29
27
  }
30
28
  updateToLatest(packageName) {
31
- (0, user_package_installer_1.updatePackageToLatest)(this.store, {
29
+ updatePackageToLatest(this.store, {
32
30
  packageJsonName: UNITS_PACKAGE_JSON_NAME,
33
31
  packageName
34
32
  });
@@ -37,18 +35,16 @@ class UnitStore {
37
35
  return this.store.importModule(UNITS_PACKAGE_JSON_NAME, packageName);
38
36
  }
39
37
  async instantiateFromRef(ref, args) {
40
- const pinned = (0, parse_pinned_spec_1.parsePinnedSpec)(ref);
38
+ const pinned = parsePinnedSpec(ref);
41
39
  const mod = await this.importUnitModule(pinned.name);
42
- const def = mod.default;
43
- if (typeof def !== "function") {
44
- throw new Error(`Unit ${pinned.name} must default export a constructor.`);
40
+ const ctor = resolveUnitConstructor(mod);
41
+ if (!ctor) {
42
+ throw new Error(`Unit ${pinned.name} does not export a Unit constructor.`);
45
43
  }
46
- const ctor = def;
47
44
  const instance = new ctor(...args);
48
- if (!(0, unit_validate_1.isUnitLike)(instance)) {
49
- throw new Error(`Unit ${pinned.name} default export did not construct a Unit.`);
45
+ if (!isUnitLike(instance)) {
46
+ throw new Error(`Unit ${pinned.name} exported constructor did not produce a Unit.`);
50
47
  }
51
48
  return instance;
52
49
  }
53
50
  }
54
- exports.UnitStore = UnitStore;
@@ -1,13 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isUnitLike = void 0;
4
1
  const isRecord = (value) => {
5
2
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6
3
  };
7
4
  const isCallable = (value) => {
8
5
  return typeof value === "function";
9
6
  };
10
- const isUnitLike = (value) => {
7
+ export const isUnitLike = (value) => {
11
8
  if (!isRecord(value)) {
12
9
  return false;
13
10
  }
@@ -25,4 +22,22 @@ const isUnitLike = (value) => {
25
22
  }
26
23
  return true;
27
24
  };
28
- exports.isUnitLike = isUnitLike;
25
+ /**
26
+ * Resolve a Unit constructor from an imported ESM module.
27
+ *
28
+ * Checks `mod.default` first. If it is not a function (e.g. older packages
29
+ * that only use named exports), falls back to the first exported function
30
+ * whose name ends with "Unit".
31
+ *
32
+ * @returns The constructor function, or `undefined` when none is found.
33
+ */
34
+ export const resolveUnitConstructor = (mod) => {
35
+ if (typeof mod.default === "function") {
36
+ return mod.default;
37
+ }
38
+ const fallback = Object.values(mod).find((v) => typeof v === "function" && v.name?.endsWith("Unit"));
39
+ if (typeof fallback === "function") {
40
+ return fallback;
41
+ }
42
+ return undefined;
43
+ };
@@ -1,23 +1,18 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.parsePinnedSpec = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- const node_module_1 = require("node:module");
1
+ import path from "node:path";
2
+ import { createRequire } from "node:module";
3
+ import { fileURLToPath } from "node:url";
9
4
  const isRecord = (value) => {
10
5
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11
6
  };
12
7
  const isExactSemver = (value) => {
13
8
  return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(value);
14
9
  };
15
- const parsePinnedSpec = (input) => {
10
+ export const parsePinnedSpec = (input) => {
16
11
  const trimmed = input.trim();
17
12
  if (!trimmed) {
18
13
  throw new Error("package spec is empty");
19
14
  }
20
- const req = (0, node_module_1.createRequire)(typeof __filename === "string" ? __filename : node_path_1.default.join(process.cwd(), "package.json"));
15
+ const req = createRequire(import.meta.url ? fileURLToPath(import.meta.url) : path.join(process.cwd(), "package.json"));
21
16
  const npa = req("npm-package-arg");
22
17
  const parsed = npa(trimmed);
23
18
  if (!isRecord(parsed)) {
@@ -40,4 +35,3 @@ const parsePinnedSpec = (input) => {
40
35
  }
41
36
  return { name, version: rawSpec, spec: `${name}@${rawSpec}` };
42
37
  };
43
- exports.parsePinnedSpec = parsePinnedSpec;