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