@jackwener/opencli 1.7.14 → 1.7.15
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/cli-manifest.json +215 -45
- package/clis/bilibili/subtitle.js +1 -1
- package/clis/dianping/cityResolver.js +185 -0
- package/clis/dianping/dianping.test.js +154 -0
- package/clis/dianping/search.js +6 -3
- package/clis/douyin/_shared/browser-fetch.js +14 -2
- package/clis/douyin/_shared/browser-fetch.test.js +13 -0
- package/clis/douyin/stats.js +1 -1
- package/clis/douyin/update.js +1 -1
- package/clis/jike/search.js +1 -1
- package/clis/reddit/search.js +1 -1
- package/clis/reddit/subreddit.js +1 -1
- package/clis/reddit/user-comments.js +1 -1
- package/clis/reddit/user-posts.js +1 -1
- package/clis/reddit/user.js +1 -1
- package/clis/twitter/article.js +2 -1
- package/clis/twitter/bookmark-folder.js +189 -0
- package/clis/twitter/bookmark-folder.test.js +334 -0
- package/clis/twitter/bookmark-folders.js +117 -0
- package/clis/twitter/bookmark-folders.test.js +150 -0
- package/clis/twitter/bookmark.js +15 -6
- package/clis/twitter/bookmark.test.js +74 -0
- package/clis/twitter/bookmarks.js +7 -5
- package/clis/twitter/delete.js +11 -35
- package/clis/twitter/delete.test.js +21 -9
- package/clis/twitter/download.js +5 -5
- package/clis/twitter/followers.js +9 -3
- package/clis/twitter/following.js +11 -5
- package/clis/twitter/hide-reply.js +24 -5
- package/clis/twitter/hide-reply.test.js +76 -0
- package/clis/twitter/like.js +21 -11
- package/clis/twitter/like.test.js +73 -0
- package/clis/twitter/likes.js +8 -6
- package/clis/twitter/list-add.js +4 -4
- package/clis/twitter/list-remove.js +4 -4
- package/clis/twitter/list-tweets.js +6 -4
- package/clis/twitter/lists.js +3 -3
- package/clis/twitter/notifications.js +2 -2
- package/clis/twitter/profile.js +4 -3
- package/clis/twitter/quote.js +60 -32
- package/clis/twitter/quote.test.js +96 -8
- package/clis/twitter/reply.js +24 -178
- package/clis/twitter/reply.test.js +29 -11
- package/clis/twitter/retweet.js +9 -14
- package/clis/twitter/retweet.test.js +5 -1
- package/clis/twitter/search.js +175 -23
- package/clis/twitter/search.test.js +266 -1
- package/clis/twitter/shared.js +43 -0
- package/clis/twitter/shared.test.js +107 -1
- package/clis/twitter/thread.js +6 -4
- package/clis/twitter/timeline.js +8 -6
- package/clis/twitter/tweets.js +5 -3
- package/clis/twitter/unbookmark.js +13 -6
- package/clis/twitter/unbookmark.test.js +73 -0
- package/clis/twitter/unlike.js +6 -13
- package/clis/twitter/unlike.test.js +5 -2
- package/clis/twitter/unretweet.js +9 -14
- package/clis/twitter/unretweet.test.js +5 -1
- package/clis/twitter/utils.js +286 -0
- package/clis/twitter/utils.test.js +169 -0
- package/dist/src/browser/ax-snapshot.d.ts +37 -0
- package/dist/src/browser/ax-snapshot.js +217 -0
- package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
- package/dist/src/browser/ax-snapshot.test.js +91 -0
- package/dist/src/browser/base-page.d.ts +51 -0
- package/dist/src/browser/base-page.js +545 -2
- package/dist/src/browser/base-page.test.js +520 -4
- package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
- package/dist/src/browser/cdp-click-fixture.test.js +87 -0
- package/dist/src/browser/cdp.js +5 -0
- package/dist/src/browser/cdp.test.js +1 -0
- package/dist/src/browser/daemon-client.d.ts +3 -1
- package/dist/src/browser/find.d.ts +9 -1
- package/dist/src/browser/find.js +219 -0
- package/dist/src/browser/find.test.js +61 -1
- package/dist/src/browser/page.d.ts +2 -1
- package/dist/src/browser/page.js +13 -0
- package/dist/src/browser/page.test.js +28 -0
- package/dist/src/browser/target-errors.d.ts +3 -1
- package/dist/src/browser/target-errors.js +2 -0
- package/dist/src/browser/target-resolver.d.ts +14 -0
- package/dist/src/browser/target-resolver.js +28 -0
- package/dist/src/browser/visual-refs.d.ts +11 -0
- package/dist/src/browser/visual-refs.js +108 -0
- package/dist/src/build-manifest.d.ts +23 -0
- package/dist/src/build-manifest.js +34 -0
- package/dist/src/build-manifest.test.js +108 -1
- package/dist/src/cli.js +560 -58
- package/dist/src/cli.test.js +598 -0
- package/dist/src/help.d.ts +32 -0
- package/dist/src/help.js +145 -0
- package/dist/src/types.d.ts +82 -0
- package/package.json +1 -1
- package/scripts/typed-error-lint-baseline.json +18 -18
|
@@ -209,6 +209,28 @@ export async function buildManifest() {
|
|
|
209
209
|
export function serializeManifest(manifest) {
|
|
210
210
|
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
211
211
|
}
|
|
212
|
+
export function findManifestMetadataIssues(entries) {
|
|
213
|
+
const issues = [];
|
|
214
|
+
for (const entry of entries) {
|
|
215
|
+
if (!Array.isArray(entry.args))
|
|
216
|
+
continue;
|
|
217
|
+
for (const arg of entry.args) {
|
|
218
|
+
if (!arg.positional)
|
|
219
|
+
continue;
|
|
220
|
+
const help = typeof arg.help === 'string' ? arg.help.trim() : '';
|
|
221
|
+
if (help === '') {
|
|
222
|
+
issues.push({
|
|
223
|
+
site: entry.site,
|
|
224
|
+
command: entry.name,
|
|
225
|
+
arg: arg.name,
|
|
226
|
+
sourceFile: entry.sourceFile,
|
|
227
|
+
reason: 'positional arg missing non-empty `help` text',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return issues;
|
|
233
|
+
}
|
|
212
234
|
/**
|
|
213
235
|
* Diff helper: returns site/name keys that exist in `prev` but not in
|
|
214
236
|
* `next`. Used as a safety net to detect accidental mass-deletions caused
|
|
@@ -278,6 +300,18 @@ async function main() {
|
|
|
278
300
|
+ `Always run via tsx (\`npm run build-manifest\`), not against compiled dist/.\n`);
|
|
279
301
|
process.exit(1);
|
|
280
302
|
}
|
|
303
|
+
const metadataIssues = findManifestMetadataIssues(entries);
|
|
304
|
+
if (metadataIssues.length > 0) {
|
|
305
|
+
process.stderr.write(`❌ ${metadataIssues.length} positional arg(s) missing \`help\` text:\n`);
|
|
306
|
+
for (const issue of metadataIssues) {
|
|
307
|
+
const where = issue.sourceFile ? ` (${issue.sourceFile})` : '';
|
|
308
|
+
process.stderr.write(` - ${issue.site}/${issue.command} positional "${issue.arg}"${where}\n`);
|
|
309
|
+
}
|
|
310
|
+
process.stderr.write(`\nEvery positional arg must declare a non-empty \`help\` string so\n`
|
|
311
|
+
+ `\`opencli <site> <cmd> --help\` shows callers what the parameter is for.\n`
|
|
312
|
+
+ `Add \`help: '...'\` to each arg above and re-run the build.\n`);
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
281
315
|
const existing = readExistingManifest(OUTPUT);
|
|
282
316
|
if (existing) {
|
|
283
317
|
const removed = diffRemovedEntries(existing, entries);
|
|
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
|
|
|
3
3
|
import * as os from 'node:os';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import { cli, getRegistry, Strategy } from './registry.js';
|
|
6
|
-
import { ManifestImportError, diffRemovedEntries, loadManifestEntries, normalizeManifestPath, parseBuildManifestArgs, scanClisDir, serializeManifest, } from './build-manifest.js';
|
|
6
|
+
import { ManifestImportError, diffRemovedEntries, findManifestMetadataIssues, loadManifestEntries, normalizeManifestPath, parseBuildManifestArgs, scanClisDir, serializeManifest, } from './build-manifest.js';
|
|
7
7
|
describe('manifest helper rules', () => {
|
|
8
8
|
const tempDirs = [];
|
|
9
9
|
afterEach(() => {
|
|
@@ -222,6 +222,113 @@ describe('manifest helper rules', () => {
|
|
|
222
222
|
expect(diffRemovedEntries(prev, prev)).toEqual([]);
|
|
223
223
|
expect(diffRemovedEntries([], next)).toEqual([]);
|
|
224
224
|
});
|
|
225
|
+
it('findManifestMetadataIssues flags positionals with empty/missing help', () => {
|
|
226
|
+
// The build-time hard gate. A positional with `help: ''` or no `help` at
|
|
227
|
+
// all renders `Arguments:\n <name>` with a blank trailing column —
|
|
228
|
+
// unrecoverable for both humans and agents reading help. Failing closed
|
|
229
|
+
// here is the only way to keep help text trustworthy as adapters land.
|
|
230
|
+
//
|
|
231
|
+
// Semantic quality (e.g. what does an *optional* positional mean when
|
|
232
|
+
// omitted?) is intentionally NOT enforced — that belongs to the planned
|
|
233
|
+
// Arg metadata v2 advisory pass.
|
|
234
|
+
const entries = [
|
|
235
|
+
// Positional with usable help — clean.
|
|
236
|
+
{
|
|
237
|
+
site: 'demo',
|
|
238
|
+
name: 'ok',
|
|
239
|
+
access: 'read',
|
|
240
|
+
description: '',
|
|
241
|
+
strategy: 'public',
|
|
242
|
+
browser: false,
|
|
243
|
+
args: [
|
|
244
|
+
{ name: 'q', positional: true, required: true, help: 'Search query' },
|
|
245
|
+
],
|
|
246
|
+
type: 'js',
|
|
247
|
+
sourceFile: 'demo/ok.js',
|
|
248
|
+
},
|
|
249
|
+
// Positional with empty help string — must flag.
|
|
250
|
+
{
|
|
251
|
+
site: 'demo',
|
|
252
|
+
name: 'empty-help',
|
|
253
|
+
access: 'read',
|
|
254
|
+
description: '',
|
|
255
|
+
strategy: 'public',
|
|
256
|
+
browser: false,
|
|
257
|
+
args: [
|
|
258
|
+
{ name: 'user', positional: true, required: false, help: '' },
|
|
259
|
+
],
|
|
260
|
+
type: 'js',
|
|
261
|
+
sourceFile: 'demo/empty.js',
|
|
262
|
+
},
|
|
263
|
+
// Positional with whitespace-only help — must flag.
|
|
264
|
+
{
|
|
265
|
+
site: 'demo',
|
|
266
|
+
name: 'whitespace-help',
|
|
267
|
+
access: 'read',
|
|
268
|
+
description: '',
|
|
269
|
+
strategy: 'public',
|
|
270
|
+
browser: false,
|
|
271
|
+
args: [
|
|
272
|
+
{ name: 'id', positional: true, required: true, help: ' ' },
|
|
273
|
+
],
|
|
274
|
+
type: 'js',
|
|
275
|
+
},
|
|
276
|
+
// Positional with no help field at all — must flag.
|
|
277
|
+
{
|
|
278
|
+
site: 'demo',
|
|
279
|
+
name: 'missing-help',
|
|
280
|
+
access: 'read',
|
|
281
|
+
description: '',
|
|
282
|
+
strategy: 'public',
|
|
283
|
+
browser: false,
|
|
284
|
+
args: [
|
|
285
|
+
{ name: 'name', positional: true, required: true },
|
|
286
|
+
],
|
|
287
|
+
type: 'js',
|
|
288
|
+
},
|
|
289
|
+
// NON-positional flag with empty help — must NOT flag (gate is
|
|
290
|
+
// intentionally scoped to positionals; named flags carry the flag
|
|
291
|
+
// name itself in the help line).
|
|
292
|
+
{
|
|
293
|
+
site: 'demo',
|
|
294
|
+
name: 'flag-only',
|
|
295
|
+
access: 'read',
|
|
296
|
+
description: '',
|
|
297
|
+
strategy: 'public',
|
|
298
|
+
browser: false,
|
|
299
|
+
args: [
|
|
300
|
+
{ name: 'limit', required: false, help: '' },
|
|
301
|
+
],
|
|
302
|
+
type: 'js',
|
|
303
|
+
},
|
|
304
|
+
];
|
|
305
|
+
const issues = findManifestMetadataIssues(entries);
|
|
306
|
+
expect(issues).toHaveLength(3);
|
|
307
|
+
expect(issues.map(i => `${i.site}/${i.command}/${i.arg}`).sort()).toEqual([
|
|
308
|
+
'demo/empty-help/user',
|
|
309
|
+
'demo/missing-help/name',
|
|
310
|
+
'demo/whitespace-help/id',
|
|
311
|
+
]);
|
|
312
|
+
// sourceFile flows through when present so the build error points at the
|
|
313
|
+
// exact file to fix.
|
|
314
|
+
const emptyHelp = issues.find(i => i.command === 'empty-help');
|
|
315
|
+
expect(emptyHelp?.sourceFile).toBe('demo/empty.js');
|
|
316
|
+
});
|
|
317
|
+
it('findManifestMetadataIssues returns [] for fully-documented entries', () => {
|
|
318
|
+
expect(findManifestMetadataIssues([])).toEqual([]);
|
|
319
|
+
expect(findManifestMetadataIssues([
|
|
320
|
+
{
|
|
321
|
+
site: 'demo',
|
|
322
|
+
name: 'no-args',
|
|
323
|
+
access: 'read',
|
|
324
|
+
description: '',
|
|
325
|
+
strategy: 'public',
|
|
326
|
+
browser: false,
|
|
327
|
+
args: [],
|
|
328
|
+
type: 'js',
|
|
329
|
+
},
|
|
330
|
+
])).toEqual([]);
|
|
331
|
+
});
|
|
225
332
|
it('parseBuildManifestArgs reads --allow-removals[=N]', () => {
|
|
226
333
|
expect(parseBuildManifestArgs([]).allowRemovals).toBe(0);
|
|
227
334
|
expect(parseBuildManifestArgs(['--allow-removals=5']).allowRemovals).toBe(5);
|