@reporting-bi/cli 0.1.11 → 0.1.12
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/dist/index.js +786 -549
- package/package.json +32 -32
package/dist/index.js
CHANGED
|
@@ -30,91 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
mod
|
|
31
31
|
));
|
|
32
32
|
|
|
33
|
-
// ../rp-client/dist/types.js
|
|
34
|
-
var require_types = __commonJS({
|
|
35
|
-
"../rp-client/dist/types.js"(exports2) {
|
|
36
|
-
"use strict";
|
|
37
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// ../rp-client/dist/cache.js
|
|
42
|
-
var require_cache = __commonJS({
|
|
43
|
-
"../rp-client/dist/cache.js"(exports2) {
|
|
44
|
-
"use strict";
|
|
45
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
46
|
-
exports2.ServiceCache = void 0;
|
|
47
|
-
var ServiceCache = class {
|
|
48
|
-
constructor() {
|
|
49
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
50
|
-
}
|
|
51
|
-
createKey(params3) {
|
|
52
|
-
let key = params3.path;
|
|
53
|
-
if (params3.params) {
|
|
54
|
-
const paramStrings = [];
|
|
55
|
-
for (const k of Object.keys(params3.params).sort()) {
|
|
56
|
-
paramStrings.push(`${k}=${params3.params[k]}`);
|
|
57
|
-
}
|
|
58
|
-
if (paramStrings.length > 0) {
|
|
59
|
-
key += `?${paramStrings.join("&")}`;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return key;
|
|
63
|
-
}
|
|
64
|
-
set(params3, data) {
|
|
65
|
-
const key = this.createKey(params3);
|
|
66
|
-
this.cache.set(key, data);
|
|
67
|
-
}
|
|
68
|
-
get(params3) {
|
|
69
|
-
const key = this.createKey(params3);
|
|
70
|
-
return this.cache.get(key);
|
|
71
|
-
}
|
|
72
|
-
has(params3) {
|
|
73
|
-
const key = this.createKey(params3);
|
|
74
|
-
return this.cache.has(key);
|
|
75
|
-
}
|
|
76
|
-
clear() {
|
|
77
|
-
this.cache.clear();
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
exports2.ServiceCache = ServiceCache;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// ../rp-client/dist/accountingProvider.js
|
|
85
|
-
var require_accountingProvider = __commonJS({
|
|
86
|
-
"../rp-client/dist/accountingProvider.js"(exports2) {
|
|
87
|
-
"use strict";
|
|
88
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
89
|
-
exports2.AccountingProvider = void 0;
|
|
90
|
-
var AccountingProvider2 = class {
|
|
91
|
-
constructor() {
|
|
92
|
-
this._a = null;
|
|
93
|
-
this._accounting = null;
|
|
94
|
-
}
|
|
95
|
-
get a() {
|
|
96
|
-
return this._a;
|
|
97
|
-
}
|
|
98
|
-
set a(a) {
|
|
99
|
-
this._a = a;
|
|
100
|
-
if (this.accounting?.accounting != a) {
|
|
101
|
-
this._accounting = null;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
get accounting() {
|
|
105
|
-
return this._accounting;
|
|
106
|
-
}
|
|
107
|
-
set accounting(accounting2) {
|
|
108
|
-
if (accounting2) {
|
|
109
|
-
this._a = accounting2.accounting ?? null;
|
|
110
|
-
}
|
|
111
|
-
this._accounting = accounting2;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
exports2.AccountingProvider = AccountingProvider2;
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
33
|
// ../../.yarn/cache/es-errors-npm-1.3.0-fda0c9b8a8-0a61325670.zip/node_modules/es-errors/type.js
|
|
119
34
|
var require_type = __commonJS({
|
|
120
35
|
"../../.yarn/cache/es-errors-npm-1.3.0-fda0c9b8a8-0a61325670.zip/node_modules/es-errors/type.js"(exports2, module2) {
|
|
@@ -2628,249 +2543,6 @@ var require_lib = __commonJS({
|
|
|
2628
2543
|
}
|
|
2629
2544
|
});
|
|
2630
2545
|
|
|
2631
|
-
// ../rp-client/dist/service.js
|
|
2632
|
-
var require_service = __commonJS({
|
|
2633
|
-
"../rp-client/dist/service.js"(exports2) {
|
|
2634
|
-
"use strict";
|
|
2635
|
-
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
2636
|
-
return mod && mod.__esModule ? mod : { "default": mod };
|
|
2637
|
-
};
|
|
2638
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2639
|
-
exports2.Service = exports2.ServiceAuthException = exports2.ServiceEvent = exports2.ServiceException = exports2.serializeRequestParams = void 0;
|
|
2640
|
-
var qs_1 = __importDefault(require_lib());
|
|
2641
|
-
var cache_js_1 = require_cache();
|
|
2642
|
-
function isObject2(value) {
|
|
2643
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2644
|
-
}
|
|
2645
|
-
function serializeRequestParams(params3) {
|
|
2646
|
-
const p = {};
|
|
2647
|
-
for (const k in params3) {
|
|
2648
|
-
switch (k) {
|
|
2649
|
-
case "customParams":
|
|
2650
|
-
p["p"] = JSON.stringify(params3.customParams);
|
|
2651
|
-
break;
|
|
2652
|
-
default:
|
|
2653
|
-
p[k] = isObject2(params3[k]) || Array.isArray(params3[k]) ? JSON.stringify(params3[k]) : params3[k];
|
|
2654
|
-
break;
|
|
2655
|
-
}
|
|
2656
|
-
}
|
|
2657
|
-
return qs_1.default.stringify(p, { addQueryPrefix: false });
|
|
2658
|
-
}
|
|
2659
|
-
exports2.serializeRequestParams = serializeRequestParams;
|
|
2660
|
-
var ServiceException = class extends Error {
|
|
2661
|
-
constructor(args) {
|
|
2662
|
-
super(args?.data?.message || "Unknown error");
|
|
2663
|
-
Object.assign(this, args);
|
|
2664
|
-
}
|
|
2665
|
-
};
|
|
2666
|
-
exports2.ServiceException = ServiceException;
|
|
2667
|
-
var ServiceEvent2 = class extends Event {
|
|
2668
|
-
constructor(name, args) {
|
|
2669
|
-
super(name);
|
|
2670
|
-
Object.assign(this, args);
|
|
2671
|
-
}
|
|
2672
|
-
};
|
|
2673
|
-
exports2.ServiceEvent = ServiceEvent2;
|
|
2674
|
-
var ServiceAuthException = class extends Error {
|
|
2675
|
-
};
|
|
2676
|
-
exports2.ServiceAuthException = ServiceAuthException;
|
|
2677
|
-
var Service2 = class extends EventTarget {
|
|
2678
|
-
get a() {
|
|
2679
|
-
return this.accountingProvider?.a;
|
|
2680
|
-
}
|
|
2681
|
-
get name() {
|
|
2682
|
-
return this.options.name;
|
|
2683
|
-
}
|
|
2684
|
-
get cache() {
|
|
2685
|
-
if (!this._cache)
|
|
2686
|
-
this._cache = new cache_js_1.ServiceCache();
|
|
2687
|
-
return this._cache;
|
|
2688
|
-
}
|
|
2689
|
-
constructor(options) {
|
|
2690
|
-
super();
|
|
2691
|
-
this.accountingProvider = null;
|
|
2692
|
-
this.tokenProvider = null;
|
|
2693
|
-
this._cache = null;
|
|
2694
|
-
this.options = { ...options };
|
|
2695
|
-
if (!/^(https?|\/)/.test(this.options.baseUrl)) {
|
|
2696
|
-
this.options.baseUrl = `https://${this.options.baseUrl}`;
|
|
2697
|
-
}
|
|
2698
|
-
}
|
|
2699
|
-
createUrl(path9 = "", params3) {
|
|
2700
|
-
if (this.options.xdebugSession) {
|
|
2701
|
-
params3 = params3 || {};
|
|
2702
|
-
params3.XDEBUG_SESSION = this.options.xdebugSession === true ? "1" : this.options.xdebugSession.toString();
|
|
2703
|
-
}
|
|
2704
|
-
if (this.options.params && Object.keys(this.options.params).length > 0) {
|
|
2705
|
-
params3 = { ...this.options.params, ...params3 };
|
|
2706
|
-
}
|
|
2707
|
-
let queryString = params3 ? serializeRequestParams(params3) : "";
|
|
2708
|
-
if (queryString)
|
|
2709
|
-
queryString = `?${queryString}`;
|
|
2710
|
-
const a = params3 && params3.accounting ? params3.accounting.toString() : this.a ? this.a.toString() : null;
|
|
2711
|
-
path9 = path9.replace(/^\//, "");
|
|
2712
|
-
const parts = [this.options.baseUrl, a, this.options.name, path9];
|
|
2713
|
-
return parts.filter((p) => p != null && p !== "").join("/") + queryString;
|
|
2714
|
-
}
|
|
2715
|
-
async createHeaders(headers) {
|
|
2716
|
-
const defaultHeaders = {};
|
|
2717
|
-
if (this.tokenProvider) {
|
|
2718
|
-
const token = await this.tokenProvider();
|
|
2719
|
-
if (token) {
|
|
2720
|
-
defaultHeaders["Authorization"] = `Bearer ${token}`;
|
|
2721
|
-
}
|
|
2722
|
-
}
|
|
2723
|
-
return { ...defaultHeaders, ...headers };
|
|
2724
|
-
}
|
|
2725
|
-
get credentials() {
|
|
2726
|
-
return this.tokenProvider ? void 0 : "include";
|
|
2727
|
-
}
|
|
2728
|
-
async handleError(response) {
|
|
2729
|
-
const contentType = response.headers.get("Content-Type");
|
|
2730
|
-
let error48;
|
|
2731
|
-
if (contentType?.includes("application/json")) {
|
|
2732
|
-
error48 = await response.json();
|
|
2733
|
-
error48.status = response.status;
|
|
2734
|
-
} else {
|
|
2735
|
-
error48 = { status: response.status, message: "Unknown error", error: "unknown" };
|
|
2736
|
-
}
|
|
2737
|
-
if (this.options.throwExceptions) {
|
|
2738
|
-
throw new ServiceException({ data: error48, url: response.url });
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
async handleResponse(response, parse3) {
|
|
2742
|
-
if (!response.ok) {
|
|
2743
|
-
await this.handleError(response);
|
|
2744
|
-
return null;
|
|
2745
|
-
}
|
|
2746
|
-
const contentType = response.headers.get("Content-Type");
|
|
2747
|
-
if (contentType?.includes("application/json") && parse3 !== false) {
|
|
2748
|
-
return await response.json();
|
|
2749
|
-
} else {
|
|
2750
|
-
return await response.text();
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
async getRaw(path9, params3, options) {
|
|
2754
|
-
const url2 = this.createUrl(path9, params3);
|
|
2755
|
-
this.dispatchEvent(new ServiceEvent2("beforeRequest", { url: url2, params: params3, options, method: "GET" }));
|
|
2756
|
-
return fetch(url2, {
|
|
2757
|
-
headers: await this.createHeaders(options?.headers),
|
|
2758
|
-
credentials: this.credentials
|
|
2759
|
-
});
|
|
2760
|
-
}
|
|
2761
|
-
async get(path9, params3, options) {
|
|
2762
|
-
if (options?.cache) {
|
|
2763
|
-
const cachedData = this.cache.get({ path: path9, params: params3 });
|
|
2764
|
-
if (cachedData)
|
|
2765
|
-
return cachedData;
|
|
2766
|
-
}
|
|
2767
|
-
const response = await this.getRaw(path9, params3, options);
|
|
2768
|
-
const responseData = await this.handleResponse(response, options?.parseResponse);
|
|
2769
|
-
if (options?.cache && responseData) {
|
|
2770
|
-
this.cache.set({ path: path9, params: params3 }, responseData);
|
|
2771
|
-
}
|
|
2772
|
-
return responseData;
|
|
2773
|
-
}
|
|
2774
|
-
async postRaw(path9, data, params3, options) {
|
|
2775
|
-
const url2 = this.createUrl(path9, params3);
|
|
2776
|
-
this.dispatchEvent(new ServiceEvent2("beforeRequest", { url: url2, params: params3, options, method: "POST" }));
|
|
2777
|
-
const json3 = isObject2(data) || Array.isArray(data);
|
|
2778
|
-
return fetch(url2, {
|
|
2779
|
-
method: "POST",
|
|
2780
|
-
body: json3 ? JSON.stringify(data) : data,
|
|
2781
|
-
headers: await this.createHeaders({
|
|
2782
|
-
...options?.headers ?? {},
|
|
2783
|
-
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
2784
|
-
}),
|
|
2785
|
-
credentials: this.credentials
|
|
2786
|
-
});
|
|
2787
|
-
}
|
|
2788
|
-
async post(path9, data, params3, options) {
|
|
2789
|
-
const response = await this.postRaw(path9, data, params3, options);
|
|
2790
|
-
return this.handleResponse(response);
|
|
2791
|
-
}
|
|
2792
|
-
async deleteRaw(path9, params3, options) {
|
|
2793
|
-
const url2 = this.createUrl(path9, params3);
|
|
2794
|
-
this.dispatchEvent(new ServiceEvent2("beforeRequest", { url: url2, params: params3, options, method: "DELETE" }));
|
|
2795
|
-
return fetch(url2, {
|
|
2796
|
-
method: "DELETE",
|
|
2797
|
-
headers: await this.createHeaders(options?.headers),
|
|
2798
|
-
credentials: this.credentials
|
|
2799
|
-
});
|
|
2800
|
-
}
|
|
2801
|
-
async delete(path9, params3, options) {
|
|
2802
|
-
const response = await this.deleteRaw(path9, params3, options);
|
|
2803
|
-
return this.handleResponse(response);
|
|
2804
|
-
}
|
|
2805
|
-
async putRaw(path9, data, params3, options) {
|
|
2806
|
-
const url2 = this.createUrl(path9, params3);
|
|
2807
|
-
this.dispatchEvent(new ServiceEvent2("beforeRequest", { url: url2, params: params3, options, method: "PUT" }));
|
|
2808
|
-
const json3 = isObject2(data) || Array.isArray(data);
|
|
2809
|
-
return fetch(url2, {
|
|
2810
|
-
method: "PUT",
|
|
2811
|
-
body: json3 ? JSON.stringify(data) : data,
|
|
2812
|
-
headers: await this.createHeaders({
|
|
2813
|
-
...options?.headers ?? {},
|
|
2814
|
-
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
2815
|
-
}),
|
|
2816
|
-
credentials: this.credentials
|
|
2817
|
-
});
|
|
2818
|
-
}
|
|
2819
|
-
async put(path9, data, params3, options) {
|
|
2820
|
-
const response = await this.putRaw(path9, data, params3, options);
|
|
2821
|
-
return this.handleResponse(response);
|
|
2822
|
-
}
|
|
2823
|
-
async patchRaw(path9, data, params3, options) {
|
|
2824
|
-
const url2 = this.createUrl(path9, params3);
|
|
2825
|
-
this.dispatchEvent(new ServiceEvent2("beforeRequest", { url: url2, params: params3, options, method: "PATCH" }));
|
|
2826
|
-
const json3 = isObject2(data) || Array.isArray(data);
|
|
2827
|
-
return fetch(url2, {
|
|
2828
|
-
method: "PATCH",
|
|
2829
|
-
body: json3 ? JSON.stringify(data) : data,
|
|
2830
|
-
headers: await this.createHeaders({
|
|
2831
|
-
...options?.headers ?? {},
|
|
2832
|
-
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
2833
|
-
}),
|
|
2834
|
-
credentials: this.credentials
|
|
2835
|
-
});
|
|
2836
|
-
}
|
|
2837
|
-
async patch(path9, data, params3, options) {
|
|
2838
|
-
const response = await this.patchRaw(path9, data, params3, options);
|
|
2839
|
-
return this.handleResponse(response);
|
|
2840
|
-
}
|
|
2841
|
-
};
|
|
2842
|
-
exports2.Service = Service2;
|
|
2843
|
-
}
|
|
2844
|
-
});
|
|
2845
|
-
|
|
2846
|
-
// ../rp-client/dist/index.js
|
|
2847
|
-
var require_dist = __commonJS({
|
|
2848
|
-
"../rp-client/dist/index.js"(exports2) {
|
|
2849
|
-
"use strict";
|
|
2850
|
-
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
2851
|
-
if (k2 === void 0) k2 = k;
|
|
2852
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
2853
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
2854
|
-
desc = { enumerable: true, get: function() {
|
|
2855
|
-
return m[k];
|
|
2856
|
-
} };
|
|
2857
|
-
}
|
|
2858
|
-
Object.defineProperty(o, k2, desc);
|
|
2859
|
-
} : function(o, m, k, k2) {
|
|
2860
|
-
if (k2 === void 0) k2 = k;
|
|
2861
|
-
o[k2] = m[k];
|
|
2862
|
-
});
|
|
2863
|
-
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2864
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
2865
|
-
};
|
|
2866
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2867
|
-
__exportStar(require_types(), exports2);
|
|
2868
|
-
__exportStar(require_cache(), exports2);
|
|
2869
|
-
__exportStar(require_accountingProvider(), exports2);
|
|
2870
|
-
__exportStar(require_service(), exports2);
|
|
2871
|
-
}
|
|
2872
|
-
});
|
|
2873
|
-
|
|
2874
2546
|
// ../../.yarn/cache/ajv-npm-8.18.0-6e5e062765-e7517c4261.zip/node_modules/ajv/dist/compile/codegen/code.js
|
|
2875
2547
|
var require_code = __commonJS({
|
|
2876
2548
|
"../../.yarn/cache/ajv-npm-8.18.0-6e5e062765-e7517c4261.zip/node_modules/ajv/dist/compile/codegen/code.js"(exports2) {
|
|
@@ -5822,7 +5494,7 @@ var require_compile = __commonJS({
|
|
|
5822
5494
|
const schOrFunc = root.refs[ref];
|
|
5823
5495
|
if (schOrFunc)
|
|
5824
5496
|
return schOrFunc;
|
|
5825
|
-
let _sch =
|
|
5497
|
+
let _sch = resolve8.call(this, root, ref);
|
|
5826
5498
|
if (_sch === void 0) {
|
|
5827
5499
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
5828
5500
|
const { schemaId } = this.opts;
|
|
@@ -5849,7 +5521,7 @@ var require_compile = __commonJS({
|
|
|
5849
5521
|
function sameSchemaEnv(s1, s2) {
|
|
5850
5522
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
5851
5523
|
}
|
|
5852
|
-
function
|
|
5524
|
+
function resolve8(root, ref) {
|
|
5853
5525
|
let sch;
|
|
5854
5526
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
5855
5527
|
ref = sch;
|
|
@@ -6424,7 +6096,7 @@ var require_fast_uri = __commonJS({
|
|
|
6424
6096
|
}
|
|
6425
6097
|
return uri;
|
|
6426
6098
|
}
|
|
6427
|
-
function
|
|
6099
|
+
function resolve8(baseURI, relativeURI, options) {
|
|
6428
6100
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
6429
6101
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
6430
6102
|
schemelessOptions.skipEscape = true;
|
|
@@ -6651,7 +6323,7 @@ var require_fast_uri = __commonJS({
|
|
|
6651
6323
|
var fastUri = {
|
|
6652
6324
|
SCHEMES,
|
|
6653
6325
|
normalize,
|
|
6654
|
-
resolve:
|
|
6326
|
+
resolve: resolve8,
|
|
6655
6327
|
resolveComponent,
|
|
6656
6328
|
equal,
|
|
6657
6329
|
serialize,
|
|
@@ -8978,7 +8650,7 @@ var require_draft7 = __commonJS({
|
|
|
8978
8650
|
});
|
|
8979
8651
|
|
|
8980
8652
|
// ../../.yarn/cache/ajv-npm-8.18.0-6e5e062765-e7517c4261.zip/node_modules/ajv/dist/vocabularies/discriminator/types.js
|
|
8981
|
-
var
|
|
8653
|
+
var require_types = __commonJS({
|
|
8982
8654
|
"../../.yarn/cache/ajv-npm-8.18.0-6e5e062765-e7517c4261.zip/node_modules/ajv/dist/vocabularies/discriminator/types.js"(exports2) {
|
|
8983
8655
|
"use strict";
|
|
8984
8656
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -8997,7 +8669,7 @@ var require_discriminator = __commonJS({
|
|
|
8997
8669
|
"use strict";
|
|
8998
8670
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
8999
8671
|
var codegen_1 = require_codegen();
|
|
9000
|
-
var types_1 =
|
|
8672
|
+
var types_1 = require_types();
|
|
9001
8673
|
var compile_1 = require_compile();
|
|
9002
8674
|
var ref_error_1 = require_ref_error();
|
|
9003
8675
|
var util_1 = require_util();
|
|
@@ -9599,7 +9271,7 @@ var require_limit = __commonJS({
|
|
|
9599
9271
|
});
|
|
9600
9272
|
|
|
9601
9273
|
// ../../.yarn/__virtual__/ajv-formats-virtual-7723216a4c/0/cache/ajv-formats-npm-3.0.1-2662cf5b12-168d6bca1e.zip/node_modules/ajv-formats/dist/index.js
|
|
9602
|
-
var
|
|
9274
|
+
var require_dist = __commonJS({
|
|
9603
9275
|
"../../.yarn/__virtual__/ajv-formats-virtual-7723216a4c/0/cache/ajv-formats-npm-3.0.1-2662cf5b12-168d6bca1e.zip/node_modules/ajv-formats/dist/index.js"(exports2, module2) {
|
|
9604
9276
|
"use strict";
|
|
9605
9277
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -9649,7 +9321,7 @@ var fs2 = __toESM(require("node:fs"));
|
|
|
9649
9321
|
var path = __toESM(require("node:path"));
|
|
9650
9322
|
var os2 = __toESM(require("node:os"));
|
|
9651
9323
|
|
|
9652
|
-
// ../rp-auth-client-v2/
|
|
9324
|
+
// ../rp-auth-client-v2/src/client.ts
|
|
9653
9325
|
var DEFAULT_OPTIONS = {
|
|
9654
9326
|
serviceUrl: null,
|
|
9655
9327
|
redirectUrl: typeof window !== "undefined" ? window.location.href : null,
|
|
@@ -9663,8 +9335,7 @@ var ReportingAuthClientException = class extends Error {
|
|
|
9663
9335
|
}
|
|
9664
9336
|
};
|
|
9665
9337
|
function accountingServiceUrl(serviceUrl, accounting2) {
|
|
9666
|
-
if (accounting2 == null)
|
|
9667
|
-
return serviceUrl;
|
|
9338
|
+
if (accounting2 == null) return serviceUrl;
|
|
9668
9339
|
const match = /^(.*)\/ms\/auth\/?$/.exec(serviceUrl);
|
|
9669
9340
|
if (!match) {
|
|
9670
9341
|
throw new ReportingAuthClientException({
|
|
@@ -9674,12 +9345,26 @@ function accountingServiceUrl(serviceUrl, accounting2) {
|
|
|
9674
9345
|
return `${match[1]}/ms/${accounting2}/auth`;
|
|
9675
9346
|
}
|
|
9676
9347
|
var ReportingAuthClient = class {
|
|
9348
|
+
constructor(options) {
|
|
9349
|
+
this.options = DEFAULT_OPTIONS;
|
|
9350
|
+
/**
|
|
9351
|
+
* Body of the last response, already parsed. A fetch body may be read only once, so every
|
|
9352
|
+
* method that consumes it parks the result here for readCredentials() to hand out — reading
|
|
9353
|
+
* it a second time throws "Body is unusable", which used to cost rp-cli the tokens it had
|
|
9354
|
+
* just been issued.
|
|
9355
|
+
*
|
|
9356
|
+
* Boxed because the parsed value may legitimately be null, and a body that never held
|
|
9357
|
+
* credentials (token info, an error) parks { value: null } so it is not read again either.
|
|
9358
|
+
*/
|
|
9359
|
+
this.parsedResponse = null;
|
|
9360
|
+
this._expiresAt = null;
|
|
9361
|
+
this.setOptions(options);
|
|
9362
|
+
}
|
|
9677
9363
|
get expiresAt() {
|
|
9678
9364
|
return this._expiresAt;
|
|
9679
9365
|
}
|
|
9680
9366
|
get expiresIn() {
|
|
9681
|
-
if (this._expiresAt === null)
|
|
9682
|
-
return null;
|
|
9367
|
+
if (this._expiresAt === null) return null;
|
|
9683
9368
|
return this._expiresAt - Math.floor(Date.now() / 1e3);
|
|
9684
9369
|
}
|
|
9685
9370
|
async getAuthInit() {
|
|
@@ -9700,17 +9385,28 @@ var ReportingAuthClient = class {
|
|
|
9700
9385
|
}
|
|
9701
9386
|
});
|
|
9702
9387
|
}
|
|
9388
|
+
/** Keeps the parked body in step with the response it was read from */
|
|
9389
|
+
setResponse(response) {
|
|
9390
|
+
this.response = response;
|
|
9391
|
+
this.parsedResponse = null;
|
|
9392
|
+
return response;
|
|
9393
|
+
}
|
|
9394
|
+
/**
|
|
9395
|
+
* Reads the error body of the last response. It carries no credentials and the body is spent
|
|
9396
|
+
* afterwards, so it is parked as such. The HTTP status is attached because callers need to
|
|
9397
|
+
* tell a rejected token (401) from a service that is merely unwell (5xx).
|
|
9398
|
+
*/
|
|
9399
|
+
async readErrorBody() {
|
|
9400
|
+
const body = await this.response.json();
|
|
9401
|
+
this.parsedResponse = { value: null };
|
|
9402
|
+
return { status: this.response.status, ...body };
|
|
9403
|
+
}
|
|
9703
9404
|
setOptions(options) {
|
|
9704
9405
|
Object.assign(this.options, options);
|
|
9705
9406
|
if (!/^(https?|\/)/.test(this.options.serviceUrl)) {
|
|
9706
9407
|
this.options.serviceUrl = `https://${this.options.serviceUrl}`;
|
|
9707
9408
|
}
|
|
9708
9409
|
}
|
|
9709
|
-
constructor(options) {
|
|
9710
|
-
this.options = DEFAULT_OPTIONS;
|
|
9711
|
-
this._expiresAt = null;
|
|
9712
|
-
this.setOptions(options);
|
|
9713
|
-
}
|
|
9714
9410
|
/**
|
|
9715
9411
|
* Issues a token for another user. Like impersonate(), the accounting belongs in the
|
|
9716
9412
|
* URL: delegateToken checks the caller's Admin right against the accounting of the
|
|
@@ -9721,7 +9417,7 @@ var ReportingAuthClient = class {
|
|
|
9721
9417
|
const scope = options.scope ? Array.isArray(options.scope) ? options.scope.join(" ") : options.scope : "";
|
|
9722
9418
|
const accounting2 = options.accounting ?? this.options.accounting;
|
|
9723
9419
|
const serviceUrl = accountingServiceUrl(this.options.serviceUrl, accounting2);
|
|
9724
|
-
this.
|
|
9420
|
+
this.setResponse(await this.fetchWithAuth(`${serviceUrl}/delegateToken`, {
|
|
9725
9421
|
method: "POST",
|
|
9726
9422
|
headers: {
|
|
9727
9423
|
"Content-Type": "application/json"
|
|
@@ -9734,8 +9430,10 @@ var ReportingAuthClient = class {
|
|
|
9734
9430
|
"scope": scope,
|
|
9735
9431
|
"accounting": accounting2
|
|
9736
9432
|
}))
|
|
9737
|
-
});
|
|
9738
|
-
|
|
9433
|
+
}));
|
|
9434
|
+
const credentials = await this.response.json();
|
|
9435
|
+
this.parsedResponse = { value: credentials };
|
|
9436
|
+
return credentials;
|
|
9739
9437
|
}
|
|
9740
9438
|
/**
|
|
9741
9439
|
* Impersonates the given user. The accounting is required in practice: rights are
|
|
@@ -9778,7 +9476,7 @@ var ReportingAuthClient = class {
|
|
|
9778
9476
|
}
|
|
9779
9477
|
}
|
|
9780
9478
|
async authorize(authorizationCode) {
|
|
9781
|
-
this.
|
|
9479
|
+
this.setResponse(await this.fetchWithAuth(`${this.options.serviceUrl}/token`, {
|
|
9782
9480
|
method: "POST",
|
|
9783
9481
|
headers: {
|
|
9784
9482
|
"Content-Type": "application/json"
|
|
@@ -9789,10 +9487,9 @@ var ReportingAuthClient = class {
|
|
|
9789
9487
|
"grant_type": "code",
|
|
9790
9488
|
"code": authorizationCode
|
|
9791
9489
|
}))
|
|
9792
|
-
});
|
|
9490
|
+
}));
|
|
9793
9491
|
if (!this.response.ok) {
|
|
9794
|
-
|
|
9795
|
-
throw new ReportingAuthClientException(err);
|
|
9492
|
+
throw new ReportingAuthClientException(await this.readErrorBody());
|
|
9796
9493
|
}
|
|
9797
9494
|
return this.response;
|
|
9798
9495
|
}
|
|
@@ -9816,17 +9513,16 @@ var ReportingAuthClient = class {
|
|
|
9816
9513
|
window.location.href = url2;
|
|
9817
9514
|
}
|
|
9818
9515
|
async getTokenInfo() {
|
|
9819
|
-
this.
|
|
9516
|
+
this.setResponse(await this.fetchWithAuth(`${this.options.serviceUrl}/info`, {
|
|
9820
9517
|
method: "GET",
|
|
9821
9518
|
headers: {
|
|
9822
9519
|
"Content-Type": "application/json"
|
|
9823
9520
|
}
|
|
9824
|
-
});
|
|
9521
|
+
}));
|
|
9825
9522
|
this._expiresAt = null;
|
|
9826
9523
|
if (!this.response.ok) {
|
|
9827
9524
|
if (this.response.headers.get("content-type")?.includes("application/json")) {
|
|
9828
|
-
|
|
9829
|
-
throw new ReportingAuthClientException(err);
|
|
9525
|
+
throw new ReportingAuthClientException(await this.readErrorBody());
|
|
9830
9526
|
} else {
|
|
9831
9527
|
throw new ReportingAuthClientException({
|
|
9832
9528
|
message: "Gateway communication error"
|
|
@@ -9834,6 +9530,7 @@ var ReportingAuthClient = class {
|
|
|
9834
9530
|
}
|
|
9835
9531
|
}
|
|
9836
9532
|
const tokenInfo = await this.response.json();
|
|
9533
|
+
this.parsedResponse = { value: null };
|
|
9837
9534
|
if (tokenInfo.expires_in != null) {
|
|
9838
9535
|
this._expiresAt = Math.floor(Date.now() / 1e3) + tokenInfo.expires_in;
|
|
9839
9536
|
}
|
|
@@ -9848,10 +9545,8 @@ var ReportingAuthClient = class {
|
|
|
9848
9545
|
});
|
|
9849
9546
|
}
|
|
9850
9547
|
redirectToLogin() {
|
|
9851
|
-
if (typeof window === "undefined")
|
|
9852
|
-
|
|
9853
|
-
if (!this.options.loginUrl)
|
|
9854
|
-
throw new Error("Login URL not set");
|
|
9548
|
+
if (typeof window === "undefined") throw new Error("Not in browser environment");
|
|
9549
|
+
if (!this.options.loginUrl) throw new Error("Login URL not set");
|
|
9855
9550
|
let url2 = this.options.loginUrl;
|
|
9856
9551
|
const queryParams = [];
|
|
9857
9552
|
if (this.options.clientId) {
|
|
@@ -9866,9 +9561,11 @@ var ReportingAuthClient = class {
|
|
|
9866
9561
|
window.location.href = url2;
|
|
9867
9562
|
}
|
|
9868
9563
|
async readCredentials() {
|
|
9869
|
-
if (!this.response)
|
|
9870
|
-
|
|
9871
|
-
|
|
9564
|
+
if (!this.response) return null;
|
|
9565
|
+
if (!this.parsedResponse) {
|
|
9566
|
+
this.parsedResponse = { value: await this.response.json() };
|
|
9567
|
+
}
|
|
9568
|
+
return this.parsedResponse.value;
|
|
9872
9569
|
}
|
|
9873
9570
|
async refreshToken() {
|
|
9874
9571
|
const body = { grant_type: "refresh_token" };
|
|
@@ -9878,26 +9575,24 @@ var ReportingAuthClient = class {
|
|
|
9878
9575
|
body.refresh_token = token.refresh_token;
|
|
9879
9576
|
}
|
|
9880
9577
|
}
|
|
9881
|
-
if (this.options.clientId)
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
body.client_secret = this.options.clientSecret;
|
|
9885
|
-
this.response = await fetch(`${this.options.serviceUrl}/token`, {
|
|
9578
|
+
if (this.options.clientId) body.client_id = this.options.clientId;
|
|
9579
|
+
if (this.options.clientSecret) body.client_secret = this.options.clientSecret;
|
|
9580
|
+
this.setResponse(await fetch(`${this.options.serviceUrl}/token`, {
|
|
9886
9581
|
method: "POST",
|
|
9887
9582
|
headers: {
|
|
9888
9583
|
"Content-Type": "application/json"
|
|
9889
9584
|
},
|
|
9890
9585
|
credentials: body.refresh_token ? "omit" : "include",
|
|
9891
9586
|
body: JSON.stringify(body)
|
|
9892
|
-
});
|
|
9587
|
+
}));
|
|
9893
9588
|
if (this.response.ok) {
|
|
9894
9589
|
const result = await this.response.json();
|
|
9590
|
+
this.parsedResponse = { value: result };
|
|
9895
9591
|
if (result?.expires_in) {
|
|
9896
9592
|
this._expiresAt = Math.floor(Date.now() / 1e3) + result.expires_in;
|
|
9897
9593
|
}
|
|
9898
9594
|
} else {
|
|
9899
|
-
|
|
9900
|
-
throw new ReportingAuthClientException(err);
|
|
9595
|
+
throw new ReportingAuthClientException(await this.readErrorBody());
|
|
9901
9596
|
}
|
|
9902
9597
|
return this.response;
|
|
9903
9598
|
}
|
|
@@ -9908,8 +9603,260 @@ var ReportingAuthClient = class {
|
|
|
9908
9603
|
}
|
|
9909
9604
|
};
|
|
9910
9605
|
|
|
9911
|
-
// src/
|
|
9912
|
-
var
|
|
9606
|
+
// ../rp-client/src/cache.ts
|
|
9607
|
+
var ServiceCache = class {
|
|
9608
|
+
constructor() {
|
|
9609
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
9610
|
+
}
|
|
9611
|
+
createKey(params3) {
|
|
9612
|
+
let key = params3.path;
|
|
9613
|
+
if (params3.params) {
|
|
9614
|
+
const paramStrings = [];
|
|
9615
|
+
for (const k of Object.keys(params3.params).sort()) {
|
|
9616
|
+
paramStrings.push(`${k}=${params3.params[k]}`);
|
|
9617
|
+
}
|
|
9618
|
+
if (paramStrings.length > 0) {
|
|
9619
|
+
key += `?${paramStrings.join("&")}`;
|
|
9620
|
+
}
|
|
9621
|
+
}
|
|
9622
|
+
return key;
|
|
9623
|
+
}
|
|
9624
|
+
set(params3, data) {
|
|
9625
|
+
const key = this.createKey(params3);
|
|
9626
|
+
this.cache.set(key, data);
|
|
9627
|
+
}
|
|
9628
|
+
get(params3) {
|
|
9629
|
+
const key = this.createKey(params3);
|
|
9630
|
+
return this.cache.get(key);
|
|
9631
|
+
}
|
|
9632
|
+
has(params3) {
|
|
9633
|
+
const key = this.createKey(params3);
|
|
9634
|
+
return this.cache.has(key);
|
|
9635
|
+
}
|
|
9636
|
+
clear() {
|
|
9637
|
+
this.cache.clear();
|
|
9638
|
+
}
|
|
9639
|
+
};
|
|
9640
|
+
|
|
9641
|
+
// ../rp-client/src/accountingProvider.ts
|
|
9642
|
+
var AccountingProvider = class {
|
|
9643
|
+
constructor() {
|
|
9644
|
+
this._a = null;
|
|
9645
|
+
this._accounting = null;
|
|
9646
|
+
}
|
|
9647
|
+
get a() {
|
|
9648
|
+
return this._a;
|
|
9649
|
+
}
|
|
9650
|
+
set a(a) {
|
|
9651
|
+
this._a = a;
|
|
9652
|
+
if (this.accounting?.accounting != a) {
|
|
9653
|
+
this._accounting = null;
|
|
9654
|
+
}
|
|
9655
|
+
}
|
|
9656
|
+
get accounting() {
|
|
9657
|
+
return this._accounting;
|
|
9658
|
+
}
|
|
9659
|
+
set accounting(accounting2) {
|
|
9660
|
+
if (accounting2) {
|
|
9661
|
+
this._a = accounting2.accounting ?? null;
|
|
9662
|
+
}
|
|
9663
|
+
this._accounting = accounting2;
|
|
9664
|
+
}
|
|
9665
|
+
};
|
|
9666
|
+
|
|
9667
|
+
// ../rp-client/src/service.ts
|
|
9668
|
+
var import_qs = __toESM(require_lib());
|
|
9669
|
+
function isObject(value) {
|
|
9670
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
9671
|
+
}
|
|
9672
|
+
function serializeRequestParams(params3) {
|
|
9673
|
+
const p = {};
|
|
9674
|
+
for (const k in params3) {
|
|
9675
|
+
switch (k) {
|
|
9676
|
+
case "customParams":
|
|
9677
|
+
p["p"] = JSON.stringify(params3.customParams);
|
|
9678
|
+
break;
|
|
9679
|
+
default:
|
|
9680
|
+
p[k] = isObject(params3[k]) || Array.isArray(params3[k]) ? JSON.stringify(params3[k]) : params3[k];
|
|
9681
|
+
break;
|
|
9682
|
+
}
|
|
9683
|
+
}
|
|
9684
|
+
return import_qs.default.stringify(p, { addQueryPrefix: false });
|
|
9685
|
+
}
|
|
9686
|
+
var ServiceException = class extends Error {
|
|
9687
|
+
constructor(args) {
|
|
9688
|
+
super(args?.data?.message || "Unknown error");
|
|
9689
|
+
Object.assign(this, args);
|
|
9690
|
+
}
|
|
9691
|
+
};
|
|
9692
|
+
var ServiceEvent = class extends Event {
|
|
9693
|
+
constructor(name, args) {
|
|
9694
|
+
super(name);
|
|
9695
|
+
Object.assign(this, args);
|
|
9696
|
+
}
|
|
9697
|
+
};
|
|
9698
|
+
var Service = class extends EventTarget {
|
|
9699
|
+
constructor(options) {
|
|
9700
|
+
super();
|
|
9701
|
+
this.accountingProvider = null;
|
|
9702
|
+
this.tokenProvider = null;
|
|
9703
|
+
this._cache = null;
|
|
9704
|
+
this.options = { ...options };
|
|
9705
|
+
if (!/^(https?|\/)/.test(this.options.baseUrl)) {
|
|
9706
|
+
this.options.baseUrl = `https://${this.options.baseUrl}`;
|
|
9707
|
+
}
|
|
9708
|
+
}
|
|
9709
|
+
get a() {
|
|
9710
|
+
return this.accountingProvider?.a;
|
|
9711
|
+
}
|
|
9712
|
+
get name() {
|
|
9713
|
+
return this.options.name;
|
|
9714
|
+
}
|
|
9715
|
+
get cache() {
|
|
9716
|
+
if (!this._cache) this._cache = new ServiceCache();
|
|
9717
|
+
return this._cache;
|
|
9718
|
+
}
|
|
9719
|
+
createUrl(path9 = "", params3) {
|
|
9720
|
+
if (this.options.xdebugSession) {
|
|
9721
|
+
params3 = params3 || {};
|
|
9722
|
+
params3.XDEBUG_SESSION = this.options.xdebugSession === true ? "1" : this.options.xdebugSession.toString();
|
|
9723
|
+
}
|
|
9724
|
+
if (this.options.params && Object.keys(this.options.params).length > 0) {
|
|
9725
|
+
params3 = { ...this.options.params, ...params3 };
|
|
9726
|
+
}
|
|
9727
|
+
let queryString = params3 ? serializeRequestParams(params3) : "";
|
|
9728
|
+
if (queryString) queryString = `?${queryString}`;
|
|
9729
|
+
const a = params3 && params3.accounting ? params3.accounting.toString() : this.a ? this.a.toString() : null;
|
|
9730
|
+
path9 = path9.replace(/^\//, "");
|
|
9731
|
+
const parts = [this.options.baseUrl, a, this.options.name, path9];
|
|
9732
|
+
return parts.filter((p) => p != null && p !== "").join("/") + queryString;
|
|
9733
|
+
}
|
|
9734
|
+
async createHeaders(headers) {
|
|
9735
|
+
const defaultHeaders = {};
|
|
9736
|
+
if (this.tokenProvider) {
|
|
9737
|
+
const token = await this.tokenProvider();
|
|
9738
|
+
if (token) {
|
|
9739
|
+
defaultHeaders["Authorization"] = `Bearer ${token}`;
|
|
9740
|
+
}
|
|
9741
|
+
}
|
|
9742
|
+
return { ...defaultHeaders, ...headers };
|
|
9743
|
+
}
|
|
9744
|
+
get credentials() {
|
|
9745
|
+
return this.tokenProvider ? void 0 : "include";
|
|
9746
|
+
}
|
|
9747
|
+
async handleError(response) {
|
|
9748
|
+
const contentType = response.headers.get("Content-Type");
|
|
9749
|
+
let error48;
|
|
9750
|
+
if (contentType?.includes("application/json")) {
|
|
9751
|
+
error48 = await response.json();
|
|
9752
|
+
error48.status = response.status;
|
|
9753
|
+
} else {
|
|
9754
|
+
error48 = { status: response.status, message: "Unknown error", error: "unknown" };
|
|
9755
|
+
}
|
|
9756
|
+
if (this.options.throwExceptions) {
|
|
9757
|
+
throw new ServiceException({ data: error48, url: response.url });
|
|
9758
|
+
}
|
|
9759
|
+
}
|
|
9760
|
+
async handleResponse(response, parse3) {
|
|
9761
|
+
if (!response.ok) {
|
|
9762
|
+
await this.handleError(response);
|
|
9763
|
+
return null;
|
|
9764
|
+
}
|
|
9765
|
+
const contentType = response.headers.get("Content-Type");
|
|
9766
|
+
if (contentType?.includes("application/json") && parse3 !== false) {
|
|
9767
|
+
return await response.json();
|
|
9768
|
+
} else {
|
|
9769
|
+
return await response.text();
|
|
9770
|
+
}
|
|
9771
|
+
}
|
|
9772
|
+
async getRaw(path9, params3, options) {
|
|
9773
|
+
const url2 = this.createUrl(path9, params3);
|
|
9774
|
+
this.dispatchEvent(new ServiceEvent("beforeRequest", { url: url2, params: params3, options, method: "GET" }));
|
|
9775
|
+
return fetch(url2, {
|
|
9776
|
+
headers: await this.createHeaders(options?.headers),
|
|
9777
|
+
credentials: this.credentials
|
|
9778
|
+
});
|
|
9779
|
+
}
|
|
9780
|
+
async get(path9, params3, options) {
|
|
9781
|
+
if (options?.cache) {
|
|
9782
|
+
const cachedData = this.cache.get({ path: path9, params: params3 });
|
|
9783
|
+
if (cachedData) return cachedData;
|
|
9784
|
+
}
|
|
9785
|
+
const response = await this.getRaw(path9, params3, options);
|
|
9786
|
+
const responseData = await this.handleResponse(response, options?.parseResponse);
|
|
9787
|
+
if (options?.cache && responseData) {
|
|
9788
|
+
this.cache.set({ path: path9, params: params3 }, responseData);
|
|
9789
|
+
}
|
|
9790
|
+
return responseData;
|
|
9791
|
+
}
|
|
9792
|
+
async postRaw(path9, data, params3, options) {
|
|
9793
|
+
const url2 = this.createUrl(path9, params3);
|
|
9794
|
+
this.dispatchEvent(new ServiceEvent("beforeRequest", { url: url2, params: params3, options, method: "POST" }));
|
|
9795
|
+
const json3 = isObject(data) || Array.isArray(data);
|
|
9796
|
+
return fetch(url2, {
|
|
9797
|
+
method: "POST",
|
|
9798
|
+
body: json3 ? JSON.stringify(data) : data,
|
|
9799
|
+
headers: await this.createHeaders({
|
|
9800
|
+
...options?.headers ?? {},
|
|
9801
|
+
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
9802
|
+
}),
|
|
9803
|
+
credentials: this.credentials
|
|
9804
|
+
});
|
|
9805
|
+
}
|
|
9806
|
+
async post(path9, data, params3, options) {
|
|
9807
|
+
const response = await this.postRaw(path9, data, params3, options);
|
|
9808
|
+
return this.handleResponse(response);
|
|
9809
|
+
}
|
|
9810
|
+
async deleteRaw(path9, params3, options) {
|
|
9811
|
+
const url2 = this.createUrl(path9, params3);
|
|
9812
|
+
this.dispatchEvent(new ServiceEvent("beforeRequest", { url: url2, params: params3, options, method: "DELETE" }));
|
|
9813
|
+
return fetch(url2, {
|
|
9814
|
+
method: "DELETE",
|
|
9815
|
+
headers: await this.createHeaders(options?.headers),
|
|
9816
|
+
credentials: this.credentials
|
|
9817
|
+
});
|
|
9818
|
+
}
|
|
9819
|
+
async delete(path9, params3, options) {
|
|
9820
|
+
const response = await this.deleteRaw(path9, params3, options);
|
|
9821
|
+
return this.handleResponse(response);
|
|
9822
|
+
}
|
|
9823
|
+
async putRaw(path9, data, params3, options) {
|
|
9824
|
+
const url2 = this.createUrl(path9, params3);
|
|
9825
|
+
this.dispatchEvent(new ServiceEvent("beforeRequest", { url: url2, params: params3, options, method: "PUT" }));
|
|
9826
|
+
const json3 = isObject(data) || Array.isArray(data);
|
|
9827
|
+
return fetch(url2, {
|
|
9828
|
+
method: "PUT",
|
|
9829
|
+
body: json3 ? JSON.stringify(data) : data,
|
|
9830
|
+
headers: await this.createHeaders({
|
|
9831
|
+
...options?.headers ?? {},
|
|
9832
|
+
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
9833
|
+
}),
|
|
9834
|
+
credentials: this.credentials
|
|
9835
|
+
});
|
|
9836
|
+
}
|
|
9837
|
+
async put(path9, data, params3, options) {
|
|
9838
|
+
const response = await this.putRaw(path9, data, params3, options);
|
|
9839
|
+
return this.handleResponse(response);
|
|
9840
|
+
}
|
|
9841
|
+
async patchRaw(path9, data, params3, options) {
|
|
9842
|
+
const url2 = this.createUrl(path9, params3);
|
|
9843
|
+
this.dispatchEvent(new ServiceEvent("beforeRequest", { url: url2, params: params3, options, method: "PATCH" }));
|
|
9844
|
+
const json3 = isObject(data) || Array.isArray(data);
|
|
9845
|
+
return fetch(url2, {
|
|
9846
|
+
method: "PATCH",
|
|
9847
|
+
body: json3 ? JSON.stringify(data) : data,
|
|
9848
|
+
headers: await this.createHeaders({
|
|
9849
|
+
...options?.headers ?? {},
|
|
9850
|
+
"Content-Type": `${json3 ? "application/json" : "text/plain"}; charset=UTF-8`
|
|
9851
|
+
}),
|
|
9852
|
+
credentials: this.credentials
|
|
9853
|
+
});
|
|
9854
|
+
}
|
|
9855
|
+
async patch(path9, data, params3, options) {
|
|
9856
|
+
const response = await this.patchRaw(path9, data, params3, options);
|
|
9857
|
+
return this.handleResponse(response);
|
|
9858
|
+
}
|
|
9859
|
+
};
|
|
9913
9860
|
|
|
9914
9861
|
// src/crypto.ts
|
|
9915
9862
|
var crypto = __toESM(require("node:crypto"));
|
|
@@ -9971,6 +9918,44 @@ var CONFIG_DIR = path.join(os2.homedir(), ".config", "reporting-bi");
|
|
|
9971
9918
|
var CREDENTIALS_FILE = path.join(CONFIG_DIR, "credentials.json");
|
|
9972
9919
|
var CLIENT_ID = "0D6693D4-4358-4C08-BA80-A94A97B7F47C";
|
|
9973
9920
|
var CLIENT_SECRET = "48481427819bb41798bd74fa109c90b184ca4d64d20e60dfbe8430299f06f73e";
|
|
9921
|
+
var EXIT_LOGIN_REQUIRED = 2;
|
|
9922
|
+
var LOGIN_REQUIRED_MARKER = "rpbi: login_required";
|
|
9923
|
+
var SPID_MARKER = "rpbi: spid";
|
|
9924
|
+
var LoginRequiredError = class extends Error {
|
|
9925
|
+
constructor(domain2, detail) {
|
|
9926
|
+
super(`Session expired. Run "rpbi login ${domain2}" again.`);
|
|
9927
|
+
this.domain = domain2;
|
|
9928
|
+
this.detail = detail;
|
|
9929
|
+
}
|
|
9930
|
+
};
|
|
9931
|
+
var mcpMode = false;
|
|
9932
|
+
function setMcpMode() {
|
|
9933
|
+
mcpMode = true;
|
|
9934
|
+
}
|
|
9935
|
+
function tokenExpiration(token) {
|
|
9936
|
+
if (!token) return void 0;
|
|
9937
|
+
try {
|
|
9938
|
+
const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString("utf-8"));
|
|
9939
|
+
return typeof payload.exp === "number" ? payload.exp : void 0;
|
|
9940
|
+
} catch {
|
|
9941
|
+
return void 0;
|
|
9942
|
+
}
|
|
9943
|
+
}
|
|
9944
|
+
function sessionExpiration(tokens) {
|
|
9945
|
+
return tokens.refresh_expires_at ?? tokenExpiration(tokens.refresh_token);
|
|
9946
|
+
}
|
|
9947
|
+
function accessExpiration(tokens) {
|
|
9948
|
+
return tokens.expires_at || tokenExpiration(tokens.access_token);
|
|
9949
|
+
}
|
|
9950
|
+
function sessionState(tokens, now = Math.floor(Date.now() / 1e3)) {
|
|
9951
|
+
const accessEnd = accessExpiration(tokens);
|
|
9952
|
+
const accessValid = accessEnd === void 0 || accessEnd > now;
|
|
9953
|
+
if (!tokens.refresh_token) return accessValid ? "unknown" : "expired";
|
|
9954
|
+
const sessionEnd = sessionExpiration(tokens);
|
|
9955
|
+
if (sessionEnd === void 0) return "unknown";
|
|
9956
|
+
if (sessionEnd <= now) return "expired";
|
|
9957
|
+
return accessValid ? "ok" : "stale";
|
|
9958
|
+
}
|
|
9974
9959
|
function loadCredentials() {
|
|
9975
9960
|
try {
|
|
9976
9961
|
const raw = fs2.readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
@@ -9999,21 +9984,29 @@ function findLocalConfig(startDir) {
|
|
|
9999
9984
|
dir = parent;
|
|
10000
9985
|
}
|
|
10001
9986
|
}
|
|
10002
|
-
function getActiveConnection(cwd) {
|
|
9987
|
+
function getActiveConnection(cwd, connection) {
|
|
10003
9988
|
const creds = loadCredentials();
|
|
10004
9989
|
const local = findLocalConfig(cwd);
|
|
10005
|
-
const domain2 = local?.domain ?? creds.active;
|
|
9990
|
+
const domain2 = connection ?? local?.domain ?? creds.active;
|
|
10006
9991
|
if (!domain2 || !creds.connections[domain2]) return null;
|
|
10007
9992
|
const tokens = { ...creds.connections[domain2] };
|
|
10008
|
-
if (local?.accounting) {
|
|
9993
|
+
if (local?.accounting && local.domain === domain2) {
|
|
10009
9994
|
tokens.accounting = local.accounting;
|
|
10010
9995
|
}
|
|
10011
9996
|
return { domain: domain2, tokens };
|
|
10012
9997
|
}
|
|
10013
|
-
function storeTokens(domain2, tokens) {
|
|
9998
|
+
function storeTokens(domain2, tokens, activate = true) {
|
|
10014
9999
|
const creds = loadCredentials();
|
|
10015
|
-
creds.connections[domain2]
|
|
10016
|
-
creds.
|
|
10000
|
+
const previous = creds.connections[domain2];
|
|
10001
|
+
creds.connections[domain2] = {
|
|
10002
|
+
...previous,
|
|
10003
|
+
...tokens,
|
|
10004
|
+
// spelled out because both are optional: a refresh token with no readable expiry must
|
|
10005
|
+
// not inherit the previous one, while an unspecified accounting keeps the current pick
|
|
10006
|
+
refresh_expires_at: tokens.refresh_expires_at,
|
|
10007
|
+
accounting: tokens.accounting ?? previous?.accounting
|
|
10008
|
+
};
|
|
10009
|
+
if (activate) creds.active = domain2;
|
|
10017
10010
|
saveCredentials(creds);
|
|
10018
10011
|
}
|
|
10019
10012
|
function removeTokens(domain2) {
|
|
@@ -10035,6 +10028,31 @@ function setActive(domain2, accounting2) {
|
|
|
10035
10028
|
saveCredentials(creds);
|
|
10036
10029
|
return true;
|
|
10037
10030
|
}
|
|
10031
|
+
function statusReport(cwd, now = Math.floor(Date.now() / 1e3)) {
|
|
10032
|
+
const creds = loadCredentials();
|
|
10033
|
+
const local = findLocalConfig(cwd);
|
|
10034
|
+
const activeDomain = local?.domain ?? creds.active;
|
|
10035
|
+
return {
|
|
10036
|
+
active: creds.active,
|
|
10037
|
+
local,
|
|
10038
|
+
connections: Object.keys(creds.connections).map((domain2) => {
|
|
10039
|
+
const tokens = creds.connections[domain2];
|
|
10040
|
+
const accessEnd = accessExpiration(tokens);
|
|
10041
|
+
const sessionEnd = sessionExpiration(tokens);
|
|
10042
|
+
return {
|
|
10043
|
+
domain: domain2,
|
|
10044
|
+
active: domain2 === activeDomain,
|
|
10045
|
+
accounting: tokens.accounting ?? null,
|
|
10046
|
+
state: sessionState(tokens, now),
|
|
10047
|
+
token_expires_at: accessEnd ?? null,
|
|
10048
|
+
token_expires_in: accessEnd === void 0 ? null : accessEnd - now,
|
|
10049
|
+
session_expires_at: sessionEnd ?? null,
|
|
10050
|
+
session_expires_in: sessionEnd === void 0 ? null : sessionEnd - now,
|
|
10051
|
+
has_refresh_token: !!tokens.refresh_token
|
|
10052
|
+
};
|
|
10053
|
+
})
|
|
10054
|
+
};
|
|
10055
|
+
}
|
|
10038
10056
|
function createAuthClient(domain2, tokens) {
|
|
10039
10057
|
return new ReportingAuthClient({
|
|
10040
10058
|
serviceUrl: `${domain2}/auth`,
|
|
@@ -10043,49 +10061,107 @@ function createAuthClient(domain2, tokens) {
|
|
|
10043
10061
|
tokenProvider: tokens ? () => ({ access_token: tokens.access_token, refresh_token: tokens.refresh_token }) : void 0
|
|
10044
10062
|
});
|
|
10045
10063
|
}
|
|
10064
|
+
var DEAD_TOKEN_ERRORS = ["invalid_grant", "invalid_jwt", "invalid_token"];
|
|
10065
|
+
function isSessionRefused(err) {
|
|
10066
|
+
return err.data?.status === 401 || DEAD_TOKEN_ERRORS.includes(err.data?.error ?? "");
|
|
10067
|
+
}
|
|
10068
|
+
function refusalReason(err) {
|
|
10069
|
+
if (err instanceof ReportingAuthClientException) {
|
|
10070
|
+
return err.message || err.data?.error_description || err.data?.error || "refresh refused";
|
|
10071
|
+
}
|
|
10072
|
+
return err instanceof Error ? err.message : String(err);
|
|
10073
|
+
}
|
|
10074
|
+
async function awaitRotatedTokens(domain2, spentRefreshToken) {
|
|
10075
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
10076
|
+
const stored = loadCredentials().connections[domain2];
|
|
10077
|
+
if (stored?.refresh_token && stored.refresh_token !== spentRefreshToken) return stored;
|
|
10078
|
+
await new Promise((resolve8) => setTimeout(resolve8, 100));
|
|
10079
|
+
}
|
|
10080
|
+
return null;
|
|
10081
|
+
}
|
|
10082
|
+
async function refreshTokens(conn, now) {
|
|
10083
|
+
const client = createAuthClient(conn.domain, conn.tokens);
|
|
10084
|
+
await client.refreshToken();
|
|
10085
|
+
const credentials = await client.readCredentials();
|
|
10086
|
+
if (!credentials?.access_token) throw new LoginRequiredError(conn.domain, "no access token in the refresh response");
|
|
10087
|
+
conn.tokens.access_token = credentials.access_token;
|
|
10088
|
+
if (credentials.refresh_token) {
|
|
10089
|
+
conn.tokens.refresh_token = credentials.refresh_token;
|
|
10090
|
+
conn.tokens.refresh_expires_at = tokenExpiration(credentials.refresh_token);
|
|
10091
|
+
}
|
|
10092
|
+
conn.tokens.expires_at = credentials.expires_in ? now + credentials.expires_in : 0;
|
|
10093
|
+
storeTokens(conn.domain, conn.tokens, false);
|
|
10094
|
+
}
|
|
10046
10095
|
async function ensureValidToken(conn) {
|
|
10047
10096
|
const now = Math.floor(Date.now() / 1e3);
|
|
10048
10097
|
const margin = 60;
|
|
10049
|
-
|
|
10098
|
+
const accessEnd = accessExpiration(conn.tokens);
|
|
10099
|
+
if (accessEnd !== void 0 && accessEnd > now + margin) return;
|
|
10100
|
+
if (sessionState(conn.tokens, now) === "expired") throw new LoginRequiredError(conn.domain);
|
|
10050
10101
|
if (!conn.tokens.refresh_token) return;
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
if (
|
|
10058
|
-
|
|
10059
|
-
|
|
10102
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
10103
|
+
try {
|
|
10104
|
+
await refreshTokens(conn, now);
|
|
10105
|
+
return;
|
|
10106
|
+
} catch (err) {
|
|
10107
|
+
if (err instanceof LoginRequiredError) throw err;
|
|
10108
|
+
if (!(err instanceof ReportingAuthClientException) || !isSessionRefused(err)) {
|
|
10109
|
+
console.error("Token refresh failed:", refusalReason(err));
|
|
10110
|
+
return;
|
|
10111
|
+
}
|
|
10112
|
+
const stored = await awaitRotatedTokens(conn.domain, conn.tokens.refresh_token);
|
|
10113
|
+
if (!stored) throw new LoginRequiredError(conn.domain, refusalReason(err));
|
|
10114
|
+
conn.tokens.access_token = stored.access_token;
|
|
10115
|
+
conn.tokens.refresh_token = stored.refresh_token;
|
|
10116
|
+
conn.tokens.expires_at = stored.expires_at;
|
|
10117
|
+
conn.tokens.refresh_expires_at = stored.refresh_expires_at;
|
|
10118
|
+
const adoptedEnd = accessExpiration(conn.tokens);
|
|
10119
|
+
if (adoptedEnd !== void 0 && adoptedEnd > now + margin) return;
|
|
10060
10120
|
}
|
|
10061
|
-
} catch (err) {
|
|
10062
|
-
console.error("Token refresh failed:", err instanceof Error ? err.message : err);
|
|
10063
|
-
console.error(`Session expired. Run "rpbi login ${conn.domain}" again.`);
|
|
10064
10121
|
}
|
|
10122
|
+
throw new LoginRequiredError(conn.domain, "the refresh token was refused repeatedly");
|
|
10123
|
+
}
|
|
10124
|
+
function abort(message) {
|
|
10125
|
+
if (mcpMode) throw new Error(message);
|
|
10126
|
+
console.error(message);
|
|
10127
|
+
process.exit(1);
|
|
10128
|
+
}
|
|
10129
|
+
function globalFlagValue(flag) {
|
|
10130
|
+
const index = process.argv.indexOf(`--${flag}`);
|
|
10131
|
+
if (index === -1) return void 0;
|
|
10132
|
+
const value = process.argv[index + 1];
|
|
10133
|
+
return value && !value.startsWith("-") ? value : void 0;
|
|
10065
10134
|
}
|
|
10066
10135
|
async function createService(name, options) {
|
|
10067
10136
|
const cwd = typeof options === "object" ? options.cwd : void 0;
|
|
10068
|
-
const
|
|
10137
|
+
const connection = (typeof options === "object" ? options.connection : void 0) ?? globalFlagValue("connection");
|
|
10138
|
+
const conn = getActiveConnection(cwd, connection);
|
|
10069
10139
|
if (!conn) {
|
|
10070
|
-
|
|
10071
|
-
process.exit(1);
|
|
10140
|
+
abort(connection ? `Not logged in to "${connection}". Run "rpbi login ${connection}" first.` : 'Not logged in. Run "rpbi login" first.');
|
|
10072
10141
|
}
|
|
10073
10142
|
const accountingOverride = typeof options === "number" ? options : void 0;
|
|
10074
10143
|
const accountingOptional = typeof options === "object" && options.accountingOptional;
|
|
10075
10144
|
const accounting2 = accountingOverride ?? conn.tokens.accounting;
|
|
10076
|
-
if (!accounting2 && !accountingOptional)
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
}
|
|
10080
|
-
|
|
10081
|
-
|
|
10145
|
+
if (!accounting2 && !accountingOptional) abort('No accounting set. Run "rpbi use <domain> --accounting <id>" first.');
|
|
10146
|
+
try {
|
|
10147
|
+
await ensureValidToken(conn);
|
|
10148
|
+
} catch (err) {
|
|
10149
|
+
if (mcpMode || !(err instanceof LoginRequiredError)) throw err;
|
|
10150
|
+
const detail = err.detail ? `Token refresh failed: ${err.detail}
|
|
10151
|
+
` : "";
|
|
10152
|
+
fs2.writeSync(2, `${detail}${LOGIN_REQUIRED_MARKER} ${conn.domain}
|
|
10153
|
+
${err.message}
|
|
10154
|
+
`);
|
|
10155
|
+
process.exit(EXIT_LOGIN_REQUIRED);
|
|
10156
|
+
}
|
|
10157
|
+
const service = new Service({
|
|
10082
10158
|
name,
|
|
10083
10159
|
baseUrl: `${conn.domain}/ms`,
|
|
10084
10160
|
throwExceptions: true
|
|
10085
10161
|
});
|
|
10086
10162
|
service.tokenProvider = () => conn.tokens.access_token;
|
|
10087
10163
|
if (accounting2) {
|
|
10088
|
-
const ap = new
|
|
10164
|
+
const ap = new AccountingProvider();
|
|
10089
10165
|
ap.a = accounting2;
|
|
10090
10166
|
service.accountingProvider = ap;
|
|
10091
10167
|
}
|
|
@@ -10309,6 +10385,8 @@ async function login(args) {
|
|
|
10309
10385
|
access_token: credentials.access_token,
|
|
10310
10386
|
refresh_token: credentials.refresh_token || "",
|
|
10311
10387
|
expires_at: expiresAt,
|
|
10388
|
+
// only the JWT carries the session length, the token response does not
|
|
10389
|
+
refresh_expires_at: tokenExpiration(credentials.refresh_token),
|
|
10312
10390
|
accounting: accounting2
|
|
10313
10391
|
});
|
|
10314
10392
|
console.log(`Logged in to ${domain2} successfully.`);
|
|
@@ -10324,12 +10402,12 @@ async function login(args) {
|
|
|
10324
10402
|
}
|
|
10325
10403
|
}
|
|
10326
10404
|
function getAuthorizationCode(domain2) {
|
|
10327
|
-
return new Promise((
|
|
10405
|
+
return new Promise((resolve8) => {
|
|
10328
10406
|
let timeout;
|
|
10329
10407
|
const done = (result) => {
|
|
10330
10408
|
clearTimeout(timeout);
|
|
10331
10409
|
server.close();
|
|
10332
|
-
|
|
10410
|
+
resolve8(result);
|
|
10333
10411
|
};
|
|
10334
10412
|
const server = http.createServer((req, res) => {
|
|
10335
10413
|
const url2 = new URL(req.url || "", "http://localhost");
|
|
@@ -10400,41 +10478,47 @@ function printLogo() {
|
|
|
10400
10478
|
}
|
|
10401
10479
|
|
|
10402
10480
|
// src/commands/status.ts
|
|
10403
|
-
function
|
|
10481
|
+
function formatDuration(seconds) {
|
|
10482
|
+
const days = Math.floor(seconds / 86400);
|
|
10483
|
+
const hours = Math.floor(seconds % 86400 / 3600);
|
|
10484
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
10485
|
+
if (days > 0) return `${days}d ${hours}h`;
|
|
10486
|
+
if (hours > 0) return `${hours}h ${minutes}m`;
|
|
10487
|
+
return `${minutes}m`;
|
|
10488
|
+
}
|
|
10489
|
+
function tokenExpiry(expiresIn) {
|
|
10490
|
+
if (expiresIn === null) return "unknown";
|
|
10491
|
+
return expiresIn <= 0 ? "expired" : formatDuration(expiresIn);
|
|
10492
|
+
}
|
|
10493
|
+
function sessionExpiry(connection) {
|
|
10494
|
+
if (connection.state === "expired") return `expired \u2014 run "rpbi login ${connection.domain}"`;
|
|
10495
|
+
if (connection.session_expires_in === null) return "unknown";
|
|
10496
|
+
return `${formatDuration(connection.session_expires_in)} left`;
|
|
10497
|
+
}
|
|
10498
|
+
function status(args = []) {
|
|
10499
|
+
const { flags } = parseArgs(args);
|
|
10500
|
+
const report2 = statusReport();
|
|
10501
|
+
if (flags.json) {
|
|
10502
|
+
console.log(JSON.stringify(report2, null, 2));
|
|
10503
|
+
return;
|
|
10504
|
+
}
|
|
10404
10505
|
printLogo();
|
|
10405
|
-
|
|
10406
|
-
const local = findLocalConfig();
|
|
10407
|
-
const domains = Object.keys(creds.connections);
|
|
10408
|
-
if (local) {
|
|
10506
|
+
if (report2.local) {
|
|
10409
10507
|
console.log(`Local config (.rpbi/config.json):`);
|
|
10410
|
-
console.log(` domain: ${local.domain}`);
|
|
10411
|
-
console.log(` accounting: ${local.accounting ?? "not set"}`);
|
|
10508
|
+
console.log(` domain: ${report2.local.domain}`);
|
|
10509
|
+
console.log(` accounting: ${report2.local.accounting ?? "not set"}`);
|
|
10412
10510
|
console.log();
|
|
10413
10511
|
}
|
|
10414
|
-
if (
|
|
10512
|
+
if (report2.connections.length === 0) {
|
|
10415
10513
|
console.log("Not logged in.");
|
|
10416
10514
|
return;
|
|
10417
10515
|
}
|
|
10418
|
-
for (const
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
if (tokens.expires_at === 0) {
|
|
10425
|
-
expiry = "unknown";
|
|
10426
|
-
} else if (expiresIn <= 0) {
|
|
10427
|
-
expiry = "expired";
|
|
10428
|
-
} else {
|
|
10429
|
-
const minutes = Math.floor(expiresIn / 60);
|
|
10430
|
-
const hours = Math.floor(minutes / 60);
|
|
10431
|
-
expiry = hours > 0 ? `${hours}h ${minutes % 60}m` : `${minutes}m`;
|
|
10432
|
-
}
|
|
10433
|
-
const marker = isActive ? " (active)" : "";
|
|
10434
|
-
console.log(`${domain2}${marker}`);
|
|
10435
|
-
console.log(` accounting: ${tokens.accounting ?? "not set"}`);
|
|
10436
|
-
console.log(` token expires: ${expiry}`);
|
|
10437
|
-
console.log(` refresh token: ${tokens.refresh_token ? "yes" : "no"}`);
|
|
10516
|
+
for (const connection of report2.connections) {
|
|
10517
|
+
console.log(`${connection.domain}${connection.active ? " (active)" : ""}`);
|
|
10518
|
+
console.log(` accounting: ${connection.accounting ?? "not set"}`);
|
|
10519
|
+
console.log(` token expires: ${tokenExpiry(connection.token_expires_in)}`);
|
|
10520
|
+
console.log(` session: ${sessionExpiry(connection)}`);
|
|
10521
|
+
console.log(` refresh token: ${connection.has_refresh_token ? "yes" : "no"}`);
|
|
10438
10522
|
}
|
|
10439
10523
|
}
|
|
10440
10524
|
|
|
@@ -10599,6 +10683,43 @@ function walkDir(dir, root, knownPaths, result) {
|
|
|
10599
10683
|
}
|
|
10600
10684
|
}
|
|
10601
10685
|
}
|
|
10686
|
+
function removeEmptyDirs(dir, root) {
|
|
10687
|
+
dir = path3.resolve(dir);
|
|
10688
|
+
root = path3.resolve(root);
|
|
10689
|
+
while (dir.startsWith(root) && dir !== root) {
|
|
10690
|
+
try {
|
|
10691
|
+
if (fs4.readdirSync(dir).length > 0) return;
|
|
10692
|
+
fs4.rmdirSync(dir);
|
|
10693
|
+
} catch {
|
|
10694
|
+
return;
|
|
10695
|
+
}
|
|
10696
|
+
dir = path3.dirname(dir);
|
|
10697
|
+
}
|
|
10698
|
+
}
|
|
10699
|
+
function removeVanishedFiles(root, previousIndex, serverPaths, computeCurrentHash) {
|
|
10700
|
+
for (const entry of previousIndex) {
|
|
10701
|
+
if (serverPaths.has(entry.path) || isInternalPath(entry.path)) continue;
|
|
10702
|
+
const absPath = path3.join(root, entry.path);
|
|
10703
|
+
if (!fs4.existsSync(absPath)) continue;
|
|
10704
|
+
try {
|
|
10705
|
+
if (computeCurrentHash(absPath, entry) !== entry.hash) {
|
|
10706
|
+
console.log(` Kept ${entry.path} (deleted on server, but modified locally)`);
|
|
10707
|
+
continue;
|
|
10708
|
+
}
|
|
10709
|
+
fs4.rmSync(absPath);
|
|
10710
|
+
removeEmptyDirs(path3.dirname(absPath), root);
|
|
10711
|
+
console.log(` Removed ${entry.path} (deleted on server)`);
|
|
10712
|
+
} catch (err) {
|
|
10713
|
+
console.error(` Failed to remove ${entry.path}: ${err instanceof Error ? err.message : err}`);
|
|
10714
|
+
}
|
|
10715
|
+
}
|
|
10716
|
+
}
|
|
10717
|
+
function entriesToDelete(root, index, relPath) {
|
|
10718
|
+
const prefix = `${relPath}/`;
|
|
10719
|
+
return index.filter(
|
|
10720
|
+
(e) => (e.path === relPath || e.path.startsWith(prefix)) && !fs4.existsSync(path3.join(root, e.path))
|
|
10721
|
+
);
|
|
10722
|
+
}
|
|
10602
10723
|
function detectModifiedFiles(root, index, getPath, computeCurrentHash, getStoredHash) {
|
|
10603
10724
|
const modified = [];
|
|
10604
10725
|
for (const entry of index) {
|
|
@@ -10694,7 +10815,7 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10694
10815
|
for (const key of Object.keys(result)) {
|
|
10695
10816
|
result[key] = result[key].filter((f) => !isInternalPath(f));
|
|
10696
10817
|
}
|
|
10697
|
-
const { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly } = result;
|
|
10818
|
+
const { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly } = result;
|
|
10698
10819
|
if (flags.json === "true") {
|
|
10699
10820
|
console.log(JSON.stringify(result));
|
|
10700
10821
|
return;
|
|
@@ -10702,7 +10823,7 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10702
10823
|
console.log(`${label} workspace: ${root}`);
|
|
10703
10824
|
console.log(`Domain: ${config2?.domain} | Accounting: ${config2?.accounting}`);
|
|
10704
10825
|
console.log("");
|
|
10705
|
-
const total = modifiedLocally.length + modifiedOnServer.length + conflict.length + newFiles.length + localOnly.length + serverOnly.length;
|
|
10826
|
+
const total = modifiedLocally.length + modifiedOnServer.length + conflict.length + newFiles.length + deletedLocally.length + localOnly.length + serverOnly.length;
|
|
10706
10827
|
if (total === 0) {
|
|
10707
10828
|
console.log("In sync with server.");
|
|
10708
10829
|
return;
|
|
@@ -10723,8 +10844,12 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10723
10844
|
console.log("New (untracked):");
|
|
10724
10845
|
for (const f of newFiles) console.log(` + ${f}`);
|
|
10725
10846
|
}
|
|
10847
|
+
if (deletedLocally.length > 0) {
|
|
10848
|
+
console.log("Deleted locally (push deletes them on the server):");
|
|
10849
|
+
for (const f of deletedLocally) console.log(` D ${f}`);
|
|
10850
|
+
}
|
|
10726
10851
|
if (localOnly.length > 0) {
|
|
10727
|
-
console.log("
|
|
10852
|
+
console.log("Deleted on server (pull removes them locally):");
|
|
10728
10853
|
for (const f of localOnly) console.log(` - ${f}`);
|
|
10729
10854
|
}
|
|
10730
10855
|
if (serverOnly.length > 0) {
|
|
@@ -10770,7 +10895,9 @@ async function pull(flags) {
|
|
|
10770
10895
|
const wikiService = await createService("wiki", { cwd: dir });
|
|
10771
10896
|
const langs = flags.langs ? flags.langs.split(",") : SYNC_LANGS;
|
|
10772
10897
|
console.log(`Pulling wiki to ${dir}...`);
|
|
10898
|
+
const previousIndex = readIndex(dir);
|
|
10773
10899
|
const index = [];
|
|
10900
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
10774
10901
|
for (const lang of langs) {
|
|
10775
10902
|
console.log(`Pulling pages for language: ${lang}`);
|
|
10776
10903
|
const pages = await wikiService.get("pages", {
|
|
@@ -10783,6 +10910,7 @@ async function pull(flags) {
|
|
|
10783
10910
|
if (!page.id_wiki_page || !page.name) continue;
|
|
10784
10911
|
const relPath = pageToRelPath({ ...page, lang });
|
|
10785
10912
|
const absPath = path4.join(dir, relPath);
|
|
10913
|
+
serverPaths.add(relPath);
|
|
10786
10914
|
try {
|
|
10787
10915
|
const content4 = await wikiService.get(
|
|
10788
10916
|
`pages/${page.id_wiki_page}/content`,
|
|
@@ -10817,6 +10945,7 @@ async function pull(flags) {
|
|
|
10817
10945
|
const lang = file2.lang || "cs";
|
|
10818
10946
|
const relPath = fileToRelPath({ ...file2, lang });
|
|
10819
10947
|
const absPath = path4.join(dir, relPath);
|
|
10948
|
+
serverPaths.add(relPath);
|
|
10820
10949
|
try {
|
|
10821
10950
|
const response = await wikiService.getRaw(`download/${file2.id_wiki_file}`);
|
|
10822
10951
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
@@ -10836,6 +10965,18 @@ async function pull(flags) {
|
|
|
10836
10965
|
}
|
|
10837
10966
|
}
|
|
10838
10967
|
console.log(` Pulled ${pulledFiles} files`);
|
|
10968
|
+
for (const entry of previousIndex) {
|
|
10969
|
+
if (entry.type === "page" && !langs.includes(entry.lang)) {
|
|
10970
|
+
index.push(entry);
|
|
10971
|
+
serverPaths.add(entry.path);
|
|
10972
|
+
}
|
|
10973
|
+
}
|
|
10974
|
+
removeVanishedFiles(
|
|
10975
|
+
dir,
|
|
10976
|
+
previousIndex,
|
|
10977
|
+
serverPaths,
|
|
10978
|
+
(absPath, entry) => entry.type === "page" ? computePageHash(absPath) : computeFileHash(absPath)
|
|
10979
|
+
);
|
|
10839
10980
|
writeConfig(dir, {
|
|
10840
10981
|
domain: conn.domain,
|
|
10841
10982
|
accounting: conn.tokens.accounting,
|
|
@@ -10874,8 +11015,12 @@ async function push(flags, files) {
|
|
|
10874
11015
|
for (const relPath of filesToPush) {
|
|
10875
11016
|
const absPath = path4.join(root, relPath);
|
|
10876
11017
|
if (!fs5.existsSync(absPath)) {
|
|
10877
|
-
const
|
|
10878
|
-
if (
|
|
11018
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
11019
|
+
if (entries.length === 0) {
|
|
11020
|
+
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11021
|
+
continue;
|
|
11022
|
+
}
|
|
11023
|
+
for (const entry2 of entries) {
|
|
10879
11024
|
try {
|
|
10880
11025
|
if (entry2.type === "page") {
|
|
10881
11026
|
await wikiService.delete(`pages/${entry2.id}`, { lang: entry2.lang });
|
|
@@ -10884,13 +11029,11 @@ async function push(flags, files) {
|
|
|
10884
11029
|
}
|
|
10885
11030
|
const idx = index.indexOf(entry2);
|
|
10886
11031
|
if (idx !== -1) index.splice(idx, 1);
|
|
10887
|
-
indexMap.delete(
|
|
10888
|
-
console.log(` Deleted: ${
|
|
11032
|
+
indexMap.delete(entry2.path);
|
|
11033
|
+
console.log(` Deleted: ${entry2.path}`);
|
|
10889
11034
|
} catch (err) {
|
|
10890
|
-
console.error(` Failed to delete ${
|
|
11035
|
+
console.error(` Failed to delete ${entry2.path}: ${err instanceof Error ? err.message : err}`);
|
|
10891
11036
|
}
|
|
10892
|
-
} else {
|
|
10893
|
-
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
10894
11037
|
}
|
|
10895
11038
|
continue;
|
|
10896
11039
|
}
|
|
@@ -11023,6 +11166,7 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11023
11166
|
const modifiedLocally = [];
|
|
11024
11167
|
const modifiedOnServer = [];
|
|
11025
11168
|
const conflict = [];
|
|
11169
|
+
const deletedLocally = [];
|
|
11026
11170
|
const localOnly = [];
|
|
11027
11171
|
const serverOnly = [];
|
|
11028
11172
|
for (const lang of langs) {
|
|
@@ -11040,7 +11184,11 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11040
11184
|
serverOnly.push(relPath);
|
|
11041
11185
|
} else {
|
|
11042
11186
|
const absPath = path4.join(root, relPath);
|
|
11043
|
-
|
|
11187
|
+
if (!fs5.existsSync(absPath)) {
|
|
11188
|
+
deletedLocally.push(relPath);
|
|
11189
|
+
continue;
|
|
11190
|
+
}
|
|
11191
|
+
const localChanged = computePageHash(absPath) !== localEntry.hash;
|
|
11044
11192
|
const serverChanged = page.date_created != null && localEntry.serverDate != null && page.date_created !== localEntry.serverDate;
|
|
11045
11193
|
if (localChanged && serverChanged) {
|
|
11046
11194
|
conflict.push(relPath);
|
|
@@ -11052,7 +11200,7 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11052
11200
|
}
|
|
11053
11201
|
}
|
|
11054
11202
|
for (const [relPath, entry] of localPages) {
|
|
11055
|
-
if (entry.lang === lang && !serverPagePaths.has(relPath)) {
|
|
11203
|
+
if (entry.lang === lang && !serverPagePaths.has(relPath) && fs5.existsSync(path4.join(root, relPath))) {
|
|
11056
11204
|
localOnly.push(relPath);
|
|
11057
11205
|
}
|
|
11058
11206
|
}
|
|
@@ -11071,7 +11219,11 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11071
11219
|
serverOnly.push(relPath);
|
|
11072
11220
|
} else {
|
|
11073
11221
|
const absPath = path4.join(root, relPath);
|
|
11074
|
-
|
|
11222
|
+
if (!fs5.existsSync(absPath)) {
|
|
11223
|
+
deletedLocally.push(relPath);
|
|
11224
|
+
continue;
|
|
11225
|
+
}
|
|
11226
|
+
const localChanged = computeFileHash(absPath) !== localEntry.hash;
|
|
11075
11227
|
const serverChanged = file2.date_created != null && localEntry.serverDate != null && file2.date_created !== localEntry.serverDate;
|
|
11076
11228
|
if (localChanged && serverChanged) {
|
|
11077
11229
|
conflict.push(relPath);
|
|
@@ -11083,12 +11235,12 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11083
11235
|
}
|
|
11084
11236
|
}
|
|
11085
11237
|
for (const [relPath] of localFiles) {
|
|
11086
|
-
if (!serverFilePaths.has(relPath)) {
|
|
11238
|
+
if (!serverFilePaths.has(relPath) && fs5.existsSync(path4.join(root, relPath))) {
|
|
11087
11239
|
localOnly.push(relPath);
|
|
11088
11240
|
}
|
|
11089
11241
|
}
|
|
11090
11242
|
const newFiles = detectNewFiles2(root, index);
|
|
11091
|
-
printRemoteStatus("Wiki", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
11243
|
+
printRemoteStatus("Wiki", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
11092
11244
|
}
|
|
11093
11245
|
function watch3(flags) {
|
|
11094
11246
|
return watch2("wiki", flags, push);
|
|
@@ -11126,11 +11278,11 @@ async function readContent(flags) {
|
|
|
11126
11278
|
return flags.content;
|
|
11127
11279
|
}
|
|
11128
11280
|
if (!process.stdin.isTTY) {
|
|
11129
|
-
return new Promise((
|
|
11281
|
+
return new Promise((resolve8) => {
|
|
11130
11282
|
let data = "";
|
|
11131
11283
|
process.stdin.setEncoding("utf-8");
|
|
11132
11284
|
process.stdin.on("data", (chunk) => data += chunk);
|
|
11133
|
-
process.stdin.on("end", () =>
|
|
11285
|
+
process.stdin.on("end", () => resolve8(data));
|
|
11134
11286
|
});
|
|
11135
11287
|
}
|
|
11136
11288
|
console.error("No content provided. Use --file, --content, or pipe to stdin.");
|
|
@@ -11337,12 +11489,15 @@ async function pull2(flags) {
|
|
|
11337
11489
|
if (allThreads.length > threads.length) {
|
|
11338
11490
|
console.log(` Skipped ${allThreads.length - threads.length} shared thread(s) from another accounting`);
|
|
11339
11491
|
}
|
|
11492
|
+
const previousIndex = readIndex(dir);
|
|
11340
11493
|
const index = [];
|
|
11494
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
11341
11495
|
let pulled = 0;
|
|
11342
11496
|
for (const thread of threads) {
|
|
11343
11497
|
if (!thread.id_thread || !thread.type || !thread.description) continue;
|
|
11344
11498
|
const relPath = threadToRelPath(thread);
|
|
11345
11499
|
const absPath = path5.join(dir, relPath);
|
|
11500
|
+
serverPaths.add(relPath);
|
|
11346
11501
|
try {
|
|
11347
11502
|
const content4 = await etlService.get(
|
|
11348
11503
|
`threads/${thread.id_thread}/content`,
|
|
@@ -11396,6 +11551,12 @@ async function pull2(flags) {
|
|
|
11396
11551
|
if (!flags["no-context"]) {
|
|
11397
11552
|
await pullContext(dir, etlService, defService);
|
|
11398
11553
|
}
|
|
11554
|
+
removeVanishedFiles(
|
|
11555
|
+
dir,
|
|
11556
|
+
previousIndex,
|
|
11557
|
+
serverPaths,
|
|
11558
|
+
(absPath) => computeHash(fs7.readFileSync(absPath, "utf-8"))
|
|
11559
|
+
);
|
|
11399
11560
|
writeConfig(dir, {
|
|
11400
11561
|
domain: conn.domain,
|
|
11401
11562
|
accounting: conn.tokens.accounting,
|
|
@@ -11449,19 +11610,21 @@ async function push2(flags, files) {
|
|
|
11449
11610
|
for (const relPath of filesToPush) {
|
|
11450
11611
|
const absPath = path5.join(root, relPath);
|
|
11451
11612
|
if (!fs7.existsSync(absPath)) {
|
|
11452
|
-
const
|
|
11453
|
-
if (
|
|
11613
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
11614
|
+
if (entries.length === 0) {
|
|
11615
|
+
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11616
|
+
continue;
|
|
11617
|
+
}
|
|
11618
|
+
for (const entry2 of entries) {
|
|
11454
11619
|
try {
|
|
11455
11620
|
await etlService.delete(`threads/${entry2.id_thread}`);
|
|
11456
11621
|
const idx = index.indexOf(entry2);
|
|
11457
11622
|
if (idx !== -1) index.splice(idx, 1);
|
|
11458
|
-
indexMap.delete(
|
|
11459
|
-
console.log(` Deleted: ${
|
|
11623
|
+
indexMap.delete(entry2.path);
|
|
11624
|
+
console.log(` Deleted: ${entry2.path}`);
|
|
11460
11625
|
} catch (err) {
|
|
11461
|
-
console.error(` Failed to delete ${
|
|
11626
|
+
console.error(` Failed to delete ${entry2.path}: ${err instanceof Error ? err.message : err}`);
|
|
11462
11627
|
}
|
|
11463
|
-
} else {
|
|
11464
|
-
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11465
11628
|
}
|
|
11466
11629
|
continue;
|
|
11467
11630
|
}
|
|
@@ -11599,6 +11762,7 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11599
11762
|
const modifiedLocally = [];
|
|
11600
11763
|
const modifiedOnServer = [];
|
|
11601
11764
|
const conflict = [];
|
|
11765
|
+
const deletedLocally = [];
|
|
11602
11766
|
const localOnly = [];
|
|
11603
11767
|
const serverOnly = [];
|
|
11604
11768
|
const serverPaths = /* @__PURE__ */ new Set();
|
|
@@ -11611,7 +11775,11 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11611
11775
|
serverOnly.push(relPath);
|
|
11612
11776
|
} else {
|
|
11613
11777
|
const absPath = path5.join(root, relPath);
|
|
11614
|
-
|
|
11778
|
+
if (!fs7.existsSync(absPath)) {
|
|
11779
|
+
deletedLocally.push(relPath);
|
|
11780
|
+
continue;
|
|
11781
|
+
}
|
|
11782
|
+
const localChanged = computeHash(fs7.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
11615
11783
|
const serverChanged = thread.date_created != null && localEntry.serverDate != null && thread.date_created !== localEntry.serverDate;
|
|
11616
11784
|
if (localChanged && serverChanged) {
|
|
11617
11785
|
conflict.push(relPath);
|
|
@@ -11623,12 +11791,12 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11623
11791
|
}
|
|
11624
11792
|
}
|
|
11625
11793
|
for (const entry of index) {
|
|
11626
|
-
if (!serverPaths.has(entry.path)) {
|
|
11794
|
+
if (!serverPaths.has(entry.path) && fs7.existsSync(path5.join(root, entry.path))) {
|
|
11627
11795
|
localOnly.push(entry.path);
|
|
11628
11796
|
}
|
|
11629
11797
|
}
|
|
11630
11798
|
const newFiles = detectNewFiles3(root, index);
|
|
11631
|
-
printRemoteStatus("ETL", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
11799
|
+
printRemoteStatus("ETL", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
11632
11800
|
}
|
|
11633
11801
|
function watch4(flags) {
|
|
11634
11802
|
return watch2("etl", flags, push2);
|
|
@@ -11664,8 +11832,14 @@ async function exec2(id, flags) {
|
|
|
11664
11832
|
csv_delimiter: " ",
|
|
11665
11833
|
csv_header: "1",
|
|
11666
11834
|
csv_header_json: "1",
|
|
11667
|
-
csv_null_value: "NULL"
|
|
11835
|
+
csv_null_value: "NULL",
|
|
11836
|
+
// makes the server flush the response headers before the query finishes, so X-Spid
|
|
11837
|
+
// is readable while it still runs (IIS holds headers back until the first body flush)
|
|
11838
|
+
flush_headers: "1"
|
|
11668
11839
|
}, { headers: { accept: "text/csv" } });
|
|
11840
|
+
const spid = response.headers.get("x-spid");
|
|
11841
|
+
if (spid) fs8.writeSync(2, `${SPID_MARKER} ${spid}
|
|
11842
|
+
`);
|
|
11669
11843
|
if (!response.ok) {
|
|
11670
11844
|
const text3 = await response.text();
|
|
11671
11845
|
console.error(text3);
|
|
@@ -11678,6 +11852,11 @@ async function exec2(id, flags) {
|
|
|
11678
11852
|
process.stdout.write(result || "");
|
|
11679
11853
|
}
|
|
11680
11854
|
}
|
|
11855
|
+
async function abort2(spid, flags) {
|
|
11856
|
+
const service = await createService("etl", { cwd: flags.dir || "." });
|
|
11857
|
+
const result = await service.get(`abort/${spid}`);
|
|
11858
|
+
output(result, flags);
|
|
11859
|
+
}
|
|
11681
11860
|
async function search2(query, flags) {
|
|
11682
11861
|
const service = await createService("etl");
|
|
11683
11862
|
const results = await service.get("search", { ...getListParams(flags, DEFAULT_FIELDS), q: query });
|
|
@@ -11731,6 +11910,12 @@ async function etl(args) {
|
|
|
11731
11910
|
process.exit(1);
|
|
11732
11911
|
}
|
|
11733
11912
|
return exec2(rest[0], flags);
|
|
11913
|
+
case "abort":
|
|
11914
|
+
if (!rest[0]) {
|
|
11915
|
+
console.error("Usage: rpbi etl abort <spid>");
|
|
11916
|
+
process.exit(1);
|
|
11917
|
+
}
|
|
11918
|
+
return abort2(rest[0], flags);
|
|
11734
11919
|
case "search":
|
|
11735
11920
|
if (!rest[0]) {
|
|
11736
11921
|
console.error("Usage: rpbi etl search <query>");
|
|
@@ -11754,7 +11939,7 @@ async function etl(args) {
|
|
|
11754
11939
|
case "watch":
|
|
11755
11940
|
return watch4(flags);
|
|
11756
11941
|
default:
|
|
11757
|
-
console.log("Usage: rpbi etl <list|get|content|exec|search|params|pull|push|context|status|watch> [options]");
|
|
11942
|
+
console.log("Usage: rpbi etl <list|get|content|exec|abort|search|params|pull|push|context|status|watch> [options]");
|
|
11758
11943
|
break;
|
|
11759
11944
|
}
|
|
11760
11945
|
}
|
|
@@ -11822,12 +12007,15 @@ async function pull3(flags) {
|
|
|
11822
12007
|
order: [["type", "asc"], ["description", "asc"]]
|
|
11823
12008
|
}) || [];
|
|
11824
12009
|
console.log(`Found ${threads.length} threads`);
|
|
12010
|
+
const previousIndex = readIndex(dir);
|
|
11825
12011
|
const index = [];
|
|
12012
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
11826
12013
|
let pulled = 0;
|
|
11827
12014
|
for (const thread of threads) {
|
|
11828
12015
|
if (!thread.id_thread || !thread.type || !thread.description) continue;
|
|
11829
12016
|
const relPath = threadToRelPath2(thread);
|
|
11830
12017
|
const absPath = path6.join(dir, relPath);
|
|
12018
|
+
serverPaths.add(relPath);
|
|
11831
12019
|
try {
|
|
11832
12020
|
const content4 = await service.get(
|
|
11833
12021
|
`threads/${thread.id_thread}/content`,
|
|
@@ -11851,6 +12039,7 @@ async function pull3(flags) {
|
|
|
11851
12039
|
}
|
|
11852
12040
|
if (thread.has_doc) {
|
|
11853
12041
|
const docPath = threadToDocPath(thread);
|
|
12042
|
+
serverPaths.add(docPath);
|
|
11854
12043
|
try {
|
|
11855
12044
|
const doc2 = await service.get(
|
|
11856
12045
|
`threads/${thread.id_thread}/doc`,
|
|
@@ -11874,6 +12063,12 @@ async function pull3(flags) {
|
|
|
11874
12063
|
}
|
|
11875
12064
|
}
|
|
11876
12065
|
}
|
|
12066
|
+
removeVanishedFiles(
|
|
12067
|
+
dir,
|
|
12068
|
+
previousIndex,
|
|
12069
|
+
serverPaths,
|
|
12070
|
+
(absPath) => computeHash(fs9.readFileSync(absPath, "utf-8"))
|
|
12071
|
+
);
|
|
11877
12072
|
writeConfig(dir, {
|
|
11878
12073
|
domain: conn.domain,
|
|
11879
12074
|
accounting: conn.tokens.accounting,
|
|
@@ -11913,25 +12108,28 @@ async function push3(flags, files) {
|
|
|
11913
12108
|
const absPath = path6.join(root, relPath);
|
|
11914
12109
|
const entry = indexMap.get(relPath);
|
|
11915
12110
|
if (!fs9.existsSync(absPath)) {
|
|
11916
|
-
|
|
12111
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
12112
|
+
if (entries.length === 0) {
|
|
11917
12113
|
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11918
12114
|
continue;
|
|
11919
12115
|
}
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
12116
|
+
for (const gone of entries) {
|
|
12117
|
+
try {
|
|
12118
|
+
if (gone.kind === "doc") {
|
|
12119
|
+
await service.patch(`threads/${gone.id_thread}/doc`, "", { accounting: entryAccounting(gone) });
|
|
12120
|
+
console.log(` Cleared doc: ${gone.path}`);
|
|
12121
|
+
} else {
|
|
12122
|
+
const current = await service.get(`threads/${gone.id_thread}`, { fields: ["idz"] });
|
|
12123
|
+
if (!current?.idz) throw new Error("Thread not found on server");
|
|
12124
|
+
await service.delete(`threads/${current.idz}`, { accounting: entryAccounting(gone) });
|
|
12125
|
+
console.log(` Deleted: ${gone.path}`);
|
|
12126
|
+
}
|
|
12127
|
+
const idx = index.indexOf(gone);
|
|
12128
|
+
if (idx !== -1) index.splice(idx, 1);
|
|
12129
|
+
indexMap.delete(gone.path);
|
|
12130
|
+
} catch (err) {
|
|
12131
|
+
console.error(` Failed to delete ${gone.path}: ${err instanceof Error ? err.message : err}`);
|
|
12132
|
+
}
|
|
11935
12133
|
}
|
|
11936
12134
|
continue;
|
|
11937
12135
|
}
|
|
@@ -12048,16 +12246,21 @@ async function statusRemote3(root, config2, index, flags) {
|
|
|
12048
12246
|
const modifiedLocally = [];
|
|
12049
12247
|
const modifiedOnServer = [];
|
|
12050
12248
|
const conflict = [];
|
|
12249
|
+
const deletedLocally = [];
|
|
12051
12250
|
const localOnly = [];
|
|
12052
12251
|
const serverOnly = [];
|
|
12053
|
-
const compareEntry = (relPath, serverDate,
|
|
12252
|
+
const compareEntry = (relPath, serverDate, onServer) => {
|
|
12054
12253
|
const localEntry = indexMap.get(relPath);
|
|
12055
12254
|
if (!localEntry) {
|
|
12056
|
-
if (
|
|
12255
|
+
if (onServer) serverOnly.push(relPath);
|
|
12057
12256
|
return;
|
|
12058
12257
|
}
|
|
12059
12258
|
const absPath = path6.join(root, relPath);
|
|
12060
|
-
|
|
12259
|
+
if (!fs9.existsSync(absPath)) {
|
|
12260
|
+
if (onServer) deletedLocally.push(relPath);
|
|
12261
|
+
return;
|
|
12262
|
+
}
|
|
12263
|
+
const localChanged = computeHash(fs9.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
12061
12264
|
const serverChanged = serverDate != null && localEntry.serverDate != null && serverDate !== localEntry.serverDate;
|
|
12062
12265
|
if (localChanged && serverChanged) {
|
|
12063
12266
|
conflict.push(relPath);
|
|
@@ -12083,12 +12286,12 @@ async function statusRemote3(root, config2, index, flags) {
|
|
|
12083
12286
|
}
|
|
12084
12287
|
}
|
|
12085
12288
|
for (const entry of index) {
|
|
12086
|
-
if (!serverPaths.has(entry.path)) {
|
|
12289
|
+
if (!serverPaths.has(entry.path) && fs9.existsSync(path6.join(root, entry.path))) {
|
|
12087
12290
|
localOnly.push(entry.path);
|
|
12088
12291
|
}
|
|
12089
12292
|
}
|
|
12090
12293
|
const newFiles = detectNewFiles4(root, index);
|
|
12091
|
-
printRemoteStatus("Deployment", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
12294
|
+
printRemoteStatus("Deployment", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
12092
12295
|
}
|
|
12093
12296
|
function watch5(flags) {
|
|
12094
12297
|
return watch2("deployment", flags, push3);
|
|
@@ -12282,7 +12485,9 @@ async function pull4(flags) {
|
|
|
12282
12485
|
const projects2 = await fetchProjects(service);
|
|
12283
12486
|
const projectNames = buildProjectMap(projects2);
|
|
12284
12487
|
console.log(`Found ${projects2.length} projects`);
|
|
12488
|
+
const previousIndex = readIndex(dir);
|
|
12285
12489
|
const index = [];
|
|
12490
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
12286
12491
|
const resources2 = await service.get("resources", {
|
|
12287
12492
|
fields: RESOURCE_FIELDS,
|
|
12288
12493
|
order: [["name", "asc"]]
|
|
@@ -12297,6 +12502,7 @@ async function pull4(flags) {
|
|
|
12297
12502
|
continue;
|
|
12298
12503
|
}
|
|
12299
12504
|
const relPath = resourceToRelPath(projectName, resource);
|
|
12505
|
+
serverPaths.add(relPath);
|
|
12300
12506
|
try {
|
|
12301
12507
|
const content4 = await service.get(
|
|
12302
12508
|
`resourceContent/${resource.id_custom_resource}`,
|
|
@@ -12328,6 +12534,7 @@ async function pull4(flags) {
|
|
|
12328
12534
|
const projectName = query.id_custom_page ? projectNames.get(query.id_custom_page) : void 0;
|
|
12329
12535
|
if (!projectName) continue;
|
|
12330
12536
|
const relPath = queryToRelPath(projectName, query);
|
|
12537
|
+
serverPaths.add(relPath);
|
|
12331
12538
|
try {
|
|
12332
12539
|
const content4 = await service.get(
|
|
12333
12540
|
`queryContent/${query.id_thread}`,
|
|
@@ -12354,6 +12561,12 @@ async function pull4(flags) {
|
|
|
12354
12561
|
if (!project.id_custom_page || !project.name) continue;
|
|
12355
12562
|
await refreshProjectMeta(service, dir, project, queries2.filter((q) => q.id_custom_page === project.id_custom_page));
|
|
12356
12563
|
}
|
|
12564
|
+
removeVanishedFiles(
|
|
12565
|
+
dir,
|
|
12566
|
+
previousIndex,
|
|
12567
|
+
serverPaths,
|
|
12568
|
+
(absPath) => computeHash(fs11.readFileSync(absPath, "utf-8"))
|
|
12569
|
+
);
|
|
12357
12570
|
writeConfig(dir, {
|
|
12358
12571
|
domain: conn.domain,
|
|
12359
12572
|
accounting: conn.tokens.accounting,
|
|
@@ -12406,18 +12619,21 @@ async function push4(flags, files) {
|
|
|
12406
12619
|
const absPath = path7.join(root, relPath);
|
|
12407
12620
|
const entry = indexMap.get(relPath);
|
|
12408
12621
|
if (!fs11.existsSync(absPath)) {
|
|
12409
|
-
|
|
12622
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
12623
|
+
if (entries.length === 0) {
|
|
12410
12624
|
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
12411
12625
|
continue;
|
|
12412
12626
|
}
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12627
|
+
for (const gone of entries) {
|
|
12628
|
+
try {
|
|
12629
|
+
await service.delete(gone.kind === "query" ? `queries/${gone.id}` : `resources/${gone.id}`);
|
|
12630
|
+
const idx = index.indexOf(gone);
|
|
12631
|
+
if (idx !== -1) index.splice(idx, 1);
|
|
12632
|
+
indexMap.delete(gone.path);
|
|
12633
|
+
console.log(` Deleted: ${gone.path}`);
|
|
12634
|
+
} catch (err) {
|
|
12635
|
+
console.error(` Failed to delete ${gone.path}: ${err instanceof Error ? err.message : err}`);
|
|
12636
|
+
}
|
|
12421
12637
|
}
|
|
12422
12638
|
continue;
|
|
12423
12639
|
}
|
|
@@ -12532,6 +12748,7 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12532
12748
|
const modifiedLocally = [];
|
|
12533
12749
|
const modifiedOnServer = [];
|
|
12534
12750
|
const conflict = [];
|
|
12751
|
+
const deletedLocally = [];
|
|
12535
12752
|
const localOnly = [];
|
|
12536
12753
|
const serverOnly = [];
|
|
12537
12754
|
const compareEntry = (relPath, serverDate) => {
|
|
@@ -12541,7 +12758,11 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12541
12758
|
return;
|
|
12542
12759
|
}
|
|
12543
12760
|
const absPath = path7.join(root, relPath);
|
|
12544
|
-
|
|
12761
|
+
if (!fs11.existsSync(absPath)) {
|
|
12762
|
+
deletedLocally.push(relPath);
|
|
12763
|
+
return;
|
|
12764
|
+
}
|
|
12765
|
+
const localChanged = computeHash(fs11.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
12545
12766
|
const serverChanged = serverDate != null && localEntry.serverDate != null && serverDate !== localEntry.serverDate;
|
|
12546
12767
|
if (localChanged && serverChanged) {
|
|
12547
12768
|
conflict.push(relPath);
|
|
@@ -12571,12 +12792,12 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12571
12792
|
compareEntry(relPath, query.date_created);
|
|
12572
12793
|
}
|
|
12573
12794
|
for (const entry of index) {
|
|
12574
|
-
if (!serverPaths.has(entry.path)) {
|
|
12795
|
+
if (!serverPaths.has(entry.path) && fs11.existsSync(path7.join(root, entry.path))) {
|
|
12575
12796
|
localOnly.push(entry.path);
|
|
12576
12797
|
}
|
|
12577
12798
|
}
|
|
12578
12799
|
const newFiles = detectNewFiles5(root, index);
|
|
12579
|
-
printRemoteStatus("Extensions", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
12800
|
+
printRemoteStatus("Extensions", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
12580
12801
|
}
|
|
12581
12802
|
function watch6(flags) {
|
|
12582
12803
|
return watch2("ext", flags, push4);
|
|
@@ -12703,8 +12924,14 @@ async function exec4(id, flags) {
|
|
|
12703
12924
|
csv_delimiter: " ",
|
|
12704
12925
|
csv_header: "1",
|
|
12705
12926
|
csv_header_json: "1",
|
|
12706
|
-
csv_null_value: "NULL"
|
|
12927
|
+
csv_null_value: "NULL",
|
|
12928
|
+
// makes the server flush the response headers before the query finishes, so X-Spid
|
|
12929
|
+
// is readable while it still runs (IIS holds headers back until the first body flush)
|
|
12930
|
+
flush_headers: "1"
|
|
12707
12931
|
}, { headers: { accept: "text/csv" } });
|
|
12932
|
+
const spid = response.headers.get("x-spid");
|
|
12933
|
+
if (spid) fs12.writeSync(2, `${SPID_MARKER} ${spid}
|
|
12934
|
+
`);
|
|
12708
12935
|
if (!response.ok) {
|
|
12709
12936
|
const text3 = await response.text();
|
|
12710
12937
|
console.error(text3);
|
|
@@ -12717,6 +12944,11 @@ async function exec4(id, flags) {
|
|
|
12717
12944
|
process.stdout.write(result || "");
|
|
12718
12945
|
}
|
|
12719
12946
|
}
|
|
12947
|
+
async function abort3(spid, flags) {
|
|
12948
|
+
const service = await createService("extensions", { cwd: flags.dir || "." });
|
|
12949
|
+
const result = await service.get(`abort/${spid}`);
|
|
12950
|
+
output(result, flags);
|
|
12951
|
+
}
|
|
12720
12952
|
async function ext(args) {
|
|
12721
12953
|
const { positional, flags } = parseArgs(args);
|
|
12722
12954
|
const [subcommand, ...rest] = positional;
|
|
@@ -12739,6 +12971,12 @@ async function ext(args) {
|
|
|
12739
12971
|
process.exit(1);
|
|
12740
12972
|
}
|
|
12741
12973
|
return exec4(rest[0], flags);
|
|
12974
|
+
case "abort":
|
|
12975
|
+
if (!rest[0]) {
|
|
12976
|
+
console.error("Usage: rpbi ext abort <spid>");
|
|
12977
|
+
process.exit(1);
|
|
12978
|
+
}
|
|
12979
|
+
return abort3(rest[0], flags);
|
|
12742
12980
|
case "params":
|
|
12743
12981
|
if (!rest[0]) {
|
|
12744
12982
|
console.error("Usage: rpbi ext params <query_id> [--save <json file>] [--delete <idz>]");
|
|
@@ -12756,7 +12994,7 @@ async function ext(args) {
|
|
|
12756
12994
|
case "watch":
|
|
12757
12995
|
return watch6(flags);
|
|
12758
12996
|
default:
|
|
12759
|
-
console.log("Usage: rpbi ext <projects|resources|queries|content|exec|params|deps|pull|push|status|watch> [options]");
|
|
12997
|
+
console.log("Usage: rpbi ext <projects|resources|queries|content|exec|abort|params|deps|pull|push|status|watch> [options]");
|
|
12760
12998
|
break;
|
|
12761
12999
|
}
|
|
12762
13000
|
}
|
|
@@ -17366,7 +17604,7 @@ __export(util_exports, {
|
|
|
17366
17604
|
getParsedType: () => getParsedType2,
|
|
17367
17605
|
getSizableOrigin: () => getSizableOrigin,
|
|
17368
17606
|
hexToUint8Array: () => hexToUint8Array,
|
|
17369
|
-
isObject: () =>
|
|
17607
|
+
isObject: () => isObject2,
|
|
17370
17608
|
isPlainObject: () => isPlainObject,
|
|
17371
17609
|
issue: () => issue,
|
|
17372
17610
|
joinValues: () => joinValues,
|
|
@@ -17536,7 +17774,7 @@ function slugify(input) {
|
|
|
17536
17774
|
}
|
|
17537
17775
|
var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
|
|
17538
17776
|
};
|
|
17539
|
-
function
|
|
17777
|
+
function isObject2(data) {
|
|
17540
17778
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
17541
17779
|
}
|
|
17542
17780
|
var allowsEval = cached(() => {
|
|
@@ -17552,7 +17790,7 @@ var allowsEval = cached(() => {
|
|
|
17552
17790
|
}
|
|
17553
17791
|
});
|
|
17554
17792
|
function isPlainObject(o) {
|
|
17555
|
-
if (
|
|
17793
|
+
if (isObject2(o) === false)
|
|
17556
17794
|
return false;
|
|
17557
17795
|
const ctor = o.constructor;
|
|
17558
17796
|
if (ctor === void 0)
|
|
@@ -17560,7 +17798,7 @@ function isPlainObject(o) {
|
|
|
17560
17798
|
if (typeof ctor !== "function")
|
|
17561
17799
|
return true;
|
|
17562
17800
|
const prot = ctor.prototype;
|
|
17563
|
-
if (
|
|
17801
|
+
if (isObject2(prot) === false)
|
|
17564
17802
|
return false;
|
|
17565
17803
|
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
|
17566
17804
|
return false;
|
|
@@ -19718,13 +19956,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def2) => {
|
|
|
19718
19956
|
}
|
|
19719
19957
|
return propValues;
|
|
19720
19958
|
});
|
|
19721
|
-
const
|
|
19959
|
+
const isObject3 = isObject2;
|
|
19722
19960
|
const catchall = def2.catchall;
|
|
19723
19961
|
let value;
|
|
19724
19962
|
inst._zod.parse = (payload, ctx) => {
|
|
19725
19963
|
value ?? (value = _normalized.value);
|
|
19726
19964
|
const input = payload.value;
|
|
19727
|
-
if (!
|
|
19965
|
+
if (!isObject3(input)) {
|
|
19728
19966
|
payload.issues.push({
|
|
19729
19967
|
expected: "object",
|
|
19730
19968
|
code: "invalid_type",
|
|
@@ -19822,7 +20060,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
|
|
|
19822
20060
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
19823
20061
|
};
|
|
19824
20062
|
let fastpass;
|
|
19825
|
-
const
|
|
20063
|
+
const isObject3 = isObject2;
|
|
19826
20064
|
const jit = !globalConfig.jitless;
|
|
19827
20065
|
const allowsEval2 = allowsEval;
|
|
19828
20066
|
const fastEnabled = jit && allowsEval2.value;
|
|
@@ -19831,7 +20069,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
|
|
|
19831
20069
|
inst._zod.parse = (payload, ctx) => {
|
|
19832
20070
|
value ?? (value = _normalized.value);
|
|
19833
20071
|
const input = payload.value;
|
|
19834
|
-
if (!
|
|
20072
|
+
if (!isObject3(input)) {
|
|
19835
20073
|
payload.issues.push({
|
|
19836
20074
|
expected: "object",
|
|
19837
20075
|
code: "invalid_type",
|
|
@@ -20009,7 +20247,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
20009
20247
|
});
|
|
20010
20248
|
inst._zod.parse = (payload, ctx) => {
|
|
20011
20249
|
const input = payload.value;
|
|
20012
|
-
if (!
|
|
20250
|
+
if (!isObject2(input)) {
|
|
20013
20251
|
payload.issues.push({
|
|
20014
20252
|
code: "invalid_type",
|
|
20015
20253
|
expected: "object",
|
|
@@ -34277,7 +34515,7 @@ var Protocol = class {
|
|
|
34277
34515
|
return;
|
|
34278
34516
|
}
|
|
34279
34517
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
34280
|
-
await new Promise((
|
|
34518
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
34281
34519
|
options?.signal?.throwIfAborted();
|
|
34282
34520
|
}
|
|
34283
34521
|
} catch (error48) {
|
|
@@ -34294,7 +34532,7 @@ var Protocol = class {
|
|
|
34294
34532
|
*/
|
|
34295
34533
|
request(request, resultSchema, options) {
|
|
34296
34534
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
34297
|
-
return new Promise((
|
|
34535
|
+
return new Promise((resolve8, reject) => {
|
|
34298
34536
|
const earlyReject = (error48) => {
|
|
34299
34537
|
reject(error48);
|
|
34300
34538
|
};
|
|
@@ -34372,7 +34610,7 @@ var Protocol = class {
|
|
|
34372
34610
|
if (!parseResult.success) {
|
|
34373
34611
|
reject(parseResult.error);
|
|
34374
34612
|
} else {
|
|
34375
|
-
|
|
34613
|
+
resolve8(parseResult.data);
|
|
34376
34614
|
}
|
|
34377
34615
|
} catch (error48) {
|
|
34378
34616
|
reject(error48);
|
|
@@ -34633,12 +34871,12 @@ var Protocol = class {
|
|
|
34633
34871
|
}
|
|
34634
34872
|
} catch {
|
|
34635
34873
|
}
|
|
34636
|
-
return new Promise((
|
|
34874
|
+
return new Promise((resolve8, reject) => {
|
|
34637
34875
|
if (signal.aborted) {
|
|
34638
34876
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
34639
34877
|
return;
|
|
34640
34878
|
}
|
|
34641
|
-
const timeoutId = setTimeout(
|
|
34879
|
+
const timeoutId = setTimeout(resolve8, interval);
|
|
34642
34880
|
signal.addEventListener("abort", () => {
|
|
34643
34881
|
clearTimeout(timeoutId);
|
|
34644
34882
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -34733,7 +34971,7 @@ function mergeCapabilities(base, additional) {
|
|
|
34733
34971
|
|
|
34734
34972
|
// ../../.yarn/__virtual__/@modelcontextprotocol-sdk-virtual-4beea6215a/0/cache/@modelcontextprotocol-sdk-npm-1.26.0-380479a6f8-b4098789d9.zip/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
34735
34973
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
34736
|
-
var import_ajv_formats = __toESM(
|
|
34974
|
+
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
34737
34975
|
function createDefaultAjvInstance() {
|
|
34738
34976
|
const ajv = new import_ajv.default({
|
|
34739
34977
|
strict: false,
|
|
@@ -35597,7 +35835,7 @@ var McpServer = class {
|
|
|
35597
35835
|
let task = createTaskResult.task;
|
|
35598
35836
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
35599
35837
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
35600
|
-
await new Promise((
|
|
35838
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
35601
35839
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
35602
35840
|
if (!updatedTask) {
|
|
35603
35841
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -36240,12 +36478,12 @@ var StdioServerTransport = class {
|
|
|
36240
36478
|
this.onclose?.();
|
|
36241
36479
|
}
|
|
36242
36480
|
send(message) {
|
|
36243
|
-
return new Promise((
|
|
36481
|
+
return new Promise((resolve8) => {
|
|
36244
36482
|
const json3 = serializeMessage(message);
|
|
36245
36483
|
if (this._stdout.write(json3)) {
|
|
36246
|
-
|
|
36484
|
+
resolve8();
|
|
36247
36485
|
} else {
|
|
36248
|
-
this._stdout.once("drain",
|
|
36486
|
+
this._stdout.once("drain", resolve8);
|
|
36249
36487
|
}
|
|
36250
36488
|
});
|
|
36251
36489
|
}
|
|
@@ -36283,31 +36521,19 @@ function text(data) {
|
|
|
36283
36521
|
return { content: [{ type: "text", text: data }] };
|
|
36284
36522
|
}
|
|
36285
36523
|
async function mcp() {
|
|
36524
|
+
setMcpMode();
|
|
36286
36525
|
const server = new McpServer({
|
|
36287
36526
|
name: "reporting-bi",
|
|
36288
|
-
version: "0.1.
|
|
36527
|
+
version: "0.1.12"
|
|
36289
36528
|
});
|
|
36290
36529
|
server.tool(
|
|
36291
36530
|
"status",
|
|
36292
|
-
"Show active connection, accounting, and token expiry for all logged-in domains",
|
|
36531
|
+
"Show active connection, accounting, and token/session expiry for all logged-in domains",
|
|
36293
36532
|
{},
|
|
36294
36533
|
async () => {
|
|
36295
|
-
const
|
|
36296
|
-
|
|
36297
|
-
|
|
36298
|
-
const result = domains.map((domain2) => {
|
|
36299
|
-
const tokens = creds.connections[domain2];
|
|
36300
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
36301
|
-
const expiresIn = tokens.expires_at - now;
|
|
36302
|
-
return {
|
|
36303
|
-
domain: domain2,
|
|
36304
|
-
active: creds.active === domain2,
|
|
36305
|
-
accounting: tokens.accounting ?? null,
|
|
36306
|
-
token_expires_in_seconds: tokens.expires_at === 0 ? null : expiresIn,
|
|
36307
|
-
has_refresh_token: !!tokens.refresh_token
|
|
36308
|
-
};
|
|
36309
|
-
});
|
|
36310
|
-
return json2(result);
|
|
36534
|
+
const report2 = statusReport();
|
|
36535
|
+
if (report2.connections.length === 0) return text("Not logged in.");
|
|
36536
|
+
return json2(report2);
|
|
36311
36537
|
}
|
|
36312
36538
|
);
|
|
36313
36539
|
server.tool(
|
|
@@ -36788,26 +37014,26 @@ function saveUpdateCheck(data) {
|
|
|
36788
37014
|
fs13.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(data, null, 2));
|
|
36789
37015
|
}
|
|
36790
37016
|
function fetchLatestVersion() {
|
|
36791
|
-
return new Promise((
|
|
37017
|
+
return new Promise((resolve8) => {
|
|
36792
37018
|
const req = https.get(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { timeout: 5e3 }, (res) => {
|
|
36793
37019
|
if (res.statusCode !== 200) {
|
|
36794
37020
|
res.resume();
|
|
36795
|
-
return
|
|
37021
|
+
return resolve8(null);
|
|
36796
37022
|
}
|
|
36797
37023
|
let body = "";
|
|
36798
37024
|
res.on("data", (chunk) => body += chunk);
|
|
36799
37025
|
res.on("end", () => {
|
|
36800
37026
|
try {
|
|
36801
|
-
|
|
37027
|
+
resolve8(JSON.parse(body).version ?? null);
|
|
36802
37028
|
} catch {
|
|
36803
|
-
|
|
37029
|
+
resolve8(null);
|
|
36804
37030
|
}
|
|
36805
37031
|
});
|
|
36806
37032
|
});
|
|
36807
|
-
req.on("error", () =>
|
|
37033
|
+
req.on("error", () => resolve8(null));
|
|
36808
37034
|
req.on("timeout", () => {
|
|
36809
37035
|
req.destroy();
|
|
36810
|
-
|
|
37036
|
+
resolve8(null);
|
|
36811
37037
|
});
|
|
36812
37038
|
});
|
|
36813
37039
|
}
|
|
@@ -36831,10 +37057,10 @@ async function checkForUpdate() {
|
|
|
36831
37057
|
saveUpdateCheck({ lastCheck: now });
|
|
36832
37058
|
const latest = await fetchLatestVersion();
|
|
36833
37059
|
if (!latest) return;
|
|
36834
|
-
if (!isNewer(latest, "0.1.
|
|
36835
|
-
console.
|
|
36836
|
-
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: "
|
|
36837
|
-
console.
|
|
37060
|
+
if (!isNewer(latest, "0.1.12")) return;
|
|
37061
|
+
console.error(`\x1B[33mUpdating ${PACKAGE_NAME} ${"0.1.12"} \u2192 ${latest}...\x1B[0m`);
|
|
37062
|
+
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: ["ignore", 2, 2] });
|
|
37063
|
+
console.error(`\x1B[32mUpdated to ${latest}.\x1B[0m`);
|
|
36838
37064
|
} catch {
|
|
36839
37065
|
}
|
|
36840
37066
|
}
|
|
@@ -36844,11 +37070,11 @@ async function forceUpdate() {
|
|
|
36844
37070
|
console.error("Could not fetch latest version from npm.");
|
|
36845
37071
|
process.exit(1);
|
|
36846
37072
|
}
|
|
36847
|
-
if (!isNewer(latest, "0.1.
|
|
36848
|
-
console.log(`Already up to date (${"0.1.
|
|
37073
|
+
if (!isNewer(latest, "0.1.12")) {
|
|
37074
|
+
console.log(`Already up to date (${"0.1.12"}).`);
|
|
36849
37075
|
return;
|
|
36850
37076
|
}
|
|
36851
|
-
console.log(`Updating ${PACKAGE_NAME} ${"0.1.
|
|
37077
|
+
console.log(`Updating ${PACKAGE_NAME} ${"0.1.12"} \u2192 ${latest}...`);
|
|
36852
37078
|
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: "inherit" });
|
|
36853
37079
|
console.log(`\x1B[32mUpdated to ${latest}.\x1B[0m`);
|
|
36854
37080
|
saveUpdateCheck({ lastCheck: Date.now() });
|
|
@@ -36859,11 +37085,20 @@ var USAGE_default = `Reporting.bi CLI
|
|
|
36859
37085
|
|
|
36860
37086
|
Usage: rpbi <command> [options]
|
|
36861
37087
|
|
|
37088
|
+
Global options:
|
|
37089
|
+
--connection <domain> Run against this login instead of the active one
|
|
37090
|
+
--json Machine-readable output
|
|
37091
|
+
--verbose Log every request to stderr
|
|
37092
|
+
|
|
37093
|
+
Workspace sync (etl/wiki/deployment/ext pull, push, status) mirrors deletions both ways:
|
|
37094
|
+
pull removes local files deleted on the server (a locally modified file is kept), push
|
|
37095
|
+
deletes on the server what was deleted locally \u2014 single files or whole folders.
|
|
37096
|
+
|
|
36862
37097
|
Commands:
|
|
36863
37098
|
login [domain] [--accounting <id>] Login to a Reporting.bi instance (opens browser)
|
|
36864
37099
|
logout [domain] Logout and revoke tokens (default: active connection)
|
|
36865
37100
|
use <domain> [--accounting <id>] Switch active connection and/or set accounting
|
|
36866
|
-
status
|
|
37101
|
+
status [--json] Show all connections, token and session expiry
|
|
36867
37102
|
init [--connection <domain>] [--accounting <id>] [--type etl|wiki|deployment|ext] Initialize .rpbi/config.json in current directory
|
|
36868
37103
|
update Force update to latest version from npm
|
|
36869
37104
|
mcp Start MCP server (for AI agents, stdio transport)
|
|
@@ -36876,6 +37111,7 @@ ETL:
|
|
|
36876
37111
|
etl get <id> Get thread metadata
|
|
36877
37112
|
etl content <id> Get thread SQL content (plain text)
|
|
36878
37113
|
etl exec <id> [--sql "..."|--file f] Execute thread (optionally with custom SQL)
|
|
37114
|
+
etl abort <spid> Abort a running exec (exec reports "rpbi: spid <n>" on stderr)
|
|
36879
37115
|
etl search <query> Search threads
|
|
36880
37116
|
etl params <id> [--save <json>|--delete <idz>] List, save or delete thread parameters
|
|
36881
37117
|
etl pull [--dir <path>] [--no-context] Pull all ETL threads, parameters, metadata & schema to local files
|
|
@@ -36901,6 +37137,7 @@ Extensions (requires the "custom.define" right):
|
|
|
36901
37137
|
ext queries List queries
|
|
36902
37138
|
ext content <id> [--query] Get resource content (--query for query SQL)
|
|
36903
37139
|
ext exec <query_id> [--sql "..."|--file f] Execute query (optionally with custom SQL)
|
|
37140
|
+
ext abort <spid> Abort a running exec (exec reports "rpbi: spid <n>" on stderr)
|
|
36904
37141
|
ext params <query_id> [--save <json>|--delete <idz>] List, save or delete query parameters
|
|
36905
37142
|
ext deps --project <id>|--query <id>|--resource <id> List SQL dependencies (resource \u2194 query links)
|
|
36906
37143
|
ext deps --query <id> --add <resource_id> Link a query to a resource (or --resource <id> --add <query_id>)
|
|
@@ -37025,7 +37262,7 @@ Examples:
|
|
|
37025
37262
|
(async () => {
|
|
37026
37263
|
const [command, ...args] = process.argv.slice(2);
|
|
37027
37264
|
if (command === "--version" || command === "-v") {
|
|
37028
|
-
console.log("0.1.
|
|
37265
|
+
console.log("0.1.12");
|
|
37029
37266
|
return;
|
|
37030
37267
|
}
|
|
37031
37268
|
await checkForUpdate();
|
|
@@ -37082,7 +37319,7 @@ Examples:
|
|
|
37082
37319
|
helpdesk(args);
|
|
37083
37320
|
break;
|
|
37084
37321
|
case "status":
|
|
37085
|
-
status();
|
|
37322
|
+
status(args);
|
|
37086
37323
|
break;
|
|
37087
37324
|
case "mcp":
|
|
37088
37325
|
mcp();
|