@compforge/harness-toolbox 0.3.4 → 0.3.5
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 +4 -0
- package/dist/chunk-99p0zt4f.js +37 -0
- package/dist/chunk-pjcrhw3n.js +22 -0
- package/dist/duration.d.ts +2 -0
- package/dist/duration.js +6 -0
- package/dist/kubernetes/client-node-pod-log.js +6 -22
- package/dist/kubernetes/client.js +2 -2
- package/dist/kubernetes/environment.js +2 -2
- package/dist/mysql/index.js +8 -8
- package/dist/opensearch/index.d.ts +1 -0
- package/dist/opensearch/index.js +8 -4
- package/dist/opensearch/search-after.d.ts +12 -0
- package/dist/opensearch/search-after.js +6 -0
- package/package.json +8 -1
- package/dist/{chunk-td11zjfb.js → chunk-bg1syayb.js} +3 -3
package/README.md
CHANGED
|
@@ -9,6 +9,10 @@ clients to access Kubernetes, MySQL, Redis, OpenSearch and S3-compatible object
|
|
|
9
9
|
command, plugin protocol, test model or verdict.
|
|
10
10
|
|
|
11
11
|
The package supports Node.js 22+ and Bun. Install with `npm install @compforge/harness-toolbox`.
|
|
12
|
+
Use `@compforge/harness-toolbox/duration` to parse a positive duration such as `30m` or `2d` into milliseconds.
|
|
13
|
+
`searchAfterPages` from `@compforge/harness-toolbox/opensearch/search-after` yields raw OpenSearch
|
|
14
|
+
hit pages with a caller supplied query and stable sort. It streams pages without owning the client or
|
|
15
|
+
claiming snapshot consistency; callers supply cancellation and decide how to persist or verify results.
|
|
12
16
|
Protocol adapters have separate entry points; importing lifecycle or transport contracts does
|
|
13
17
|
not load database or Kubernetes drivers.
|
|
14
18
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/opensearch/search-after.ts
|
|
2
|
+
async function* searchAfterPages(search, index, options) {
|
|
3
|
+
if (!Number.isSafeInteger(options.pageSize) || options.pageSize <= 0 || !options.sort.length) {
|
|
4
|
+
throw new Error("search_after requires a positive pageSize and a non-empty sort");
|
|
5
|
+
}
|
|
6
|
+
let cursor;
|
|
7
|
+
for (;; ) {
|
|
8
|
+
options.signal?.throwIfAborted();
|
|
9
|
+
const body = {
|
|
10
|
+
query: options.query,
|
|
11
|
+
sort: options.sort,
|
|
12
|
+
size: options.pageSize,
|
|
13
|
+
track_total_hits: false,
|
|
14
|
+
...cursor ? { search_after: cursor } : {}
|
|
15
|
+
};
|
|
16
|
+
const result = await search.search(index, body);
|
|
17
|
+
if (result.timed_out === true || Number(result._shards?.failed ?? 0) > 0) {
|
|
18
|
+
throw new Error(`OpenSearch search_after page failed for index '${index}'`);
|
|
19
|
+
}
|
|
20
|
+
const hits = result.hits?.hits;
|
|
21
|
+
if (!Array.isArray(hits))
|
|
22
|
+
throw new Error(`OpenSearch search_after response has no hits for index '${index}'`);
|
|
23
|
+
if (!hits.length)
|
|
24
|
+
return;
|
|
25
|
+
const page = hits;
|
|
26
|
+
const next = page.at(-1)?.sort;
|
|
27
|
+
if (!Array.isArray(next) || !next.length || cursor && JSON.stringify(next) === JSON.stringify(cursor)) {
|
|
28
|
+
throw new Error(`OpenSearch search_after cursor did not advance for index '${index}'`);
|
|
29
|
+
}
|
|
30
|
+
yield page;
|
|
31
|
+
cursor = next;
|
|
32
|
+
if (page.length < options.pageSize)
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { searchAfterPages };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/duration.ts
|
|
2
|
+
function parseDuration(value) {
|
|
3
|
+
const units = { ns: 0.000001, us: 0.001, "µs": 0.001, ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
4
|
+
const input = value.trim();
|
|
5
|
+
let total = 0;
|
|
6
|
+
let cursor = 0;
|
|
7
|
+
const segment = /(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h|d)/gy;
|
|
8
|
+
while (cursor < input.length) {
|
|
9
|
+
segment.lastIndex = cursor;
|
|
10
|
+
const match = segment.exec(input);
|
|
11
|
+
if (!match)
|
|
12
|
+
throw new Error(`Invalid duration: '${value}'`);
|
|
13
|
+
total += Number(match[1]) * units[match[2]];
|
|
14
|
+
cursor = segment.lastIndex;
|
|
15
|
+
}
|
|
16
|
+
if (!Number.isFinite(total) || total <= 0 || total > Number.MAX_SAFE_INTEGER) {
|
|
17
|
+
throw new Error(`Invalid duration: '${value}'`);
|
|
18
|
+
}
|
|
19
|
+
return total;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { parseDuration };
|
package/dist/duration.js
ADDED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
logTimestampNanos
|
|
3
3
|
} from "../chunk-mp88s7r7.js";
|
|
4
|
+
import {
|
|
5
|
+
parseDuration
|
|
6
|
+
} from "../chunk-pjcrhw3n.js";
|
|
4
7
|
|
|
5
8
|
// src/kubernetes/client-node-pod-log.ts
|
|
6
9
|
import { closeSync, openSync, writeSync } from "node:fs";
|
|
@@ -14,30 +17,11 @@ var DEFAULT_CLIENT_NODE_LOG_POLICY = {
|
|
|
14
17
|
var RFC3339_LINE = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2}))(?:\s|$)/;
|
|
15
18
|
var RECENT_LINE_LIMIT = 256;
|
|
16
19
|
function parseSinceSeconds(value) {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
try {
|
|
21
|
+
return Math.max(1, Math.ceil(parseDuration(value) / 1000));
|
|
22
|
+
} catch {
|
|
19
23
|
return;
|
|
20
|
-
const units = {
|
|
21
|
-
ns: 0.000000001,
|
|
22
|
-
us: 0.000001,
|
|
23
|
-
"µs": 0.000001,
|
|
24
|
-
ms: 0.001,
|
|
25
|
-
s: 1,
|
|
26
|
-
m: 60,
|
|
27
|
-
h: 3600
|
|
28
|
-
};
|
|
29
|
-
let seconds = 0;
|
|
30
|
-
let cursor = 0;
|
|
31
|
-
const segment = /(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)/gy;
|
|
32
|
-
while (cursor < input.length) {
|
|
33
|
-
segment.lastIndex = cursor;
|
|
34
|
-
const match = segment.exec(input);
|
|
35
|
-
if (!match)
|
|
36
|
-
return;
|
|
37
|
-
seconds += Number(match[1]) * units[match[2]];
|
|
38
|
-
cursor = segment.lastIndex;
|
|
39
24
|
}
|
|
40
|
-
return Math.max(1, Math.ceil(seconds));
|
|
41
25
|
}
|
|
42
26
|
function errorMessage(error) {
|
|
43
27
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
KubernetesClient
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import"../chunk-y3dx8jh6.js";
|
|
3
|
+
} from "../chunk-bg1syayb.js";
|
|
5
4
|
import"../chunk-qhpqse1y.js";
|
|
6
5
|
import"../chunk-j46x7j7c.js";
|
|
7
6
|
import"../chunk-6fnhzhdb.js";
|
|
8
7
|
import"../chunk-2m0mh09h.js";
|
|
8
|
+
import"../chunk-y3dx8jh6.js";
|
|
9
9
|
import"../chunk-ntfm5e85.js";
|
|
10
10
|
import"../chunk-v3hxvnrc.js";
|
|
11
11
|
import"../chunk-xh3zwhjh.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
KubernetesClient
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import"../chunk-y3dx8jh6.js";
|
|
3
|
+
} from "../chunk-bg1syayb.js";
|
|
5
4
|
import"../chunk-qhpqse1y.js";
|
|
6
5
|
import"../chunk-j46x7j7c.js";
|
|
7
6
|
import"../chunk-6fnhzhdb.js";
|
|
8
7
|
import"../chunk-2m0mh09h.js";
|
|
8
|
+
import"../chunk-y3dx8jh6.js";
|
|
9
9
|
import {
|
|
10
10
|
clientKey
|
|
11
11
|
} from "../chunk-a9htb6cr.js";
|
package/dist/mysql/index.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseMysqlEnvTarget
|
|
3
|
+
} from "../chunk-qq77x9ek.js";
|
|
4
|
+
import {
|
|
5
|
+
limitedRows,
|
|
6
|
+
limitedStatement,
|
|
7
|
+
queryLimited
|
|
8
|
+
} from "../chunk-1gyshqd9.js";
|
|
1
9
|
import"../chunk-pfar9cm3.js";
|
|
2
10
|
import {
|
|
3
11
|
withReadScope
|
|
@@ -9,14 +17,6 @@ import {
|
|
|
9
17
|
} from "../chunk-56t4qyp7.js";
|
|
10
18
|
import"../chunk-m91t44jh.js";
|
|
11
19
|
import"../chunk-kbewz29a.js";
|
|
12
|
-
import {
|
|
13
|
-
parseMysqlEnvTarget
|
|
14
|
-
} from "../chunk-qq77x9ek.js";
|
|
15
|
-
import {
|
|
16
|
-
limitedRows,
|
|
17
|
-
limitedStatement,
|
|
18
|
-
queryLimited
|
|
19
|
-
} from "../chunk-1gyshqd9.js";
|
|
20
20
|
import"../chunk-v3hxvnrc.js";
|
|
21
21
|
import"../chunk-h8fwx0k7.js";
|
|
22
22
|
import"../chunk-5fgbhx2r.js";
|
package/dist/opensearch/index.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
parseOpenSearchEndpoint
|
|
3
|
-
} from "../chunk-s1sjyem7.js";
|
|
4
|
-
import"../chunk-djk4kmxb.js";
|
|
5
1
|
import {
|
|
6
2
|
OpenSearchClient,
|
|
7
3
|
OpenSearchEngine,
|
|
8
4
|
isOpenSearchReadApi,
|
|
9
5
|
openOpenSearch
|
|
10
6
|
} from "../chunk-w3a4p6jm.js";
|
|
7
|
+
import {
|
|
8
|
+
searchAfterPages
|
|
9
|
+
} from "../chunk-99p0zt4f.js";
|
|
10
|
+
import {
|
|
11
|
+
parseOpenSearchEndpoint
|
|
12
|
+
} from "../chunk-s1sjyem7.js";
|
|
13
|
+
import"../chunk-djk4kmxb.js";
|
|
11
14
|
export {
|
|
15
|
+
searchAfterPages,
|
|
12
16
|
parseOpenSearchEndpoint,
|
|
13
17
|
openOpenSearch,
|
|
14
18
|
isOpenSearchReadApi,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SearchEngine, SearchQuery } from "./types";
|
|
2
|
+
export interface SearchAfterOptions {
|
|
3
|
+
query: SearchQuery;
|
|
4
|
+
/** The caller must include a stable tie breaker in this sort. */
|
|
5
|
+
sort: readonly Record<string, unknown>[];
|
|
6
|
+
pageSize: number;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
/** Iterate raw hits with the last hit's sort tuple; caller owns the stable sort and any PIT.
|
|
10
|
+
* Without PIT, this is a live view and concurrent indexing can change later pages.
|
|
11
|
+
*/
|
|
12
|
+
export declare function searchAfterPages(search: SearchEngine, index: string, options: SearchAfterOptions): AsyncGenerator<Record<string, unknown>[]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compforge/harness-toolbox",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Shared infrastructure clients, transports and bounded data capture",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"build": "bun scripts/build.ts && tsc -p tsconfig.build.json"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
|
+
"./duration": {
|
|
13
|
+
"types": "./dist/duration.d.ts",
|
|
14
|
+
"import": "./dist/duration.js"
|
|
15
|
+
},
|
|
12
16
|
"./errors": {
|
|
13
17
|
"types": "./dist/errors.d.ts",
|
|
14
18
|
"import": "./dist/errors.js"
|
|
@@ -106,6 +110,9 @@
|
|
|
106
110
|
"@types/node-fetch": "2.6.13",
|
|
107
111
|
"@types/node": "^22"
|
|
108
112
|
},
|
|
113
|
+
"overrides": {
|
|
114
|
+
"@compforge/harness-common": "file:../common"
|
|
115
|
+
},
|
|
109
116
|
"publishConfig": {
|
|
110
117
|
"access": "public"
|
|
111
118
|
},
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveWorkload
|
|
3
|
-
} from "./chunk-y3dx8jh6.js";
|
|
4
1
|
import {
|
|
5
2
|
ServicePortForwarder
|
|
6
3
|
} from "./chunk-qhpqse1y.js";
|
|
7
4
|
import {
|
|
8
5
|
resourceAccess
|
|
9
6
|
} from "./chunk-2m0mh09h.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveWorkload
|
|
9
|
+
} from "./chunk-y3dx8jh6.js";
|
|
10
10
|
import {
|
|
11
11
|
KubernetesError
|
|
12
12
|
} from "./chunk-ntfm5e85.js";
|