@reporting-bi/cli 0.1.11 → 0.1.13
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 +824 -579
- package/package.json +1 -1
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
|
}
|
|
@@ -10194,6 +10270,14 @@ function output(data, flags) {
|
|
|
10194
10270
|
console.log(data);
|
|
10195
10271
|
}
|
|
10196
10272
|
}
|
|
10273
|
+
function errorMessage(err) {
|
|
10274
|
+
const data = err?.data;
|
|
10275
|
+
return data?.message || data?.error || (err instanceof Error ? err.message : String(err));
|
|
10276
|
+
}
|
|
10277
|
+
function fail(err, context3) {
|
|
10278
|
+
console.error(context3 ? `${context3}: ${errorMessage(err)}` : errorMessage(err));
|
|
10279
|
+
process.exit(1);
|
|
10280
|
+
}
|
|
10197
10281
|
|
|
10198
10282
|
// src/commands/accounting.ts
|
|
10199
10283
|
async function fetchAccountingName(accountingId) {
|
|
@@ -10309,6 +10393,8 @@ async function login(args) {
|
|
|
10309
10393
|
access_token: credentials.access_token,
|
|
10310
10394
|
refresh_token: credentials.refresh_token || "",
|
|
10311
10395
|
expires_at: expiresAt,
|
|
10396
|
+
// only the JWT carries the session length, the token response does not
|
|
10397
|
+
refresh_expires_at: tokenExpiration(credentials.refresh_token),
|
|
10312
10398
|
accounting: accounting2
|
|
10313
10399
|
});
|
|
10314
10400
|
console.log(`Logged in to ${domain2} successfully.`);
|
|
@@ -10324,12 +10410,12 @@ async function login(args) {
|
|
|
10324
10410
|
}
|
|
10325
10411
|
}
|
|
10326
10412
|
function getAuthorizationCode(domain2) {
|
|
10327
|
-
return new Promise((
|
|
10413
|
+
return new Promise((resolve8) => {
|
|
10328
10414
|
let timeout;
|
|
10329
10415
|
const done = (result) => {
|
|
10330
10416
|
clearTimeout(timeout);
|
|
10331
10417
|
server.close();
|
|
10332
|
-
|
|
10418
|
+
resolve8(result);
|
|
10333
10419
|
};
|
|
10334
10420
|
const server = http.createServer((req, res) => {
|
|
10335
10421
|
const url2 = new URL(req.url || "", "http://localhost");
|
|
@@ -10400,41 +10486,47 @@ function printLogo() {
|
|
|
10400
10486
|
}
|
|
10401
10487
|
|
|
10402
10488
|
// src/commands/status.ts
|
|
10403
|
-
function
|
|
10489
|
+
function formatDuration(seconds) {
|
|
10490
|
+
const days = Math.floor(seconds / 86400);
|
|
10491
|
+
const hours = Math.floor(seconds % 86400 / 3600);
|
|
10492
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
10493
|
+
if (days > 0) return `${days}d ${hours}h`;
|
|
10494
|
+
if (hours > 0) return `${hours}h ${minutes}m`;
|
|
10495
|
+
return `${minutes}m`;
|
|
10496
|
+
}
|
|
10497
|
+
function tokenExpiry(expiresIn) {
|
|
10498
|
+
if (expiresIn === null) return "unknown";
|
|
10499
|
+
return expiresIn <= 0 ? "expired" : formatDuration(expiresIn);
|
|
10500
|
+
}
|
|
10501
|
+
function sessionExpiry(connection) {
|
|
10502
|
+
if (connection.state === "expired") return `expired \u2014 run "rpbi login ${connection.domain}"`;
|
|
10503
|
+
if (connection.session_expires_in === null) return "unknown";
|
|
10504
|
+
return `${formatDuration(connection.session_expires_in)} left`;
|
|
10505
|
+
}
|
|
10506
|
+
function status(args = []) {
|
|
10507
|
+
const { flags } = parseArgs(args);
|
|
10508
|
+
const report2 = statusReport();
|
|
10509
|
+
if (flags.json) {
|
|
10510
|
+
console.log(JSON.stringify(report2, null, 2));
|
|
10511
|
+
return;
|
|
10512
|
+
}
|
|
10404
10513
|
printLogo();
|
|
10405
|
-
|
|
10406
|
-
const local = findLocalConfig();
|
|
10407
|
-
const domains = Object.keys(creds.connections);
|
|
10408
|
-
if (local) {
|
|
10514
|
+
if (report2.local) {
|
|
10409
10515
|
console.log(`Local config (.rpbi/config.json):`);
|
|
10410
|
-
console.log(` domain: ${local.domain}`);
|
|
10411
|
-
console.log(` accounting: ${local.accounting ?? "not set"}`);
|
|
10516
|
+
console.log(` domain: ${report2.local.domain}`);
|
|
10517
|
+
console.log(` accounting: ${report2.local.accounting ?? "not set"}`);
|
|
10412
10518
|
console.log();
|
|
10413
10519
|
}
|
|
10414
|
-
if (
|
|
10520
|
+
if (report2.connections.length === 0) {
|
|
10415
10521
|
console.log("Not logged in.");
|
|
10416
10522
|
return;
|
|
10417
10523
|
}
|
|
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"}`);
|
|
10524
|
+
for (const connection of report2.connections) {
|
|
10525
|
+
console.log(`${connection.domain}${connection.active ? " (active)" : ""}`);
|
|
10526
|
+
console.log(` accounting: ${connection.accounting ?? "not set"}`);
|
|
10527
|
+
console.log(` token expires: ${tokenExpiry(connection.token_expires_in)}`);
|
|
10528
|
+
console.log(` session: ${sessionExpiry(connection)}`);
|
|
10529
|
+
console.log(` refresh token: ${connection.has_refresh_token ? "yes" : "no"}`);
|
|
10438
10530
|
}
|
|
10439
10531
|
}
|
|
10440
10532
|
|
|
@@ -10599,6 +10691,43 @@ function walkDir(dir, root, knownPaths, result) {
|
|
|
10599
10691
|
}
|
|
10600
10692
|
}
|
|
10601
10693
|
}
|
|
10694
|
+
function removeEmptyDirs(dir, root) {
|
|
10695
|
+
dir = path3.resolve(dir);
|
|
10696
|
+
root = path3.resolve(root);
|
|
10697
|
+
while (dir.startsWith(root) && dir !== root) {
|
|
10698
|
+
try {
|
|
10699
|
+
if (fs4.readdirSync(dir).length > 0) return;
|
|
10700
|
+
fs4.rmdirSync(dir);
|
|
10701
|
+
} catch {
|
|
10702
|
+
return;
|
|
10703
|
+
}
|
|
10704
|
+
dir = path3.dirname(dir);
|
|
10705
|
+
}
|
|
10706
|
+
}
|
|
10707
|
+
function removeVanishedFiles(root, previousIndex, serverPaths, computeCurrentHash) {
|
|
10708
|
+
for (const entry of previousIndex) {
|
|
10709
|
+
if (serverPaths.has(entry.path) || isInternalPath(entry.path)) continue;
|
|
10710
|
+
const absPath = path3.join(root, entry.path);
|
|
10711
|
+
if (!fs4.existsSync(absPath)) continue;
|
|
10712
|
+
try {
|
|
10713
|
+
if (computeCurrentHash(absPath, entry) !== entry.hash) {
|
|
10714
|
+
console.log(` Kept ${entry.path} (deleted on server, but modified locally)`);
|
|
10715
|
+
continue;
|
|
10716
|
+
}
|
|
10717
|
+
fs4.rmSync(absPath);
|
|
10718
|
+
removeEmptyDirs(path3.dirname(absPath), root);
|
|
10719
|
+
console.log(` Removed ${entry.path} (deleted on server)`);
|
|
10720
|
+
} catch (err) {
|
|
10721
|
+
console.error(` Failed to remove ${entry.path}: ${err instanceof Error ? err.message : err}`);
|
|
10722
|
+
}
|
|
10723
|
+
}
|
|
10724
|
+
}
|
|
10725
|
+
function entriesToDelete(root, index, relPath) {
|
|
10726
|
+
const prefix = `${relPath}/`;
|
|
10727
|
+
return index.filter(
|
|
10728
|
+
(e) => (e.path === relPath || e.path.startsWith(prefix)) && !fs4.existsSync(path3.join(root, e.path))
|
|
10729
|
+
);
|
|
10730
|
+
}
|
|
10602
10731
|
function detectModifiedFiles(root, index, getPath, computeCurrentHash, getStoredHash) {
|
|
10603
10732
|
const modified = [];
|
|
10604
10733
|
for (const entry of index) {
|
|
@@ -10694,7 +10823,7 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10694
10823
|
for (const key of Object.keys(result)) {
|
|
10695
10824
|
result[key] = result[key].filter((f) => !isInternalPath(f));
|
|
10696
10825
|
}
|
|
10697
|
-
const { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly } = result;
|
|
10826
|
+
const { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly } = result;
|
|
10698
10827
|
if (flags.json === "true") {
|
|
10699
10828
|
console.log(JSON.stringify(result));
|
|
10700
10829
|
return;
|
|
@@ -10702,7 +10831,7 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10702
10831
|
console.log(`${label} workspace: ${root}`);
|
|
10703
10832
|
console.log(`Domain: ${config2?.domain} | Accounting: ${config2?.accounting}`);
|
|
10704
10833
|
console.log("");
|
|
10705
|
-
const total = modifiedLocally.length + modifiedOnServer.length + conflict.length + newFiles.length + localOnly.length + serverOnly.length;
|
|
10834
|
+
const total = modifiedLocally.length + modifiedOnServer.length + conflict.length + newFiles.length + deletedLocally.length + localOnly.length + serverOnly.length;
|
|
10706
10835
|
if (total === 0) {
|
|
10707
10836
|
console.log("In sync with server.");
|
|
10708
10837
|
return;
|
|
@@ -10723,8 +10852,12 @@ function printRemoteStatus(label, root, config2, flags, result) {
|
|
|
10723
10852
|
console.log("New (untracked):");
|
|
10724
10853
|
for (const f of newFiles) console.log(` + ${f}`);
|
|
10725
10854
|
}
|
|
10855
|
+
if (deletedLocally.length > 0) {
|
|
10856
|
+
console.log("Deleted locally (push deletes them on the server):");
|
|
10857
|
+
for (const f of deletedLocally) console.log(` D ${f}`);
|
|
10858
|
+
}
|
|
10726
10859
|
if (localOnly.length > 0) {
|
|
10727
|
-
console.log("
|
|
10860
|
+
console.log("Deleted on server (pull removes them locally):");
|
|
10728
10861
|
for (const f of localOnly) console.log(` - ${f}`);
|
|
10729
10862
|
}
|
|
10730
10863
|
if (serverOnly.length > 0) {
|
|
@@ -10770,7 +10903,9 @@ async function pull(flags) {
|
|
|
10770
10903
|
const wikiService = await createService("wiki", { cwd: dir });
|
|
10771
10904
|
const langs = flags.langs ? flags.langs.split(",") : SYNC_LANGS;
|
|
10772
10905
|
console.log(`Pulling wiki to ${dir}...`);
|
|
10906
|
+
const previousIndex = readIndex(dir);
|
|
10773
10907
|
const index = [];
|
|
10908
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
10774
10909
|
for (const lang of langs) {
|
|
10775
10910
|
console.log(`Pulling pages for language: ${lang}`);
|
|
10776
10911
|
const pages = await wikiService.get("pages", {
|
|
@@ -10783,6 +10918,7 @@ async function pull(flags) {
|
|
|
10783
10918
|
if (!page.id_wiki_page || !page.name) continue;
|
|
10784
10919
|
const relPath = pageToRelPath({ ...page, lang });
|
|
10785
10920
|
const absPath = path4.join(dir, relPath);
|
|
10921
|
+
serverPaths.add(relPath);
|
|
10786
10922
|
try {
|
|
10787
10923
|
const content4 = await wikiService.get(
|
|
10788
10924
|
`pages/${page.id_wiki_page}/content`,
|
|
@@ -10817,6 +10953,7 @@ async function pull(flags) {
|
|
|
10817
10953
|
const lang = file2.lang || "cs";
|
|
10818
10954
|
const relPath = fileToRelPath({ ...file2, lang });
|
|
10819
10955
|
const absPath = path4.join(dir, relPath);
|
|
10956
|
+
serverPaths.add(relPath);
|
|
10820
10957
|
try {
|
|
10821
10958
|
const response = await wikiService.getRaw(`download/${file2.id_wiki_file}`);
|
|
10822
10959
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
@@ -10836,6 +10973,18 @@ async function pull(flags) {
|
|
|
10836
10973
|
}
|
|
10837
10974
|
}
|
|
10838
10975
|
console.log(` Pulled ${pulledFiles} files`);
|
|
10976
|
+
for (const entry of previousIndex) {
|
|
10977
|
+
if (entry.type === "page" && !langs.includes(entry.lang)) {
|
|
10978
|
+
index.push(entry);
|
|
10979
|
+
serverPaths.add(entry.path);
|
|
10980
|
+
}
|
|
10981
|
+
}
|
|
10982
|
+
removeVanishedFiles(
|
|
10983
|
+
dir,
|
|
10984
|
+
previousIndex,
|
|
10985
|
+
serverPaths,
|
|
10986
|
+
(absPath, entry) => entry.type === "page" ? computePageHash(absPath) : computeFileHash(absPath)
|
|
10987
|
+
);
|
|
10839
10988
|
writeConfig(dir, {
|
|
10840
10989
|
domain: conn.domain,
|
|
10841
10990
|
accounting: conn.tokens.accounting,
|
|
@@ -10874,8 +11023,12 @@ async function push(flags, files) {
|
|
|
10874
11023
|
for (const relPath of filesToPush) {
|
|
10875
11024
|
const absPath = path4.join(root, relPath);
|
|
10876
11025
|
if (!fs5.existsSync(absPath)) {
|
|
10877
|
-
const
|
|
10878
|
-
if (
|
|
11026
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
11027
|
+
if (entries.length === 0) {
|
|
11028
|
+
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11029
|
+
continue;
|
|
11030
|
+
}
|
|
11031
|
+
for (const entry2 of entries) {
|
|
10879
11032
|
try {
|
|
10880
11033
|
if (entry2.type === "page") {
|
|
10881
11034
|
await wikiService.delete(`pages/${entry2.id}`, { lang: entry2.lang });
|
|
@@ -10884,13 +11037,11 @@ async function push(flags, files) {
|
|
|
10884
11037
|
}
|
|
10885
11038
|
const idx = index.indexOf(entry2);
|
|
10886
11039
|
if (idx !== -1) index.splice(idx, 1);
|
|
10887
|
-
indexMap.delete(
|
|
10888
|
-
console.log(` Deleted: ${
|
|
11040
|
+
indexMap.delete(entry2.path);
|
|
11041
|
+
console.log(` Deleted: ${entry2.path}`);
|
|
10889
11042
|
} catch (err) {
|
|
10890
|
-
console.error(` Failed to delete ${
|
|
11043
|
+
console.error(` Failed to delete ${entry2.path}: ${err instanceof Error ? err.message : err}`);
|
|
10891
11044
|
}
|
|
10892
|
-
} else {
|
|
10893
|
-
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
10894
11045
|
}
|
|
10895
11046
|
continue;
|
|
10896
11047
|
}
|
|
@@ -11023,6 +11174,7 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11023
11174
|
const modifiedLocally = [];
|
|
11024
11175
|
const modifiedOnServer = [];
|
|
11025
11176
|
const conflict = [];
|
|
11177
|
+
const deletedLocally = [];
|
|
11026
11178
|
const localOnly = [];
|
|
11027
11179
|
const serverOnly = [];
|
|
11028
11180
|
for (const lang of langs) {
|
|
@@ -11040,7 +11192,11 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11040
11192
|
serverOnly.push(relPath);
|
|
11041
11193
|
} else {
|
|
11042
11194
|
const absPath = path4.join(root, relPath);
|
|
11043
|
-
|
|
11195
|
+
if (!fs5.existsSync(absPath)) {
|
|
11196
|
+
deletedLocally.push(relPath);
|
|
11197
|
+
continue;
|
|
11198
|
+
}
|
|
11199
|
+
const localChanged = computePageHash(absPath) !== localEntry.hash;
|
|
11044
11200
|
const serverChanged = page.date_created != null && localEntry.serverDate != null && page.date_created !== localEntry.serverDate;
|
|
11045
11201
|
if (localChanged && serverChanged) {
|
|
11046
11202
|
conflict.push(relPath);
|
|
@@ -11052,7 +11208,7 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11052
11208
|
}
|
|
11053
11209
|
}
|
|
11054
11210
|
for (const [relPath, entry] of localPages) {
|
|
11055
|
-
if (entry.lang === lang && !serverPagePaths.has(relPath)) {
|
|
11211
|
+
if (entry.lang === lang && !serverPagePaths.has(relPath) && fs5.existsSync(path4.join(root, relPath))) {
|
|
11056
11212
|
localOnly.push(relPath);
|
|
11057
11213
|
}
|
|
11058
11214
|
}
|
|
@@ -11071,7 +11227,11 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11071
11227
|
serverOnly.push(relPath);
|
|
11072
11228
|
} else {
|
|
11073
11229
|
const absPath = path4.join(root, relPath);
|
|
11074
|
-
|
|
11230
|
+
if (!fs5.existsSync(absPath)) {
|
|
11231
|
+
deletedLocally.push(relPath);
|
|
11232
|
+
continue;
|
|
11233
|
+
}
|
|
11234
|
+
const localChanged = computeFileHash(absPath) !== localEntry.hash;
|
|
11075
11235
|
const serverChanged = file2.date_created != null && localEntry.serverDate != null && file2.date_created !== localEntry.serverDate;
|
|
11076
11236
|
if (localChanged && serverChanged) {
|
|
11077
11237
|
conflict.push(relPath);
|
|
@@ -11083,12 +11243,12 @@ async function statusRemote(root, config2, index, flags) {
|
|
|
11083
11243
|
}
|
|
11084
11244
|
}
|
|
11085
11245
|
for (const [relPath] of localFiles) {
|
|
11086
|
-
if (!serverFilePaths.has(relPath)) {
|
|
11246
|
+
if (!serverFilePaths.has(relPath) && fs5.existsSync(path4.join(root, relPath))) {
|
|
11087
11247
|
localOnly.push(relPath);
|
|
11088
11248
|
}
|
|
11089
11249
|
}
|
|
11090
11250
|
const newFiles = detectNewFiles2(root, index);
|
|
11091
|
-
printRemoteStatus("Wiki", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
11251
|
+
printRemoteStatus("Wiki", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
11092
11252
|
}
|
|
11093
11253
|
function watch3(flags) {
|
|
11094
11254
|
return watch2("wiki", flags, push);
|
|
@@ -11126,11 +11286,11 @@ async function readContent(flags) {
|
|
|
11126
11286
|
return flags.content;
|
|
11127
11287
|
}
|
|
11128
11288
|
if (!process.stdin.isTTY) {
|
|
11129
|
-
return new Promise((
|
|
11289
|
+
return new Promise((resolve8) => {
|
|
11130
11290
|
let data = "";
|
|
11131
11291
|
process.stdin.setEncoding("utf-8");
|
|
11132
11292
|
process.stdin.on("data", (chunk) => data += chunk);
|
|
11133
|
-
process.stdin.on("end", () =>
|
|
11293
|
+
process.stdin.on("end", () => resolve8(data));
|
|
11134
11294
|
});
|
|
11135
11295
|
}
|
|
11136
11296
|
console.error("No content provided. Use --file, --content, or pipe to stdin.");
|
|
@@ -11337,12 +11497,15 @@ async function pull2(flags) {
|
|
|
11337
11497
|
if (allThreads.length > threads.length) {
|
|
11338
11498
|
console.log(` Skipped ${allThreads.length - threads.length} shared thread(s) from another accounting`);
|
|
11339
11499
|
}
|
|
11500
|
+
const previousIndex = readIndex(dir);
|
|
11340
11501
|
const index = [];
|
|
11502
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
11341
11503
|
let pulled = 0;
|
|
11342
11504
|
for (const thread of threads) {
|
|
11343
11505
|
if (!thread.id_thread || !thread.type || !thread.description) continue;
|
|
11344
11506
|
const relPath = threadToRelPath(thread);
|
|
11345
11507
|
const absPath = path5.join(dir, relPath);
|
|
11508
|
+
serverPaths.add(relPath);
|
|
11346
11509
|
try {
|
|
11347
11510
|
const content4 = await etlService.get(
|
|
11348
11511
|
`threads/${thread.id_thread}/content`,
|
|
@@ -11396,6 +11559,12 @@ async function pull2(flags) {
|
|
|
11396
11559
|
if (!flags["no-context"]) {
|
|
11397
11560
|
await pullContext(dir, etlService, defService);
|
|
11398
11561
|
}
|
|
11562
|
+
removeVanishedFiles(
|
|
11563
|
+
dir,
|
|
11564
|
+
previousIndex,
|
|
11565
|
+
serverPaths,
|
|
11566
|
+
(absPath) => computeHash(fs7.readFileSync(absPath, "utf-8"))
|
|
11567
|
+
);
|
|
11399
11568
|
writeConfig(dir, {
|
|
11400
11569
|
domain: conn.domain,
|
|
11401
11570
|
accounting: conn.tokens.accounting,
|
|
@@ -11449,19 +11618,21 @@ async function push2(flags, files) {
|
|
|
11449
11618
|
for (const relPath of filesToPush) {
|
|
11450
11619
|
const absPath = path5.join(root, relPath);
|
|
11451
11620
|
if (!fs7.existsSync(absPath)) {
|
|
11452
|
-
const
|
|
11453
|
-
if (
|
|
11621
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
11622
|
+
if (entries.length === 0) {
|
|
11623
|
+
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11624
|
+
continue;
|
|
11625
|
+
}
|
|
11626
|
+
for (const entry2 of entries) {
|
|
11454
11627
|
try {
|
|
11455
11628
|
await etlService.delete(`threads/${entry2.id_thread}`);
|
|
11456
11629
|
const idx = index.indexOf(entry2);
|
|
11457
11630
|
if (idx !== -1) index.splice(idx, 1);
|
|
11458
|
-
indexMap.delete(
|
|
11459
|
-
console.log(` Deleted: ${
|
|
11631
|
+
indexMap.delete(entry2.path);
|
|
11632
|
+
console.log(` Deleted: ${entry2.path}`);
|
|
11460
11633
|
} catch (err) {
|
|
11461
|
-
console.error(` Failed to delete ${
|
|
11634
|
+
console.error(` Failed to delete ${entry2.path}: ${err instanceof Error ? err.message : err}`);
|
|
11462
11635
|
}
|
|
11463
|
-
} else {
|
|
11464
|
-
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11465
11636
|
}
|
|
11466
11637
|
continue;
|
|
11467
11638
|
}
|
|
@@ -11599,6 +11770,7 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11599
11770
|
const modifiedLocally = [];
|
|
11600
11771
|
const modifiedOnServer = [];
|
|
11601
11772
|
const conflict = [];
|
|
11773
|
+
const deletedLocally = [];
|
|
11602
11774
|
const localOnly = [];
|
|
11603
11775
|
const serverOnly = [];
|
|
11604
11776
|
const serverPaths = /* @__PURE__ */ new Set();
|
|
@@ -11611,7 +11783,11 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11611
11783
|
serverOnly.push(relPath);
|
|
11612
11784
|
} else {
|
|
11613
11785
|
const absPath = path5.join(root, relPath);
|
|
11614
|
-
|
|
11786
|
+
if (!fs7.existsSync(absPath)) {
|
|
11787
|
+
deletedLocally.push(relPath);
|
|
11788
|
+
continue;
|
|
11789
|
+
}
|
|
11790
|
+
const localChanged = computeHash(fs7.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
11615
11791
|
const serverChanged = thread.date_created != null && localEntry.serverDate != null && thread.date_created !== localEntry.serverDate;
|
|
11616
11792
|
if (localChanged && serverChanged) {
|
|
11617
11793
|
conflict.push(relPath);
|
|
@@ -11623,12 +11799,12 @@ async function statusRemote2(root, config2, index, flags) {
|
|
|
11623
11799
|
}
|
|
11624
11800
|
}
|
|
11625
11801
|
for (const entry of index) {
|
|
11626
|
-
if (!serverPaths.has(entry.path)) {
|
|
11802
|
+
if (!serverPaths.has(entry.path) && fs7.existsSync(path5.join(root, entry.path))) {
|
|
11627
11803
|
localOnly.push(entry.path);
|
|
11628
11804
|
}
|
|
11629
11805
|
}
|
|
11630
11806
|
const newFiles = detectNewFiles3(root, index);
|
|
11631
|
-
printRemoteStatus("ETL", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
11807
|
+
printRemoteStatus("ETL", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
11632
11808
|
}
|
|
11633
11809
|
function watch4(flags) {
|
|
11634
11810
|
return watch2("etl", flags, push2);
|
|
@@ -11664,8 +11840,14 @@ async function exec2(id, flags) {
|
|
|
11664
11840
|
csv_delimiter: " ",
|
|
11665
11841
|
csv_header: "1",
|
|
11666
11842
|
csv_header_json: "1",
|
|
11667
|
-
csv_null_value: "NULL"
|
|
11843
|
+
csv_null_value: "NULL",
|
|
11844
|
+
// makes the server flush the response headers before the query finishes, so X-Spid
|
|
11845
|
+
// is readable while it still runs (IIS holds headers back until the first body flush)
|
|
11846
|
+
flush_headers: "1"
|
|
11668
11847
|
}, { headers: { accept: "text/csv" } });
|
|
11848
|
+
const spid = response.headers.get("x-spid");
|
|
11849
|
+
if (spid) fs8.writeSync(2, `${SPID_MARKER} ${spid}
|
|
11850
|
+
`);
|
|
11669
11851
|
if (!response.ok) {
|
|
11670
11852
|
const text3 = await response.text();
|
|
11671
11853
|
console.error(text3);
|
|
@@ -11678,6 +11860,11 @@ async function exec2(id, flags) {
|
|
|
11678
11860
|
process.stdout.write(result || "");
|
|
11679
11861
|
}
|
|
11680
11862
|
}
|
|
11863
|
+
async function abort2(spid, flags) {
|
|
11864
|
+
const service = await createService("etl", { cwd: flags.dir || "." });
|
|
11865
|
+
const result = await service.get(`abort/${spid}`);
|
|
11866
|
+
output(result, flags);
|
|
11867
|
+
}
|
|
11681
11868
|
async function search2(query, flags) {
|
|
11682
11869
|
const service = await createService("etl");
|
|
11683
11870
|
const results = await service.get("search", { ...getListParams(flags, DEFAULT_FIELDS), q: query });
|
|
@@ -11695,11 +11882,11 @@ async function params(id, flags) {
|
|
|
11695
11882
|
if (flags.save) {
|
|
11696
11883
|
const data = JSON.parse(fs8.readFileSync(flags.save, "utf-8"));
|
|
11697
11884
|
data.id_thread ??= parseInt(id);
|
|
11698
|
-
const result = await service.post(`threads/${id}/parameters`, data);
|
|
11885
|
+
const result = await service.post(`threads/${id}/parameters`, data).catch((err) => fail(err, "Parameter not saved"));
|
|
11699
11886
|
await refreshYaml();
|
|
11700
11887
|
output(result, flags);
|
|
11701
11888
|
} else if (flags.delete) {
|
|
11702
|
-
await service.delete(`threads/${id}/parameters/${flags.delete}`);
|
|
11889
|
+
await service.delete(`threads/${id}/parameters/${flags.delete}`).catch((err) => fail(err, "Parameter not deleted"));
|
|
11703
11890
|
await refreshYaml();
|
|
11704
11891
|
console.log(`Parameter ${flags.delete} deleted.`);
|
|
11705
11892
|
} else {
|
|
@@ -11731,6 +11918,12 @@ async function etl(args) {
|
|
|
11731
11918
|
process.exit(1);
|
|
11732
11919
|
}
|
|
11733
11920
|
return exec2(rest[0], flags);
|
|
11921
|
+
case "abort":
|
|
11922
|
+
if (!rest[0]) {
|
|
11923
|
+
console.error("Usage: rpbi etl abort <spid>");
|
|
11924
|
+
process.exit(1);
|
|
11925
|
+
}
|
|
11926
|
+
return abort2(rest[0], flags);
|
|
11734
11927
|
case "search":
|
|
11735
11928
|
if (!rest[0]) {
|
|
11736
11929
|
console.error("Usage: rpbi etl search <query>");
|
|
@@ -11754,7 +11947,7 @@ async function etl(args) {
|
|
|
11754
11947
|
case "watch":
|
|
11755
11948
|
return watch4(flags);
|
|
11756
11949
|
default:
|
|
11757
|
-
console.log("Usage: rpbi etl <list|get|content|exec|search|params|pull|push|context|status|watch> [options]");
|
|
11950
|
+
console.log("Usage: rpbi etl <list|get|content|exec|abort|search|params|pull|push|context|status|watch> [options]");
|
|
11758
11951
|
break;
|
|
11759
11952
|
}
|
|
11760
11953
|
}
|
|
@@ -11822,12 +12015,15 @@ async function pull3(flags) {
|
|
|
11822
12015
|
order: [["type", "asc"], ["description", "asc"]]
|
|
11823
12016
|
}) || [];
|
|
11824
12017
|
console.log(`Found ${threads.length} threads`);
|
|
12018
|
+
const previousIndex = readIndex(dir);
|
|
11825
12019
|
const index = [];
|
|
12020
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
11826
12021
|
let pulled = 0;
|
|
11827
12022
|
for (const thread of threads) {
|
|
11828
12023
|
if (!thread.id_thread || !thread.type || !thread.description) continue;
|
|
11829
12024
|
const relPath = threadToRelPath2(thread);
|
|
11830
12025
|
const absPath = path6.join(dir, relPath);
|
|
12026
|
+
serverPaths.add(relPath);
|
|
11831
12027
|
try {
|
|
11832
12028
|
const content4 = await service.get(
|
|
11833
12029
|
`threads/${thread.id_thread}/content`,
|
|
@@ -11851,6 +12047,7 @@ async function pull3(flags) {
|
|
|
11851
12047
|
}
|
|
11852
12048
|
if (thread.has_doc) {
|
|
11853
12049
|
const docPath = threadToDocPath(thread);
|
|
12050
|
+
serverPaths.add(docPath);
|
|
11854
12051
|
try {
|
|
11855
12052
|
const doc2 = await service.get(
|
|
11856
12053
|
`threads/${thread.id_thread}/doc`,
|
|
@@ -11874,6 +12071,12 @@ async function pull3(flags) {
|
|
|
11874
12071
|
}
|
|
11875
12072
|
}
|
|
11876
12073
|
}
|
|
12074
|
+
removeVanishedFiles(
|
|
12075
|
+
dir,
|
|
12076
|
+
previousIndex,
|
|
12077
|
+
serverPaths,
|
|
12078
|
+
(absPath) => computeHash(fs9.readFileSync(absPath, "utf-8"))
|
|
12079
|
+
);
|
|
11877
12080
|
writeConfig(dir, {
|
|
11878
12081
|
domain: conn.domain,
|
|
11879
12082
|
accounting: conn.tokens.accounting,
|
|
@@ -11913,25 +12116,28 @@ async function push3(flags, files) {
|
|
|
11913
12116
|
const absPath = path6.join(root, relPath);
|
|
11914
12117
|
const entry = indexMap.get(relPath);
|
|
11915
12118
|
if (!fs9.existsSync(absPath)) {
|
|
11916
|
-
|
|
12119
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
12120
|
+
if (entries.length === 0) {
|
|
11917
12121
|
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
11918
12122
|
continue;
|
|
11919
12123
|
}
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
12124
|
+
for (const gone of entries) {
|
|
12125
|
+
try {
|
|
12126
|
+
if (gone.kind === "doc") {
|
|
12127
|
+
await service.patch(`threads/${gone.id_thread}/doc`, "", { accounting: entryAccounting(gone) });
|
|
12128
|
+
console.log(` Cleared doc: ${gone.path}`);
|
|
12129
|
+
} else {
|
|
12130
|
+
const current = await service.get(`threads/${gone.id_thread}`, { fields: ["idz"] });
|
|
12131
|
+
if (!current?.idz) throw new Error("Thread not found on server");
|
|
12132
|
+
await service.delete(`threads/${current.idz}`, { accounting: entryAccounting(gone) });
|
|
12133
|
+
console.log(` Deleted: ${gone.path}`);
|
|
12134
|
+
}
|
|
12135
|
+
const idx = index.indexOf(gone);
|
|
12136
|
+
if (idx !== -1) index.splice(idx, 1);
|
|
12137
|
+
indexMap.delete(gone.path);
|
|
12138
|
+
} catch (err) {
|
|
12139
|
+
console.error(` Failed to delete ${gone.path}: ${err instanceof Error ? err.message : err}`);
|
|
12140
|
+
}
|
|
11935
12141
|
}
|
|
11936
12142
|
continue;
|
|
11937
12143
|
}
|
|
@@ -12048,16 +12254,21 @@ async function statusRemote3(root, config2, index, flags) {
|
|
|
12048
12254
|
const modifiedLocally = [];
|
|
12049
12255
|
const modifiedOnServer = [];
|
|
12050
12256
|
const conflict = [];
|
|
12257
|
+
const deletedLocally = [];
|
|
12051
12258
|
const localOnly = [];
|
|
12052
12259
|
const serverOnly = [];
|
|
12053
|
-
const compareEntry = (relPath, serverDate,
|
|
12260
|
+
const compareEntry = (relPath, serverDate, onServer) => {
|
|
12054
12261
|
const localEntry = indexMap.get(relPath);
|
|
12055
12262
|
if (!localEntry) {
|
|
12056
|
-
if (
|
|
12263
|
+
if (onServer) serverOnly.push(relPath);
|
|
12057
12264
|
return;
|
|
12058
12265
|
}
|
|
12059
12266
|
const absPath = path6.join(root, relPath);
|
|
12060
|
-
|
|
12267
|
+
if (!fs9.existsSync(absPath)) {
|
|
12268
|
+
if (onServer) deletedLocally.push(relPath);
|
|
12269
|
+
return;
|
|
12270
|
+
}
|
|
12271
|
+
const localChanged = computeHash(fs9.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
12061
12272
|
const serverChanged = serverDate != null && localEntry.serverDate != null && serverDate !== localEntry.serverDate;
|
|
12062
12273
|
if (localChanged && serverChanged) {
|
|
12063
12274
|
conflict.push(relPath);
|
|
@@ -12083,12 +12294,12 @@ async function statusRemote3(root, config2, index, flags) {
|
|
|
12083
12294
|
}
|
|
12084
12295
|
}
|
|
12085
12296
|
for (const entry of index) {
|
|
12086
|
-
if (!serverPaths.has(entry.path)) {
|
|
12297
|
+
if (!serverPaths.has(entry.path) && fs9.existsSync(path6.join(root, entry.path))) {
|
|
12087
12298
|
localOnly.push(entry.path);
|
|
12088
12299
|
}
|
|
12089
12300
|
}
|
|
12090
12301
|
const newFiles = detectNewFiles4(root, index);
|
|
12091
|
-
printRemoteStatus("Deployment", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
12302
|
+
printRemoteStatus("Deployment", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
12092
12303
|
}
|
|
12093
12304
|
function watch5(flags) {
|
|
12094
12305
|
return watch2("deployment", flags, push3);
|
|
@@ -12282,7 +12493,9 @@ async function pull4(flags) {
|
|
|
12282
12493
|
const projects2 = await fetchProjects(service);
|
|
12283
12494
|
const projectNames = buildProjectMap(projects2);
|
|
12284
12495
|
console.log(`Found ${projects2.length} projects`);
|
|
12496
|
+
const previousIndex = readIndex(dir);
|
|
12285
12497
|
const index = [];
|
|
12498
|
+
const serverPaths = /* @__PURE__ */ new Set();
|
|
12286
12499
|
const resources2 = await service.get("resources", {
|
|
12287
12500
|
fields: RESOURCE_FIELDS,
|
|
12288
12501
|
order: [["name", "asc"]]
|
|
@@ -12297,6 +12510,7 @@ async function pull4(flags) {
|
|
|
12297
12510
|
continue;
|
|
12298
12511
|
}
|
|
12299
12512
|
const relPath = resourceToRelPath(projectName, resource);
|
|
12513
|
+
serverPaths.add(relPath);
|
|
12300
12514
|
try {
|
|
12301
12515
|
const content4 = await service.get(
|
|
12302
12516
|
`resourceContent/${resource.id_custom_resource}`,
|
|
@@ -12328,6 +12542,7 @@ async function pull4(flags) {
|
|
|
12328
12542
|
const projectName = query.id_custom_page ? projectNames.get(query.id_custom_page) : void 0;
|
|
12329
12543
|
if (!projectName) continue;
|
|
12330
12544
|
const relPath = queryToRelPath(projectName, query);
|
|
12545
|
+
serverPaths.add(relPath);
|
|
12331
12546
|
try {
|
|
12332
12547
|
const content4 = await service.get(
|
|
12333
12548
|
`queryContent/${query.id_thread}`,
|
|
@@ -12354,6 +12569,12 @@ async function pull4(flags) {
|
|
|
12354
12569
|
if (!project.id_custom_page || !project.name) continue;
|
|
12355
12570
|
await refreshProjectMeta(service, dir, project, queries2.filter((q) => q.id_custom_page === project.id_custom_page));
|
|
12356
12571
|
}
|
|
12572
|
+
removeVanishedFiles(
|
|
12573
|
+
dir,
|
|
12574
|
+
previousIndex,
|
|
12575
|
+
serverPaths,
|
|
12576
|
+
(absPath) => computeHash(fs11.readFileSync(absPath, "utf-8"))
|
|
12577
|
+
);
|
|
12357
12578
|
writeConfig(dir, {
|
|
12358
12579
|
domain: conn.domain,
|
|
12359
12580
|
accounting: conn.tokens.accounting,
|
|
@@ -12406,18 +12627,21 @@ async function push4(flags, files) {
|
|
|
12406
12627
|
const absPath = path7.join(root, relPath);
|
|
12407
12628
|
const entry = indexMap.get(relPath);
|
|
12408
12629
|
if (!fs11.existsSync(absPath)) {
|
|
12409
|
-
|
|
12630
|
+
const entries = entriesToDelete(root, index, relPath);
|
|
12631
|
+
if (entries.length === 0) {
|
|
12410
12632
|
console.log(` Skipping ${relPath} (file not found, not in index)`);
|
|
12411
12633
|
continue;
|
|
12412
12634
|
}
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12635
|
+
for (const gone of entries) {
|
|
12636
|
+
try {
|
|
12637
|
+
await service.delete(gone.kind === "query" ? `queries/${gone.id}` : `resources/${gone.id}`);
|
|
12638
|
+
const idx = index.indexOf(gone);
|
|
12639
|
+
if (idx !== -1) index.splice(idx, 1);
|
|
12640
|
+
indexMap.delete(gone.path);
|
|
12641
|
+
console.log(` Deleted: ${gone.path}`);
|
|
12642
|
+
} catch (err) {
|
|
12643
|
+
console.error(` Failed to delete ${gone.path}: ${err instanceof Error ? err.message : err}`);
|
|
12644
|
+
}
|
|
12421
12645
|
}
|
|
12422
12646
|
continue;
|
|
12423
12647
|
}
|
|
@@ -12532,6 +12756,7 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12532
12756
|
const modifiedLocally = [];
|
|
12533
12757
|
const modifiedOnServer = [];
|
|
12534
12758
|
const conflict = [];
|
|
12759
|
+
const deletedLocally = [];
|
|
12535
12760
|
const localOnly = [];
|
|
12536
12761
|
const serverOnly = [];
|
|
12537
12762
|
const compareEntry = (relPath, serverDate) => {
|
|
@@ -12541,7 +12766,11 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12541
12766
|
return;
|
|
12542
12767
|
}
|
|
12543
12768
|
const absPath = path7.join(root, relPath);
|
|
12544
|
-
|
|
12769
|
+
if (!fs11.existsSync(absPath)) {
|
|
12770
|
+
deletedLocally.push(relPath);
|
|
12771
|
+
return;
|
|
12772
|
+
}
|
|
12773
|
+
const localChanged = computeHash(fs11.readFileSync(absPath, "utf-8")) !== localEntry.hash;
|
|
12545
12774
|
const serverChanged = serverDate != null && localEntry.serverDate != null && serverDate !== localEntry.serverDate;
|
|
12546
12775
|
if (localChanged && serverChanged) {
|
|
12547
12776
|
conflict.push(relPath);
|
|
@@ -12571,12 +12800,12 @@ async function statusRemote4(root, config2, index, flags) {
|
|
|
12571
12800
|
compareEntry(relPath, query.date_created);
|
|
12572
12801
|
}
|
|
12573
12802
|
for (const entry of index) {
|
|
12574
|
-
if (!serverPaths.has(entry.path)) {
|
|
12803
|
+
if (!serverPaths.has(entry.path) && fs11.existsSync(path7.join(root, entry.path))) {
|
|
12575
12804
|
localOnly.push(entry.path);
|
|
12576
12805
|
}
|
|
12577
12806
|
}
|
|
12578
12807
|
const newFiles = detectNewFiles5(root, index);
|
|
12579
|
-
printRemoteStatus("Extensions", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, localOnly, serverOnly });
|
|
12808
|
+
printRemoteStatus("Extensions", root, config2, flags, { modifiedLocally, modifiedOnServer, conflict, new: newFiles, deletedLocally, localOnly, serverOnly });
|
|
12580
12809
|
}
|
|
12581
12810
|
function watch6(flags) {
|
|
12582
12811
|
return watch2("ext", flags, push4);
|
|
@@ -12631,11 +12860,11 @@ async function params2(id, flags) {
|
|
|
12631
12860
|
if (flags.save) {
|
|
12632
12861
|
const data = JSON.parse(fs12.readFileSync(flags.save, "utf-8"));
|
|
12633
12862
|
data.id_thread ??= parseInt(id);
|
|
12634
|
-
const result = await service.post("parameters", data);
|
|
12863
|
+
const result = await service.post("parameters", data).catch((err) => fail(err, "Parameter not saved"));
|
|
12635
12864
|
await refreshMeta();
|
|
12636
12865
|
output(result, flags);
|
|
12637
12866
|
} else if (flags.delete) {
|
|
12638
|
-
await service.delete(`parameters/${flags.delete}`);
|
|
12867
|
+
await service.delete(`parameters/${flags.delete}`).catch((err) => fail(err, "Parameter not deleted"));
|
|
12639
12868
|
await refreshMeta();
|
|
12640
12869
|
console.log(`Parameter ${flags.delete} deleted.`);
|
|
12641
12870
|
} else {
|
|
@@ -12703,8 +12932,14 @@ async function exec4(id, flags) {
|
|
|
12703
12932
|
csv_delimiter: " ",
|
|
12704
12933
|
csv_header: "1",
|
|
12705
12934
|
csv_header_json: "1",
|
|
12706
|
-
csv_null_value: "NULL"
|
|
12935
|
+
csv_null_value: "NULL",
|
|
12936
|
+
// makes the server flush the response headers before the query finishes, so X-Spid
|
|
12937
|
+
// is readable while it still runs (IIS holds headers back until the first body flush)
|
|
12938
|
+
flush_headers: "1"
|
|
12707
12939
|
}, { headers: { accept: "text/csv" } });
|
|
12940
|
+
const spid = response.headers.get("x-spid");
|
|
12941
|
+
if (spid) fs12.writeSync(2, `${SPID_MARKER} ${spid}
|
|
12942
|
+
`);
|
|
12708
12943
|
if (!response.ok) {
|
|
12709
12944
|
const text3 = await response.text();
|
|
12710
12945
|
console.error(text3);
|
|
@@ -12717,6 +12952,11 @@ async function exec4(id, flags) {
|
|
|
12717
12952
|
process.stdout.write(result || "");
|
|
12718
12953
|
}
|
|
12719
12954
|
}
|
|
12955
|
+
async function abort3(spid, flags) {
|
|
12956
|
+
const service = await createService("extensions", { cwd: flags.dir || "." });
|
|
12957
|
+
const result = await service.get(`abort/${spid}`);
|
|
12958
|
+
output(result, flags);
|
|
12959
|
+
}
|
|
12720
12960
|
async function ext(args) {
|
|
12721
12961
|
const { positional, flags } = parseArgs(args);
|
|
12722
12962
|
const [subcommand, ...rest] = positional;
|
|
@@ -12739,6 +12979,12 @@ async function ext(args) {
|
|
|
12739
12979
|
process.exit(1);
|
|
12740
12980
|
}
|
|
12741
12981
|
return exec4(rest[0], flags);
|
|
12982
|
+
case "abort":
|
|
12983
|
+
if (!rest[0]) {
|
|
12984
|
+
console.error("Usage: rpbi ext abort <spid>");
|
|
12985
|
+
process.exit(1);
|
|
12986
|
+
}
|
|
12987
|
+
return abort3(rest[0], flags);
|
|
12742
12988
|
case "params":
|
|
12743
12989
|
if (!rest[0]) {
|
|
12744
12990
|
console.error("Usage: rpbi ext params <query_id> [--save <json file>] [--delete <idz>]");
|
|
@@ -12756,7 +13002,7 @@ async function ext(args) {
|
|
|
12756
13002
|
case "watch":
|
|
12757
13003
|
return watch6(flags);
|
|
12758
13004
|
default:
|
|
12759
|
-
console.log("Usage: rpbi ext <projects|resources|queries|content|exec|params|deps|pull|push|status|watch> [options]");
|
|
13005
|
+
console.log("Usage: rpbi ext <projects|resources|queries|content|exec|abort|params|deps|pull|push|status|watch> [options]");
|
|
12760
13006
|
break;
|
|
12761
13007
|
}
|
|
12762
13008
|
}
|
|
@@ -13473,15 +13719,15 @@ var makeIssue = (params3) => {
|
|
|
13473
13719
|
message: issueData.message
|
|
13474
13720
|
};
|
|
13475
13721
|
}
|
|
13476
|
-
let
|
|
13722
|
+
let errorMessage2 = "";
|
|
13477
13723
|
const maps = errorMaps.filter((m) => !!m).slice().reverse();
|
|
13478
13724
|
for (const map2 of maps) {
|
|
13479
|
-
|
|
13725
|
+
errorMessage2 = map2(fullIssue, { data, defaultError: errorMessage2 }).message;
|
|
13480
13726
|
}
|
|
13481
13727
|
return {
|
|
13482
13728
|
...issueData,
|
|
13483
13729
|
path: fullPath,
|
|
13484
|
-
message:
|
|
13730
|
+
message: errorMessage2
|
|
13485
13731
|
};
|
|
13486
13732
|
};
|
|
13487
13733
|
function addIssueToContext(ctx, issueData) {
|
|
@@ -17366,7 +17612,7 @@ __export(util_exports, {
|
|
|
17366
17612
|
getParsedType: () => getParsedType2,
|
|
17367
17613
|
getSizableOrigin: () => getSizableOrigin,
|
|
17368
17614
|
hexToUint8Array: () => hexToUint8Array,
|
|
17369
|
-
isObject: () =>
|
|
17615
|
+
isObject: () => isObject2,
|
|
17370
17616
|
isPlainObject: () => isPlainObject,
|
|
17371
17617
|
issue: () => issue,
|
|
17372
17618
|
joinValues: () => joinValues,
|
|
@@ -17536,7 +17782,7 @@ function slugify(input) {
|
|
|
17536
17782
|
}
|
|
17537
17783
|
var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
|
|
17538
17784
|
};
|
|
17539
|
-
function
|
|
17785
|
+
function isObject2(data) {
|
|
17540
17786
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
17541
17787
|
}
|
|
17542
17788
|
var allowsEval = cached(() => {
|
|
@@ -17552,7 +17798,7 @@ var allowsEval = cached(() => {
|
|
|
17552
17798
|
}
|
|
17553
17799
|
});
|
|
17554
17800
|
function isPlainObject(o) {
|
|
17555
|
-
if (
|
|
17801
|
+
if (isObject2(o) === false)
|
|
17556
17802
|
return false;
|
|
17557
17803
|
const ctor = o.constructor;
|
|
17558
17804
|
if (ctor === void 0)
|
|
@@ -17560,7 +17806,7 @@ function isPlainObject(o) {
|
|
|
17560
17806
|
if (typeof ctor !== "function")
|
|
17561
17807
|
return true;
|
|
17562
17808
|
const prot = ctor.prototype;
|
|
17563
|
-
if (
|
|
17809
|
+
if (isObject2(prot) === false)
|
|
17564
17810
|
return false;
|
|
17565
17811
|
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
|
17566
17812
|
return false;
|
|
@@ -19718,13 +19964,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def2) => {
|
|
|
19718
19964
|
}
|
|
19719
19965
|
return propValues;
|
|
19720
19966
|
});
|
|
19721
|
-
const
|
|
19967
|
+
const isObject3 = isObject2;
|
|
19722
19968
|
const catchall = def2.catchall;
|
|
19723
19969
|
let value;
|
|
19724
19970
|
inst._zod.parse = (payload, ctx) => {
|
|
19725
19971
|
value ?? (value = _normalized.value);
|
|
19726
19972
|
const input = payload.value;
|
|
19727
|
-
if (!
|
|
19973
|
+
if (!isObject3(input)) {
|
|
19728
19974
|
payload.issues.push({
|
|
19729
19975
|
expected: "object",
|
|
19730
19976
|
code: "invalid_type",
|
|
@@ -19822,7 +20068,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
|
|
|
19822
20068
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
19823
20069
|
};
|
|
19824
20070
|
let fastpass;
|
|
19825
|
-
const
|
|
20071
|
+
const isObject3 = isObject2;
|
|
19826
20072
|
const jit = !globalConfig.jitless;
|
|
19827
20073
|
const allowsEval2 = allowsEval;
|
|
19828
20074
|
const fastEnabled = jit && allowsEval2.value;
|
|
@@ -19831,7 +20077,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
|
|
|
19831
20077
|
inst._zod.parse = (payload, ctx) => {
|
|
19832
20078
|
value ?? (value = _normalized.value);
|
|
19833
20079
|
const input = payload.value;
|
|
19834
|
-
if (!
|
|
20080
|
+
if (!isObject3(input)) {
|
|
19835
20081
|
payload.issues.push({
|
|
19836
20082
|
expected: "object",
|
|
19837
20083
|
code: "invalid_type",
|
|
@@ -20009,7 +20255,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
20009
20255
|
});
|
|
20010
20256
|
inst._zod.parse = (payload, ctx) => {
|
|
20011
20257
|
const input = payload.value;
|
|
20012
|
-
if (!
|
|
20258
|
+
if (!isObject2(input)) {
|
|
20013
20259
|
payload.issues.push({
|
|
20014
20260
|
code: "invalid_type",
|
|
20015
20261
|
expected: "object",
|
|
@@ -32513,19 +32759,19 @@ var getRefs = (options) => {
|
|
|
32513
32759
|
};
|
|
32514
32760
|
|
|
32515
32761
|
// ../../.yarn/__virtual__/zod-to-json-schema-virtual-00ec010bf6/0/cache/zod-to-json-schema-npm-3.25.1-850d9216b4-711b30e34d.zip/node_modules/zod-to-json-schema/dist/esm/errorMessages.js
|
|
32516
|
-
function addErrorMessage(res, key,
|
|
32762
|
+
function addErrorMessage(res, key, errorMessage2, refs) {
|
|
32517
32763
|
if (!refs?.errorMessages)
|
|
32518
32764
|
return;
|
|
32519
|
-
if (
|
|
32765
|
+
if (errorMessage2) {
|
|
32520
32766
|
res.errorMessage = {
|
|
32521
32767
|
...res.errorMessage,
|
|
32522
|
-
[key]:
|
|
32768
|
+
[key]: errorMessage2
|
|
32523
32769
|
};
|
|
32524
32770
|
}
|
|
32525
32771
|
}
|
|
32526
|
-
function setResponseValueAndErrors(res, key, value,
|
|
32772
|
+
function setResponseValueAndErrors(res, key, value, errorMessage2, refs) {
|
|
32527
32773
|
res[key] = value;
|
|
32528
|
-
addErrorMessage(res, key,
|
|
32774
|
+
addErrorMessage(res, key, errorMessage2, refs);
|
|
32529
32775
|
}
|
|
32530
32776
|
|
|
32531
32777
|
// ../../.yarn/__virtual__/zod-to-json-schema-virtual-00ec010bf6/0/cache/zod-to-json-schema-npm-3.25.1-850d9216b4-711b30e34d.zip/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
|
|
@@ -33836,8 +34082,8 @@ var Protocol = class {
|
|
|
33836
34082
|
if (queuedMessage.type === "response") {
|
|
33837
34083
|
resolver(message);
|
|
33838
34084
|
} else {
|
|
33839
|
-
const
|
|
33840
|
-
const error48 = new McpError(
|
|
34085
|
+
const errorMessage2 = message;
|
|
34086
|
+
const error48 = new McpError(errorMessage2.error.code, errorMessage2.error.message, errorMessage2.error.data);
|
|
33841
34087
|
resolver(error48);
|
|
33842
34088
|
}
|
|
33843
34089
|
} else {
|
|
@@ -34277,7 +34523,7 @@ var Protocol = class {
|
|
|
34277
34523
|
return;
|
|
34278
34524
|
}
|
|
34279
34525
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
34280
|
-
await new Promise((
|
|
34526
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
34281
34527
|
options?.signal?.throwIfAborted();
|
|
34282
34528
|
}
|
|
34283
34529
|
} catch (error48) {
|
|
@@ -34294,7 +34540,7 @@ var Protocol = class {
|
|
|
34294
34540
|
*/
|
|
34295
34541
|
request(request, resultSchema, options) {
|
|
34296
34542
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
34297
|
-
return new Promise((
|
|
34543
|
+
return new Promise((resolve8, reject) => {
|
|
34298
34544
|
const earlyReject = (error48) => {
|
|
34299
34545
|
reject(error48);
|
|
34300
34546
|
};
|
|
@@ -34372,7 +34618,7 @@ var Protocol = class {
|
|
|
34372
34618
|
if (!parseResult.success) {
|
|
34373
34619
|
reject(parseResult.error);
|
|
34374
34620
|
} else {
|
|
34375
|
-
|
|
34621
|
+
resolve8(parseResult.data);
|
|
34376
34622
|
}
|
|
34377
34623
|
} catch (error48) {
|
|
34378
34624
|
reject(error48);
|
|
@@ -34633,12 +34879,12 @@ var Protocol = class {
|
|
|
34633
34879
|
}
|
|
34634
34880
|
} catch {
|
|
34635
34881
|
}
|
|
34636
|
-
return new Promise((
|
|
34882
|
+
return new Promise((resolve8, reject) => {
|
|
34637
34883
|
if (signal.aborted) {
|
|
34638
34884
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
34639
34885
|
return;
|
|
34640
34886
|
}
|
|
34641
|
-
const timeoutId = setTimeout(
|
|
34887
|
+
const timeoutId = setTimeout(resolve8, interval);
|
|
34642
34888
|
signal.addEventListener("abort", () => {
|
|
34643
34889
|
clearTimeout(timeoutId);
|
|
34644
34890
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -34733,7 +34979,7 @@ function mergeCapabilities(base, additional) {
|
|
|
34733
34979
|
|
|
34734
34980
|
// ../../.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
34981
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
34736
|
-
var import_ajv_formats = __toESM(
|
|
34982
|
+
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
34737
34983
|
function createDefaultAjvInstance() {
|
|
34738
34984
|
const ajv = new import_ajv.default({
|
|
34739
34985
|
strict: false,
|
|
@@ -34990,23 +35236,23 @@ var Server = class extends Protocol {
|
|
|
34990
35236
|
const wrappedHandler = async (request, extra) => {
|
|
34991
35237
|
const validatedRequest = safeParse2(CallToolRequestSchema, request);
|
|
34992
35238
|
if (!validatedRequest.success) {
|
|
34993
|
-
const
|
|
34994
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${
|
|
35239
|
+
const errorMessage2 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
35240
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage2}`);
|
|
34995
35241
|
}
|
|
34996
35242
|
const { params: params3 } = validatedRequest.data;
|
|
34997
35243
|
const result = await Promise.resolve(handler(request, extra));
|
|
34998
35244
|
if (params3.task) {
|
|
34999
35245
|
const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
|
|
35000
35246
|
if (!taskValidationResult.success) {
|
|
35001
|
-
const
|
|
35002
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${
|
|
35247
|
+
const errorMessage2 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
35248
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage2}`);
|
|
35003
35249
|
}
|
|
35004
35250
|
return taskValidationResult.data;
|
|
35005
35251
|
}
|
|
35006
35252
|
const validationResult = safeParse2(CallToolResultSchema, result);
|
|
35007
35253
|
if (!validationResult.success) {
|
|
35008
|
-
const
|
|
35009
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${
|
|
35254
|
+
const errorMessage2 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
35255
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage2}`);
|
|
35010
35256
|
}
|
|
35011
35257
|
return validationResult.data;
|
|
35012
35258
|
};
|
|
@@ -35500,12 +35746,12 @@ var McpServer = class {
|
|
|
35500
35746
|
* @param errorMessage - The error message.
|
|
35501
35747
|
* @returns The tool error result.
|
|
35502
35748
|
*/
|
|
35503
|
-
createToolError(
|
|
35749
|
+
createToolError(errorMessage2) {
|
|
35504
35750
|
return {
|
|
35505
35751
|
content: [
|
|
35506
35752
|
{
|
|
35507
35753
|
type: "text",
|
|
35508
|
-
text:
|
|
35754
|
+
text: errorMessage2
|
|
35509
35755
|
}
|
|
35510
35756
|
],
|
|
35511
35757
|
isError: true
|
|
@@ -35523,8 +35769,8 @@ var McpServer = class {
|
|
|
35523
35769
|
const parseResult = await safeParseAsync2(schemaToParse, args);
|
|
35524
35770
|
if (!parseResult.success) {
|
|
35525
35771
|
const error48 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
35526
|
-
const
|
|
35527
|
-
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${
|
|
35772
|
+
const errorMessage2 = getParseErrorMessage(error48);
|
|
35773
|
+
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${errorMessage2}`);
|
|
35528
35774
|
}
|
|
35529
35775
|
return parseResult.data;
|
|
35530
35776
|
}
|
|
@@ -35548,8 +35794,8 @@ var McpServer = class {
|
|
|
35548
35794
|
const parseResult = await safeParseAsync2(outputObj, result.structuredContent);
|
|
35549
35795
|
if (!parseResult.success) {
|
|
35550
35796
|
const error48 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
35551
|
-
const
|
|
35552
|
-
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${
|
|
35797
|
+
const errorMessage2 = getParseErrorMessage(error48);
|
|
35798
|
+
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage2}`);
|
|
35553
35799
|
}
|
|
35554
35800
|
}
|
|
35555
35801
|
/**
|
|
@@ -35597,7 +35843,7 @@ var McpServer = class {
|
|
|
35597
35843
|
let task = createTaskResult.task;
|
|
35598
35844
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
35599
35845
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
35600
|
-
await new Promise((
|
|
35846
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
35601
35847
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
35602
35848
|
if (!updatedTask) {
|
|
35603
35849
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -35761,8 +36007,8 @@ var McpServer = class {
|
|
|
35761
36007
|
const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
|
|
35762
36008
|
if (!parseResult.success) {
|
|
35763
36009
|
const error48 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
35764
|
-
const
|
|
35765
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request.params.name}: ${
|
|
36010
|
+
const errorMessage2 = getParseErrorMessage(error48);
|
|
36011
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request.params.name}: ${errorMessage2}`);
|
|
35766
36012
|
}
|
|
35767
36013
|
const args = parseResult.data;
|
|
35768
36014
|
const cb = prompt.callback;
|
|
@@ -36240,12 +36486,12 @@ var StdioServerTransport = class {
|
|
|
36240
36486
|
this.onclose?.();
|
|
36241
36487
|
}
|
|
36242
36488
|
send(message) {
|
|
36243
|
-
return new Promise((
|
|
36489
|
+
return new Promise((resolve8) => {
|
|
36244
36490
|
const json3 = serializeMessage(message);
|
|
36245
36491
|
if (this._stdout.write(json3)) {
|
|
36246
|
-
|
|
36492
|
+
resolve8();
|
|
36247
36493
|
} else {
|
|
36248
|
-
this._stdout.once("drain",
|
|
36494
|
+
this._stdout.once("drain", resolve8);
|
|
36249
36495
|
}
|
|
36250
36496
|
});
|
|
36251
36497
|
}
|
|
@@ -36283,31 +36529,19 @@ function text(data) {
|
|
|
36283
36529
|
return { content: [{ type: "text", text: data }] };
|
|
36284
36530
|
}
|
|
36285
36531
|
async function mcp() {
|
|
36532
|
+
setMcpMode();
|
|
36286
36533
|
const server = new McpServer({
|
|
36287
36534
|
name: "reporting-bi",
|
|
36288
|
-
version: "0.1.
|
|
36535
|
+
version: "0.1.13"
|
|
36289
36536
|
});
|
|
36290
36537
|
server.tool(
|
|
36291
36538
|
"status",
|
|
36292
|
-
"Show active connection, accounting, and token expiry for all logged-in domains",
|
|
36539
|
+
"Show active connection, accounting, and token/session expiry for all logged-in domains",
|
|
36293
36540
|
{},
|
|
36294
36541
|
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);
|
|
36542
|
+
const report2 = statusReport();
|
|
36543
|
+
if (report2.connections.length === 0) return text("Not logged in.");
|
|
36544
|
+
return json2(report2);
|
|
36311
36545
|
}
|
|
36312
36546
|
);
|
|
36313
36547
|
server.tool(
|
|
@@ -36788,26 +37022,26 @@ function saveUpdateCheck(data) {
|
|
|
36788
37022
|
fs13.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(data, null, 2));
|
|
36789
37023
|
}
|
|
36790
37024
|
function fetchLatestVersion() {
|
|
36791
|
-
return new Promise((
|
|
37025
|
+
return new Promise((resolve8) => {
|
|
36792
37026
|
const req = https.get(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { timeout: 5e3 }, (res) => {
|
|
36793
37027
|
if (res.statusCode !== 200) {
|
|
36794
37028
|
res.resume();
|
|
36795
|
-
return
|
|
37029
|
+
return resolve8(null);
|
|
36796
37030
|
}
|
|
36797
37031
|
let body = "";
|
|
36798
37032
|
res.on("data", (chunk) => body += chunk);
|
|
36799
37033
|
res.on("end", () => {
|
|
36800
37034
|
try {
|
|
36801
|
-
|
|
37035
|
+
resolve8(JSON.parse(body).version ?? null);
|
|
36802
37036
|
} catch {
|
|
36803
|
-
|
|
37037
|
+
resolve8(null);
|
|
36804
37038
|
}
|
|
36805
37039
|
});
|
|
36806
37040
|
});
|
|
36807
|
-
req.on("error", () =>
|
|
37041
|
+
req.on("error", () => resolve8(null));
|
|
36808
37042
|
req.on("timeout", () => {
|
|
36809
37043
|
req.destroy();
|
|
36810
|
-
|
|
37044
|
+
resolve8(null);
|
|
36811
37045
|
});
|
|
36812
37046
|
});
|
|
36813
37047
|
}
|
|
@@ -36831,10 +37065,10 @@ async function checkForUpdate() {
|
|
|
36831
37065
|
saveUpdateCheck({ lastCheck: now });
|
|
36832
37066
|
const latest = await fetchLatestVersion();
|
|
36833
37067
|
if (!latest) return;
|
|
36834
|
-
if (!isNewer(latest, "0.1.
|
|
36835
|
-
console.
|
|
36836
|
-
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: "
|
|
36837
|
-
console.
|
|
37068
|
+
if (!isNewer(latest, "0.1.13")) return;
|
|
37069
|
+
console.error(`\x1B[33mUpdating ${PACKAGE_NAME} ${"0.1.13"} \u2192 ${latest}...\x1B[0m`);
|
|
37070
|
+
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: ["ignore", 2, 2] });
|
|
37071
|
+
console.error(`\x1B[32mUpdated to ${latest}.\x1B[0m`);
|
|
36838
37072
|
} catch {
|
|
36839
37073
|
}
|
|
36840
37074
|
}
|
|
@@ -36844,11 +37078,11 @@ async function forceUpdate() {
|
|
|
36844
37078
|
console.error("Could not fetch latest version from npm.");
|
|
36845
37079
|
process.exit(1);
|
|
36846
37080
|
}
|
|
36847
|
-
if (!isNewer(latest, "0.1.
|
|
36848
|
-
console.log(`Already up to date (${"0.1.
|
|
37081
|
+
if (!isNewer(latest, "0.1.13")) {
|
|
37082
|
+
console.log(`Already up to date (${"0.1.13"}).`);
|
|
36849
37083
|
return;
|
|
36850
37084
|
}
|
|
36851
|
-
console.log(`Updating ${PACKAGE_NAME} ${"0.1.
|
|
37085
|
+
console.log(`Updating ${PACKAGE_NAME} ${"0.1.13"} \u2192 ${latest}...`);
|
|
36852
37086
|
(0, import_node_child_process3.execSync)(npmInstallCmd(latest), { stdio: "inherit" });
|
|
36853
37087
|
console.log(`\x1B[32mUpdated to ${latest}.\x1B[0m`);
|
|
36854
37088
|
saveUpdateCheck({ lastCheck: Date.now() });
|
|
@@ -36859,11 +37093,20 @@ var USAGE_default = `Reporting.bi CLI
|
|
|
36859
37093
|
|
|
36860
37094
|
Usage: rpbi <command> [options]
|
|
36861
37095
|
|
|
37096
|
+
Global options:
|
|
37097
|
+
--connection <domain> Run against this login instead of the active one
|
|
37098
|
+
--json Machine-readable output
|
|
37099
|
+
--verbose Log every request to stderr
|
|
37100
|
+
|
|
37101
|
+
Workspace sync (etl/wiki/deployment/ext pull, push, status) mirrors deletions both ways:
|
|
37102
|
+
pull removes local files deleted on the server (a locally modified file is kept), push
|
|
37103
|
+
deletes on the server what was deleted locally \u2014 single files or whole folders.
|
|
37104
|
+
|
|
36862
37105
|
Commands:
|
|
36863
37106
|
login [domain] [--accounting <id>] Login to a Reporting.bi instance (opens browser)
|
|
36864
37107
|
logout [domain] Logout and revoke tokens (default: active connection)
|
|
36865
37108
|
use <domain> [--accounting <id>] Switch active connection and/or set accounting
|
|
36866
|
-
status
|
|
37109
|
+
status [--json] Show all connections, token and session expiry
|
|
36867
37110
|
init [--connection <domain>] [--accounting <id>] [--type etl|wiki|deployment|ext] Initialize .rpbi/config.json in current directory
|
|
36868
37111
|
update Force update to latest version from npm
|
|
36869
37112
|
mcp Start MCP server (for AI agents, stdio transport)
|
|
@@ -36876,8 +37119,9 @@ ETL:
|
|
|
36876
37119
|
etl get <id> Get thread metadata
|
|
36877
37120
|
etl content <id> Get thread SQL content (plain text)
|
|
36878
37121
|
etl exec <id> [--sql "..."|--file f] Execute thread (optionally with custom SQL)
|
|
37122
|
+
etl abort <spid> Abort a running exec (exec reports "rpbi: spid <n>" on stderr)
|
|
36879
37123
|
etl search <query> Search threads
|
|
36880
|
-
etl params <id> [--save <json>|--delete <idz>] List, save or delete thread parameters
|
|
37124
|
+
etl params <id> [--save <json>|--delete <idz>] List, save or delete thread parameters (save creates, or updates when the JSON carries "idz"; a name already declared alongside is refused)
|
|
36881
37125
|
etl pull [--dir <path>] [--no-context] Pull all ETL threads, parameters, metadata & schema to local files
|
|
36882
37126
|
etl push [files...] [--dir <path>] [--force] Push modified/new .sql files back to server
|
|
36883
37127
|
etl status [--dir <path>] [--remote] [--json] Show local changes (--remote compares with server)
|
|
@@ -36901,7 +37145,8 @@ Extensions (requires the "custom.define" right):
|
|
|
36901
37145
|
ext queries List queries
|
|
36902
37146
|
ext content <id> [--query] Get resource content (--query for query SQL)
|
|
36903
37147
|
ext exec <query_id> [--sql "..."|--file f] Execute query (optionally with custom SQL)
|
|
36904
|
-
ext
|
|
37148
|
+
ext abort <spid> Abort a running exec (exec reports "rpbi: spid <n>" on stderr)
|
|
37149
|
+
ext params <query_id> [--save <json>|--delete <idz>] List, save or delete query parameters (save creates, or updates when the JSON carries "idz"; a name already declared alongside is refused)
|
|
36905
37150
|
ext deps --project <id>|--query <id>|--resource <id> List SQL dependencies (resource \u2194 query links)
|
|
36906
37151
|
ext deps --query <id> --add <resource_id> Link a query to a resource (or --resource <id> --add <query_id>)
|
|
36907
37152
|
ext deps --remove <idz> Unlink a dependency
|
|
@@ -37025,7 +37270,7 @@ Examples:
|
|
|
37025
37270
|
(async () => {
|
|
37026
37271
|
const [command, ...args] = process.argv.slice(2);
|
|
37027
37272
|
if (command === "--version" || command === "-v") {
|
|
37028
|
-
console.log("0.1.
|
|
37273
|
+
console.log("0.1.13");
|
|
37029
37274
|
return;
|
|
37030
37275
|
}
|
|
37031
37276
|
await checkForUpdate();
|
|
@@ -37082,7 +37327,7 @@ Examples:
|
|
|
37082
37327
|
helpdesk(args);
|
|
37083
37328
|
break;
|
|
37084
37329
|
case "status":
|
|
37085
|
-
status();
|
|
37330
|
+
status(args);
|
|
37086
37331
|
break;
|
|
37087
37332
|
case "mcp":
|
|
37088
37333
|
mcp();
|