@nockdev/cli 1.0.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/CHANGELOG.md +31 -0
- package/README.md +85 -0
- package/bin/nock.js +17 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +149 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/plugins.d.ts +3 -0
- package/dist/core/plugins.d.ts.map +1 -0
- package/dist/core/plugins.js +90 -0
- package/dist/core/plugins.js.map +1 -0
- package/dist/core/telemetry.d.ts +2 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +63 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/version.d.ts +4 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +23 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/manager.d.ts +77 -0
- package/dist/plugins/manager.d.ts.map +1 -0
- package/dist/plugins/manager.js +474 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/plugins/types.d.ts +131 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +4 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/utils/constants.d.ts +11 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +13 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/errors.d.ts +17 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +32 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/exit-codes.d.ts +22 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/exit-codes.js +23 -0
- package/dist/utils/exit-codes.js.map +1 -0
- package/dist/utils/manifest-cache.d.ts +71 -0
- package/dist/utils/manifest-cache.d.ts.map +1 -0
- package/dist/utils/manifest-cache.js +154 -0
- package/dist/utils/manifest-cache.js.map +1 -0
- package/dist/utils/official-plugins.d.ts +13 -0
- package/dist/utils/official-plugins.d.ts.map +1 -0
- package/dist/utils/official-plugins.js +25 -0
- package/dist/utils/official-plugins.js.map +1 -0
- package/dist/utils/telemetry.d.ts +58 -0
- package/dist/utils/telemetry.d.ts.map +1 -0
- package/dist/utils/telemetry.js +191 -0
- package/dist/utils/telemetry.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// packages/cli/src/utils/constants.ts
|
|
2
|
+
// Single Source of Truth for CLI constants
|
|
3
|
+
/** CLI version - SSoT */
|
|
4
|
+
export const CLI_VERSION = "1.0.0";
|
|
5
|
+
/** CLI name */
|
|
6
|
+
export const CLI_NAME = "@nockdev/cli";
|
|
7
|
+
/** Default plugins directory name */
|
|
8
|
+
export const PLUGINS_DIR_NAME = "plugins";
|
|
9
|
+
/** Manifest file name */
|
|
10
|
+
export const MANIFEST_FILE = "plugins.json";
|
|
11
|
+
/** NOCK home directory name */
|
|
12
|
+
export const NOCK_DIR_NAME = ".nock";
|
|
13
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,2CAA2C;AAE3C,yBAAyB;AACzB,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC,eAAe;AACf,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC;AAEvC,qCAAqC;AACrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAE1C,yBAAyB;AACzB,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;AAE5C,+BAA+B;AAC/B,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display a usage error with consistent formatting
|
|
3
|
+
*/
|
|
4
|
+
export declare function showUsageError(message: string, usage: string, example?: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Display a warning message
|
|
7
|
+
*/
|
|
8
|
+
export declare function showWarning(message: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Display an info message
|
|
11
|
+
*/
|
|
12
|
+
export declare function showInfo(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Display a success message
|
|
15
|
+
*/
|
|
16
|
+
export declare function showSuccess(message: string): void;
|
|
17
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAMrF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// packages/cli/src/utils/errors.ts
|
|
2
|
+
// Error handling utilities
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
/**
|
|
5
|
+
* Display a usage error with consistent formatting
|
|
6
|
+
*/
|
|
7
|
+
export function showUsageError(message, usage, example) {
|
|
8
|
+
console.error(pc.red(`Error: ${message}`));
|
|
9
|
+
console.log(pc.dim(`Usage: ${usage}`));
|
|
10
|
+
if (example) {
|
|
11
|
+
console.log(pc.dim(`Example: ${example}`));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Display a warning message
|
|
16
|
+
*/
|
|
17
|
+
export function showWarning(message) {
|
|
18
|
+
console.warn(pc.yellow(`⚠ ${message}`));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Display an info message
|
|
22
|
+
*/
|
|
23
|
+
export function showInfo(message) {
|
|
24
|
+
console.log(pc.dim(message));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Display a success message
|
|
28
|
+
*/
|
|
29
|
+
export function showSuccess(message) {
|
|
30
|
+
console.log(pc.green(`✔ ${message}`));
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,2BAA2B;AAE3B,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAAa,EAAE,OAAgB;IAC7E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC;IACvC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const EXIT_CODES: {
|
|
2
|
+
/** Successful execution */
|
|
3
|
+
readonly SUCCESS: 0;
|
|
4
|
+
/** General error */
|
|
5
|
+
readonly GENERAL_ERROR: 1;
|
|
6
|
+
/** Invalid command or arguments */
|
|
7
|
+
readonly INVALID_COMMAND: 2;
|
|
8
|
+
/** User cancelled operation (SIGINT) */
|
|
9
|
+
readonly USER_CANCEL: 130;
|
|
10
|
+
/** Plugin-related error */
|
|
11
|
+
readonly PLUGIN_ERROR: 10;
|
|
12
|
+
/** Network error */
|
|
13
|
+
readonly NETWORK_ERROR: 11;
|
|
14
|
+
/** Permission denied */
|
|
15
|
+
readonly PERMISSION_ERROR: 12;
|
|
16
|
+
/** Resource not found */
|
|
17
|
+
readonly NOT_FOUND: 13;
|
|
18
|
+
/** Configuration error */
|
|
19
|
+
readonly CONFIG_ERROR: 14;
|
|
20
|
+
};
|
|
21
|
+
export type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];
|
|
22
|
+
//# sourceMappingURL=exit-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../../src/utils/exit-codes.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU;IACrB,2BAA2B;;IAE3B,oBAAoB;;IAEpB,mCAAmC;;IAEnC,wCAAwC;;IAExC,2BAA2B;;IAE3B,oBAAoB;;IAEpB,wBAAwB;;IAExB,yBAAyB;;IAEzB,0BAA0B;;CAElB,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// packages/cli/src/utils/exit-codes.ts
|
|
2
|
+
// Standard POSIX exit codes for CLI
|
|
3
|
+
export const EXIT_CODES = {
|
|
4
|
+
/** Successful execution */
|
|
5
|
+
SUCCESS: 0,
|
|
6
|
+
/** General error */
|
|
7
|
+
GENERAL_ERROR: 1,
|
|
8
|
+
/** Invalid command or arguments */
|
|
9
|
+
INVALID_COMMAND: 2,
|
|
10
|
+
/** User cancelled operation (SIGINT) */
|
|
11
|
+
USER_CANCEL: 130,
|
|
12
|
+
/** Plugin-related error */
|
|
13
|
+
PLUGIN_ERROR: 10,
|
|
14
|
+
/** Network error */
|
|
15
|
+
NETWORK_ERROR: 11,
|
|
16
|
+
/** Permission denied */
|
|
17
|
+
PERMISSION_ERROR: 12,
|
|
18
|
+
/** Resource not found */
|
|
19
|
+
NOT_FOUND: 13,
|
|
20
|
+
/** Configuration error */
|
|
21
|
+
CONFIG_ERROR: 14,
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=exit-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../../src/utils/exit-codes.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,oCAAoC;AAEpC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,2BAA2B;IAC3B,OAAO,EAAE,CAAC;IACV,oBAAoB;IACpB,aAAa,EAAE,CAAC;IAChB,mCAAmC;IACnC,eAAe,EAAE,CAAC;IAClB,wCAAwC;IACxC,WAAW,EAAE,GAAG;IAChB,2BAA2B;IAC3B,YAAY,EAAE,EAAE;IAChB,oBAAoB;IACpB,aAAa,EAAE,EAAE;IACjB,wBAAwB;IACxB,gBAAgB,EAAE,EAAE;IACpB,yBAAyB;IACzB,SAAS,EAAE,EAAE;IACb,0BAA0B;IAC1B,YAAY,EAAE,EAAE;CACR,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
interface CachedCommand {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
aliases?: string[];
|
|
6
|
+
topic: string;
|
|
7
|
+
}
|
|
8
|
+
interface CachedPlugin {
|
|
9
|
+
name: string;
|
|
10
|
+
version: string;
|
|
11
|
+
topic: string;
|
|
12
|
+
description: string;
|
|
13
|
+
commands: CachedCommand[];
|
|
14
|
+
path: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class ManifestCacheManager {
|
|
17
|
+
private cachePath;
|
|
18
|
+
private cache;
|
|
19
|
+
constructor();
|
|
20
|
+
/**
|
|
21
|
+
* Check if cache exists and is valid
|
|
22
|
+
*/
|
|
23
|
+
isValid(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Get cached plugins (fast lookup)
|
|
26
|
+
*/
|
|
27
|
+
getPlugins(): CachedPlugin[] | null;
|
|
28
|
+
/**
|
|
29
|
+
* Get all commands from cache (fast lookup)
|
|
30
|
+
*/
|
|
31
|
+
getCommands(): CachedCommand[] | null;
|
|
32
|
+
/**
|
|
33
|
+
* Find command by name or alias (O(n) but from cache)
|
|
34
|
+
*/
|
|
35
|
+
findCommand(topic: string, name: string): CachedCommand | null;
|
|
36
|
+
/**
|
|
37
|
+
* Update cache with plugin data
|
|
38
|
+
*/
|
|
39
|
+
update(plugins: Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
version: string;
|
|
42
|
+
topic: string;
|
|
43
|
+
description: string;
|
|
44
|
+
commands: Array<{
|
|
45
|
+
name: string;
|
|
46
|
+
id: string;
|
|
47
|
+
description: string;
|
|
48
|
+
aliases?: string[];
|
|
49
|
+
}>;
|
|
50
|
+
path: string;
|
|
51
|
+
}>): void;
|
|
52
|
+
/**
|
|
53
|
+
* Invalidate cache (force reload on next run)
|
|
54
|
+
*/
|
|
55
|
+
invalidate(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get cache stats for debugging
|
|
58
|
+
*/
|
|
59
|
+
stats(): {
|
|
60
|
+
exists: boolean;
|
|
61
|
+
valid: boolean;
|
|
62
|
+
pluginCount: number;
|
|
63
|
+
commandCount: number;
|
|
64
|
+
age: string;
|
|
65
|
+
};
|
|
66
|
+
private read;
|
|
67
|
+
private write;
|
|
68
|
+
}
|
|
69
|
+
export declare const manifestCache: ManifestCacheManager;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=manifest-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-cache.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-cache.ts"],"names":[],"mappings":"AAQA,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAWD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAA8B;;IAM3C;;OAEG;IACH,OAAO,IAAI,OAAO;IAelB;;OAEG;IACH,UAAU,IAAI,YAAY,EAAE,GAAG,IAAI;IAKnC;;OAEG;IACH,WAAW,IAAI,aAAa,EAAE,GAAG,IAAI;IAMrC;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAc9D;;OAEG;IACH,MAAM,CACJ,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,KAAK,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;YACX,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;SACpB,CAAC,CAAC;QACH,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,GACD,IAAI;IAwBP;;OAEG;IACH,UAAU,IAAI,IAAI;IAWlB;;OAEG;IACH,KAAK,IAAI;QACP,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;KACb;IA4BD,OAAO,CAAC,IAAI;IAcZ,OAAO,CAAC,KAAK;CAYd;AAGD,eAAO,MAAM,aAAa,sBAA6B,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// packages/cli/src/utils/manifest-cache.ts
|
|
2
|
+
// Manifest Cache v1.0.0 - Fast Command Discovery
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { NOCK_DIR_NAME, CLI_VERSION } from "./constants.js";
|
|
7
|
+
const MANIFEST_CACHE_FILE = "nock.manifest.json";
|
|
8
|
+
export class ManifestCacheManager {
|
|
9
|
+
cachePath;
|
|
10
|
+
cache = null;
|
|
11
|
+
constructor() {
|
|
12
|
+
this.cachePath = path.join(homedir(), NOCK_DIR_NAME, MANIFEST_CACHE_FILE);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if cache exists and is valid
|
|
16
|
+
*/
|
|
17
|
+
isValid() {
|
|
18
|
+
const cache = this.read();
|
|
19
|
+
if (!cache)
|
|
20
|
+
return false;
|
|
21
|
+
// Invalidate if CLI version changed
|
|
22
|
+
if (cache.cliVersion !== CLI_VERSION)
|
|
23
|
+
return false;
|
|
24
|
+
// Cache is valid for 24 hours
|
|
25
|
+
const lastUpdated = new Date(cache.lastUpdated).getTime();
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
const maxAge = 24 * 60 * 60 * 1000; // 24 hours
|
|
28
|
+
return now - lastUpdated < maxAge;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get cached plugins (fast lookup)
|
|
32
|
+
*/
|
|
33
|
+
getPlugins() {
|
|
34
|
+
const cache = this.read();
|
|
35
|
+
return cache?.plugins || null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get all commands from cache (fast lookup)
|
|
39
|
+
*/
|
|
40
|
+
getCommands() {
|
|
41
|
+
const plugins = this.getPlugins();
|
|
42
|
+
if (!plugins)
|
|
43
|
+
return null;
|
|
44
|
+
return plugins.flatMap((p) => p.commands);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Find command by name or alias (O(n) but from cache)
|
|
48
|
+
*/
|
|
49
|
+
findCommand(topic, name) {
|
|
50
|
+
const plugins = this.getPlugins();
|
|
51
|
+
if (!plugins)
|
|
52
|
+
return null;
|
|
53
|
+
const plugin = plugins.find((p) => p.topic === topic);
|
|
54
|
+
if (!plugin)
|
|
55
|
+
return null;
|
|
56
|
+
return (plugin.commands.find((c) => c.name === name || c.aliases?.includes(name)) || null);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update cache with plugin data
|
|
60
|
+
*/
|
|
61
|
+
update(plugins) {
|
|
62
|
+
const cache = {
|
|
63
|
+
version: "1.0.0",
|
|
64
|
+
cliVersion: CLI_VERSION,
|
|
65
|
+
lastUpdated: new Date().toISOString(),
|
|
66
|
+
plugins: plugins.map((p) => ({
|
|
67
|
+
name: p.name,
|
|
68
|
+
version: p.version,
|
|
69
|
+
topic: p.topic,
|
|
70
|
+
description: p.description,
|
|
71
|
+
path: p.path,
|
|
72
|
+
commands: p.commands.map((c) => ({
|
|
73
|
+
id: c.id,
|
|
74
|
+
name: c.name,
|
|
75
|
+
description: c.description,
|
|
76
|
+
aliases: c.aliases,
|
|
77
|
+
topic: p.topic,
|
|
78
|
+
})),
|
|
79
|
+
})),
|
|
80
|
+
};
|
|
81
|
+
this.write(cache);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Invalidate cache (force reload on next run)
|
|
85
|
+
*/
|
|
86
|
+
invalidate() {
|
|
87
|
+
try {
|
|
88
|
+
if (fs.existsSync(this.cachePath)) {
|
|
89
|
+
fs.unlinkSync(this.cachePath);
|
|
90
|
+
}
|
|
91
|
+
this.cache = null;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Ignore delete errors
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get cache stats for debugging
|
|
99
|
+
*/
|
|
100
|
+
stats() {
|
|
101
|
+
const cache = this.read();
|
|
102
|
+
if (!cache) {
|
|
103
|
+
return {
|
|
104
|
+
exists: false,
|
|
105
|
+
valid: false,
|
|
106
|
+
pluginCount: 0,
|
|
107
|
+
commandCount: 0,
|
|
108
|
+
age: "N/A",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const lastUpdated = new Date(cache.lastUpdated);
|
|
112
|
+
const now = new Date();
|
|
113
|
+
const ageMs = now.getTime() - lastUpdated.getTime();
|
|
114
|
+
const ageMins = Math.floor(ageMs / 60000);
|
|
115
|
+
return {
|
|
116
|
+
exists: true,
|
|
117
|
+
valid: this.isValid(),
|
|
118
|
+
pluginCount: cache.plugins.length,
|
|
119
|
+
commandCount: cache.plugins.reduce((sum, p) => sum + p.commands.length, 0),
|
|
120
|
+
age: ageMins < 60 ? `${ageMins}m` : `${Math.floor(ageMins / 60)}h`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Private methods
|
|
124
|
+
read() {
|
|
125
|
+
if (this.cache)
|
|
126
|
+
return this.cache;
|
|
127
|
+
try {
|
|
128
|
+
if (fs.existsSync(this.cachePath)) {
|
|
129
|
+
this.cache = JSON.parse(fs.readFileSync(this.cachePath, "utf-8"));
|
|
130
|
+
return this.cache;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Ignore read errors
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
write(cache) {
|
|
139
|
+
try {
|
|
140
|
+
const dir = path.dirname(this.cachePath);
|
|
141
|
+
if (!fs.existsSync(dir)) {
|
|
142
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
fs.writeFileSync(this.cachePath, JSON.stringify(cache, null, 2));
|
|
145
|
+
this.cache = cache;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Ignore write errors
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Singleton instance
|
|
153
|
+
export const manifestCache = new ManifestCacheManager();
|
|
154
|
+
//# sourceMappingURL=manifest-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-cache.js","sourceRoot":"","sources":["../../src/utils/manifest-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official plugins that can be auto-installed when user tries to use them
|
|
3
|
+
*/
|
|
4
|
+
export declare const OFFICIAL_PLUGINS: Record<string, string>;
|
|
5
|
+
/**
|
|
6
|
+
* Check if topic matches an official plugin
|
|
7
|
+
*/
|
|
8
|
+
export declare function getOfficialPlugin(topic: string): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Get all official plugin topics
|
|
11
|
+
*/
|
|
12
|
+
export declare function getOfficialTopics(): string[];
|
|
13
|
+
//# sourceMappingURL=official-plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"official-plugins.d.ts","sourceRoot":"","sources":["../../src/utils/official-plugins.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// packages/cli/src/utils/official-plugins.ts
|
|
2
|
+
// Official Plugins Registry - Auto-install support
|
|
3
|
+
/**
|
|
4
|
+
* Official plugins that can be auto-installed when user tries to use them
|
|
5
|
+
*/
|
|
6
|
+
export const OFFICIAL_PLUGINS = {
|
|
7
|
+
// Topic -> npm package name
|
|
8
|
+
awf: "@nockdev/awf", // AI Workflow Framework
|
|
9
|
+
hsa: "@nockdev/hsa", // Hierarchical Smart Agent (MCP Server)
|
|
10
|
+
// Future plugins:
|
|
11
|
+
// ui: "@nockdev/ui", // UI Components
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Check if topic matches an official plugin
|
|
15
|
+
*/
|
|
16
|
+
export function getOfficialPlugin(topic) {
|
|
17
|
+
return OFFICIAL_PLUGINS[topic] || null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get all official plugin topics
|
|
21
|
+
*/
|
|
22
|
+
export function getOfficialTopics() {
|
|
23
|
+
return Object.keys(OFFICIAL_PLUGINS);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=official-plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"official-plugins.js","sourceRoot":"","sources":["../../src/utils/official-plugins.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,mDAAmD;AAEnD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,4BAA4B;IAC5B,GAAG,EAAE,cAAc,EAAM,wBAAwB;IACjD,GAAG,EAAE,cAAc,EAAM,wCAAwC;IACjE,kBAAkB;IAClB,0CAA0C;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface TelemetryEvent {
|
|
2
|
+
event: string;
|
|
3
|
+
properties?: Record<string, unknown>;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class Telemetry {
|
|
7
|
+
private configPath;
|
|
8
|
+
private eventsPath;
|
|
9
|
+
private config;
|
|
10
|
+
private startTime;
|
|
11
|
+
constructor();
|
|
12
|
+
/**
|
|
13
|
+
* Check if telemetry is enabled
|
|
14
|
+
*/
|
|
15
|
+
isEnabled(): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Enable telemetry
|
|
18
|
+
*/
|
|
19
|
+
enable(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Disable telemetry
|
|
22
|
+
*/
|
|
23
|
+
disable(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get current status
|
|
26
|
+
*/
|
|
27
|
+
status(): {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
eventCount: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Track command execution start
|
|
33
|
+
*/
|
|
34
|
+
trackStart(_command: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Track command execution end
|
|
37
|
+
*/
|
|
38
|
+
trackEnd(command: string, exitCode?: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Track custom event
|
|
41
|
+
*/
|
|
42
|
+
track(event: string, properties?: Record<string, unknown>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Flush events (for future remote sending)
|
|
45
|
+
*/
|
|
46
|
+
flush(): TelemetryEvent[];
|
|
47
|
+
private getConfig;
|
|
48
|
+
private createDefaultConfig;
|
|
49
|
+
private saveConfig;
|
|
50
|
+
private getEvents;
|
|
51
|
+
private addEvent;
|
|
52
|
+
private clearEvents;
|
|
53
|
+
private generateAnonymousId;
|
|
54
|
+
private isCI;
|
|
55
|
+
}
|
|
56
|
+
export declare const telemetry: Telemetry;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/utils/telemetry.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AA0BD,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,SAAS,CAAa;;IAQ9B;;OAEG;IACH,SAAS,IAAI,OAAO;IAKpB;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd;;OAEG;IACH,OAAO,IAAI,IAAI;IAUf;;OAEG;IACH,MAAM,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAOlD;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,IAAI;IAwBrD;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAUhE;;OAEG;IACH,KAAK,IAAI,cAAc,EAAE;IAQzB,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,IAAI;CAUb;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// packages/cli/src/utils/telemetry.ts
|
|
2
|
+
// Telemetry System v1.0.0 - Opt-in Anonymous Analytics
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { homedir, platform, release, arch } from "node:os";
|
|
6
|
+
import { NOCK_DIR_NAME, CLI_VERSION } from "./constants.js";
|
|
7
|
+
const TELEMETRY_FILE = "telemetry.json";
|
|
8
|
+
const EVENTS_FILE = "telemetry-events.json";
|
|
9
|
+
const MAX_EVENTS = 100; // Buffer before sending
|
|
10
|
+
export class Telemetry {
|
|
11
|
+
configPath;
|
|
12
|
+
eventsPath;
|
|
13
|
+
config = null;
|
|
14
|
+
startTime = 0;
|
|
15
|
+
constructor() {
|
|
16
|
+
const nockDir = path.join(homedir(), NOCK_DIR_NAME);
|
|
17
|
+
this.configPath = path.join(nockDir, TELEMETRY_FILE);
|
|
18
|
+
this.eventsPath = path.join(nockDir, EVENTS_FILE);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if telemetry is enabled
|
|
22
|
+
*/
|
|
23
|
+
isEnabled() {
|
|
24
|
+
const config = this.getConfig();
|
|
25
|
+
return config?.enabled ?? false;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Enable telemetry
|
|
29
|
+
*/
|
|
30
|
+
enable() {
|
|
31
|
+
const config = this.getConfig() || this.createDefaultConfig();
|
|
32
|
+
config.enabled = true;
|
|
33
|
+
this.saveConfig(config);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Disable telemetry
|
|
37
|
+
*/
|
|
38
|
+
disable() {
|
|
39
|
+
const config = this.getConfig();
|
|
40
|
+
if (config) {
|
|
41
|
+
config.enabled = false;
|
|
42
|
+
this.saveConfig(config);
|
|
43
|
+
}
|
|
44
|
+
// Also clear buffered events
|
|
45
|
+
this.clearEvents();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get current status
|
|
49
|
+
*/
|
|
50
|
+
status() {
|
|
51
|
+
return {
|
|
52
|
+
enabled: this.isEnabled(),
|
|
53
|
+
eventCount: this.getEvents().length,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Track command execution start
|
|
58
|
+
*/
|
|
59
|
+
trackStart(_command) {
|
|
60
|
+
if (!this.isEnabled())
|
|
61
|
+
return;
|
|
62
|
+
this.startTime = Date.now();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Track command execution end
|
|
66
|
+
*/
|
|
67
|
+
trackEnd(command, exitCode = 0) {
|
|
68
|
+
if (!this.isEnabled())
|
|
69
|
+
return;
|
|
70
|
+
const duration = this.startTime ? Date.now() - this.startTime : undefined;
|
|
71
|
+
const data = {
|
|
72
|
+
command,
|
|
73
|
+
cliVersion: CLI_VERSION,
|
|
74
|
+
os: platform(),
|
|
75
|
+
osVersion: release(),
|
|
76
|
+
arch: arch(),
|
|
77
|
+
nodeVersion: process.version,
|
|
78
|
+
isCI: this.isCI(),
|
|
79
|
+
duration,
|
|
80
|
+
exitCode,
|
|
81
|
+
};
|
|
82
|
+
this.addEvent({
|
|
83
|
+
event: "command_executed",
|
|
84
|
+
properties: data,
|
|
85
|
+
timestamp: new Date().toISOString(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Track custom event
|
|
90
|
+
*/
|
|
91
|
+
track(event, properties) {
|
|
92
|
+
if (!this.isEnabled())
|
|
93
|
+
return;
|
|
94
|
+
this.addEvent({
|
|
95
|
+
event,
|
|
96
|
+
properties,
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Flush events (for future remote sending)
|
|
102
|
+
*/
|
|
103
|
+
flush() {
|
|
104
|
+
const events = this.getEvents();
|
|
105
|
+
this.clearEvents();
|
|
106
|
+
return events;
|
|
107
|
+
}
|
|
108
|
+
// Private methods
|
|
109
|
+
getConfig() {
|
|
110
|
+
if (this.config)
|
|
111
|
+
return this.config;
|
|
112
|
+
try {
|
|
113
|
+
if (fs.existsSync(this.configPath)) {
|
|
114
|
+
this.config = JSON.parse(fs.readFileSync(this.configPath, "utf-8"));
|
|
115
|
+
return this.config;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Ignore read errors
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
createDefaultConfig() {
|
|
124
|
+
return {
|
|
125
|
+
enabled: false,
|
|
126
|
+
anonymousId: this.generateAnonymousId(),
|
|
127
|
+
firstRun: new Date().toISOString(),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
saveConfig(config) {
|
|
131
|
+
this.config = config;
|
|
132
|
+
try {
|
|
133
|
+
const dir = path.dirname(this.configPath);
|
|
134
|
+
if (!fs.existsSync(dir)) {
|
|
135
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
136
|
+
}
|
|
137
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Ignore write errors
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
getEvents() {
|
|
144
|
+
try {
|
|
145
|
+
if (fs.existsSync(this.eventsPath)) {
|
|
146
|
+
return JSON.parse(fs.readFileSync(this.eventsPath, "utf-8"));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Ignore read errors
|
|
151
|
+
}
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
addEvent(event) {
|
|
155
|
+
try {
|
|
156
|
+
const events = this.getEvents();
|
|
157
|
+
events.push(event);
|
|
158
|
+
// Keep only last MAX_EVENTS
|
|
159
|
+
const trimmed = events.slice(-MAX_EVENTS);
|
|
160
|
+
fs.writeFileSync(this.eventsPath, JSON.stringify(trimmed, null, 2));
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Ignore write errors
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
clearEvents() {
|
|
167
|
+
try {
|
|
168
|
+
if (fs.existsSync(this.eventsPath)) {
|
|
169
|
+
fs.unlinkSync(this.eventsPath);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Ignore delete errors
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
generateAnonymousId() {
|
|
177
|
+
// Simple random ID (no PII)
|
|
178
|
+
return "anon_" + Math.random().toString(36).substring(2, 15);
|
|
179
|
+
}
|
|
180
|
+
isCI() {
|
|
181
|
+
return !!(process.env.CI ||
|
|
182
|
+
process.env.CONTINUOUS_INTEGRATION ||
|
|
183
|
+
process.env.GITHUB_ACTIONS ||
|
|
184
|
+
process.env.GITLAB_CI ||
|
|
185
|
+
process.env.CIRCLECI ||
|
|
186
|
+
process.env.TRAVIS);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Singleton instance
|
|
190
|
+
export const telemetry = new Telemetry();
|
|
191
|
+
//# sourceMappingURL=telemetry.js.map
|