@pagepocket/cli 0.8.6 → 0.9.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/README.md +3 -0
- package/dist/commands/plugin/update.js +56 -0
- package/dist/commands/view.js +2 -2
- package/dist/services/config-service.js +9 -13
- package/dist/services/load-configured-plugins.js +16 -6
- package/dist/services/plugin-installer.js +23 -7
- package/dist/services/plugin-store.js +59 -22
- package/dist/utils/normalize-argv.js +0 -6
- package/dist/utils/parse-json.js +24 -0
- package/dist/utils/validate-plugin-default-export.js +16 -22
- package/dist/view.js +2 -2
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ Manage configured plugins:
|
|
|
39
39
|
```bash
|
|
40
40
|
pp plugin ls
|
|
41
41
|
pp plugin add <plugin-name>
|
|
42
|
+
pp plugin update [plugin-name]
|
|
42
43
|
pp plugin remove <plugin-name>
|
|
43
44
|
```
|
|
44
45
|
|
|
@@ -58,6 +59,8 @@ pp plugin add @scope/plugin --option 1 --option 2
|
|
|
58
59
|
Notes:
|
|
59
60
|
|
|
60
61
|
- `pp plugin remove` only removes the entry from `config.json` (it does not uninstall the package).
|
|
62
|
+
- `pp plugin update <plugin-name>` reinstalls that plugin to `latest`.
|
|
63
|
+
- `pp plugin update` reinstalls all configured plugins to `latest`.
|
|
61
64
|
- During `pp archive ...`, the CLI reads `config.json` and tries to load all configured plugins.
|
|
62
65
|
If a plugin fails to load, it will be skipped and the archive will continue.
|
|
63
66
|
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const config_service_1 = require("../../services/config-service");
|
|
9
|
+
const plugin_installer_1 = require("../../services/plugin-installer");
|
|
10
|
+
const plugin_store_1 = require("../../services/plugin-store");
|
|
11
|
+
const parse_plugin_spec_1 = require("../../utils/parse-plugin-spec");
|
|
12
|
+
/**
|
|
13
|
+
* Read configured plugins and return unique package names.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* const names = getUniqueConfiguredPluginNames(store);
|
|
17
|
+
*/
|
|
18
|
+
const getUniqueConfiguredPluginNames = (store) => {
|
|
19
|
+
const config = store.readConfig();
|
|
20
|
+
return [
|
|
21
|
+
...new Set(config.plugins
|
|
22
|
+
.map((entry) => (0, plugin_store_1.normalizePluginConfigEntry)(entry).name)
|
|
23
|
+
.filter((name) => name.trim().length > 0))
|
|
24
|
+
];
|
|
25
|
+
};
|
|
26
|
+
class PluginUpdateCommand extends core_1.Command {
|
|
27
|
+
async run() {
|
|
28
|
+
const { args } = await this.parse(PluginUpdateCommand);
|
|
29
|
+
const configService = new config_service_1.ConfigService();
|
|
30
|
+
const store = new plugin_store_1.PluginStore(configService);
|
|
31
|
+
configService.ensureConfigFileExists();
|
|
32
|
+
const targetName = args.name ? (0, parse_plugin_spec_1.parsePluginSpec)(args.name).name : undefined;
|
|
33
|
+
const configuredNames = getUniqueConfiguredPluginNames(store);
|
|
34
|
+
if (configuredNames.length === 0) {
|
|
35
|
+
this.log(chalk_1.default.gray("No plugins configured."));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (targetName && !configuredNames.includes(targetName)) {
|
|
39
|
+
this.log(chalk_1.default.gray(`Plugin not found in config: ${targetName}`));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const namesToUpdate = targetName ? [targetName] : configuredNames;
|
|
43
|
+
namesToUpdate.forEach((name) => {
|
|
44
|
+
(0, plugin_installer_1.updatePluginPackageToLatest)(store, { packageName: name });
|
|
45
|
+
this.log(chalk_1.default.green(`Updated plugin: ${name}`));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
PluginUpdateCommand.description = "Update one plugin (or all configured plugins) to latest.";
|
|
50
|
+
PluginUpdateCommand.args = {
|
|
51
|
+
name: core_1.Args.string({
|
|
52
|
+
description: "npm package name (optional; if omitted updates all configured plugins)",
|
|
53
|
+
required: false
|
|
54
|
+
})
|
|
55
|
+
};
|
|
56
|
+
exports.default = PluginUpdateCommand;
|
package/dist/commands/view.js
CHANGED
|
@@ -14,11 +14,11 @@ class ViewCommand extends core_1.Command {
|
|
|
14
14
|
const { args, flags } = await this.parse(ViewCommand);
|
|
15
15
|
const rootDir = node_path_1.default.resolve(node_process_1.default.cwd(), args.directory);
|
|
16
16
|
const indexPath = node_path_1.default.join(rootDir, "index.html");
|
|
17
|
-
const stat = await node_fs_1.default.promises.stat(rootDir).catch(() =>
|
|
17
|
+
const stat = await node_fs_1.default.promises.stat(rootDir).catch(() => undefined);
|
|
18
18
|
if (!stat || !stat.isDirectory()) {
|
|
19
19
|
throw new Error(`view: directory not found: ${rootDir}`);
|
|
20
20
|
}
|
|
21
|
-
const indexStat = await node_fs_1.default.promises.stat(indexPath).catch(() =>
|
|
21
|
+
const indexStat = await node_fs_1.default.promises.stat(indexPath).catch(() => undefined);
|
|
22
22
|
if (!indexStat || !indexStat.isFile()) {
|
|
23
23
|
throw new Error(`view: index.html not found under: ${rootDir}`);
|
|
24
24
|
}
|
|
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
8
|
const node_os_1 = __importDefault(require("node:os"));
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const env_paths_1 = __importDefault(require("env-paths"));
|
|
11
|
+
const parse_json_1 = require("../utils/parse-json");
|
|
11
12
|
const defaultConfig = {
|
|
12
13
|
plugins: []
|
|
13
14
|
};
|
|
@@ -45,7 +46,7 @@ class ConfigService {
|
|
|
45
46
|
const dir = node_path_1.default.dirname(filePath);
|
|
46
47
|
this.ensureDirExists(dir);
|
|
47
48
|
const tmpPath = `${filePath}.tmp`;
|
|
48
|
-
node_fs_1.default.writeFileSync(tmpPath, `${JSON.stringify(value,
|
|
49
|
+
node_fs_1.default.writeFileSync(tmpPath, `${JSON.stringify(value, undefined, 2)}\n`, "utf8");
|
|
49
50
|
node_fs_1.default.renameSync(tmpPath, filePath);
|
|
50
51
|
}
|
|
51
52
|
isObject(value) {
|
|
@@ -73,33 +74,28 @@ class ConfigService {
|
|
|
73
74
|
...(typeof options === "undefined" ? {} : { options })
|
|
74
75
|
};
|
|
75
76
|
}
|
|
76
|
-
return
|
|
77
|
+
return undefined;
|
|
77
78
|
})
|
|
78
|
-
.filter((x) => x !==
|
|
79
|
+
.filter((x) => typeof x !== "undefined");
|
|
79
80
|
return { plugins };
|
|
80
81
|
}
|
|
81
82
|
readConfig() {
|
|
82
83
|
const configPath = this.getConfigPath();
|
|
83
84
|
const rawText = node_fs_1.default.readFileSync(configPath, "utf8");
|
|
84
|
-
const parsed =
|
|
85
|
-
return this.normalizeConfig(parsed);
|
|
85
|
+
const parsed = (0, parse_json_1.parseJson)(rawText);
|
|
86
|
+
return this.normalizeConfig(parsed.ok ? parsed.value : undefined);
|
|
86
87
|
}
|
|
87
88
|
isConfigFilePresent() {
|
|
88
89
|
return node_fs_1.default.existsSync(this.getConfigPath());
|
|
89
90
|
}
|
|
90
91
|
readConfigOrDefault() {
|
|
91
92
|
const configPath = this.getConfigPath();
|
|
92
|
-
const text = node_fs_1.default.existsSync(configPath) ? node_fs_1.default.readFileSync(configPath, "utf8") :
|
|
93
|
+
const text = node_fs_1.default.existsSync(configPath) ? node_fs_1.default.readFileSync(configPath, "utf8") : undefined;
|
|
93
94
|
if (!text) {
|
|
94
95
|
return defaultConfig;
|
|
95
96
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return this.normalizeConfig(parsed);
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return defaultConfig;
|
|
102
|
-
}
|
|
97
|
+
const parsed = (0, parse_json_1.parseJson)(text);
|
|
98
|
+
return parsed.ok ? this.normalizeConfig(parsed.value) : defaultConfig;
|
|
103
99
|
}
|
|
104
100
|
writeConfig(config) {
|
|
105
101
|
this.writeJsonAtomic(this.getConfigPath(), this.normalizeConfig(config));
|
|
@@ -5,6 +5,18 @@ const validate_plugin_default_export_1 = require("../utils/validate-plugin-defau
|
|
|
5
5
|
const config_service_1 = require("./config-service");
|
|
6
6
|
const plugin_store_1 = require("./plugin-store");
|
|
7
7
|
const loadConfiguredPlugins = async () => {
|
|
8
|
+
const getErrorMessage = (error) => {
|
|
9
|
+
if (error instanceof Error) {
|
|
10
|
+
return error.message;
|
|
11
|
+
}
|
|
12
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
13
|
+
const msg = error.message;
|
|
14
|
+
if (typeof msg === "string") {
|
|
15
|
+
return msg;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return String(error);
|
|
19
|
+
};
|
|
8
20
|
const configService = new config_service_1.ConfigService();
|
|
9
21
|
const store = new plugin_store_1.PluginStore(configService);
|
|
10
22
|
configService.ensureConfigFileExists();
|
|
@@ -20,18 +32,16 @@ const loadConfiguredPlugins = async () => {
|
|
|
20
32
|
});
|
|
21
33
|
if (!validation.ok) {
|
|
22
34
|
console.error(`Skipping plugin ${spec.name}: ${validation.error.message}`);
|
|
23
|
-
return
|
|
35
|
+
return undefined;
|
|
24
36
|
}
|
|
25
37
|
return validation.plugin;
|
|
26
38
|
}
|
|
27
39
|
catch (e) {
|
|
28
|
-
const msg = e
|
|
29
|
-
? e.message
|
|
30
|
-
: String(e);
|
|
40
|
+
const msg = getErrorMessage(e);
|
|
31
41
|
console.error(`Failed to load plugin ${spec.name}: ${msg}`);
|
|
32
|
-
return
|
|
42
|
+
return undefined;
|
|
33
43
|
}
|
|
34
44
|
}));
|
|
35
|
-
return loaded.filter((x) => x !==
|
|
45
|
+
return loaded.filter((x) => typeof x !== "undefined");
|
|
36
46
|
};
|
|
37
47
|
exports.loadConfiguredPlugins = loadConfiguredPlugins;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.installPluginPackage = void 0;
|
|
3
|
+
exports.updatePluginPackageToLatest = exports.installPluginPackage = void 0;
|
|
4
4
|
const node_child_process_1 = require("node:child_process");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Install a package spec with pnpm first, then fallback to npm.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* tryInstallWithFallback("/path/to/plugins", "@scope/plugin@latest");
|
|
10
|
+
*/
|
|
11
|
+
const tryInstallWithFallback = (installDir, packageSpec) => {
|
|
8
12
|
const tryRun = (cmd, args) => {
|
|
9
13
|
const r = (0, node_child_process_1.spawnSync)(cmd, args, {
|
|
10
14
|
cwd: installDir,
|
|
@@ -19,14 +23,26 @@ const installPluginPackage = (store, input) => {
|
|
|
19
23
|
}
|
|
20
24
|
return { ok: true };
|
|
21
25
|
};
|
|
22
|
-
const pnpm = tryRun("pnpm", ["add", "--silent",
|
|
26
|
+
const pnpm = tryRun("pnpm", ["add", "--silent", packageSpec]);
|
|
23
27
|
if (pnpm.ok) {
|
|
24
28
|
return;
|
|
25
29
|
}
|
|
26
|
-
const npm = tryRun("npm", ["install", "--silent",
|
|
30
|
+
const npm = tryRun("npm", ["install", "--silent", packageSpec]);
|
|
27
31
|
if (npm.ok) {
|
|
28
32
|
return;
|
|
29
33
|
}
|
|
30
|
-
throw new Error(`Failed to install ${
|
|
34
|
+
throw new Error(`Failed to install ${packageSpec}. Ensure pnpm or npm is available.`);
|
|
35
|
+
};
|
|
36
|
+
const installPluginPackage = (store, input) => {
|
|
37
|
+
store.ensurePluginPackageJson();
|
|
38
|
+
const installDir = store.getInstallDir();
|
|
39
|
+
tryInstallWithFallback(installDir, input.packageName);
|
|
31
40
|
};
|
|
32
41
|
exports.installPluginPackage = installPluginPackage;
|
|
42
|
+
const updatePluginPackageToLatest = (store, input) => {
|
|
43
|
+
store.ensurePluginPackageJson();
|
|
44
|
+
const installDir = store.getInstallDir();
|
|
45
|
+
const packageSpec = `${input.packageName}@latest`;
|
|
46
|
+
tryInstallWithFallback(installDir, packageSpec);
|
|
47
|
+
};
|
|
48
|
+
exports.updatePluginPackageToLatest = updatePluginPackageToLatest;
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -8,6 +41,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
41
|
const node_module_1 = require("node:module");
|
|
9
42
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
43
|
const node_url_1 = require("node:url");
|
|
44
|
+
const parse_json_1 = require("../utils/parse-json");
|
|
45
|
+
const validate_plugin_default_export_1 = require("../utils/validate-plugin-default-export");
|
|
11
46
|
const normalizePluginConfigEntry = (entry) => {
|
|
12
47
|
if (typeof entry === "string") {
|
|
13
48
|
return { name: entry };
|
|
@@ -21,6 +56,12 @@ const normalizePluginConfigEntry = (entry) => {
|
|
|
21
56
|
exports.normalizePluginConfigEntry = normalizePluginConfigEntry;
|
|
22
57
|
const getPluginNameFromSpec = (spec) => spec.name;
|
|
23
58
|
exports.getPluginNameFromSpec = getPluginNameFromSpec;
|
|
59
|
+
const isRecord = (value) => {
|
|
60
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
61
|
+
};
|
|
62
|
+
const isCallable = (value) => {
|
|
63
|
+
return typeof value === "function";
|
|
64
|
+
};
|
|
24
65
|
class PluginStore {
|
|
25
66
|
constructor(configService) {
|
|
26
67
|
this.configService = configService;
|
|
@@ -42,7 +83,7 @@ class PluginStore {
|
|
|
42
83
|
private: true,
|
|
43
84
|
version: "0.0.0"
|
|
44
85
|
};
|
|
45
|
-
node_fs_1.default.writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson,
|
|
86
|
+
node_fs_1.default.writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson, undefined, 2)}\n`, "utf8");
|
|
46
87
|
return pkgJsonPath;
|
|
47
88
|
}
|
|
48
89
|
createPluginsRequireFromDir(dirPath) {
|
|
@@ -53,7 +94,7 @@ class PluginStore {
|
|
|
53
94
|
private: true,
|
|
54
95
|
version: "0.0.0"
|
|
55
96
|
};
|
|
56
|
-
node_fs_1.default.writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson,
|
|
97
|
+
node_fs_1.default.writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson, undefined, 2)}\n`, "utf8");
|
|
57
98
|
}
|
|
58
99
|
return (0, node_module_1.createRequire)(pkgJsonPath);
|
|
59
100
|
}
|
|
@@ -69,11 +110,11 @@ class PluginStore {
|
|
|
69
110
|
try {
|
|
70
111
|
const pkgJsonPath = this.resolveInstalledPackageJsonPath(pluginName);
|
|
71
112
|
const text = node_fs_1.default.readFileSync(pkgJsonPath, "utf8");
|
|
72
|
-
const json =
|
|
73
|
-
if (!json || typeof json !== "object") {
|
|
113
|
+
const json = (0, parse_json_1.parseJson)(text);
|
|
114
|
+
if (!json.ok || !json.value || typeof json.value !== "object") {
|
|
74
115
|
return { name: pluginName };
|
|
75
116
|
}
|
|
76
|
-
const o = json;
|
|
117
|
+
const o = json.value;
|
|
77
118
|
return {
|
|
78
119
|
name: typeof o.name === "string" ? o.name : pluginName,
|
|
79
120
|
description: typeof o.description === "string" ? o.description : undefined,
|
|
@@ -81,7 +122,7 @@ class PluginStore {
|
|
|
81
122
|
};
|
|
82
123
|
}
|
|
83
124
|
catch {
|
|
84
|
-
return
|
|
125
|
+
return undefined;
|
|
85
126
|
}
|
|
86
127
|
}
|
|
87
128
|
async importPluginModule(pluginName) {
|
|
@@ -90,30 +131,26 @@ class PluginStore {
|
|
|
90
131
|
return this.importResolvedPath(resolved);
|
|
91
132
|
}
|
|
92
133
|
async importResolvedPath(resolved) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
return (mod ?? {});
|
|
134
|
+
const mod = await Promise.resolve(`${(0, node_url_1.pathToFileURL)(resolved).href}`).then(s => __importStar(require(s)));
|
|
135
|
+
return isRecord(mod) ? mod : {};
|
|
96
136
|
}
|
|
97
137
|
async instantiatePluginFromSpec(spec) {
|
|
98
138
|
const mod = await this.importPluginModule(spec.name);
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
if (Array.isArray(spec.options)) {
|
|
108
|
-
return new ctor(...spec.options);
|
|
139
|
+
const result = (0, validate_plugin_default_export_1.validatePluginDefaultExport)({
|
|
140
|
+
pluginName: spec.name,
|
|
141
|
+
moduleExports: mod,
|
|
142
|
+
options: spec.options
|
|
143
|
+
});
|
|
144
|
+
if (!result.ok) {
|
|
145
|
+
throw result.error;
|
|
109
146
|
}
|
|
110
|
-
return
|
|
147
|
+
return result.plugin;
|
|
111
148
|
}
|
|
112
149
|
async runOptionalSetup(pluginName) {
|
|
113
150
|
const mod = await this.importPluginModule(pluginName);
|
|
114
151
|
const setup = mod.setup;
|
|
115
|
-
if (
|
|
116
|
-
await setup();
|
|
152
|
+
if (isCallable(setup)) {
|
|
153
|
+
await Promise.resolve(setup());
|
|
117
154
|
}
|
|
118
155
|
}
|
|
119
156
|
readConfig() {
|
|
@@ -21,12 +21,6 @@ const normalizeArgv = (argv) => {
|
|
|
21
21
|
return argv;
|
|
22
22
|
}
|
|
23
23
|
const first = argv[0];
|
|
24
|
-
if (first === "plugin") {
|
|
25
|
-
const sub = argv[1];
|
|
26
|
-
if (sub === "ls" || sub === "add" || sub === "remove") {
|
|
27
|
-
return [`plugin:${sub}`, ...argv.slice(2)];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
24
|
// If the first token is a URL, treat it as implicit `archive`.
|
|
31
25
|
if (first && (0, exports.isUrlLike)(first)) {
|
|
32
26
|
return ["archive", ...argv];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseJson = void 0;
|
|
4
|
+
const toErrorMessage = (value) => {
|
|
5
|
+
if (value instanceof Error) {
|
|
6
|
+
return value.message;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value === "string") {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
if (value && typeof value === "object" && "message" in value) {
|
|
12
|
+
return String(value.message);
|
|
13
|
+
}
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
};
|
|
16
|
+
const parseJson = (text) => {
|
|
17
|
+
try {
|
|
18
|
+
return { ok: true, value: JSON.parse(text) };
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return { ok: false, error: new Error(toErrorMessage(e)) };
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.parseJson = parseJson;
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validatePluginDefaultExport = void 0;
|
|
4
4
|
const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
const isPagePocketPlugin = (value) => {
|
|
6
|
+
if (!isRecord(value)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
if (typeof value.name !== "string" || value.name.trim().length === 0) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (typeof value.setup !== "function") {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value.contribute !== "undefined" && typeof value.contribute !== "function") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
5
20
|
const toError = (value) => {
|
|
6
21
|
if (value instanceof Error) {
|
|
7
22
|
return value;
|
|
@@ -24,33 +39,12 @@ const validatePluginDefaultExport = (input) => {
|
|
|
24
39
|
: Array.isArray(options)
|
|
25
40
|
? new ctor(...options)
|
|
26
41
|
: new ctor(options);
|
|
27
|
-
if (!
|
|
42
|
+
if (!isPagePocketPlugin(instance)) {
|
|
28
43
|
return {
|
|
29
44
|
ok: false,
|
|
30
45
|
error: new Error(`Plugin ${pluginName} default export did not construct an object.`)
|
|
31
46
|
};
|
|
32
47
|
}
|
|
33
|
-
const name = instance.name;
|
|
34
|
-
if (typeof name !== "string" || name.trim().length === 0) {
|
|
35
|
-
return {
|
|
36
|
-
ok: false,
|
|
37
|
-
error: new Error(`Plugin ${pluginName} instance must have a non-empty string 'name'.`)
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const setup = instance.setup;
|
|
41
|
-
if (typeof setup !== "function") {
|
|
42
|
-
return {
|
|
43
|
-
ok: false,
|
|
44
|
-
error: new Error(`Plugin ${pluginName} instance must implement setup(host).`)
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
const contribute = instance.contribute;
|
|
48
|
-
if (typeof contribute !== "undefined" && typeof contribute !== "function") {
|
|
49
|
-
return {
|
|
50
|
-
ok: false,
|
|
51
|
-
error: new Error(`Plugin ${pluginName} contribute must be a function if provided.`)
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
48
|
return { ok: true, plugin: instance };
|
|
55
49
|
}
|
|
56
50
|
catch (e) {
|
package/dist/view.js
CHANGED
|
@@ -11,11 +11,11 @@ const koa_send_1 = __importDefault(require("koa-send"));
|
|
|
11
11
|
const koa_static_1 = __importDefault(require("koa-static"));
|
|
12
12
|
const createViewServer = async (args) => {
|
|
13
13
|
const indexPath = node_path_1.default.join(args.rootDir, "index.html");
|
|
14
|
-
const stat = await node_fs_1.default.promises.stat(args.rootDir).catch(() =>
|
|
14
|
+
const stat = await node_fs_1.default.promises.stat(args.rootDir).catch(() => undefined);
|
|
15
15
|
if (!stat || !stat.isDirectory()) {
|
|
16
16
|
throw new Error(`view: directory not found: ${args.rootDir}`);
|
|
17
17
|
}
|
|
18
|
-
const indexStat = await node_fs_1.default.promises.stat(indexPath).catch(() =>
|
|
18
|
+
const indexStat = await node_fs_1.default.promises.stat(indexPath).catch(() => undefined);
|
|
19
19
|
if (!indexStat || !indexStat.isFile()) {
|
|
20
20
|
throw new Error(`view: index.html not found under: ${args.rootDir}`);
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagepocket/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "CLI for capturing offline snapshots of web pages.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
"koa-static": "^5.0.0",
|
|
22
22
|
"npm-package-arg": "^13.0.2",
|
|
23
23
|
"ora": "^9.0.0",
|
|
24
|
-
"@pagepocket/build-snapshot-unit": "0.
|
|
25
|
-
"@pagepocket/
|
|
26
|
-
"@pagepocket/capture-http-lighterceptor-unit": "0.
|
|
27
|
-
"@pagepocket/capture-http-puppeteer-unit": "0.
|
|
28
|
-
"@pagepocket/
|
|
29
|
-
"@pagepocket/
|
|
30
|
-
"@pagepocket/
|
|
31
|
-
"@pagepocket/
|
|
32
|
-
"@pagepocket/write-down-unit": "0.
|
|
24
|
+
"@pagepocket/build-snapshot-unit": "0.9.0",
|
|
25
|
+
"@pagepocket/contracts": "0.9.0",
|
|
26
|
+
"@pagepocket/capture-http-lighterceptor-unit": "0.9.0",
|
|
27
|
+
"@pagepocket/capture-http-puppeteer-unit": "0.9.0",
|
|
28
|
+
"@pagepocket/lib": "0.9.0",
|
|
29
|
+
"@pagepocket/capture-http-cdp-unit": "0.9.0",
|
|
30
|
+
"@pagepocket/single-file-unit": "0.9.0",
|
|
31
|
+
"@pagepocket/plugin-yt-dlp": "0.9.0",
|
|
32
|
+
"@pagepocket/write-down-unit": "0.9.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/koa": "^2.15.0",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"oclif": {
|
|
43
43
|
"bin": "pp",
|
|
44
|
+
"topicSeparator": " ",
|
|
44
45
|
"commands": {
|
|
45
46
|
"strategy": "pattern",
|
|
46
47
|
"target": "dist/commands"
|