@positronic/cli 0.0.2
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/src/cli.js +739 -0
- package/dist/src/commands/backend.js +199 -0
- package/dist/src/commands/brain.js +446 -0
- package/dist/src/commands/brain.test.js +2936 -0
- package/dist/src/commands/helpers.js +1315 -0
- package/dist/src/commands/helpers.test.js +832 -0
- package/dist/src/commands/project-config-manager.js +197 -0
- package/dist/src/commands/project.js +130 -0
- package/dist/src/commands/project.test.js +1201 -0
- package/dist/src/commands/resources.js +272 -0
- package/dist/src/commands/resources.test.js +2511 -0
- package/dist/src/commands/schedule.js +73 -0
- package/dist/src/commands/schedule.test.js +1235 -0
- package/dist/src/commands/secret.js +87 -0
- package/dist/src/commands/secret.test.d.js +1 -0
- package/dist/src/commands/secret.test.js +761 -0
- package/dist/src/commands/server.js +816 -0
- package/dist/src/commands/server.test.js +1237 -0
- package/dist/src/commands/test-utils.js +737 -0
- package/dist/src/components/brain-history.js +169 -0
- package/dist/src/components/brain-list.js +108 -0
- package/dist/src/components/brain-rerun.js +313 -0
- package/dist/src/components/brain-show.js +65 -0
- package/dist/src/components/error.js +19 -0
- package/dist/src/components/project-add.js +95 -0
- package/dist/src/components/project-create.js +276 -0
- package/dist/src/components/project-list.js +88 -0
- package/dist/src/components/project-remove.js +91 -0
- package/dist/src/components/project-select.js +224 -0
- package/dist/src/components/project-show.js +41 -0
- package/dist/src/components/resource-clear.js +152 -0
- package/dist/src/components/resource-delete.js +189 -0
- package/dist/src/components/resource-list.js +174 -0
- package/dist/src/components/resource-sync.js +386 -0
- package/dist/src/components/resource-types.js +243 -0
- package/dist/src/components/resource-upload.js +366 -0
- package/dist/src/components/schedule-create.js +259 -0
- package/dist/src/components/schedule-delete.js +161 -0
- package/dist/src/components/schedule-list.js +176 -0
- package/dist/src/components/schedule-runs.js +103 -0
- package/dist/src/components/secret-bulk.js +262 -0
- package/dist/src/components/secret-create.js +199 -0
- package/dist/src/components/secret-delete.js +190 -0
- package/dist/src/components/secret-list.js +190 -0
- package/dist/src/components/secret-sync.js +303 -0
- package/dist/src/components/watch.js +184 -0
- package/dist/src/hooks/useApi.js +512 -0
- package/dist/src/positronic.js +33 -0
- package/dist/src/test/mock-api-client.js +371 -0
- package/dist/src/test/test-dev-server.js +1376 -0
- package/dist/types/cli.d.ts +9 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/commands/backend.d.ts +6 -0
- package/dist/types/commands/backend.d.ts.map +1 -0
- package/dist/types/commands/brain.d.ts +35 -0
- package/dist/types/commands/brain.d.ts.map +1 -0
- package/dist/types/commands/helpers.d.ts +55 -0
- package/dist/types/commands/helpers.d.ts.map +1 -0
- package/dist/types/commands/project-config-manager.d.ts +37 -0
- package/dist/types/commands/project-config-manager.d.ts.map +1 -0
- package/dist/types/commands/project.d.ts +55 -0
- package/dist/types/commands/project.d.ts.map +1 -0
- package/dist/types/commands/resources.d.ts +13 -0
- package/dist/types/commands/resources.d.ts.map +1 -0
- package/dist/types/commands/schedule.d.ts +27 -0
- package/dist/types/commands/schedule.d.ts.map +1 -0
- package/dist/types/commands/secret.d.ts +23 -0
- package/dist/types/commands/secret.d.ts.map +1 -0
- package/dist/types/commands/server.d.ts +12 -0
- package/dist/types/commands/server.d.ts.map +1 -0
- package/dist/types/commands/test-utils.d.ts +45 -0
- package/dist/types/commands/test-utils.d.ts.map +1 -0
- package/dist/types/components/brain-history.d.ts +7 -0
- package/dist/types/components/brain-history.d.ts.map +1 -0
- package/dist/types/components/brain-list.d.ts +2 -0
- package/dist/types/components/brain-list.d.ts.map +1 -0
- package/dist/types/components/brain-rerun.d.ts +9 -0
- package/dist/types/components/brain-rerun.d.ts.map +1 -0
- package/dist/types/components/brain-show.d.ts +6 -0
- package/dist/types/components/brain-show.d.ts.map +1 -0
- package/dist/types/components/error.d.ts +10 -0
- package/dist/types/components/error.d.ts.map +1 -0
- package/dist/types/components/project-add.d.ts +9 -0
- package/dist/types/components/project-add.d.ts.map +1 -0
- package/dist/types/components/project-create.d.ts +6 -0
- package/dist/types/components/project-create.d.ts.map +1 -0
- package/dist/types/components/project-list.d.ts +7 -0
- package/dist/types/components/project-list.d.ts.map +1 -0
- package/dist/types/components/project-remove.d.ts +8 -0
- package/dist/types/components/project-remove.d.ts.map +1 -0
- package/dist/types/components/project-select.d.ts +8 -0
- package/dist/types/components/project-select.d.ts.map +1 -0
- package/dist/types/components/project-show.d.ts +7 -0
- package/dist/types/components/project-show.d.ts.map +1 -0
- package/dist/types/components/resource-clear.d.ts +2 -0
- package/dist/types/components/resource-clear.d.ts.map +1 -0
- package/dist/types/components/resource-delete.d.ts +9 -0
- package/dist/types/components/resource-delete.d.ts.map +1 -0
- package/dist/types/components/resource-list.d.ts +2 -0
- package/dist/types/components/resource-list.d.ts.map +1 -0
- package/dist/types/components/resource-sync.d.ts +8 -0
- package/dist/types/components/resource-sync.d.ts.map +1 -0
- package/dist/types/components/resource-types.d.ts +7 -0
- package/dist/types/components/resource-types.d.ts.map +1 -0
- package/dist/types/components/resource-upload.d.ts +8 -0
- package/dist/types/components/resource-upload.d.ts.map +1 -0
- package/dist/types/components/schedule-create.d.ts +7 -0
- package/dist/types/components/schedule-create.d.ts.map +1 -0
- package/dist/types/components/schedule-delete.d.ts +7 -0
- package/dist/types/components/schedule-delete.d.ts.map +1 -0
- package/dist/types/components/schedule-list.d.ts +6 -0
- package/dist/types/components/schedule-list.d.ts.map +1 -0
- package/dist/types/components/schedule-runs.d.ts +8 -0
- package/dist/types/components/schedule-runs.d.ts.map +1 -0
- package/dist/types/components/secret-bulk.d.ts +8 -0
- package/dist/types/components/secret-bulk.d.ts.map +1 -0
- package/dist/types/components/secret-create.d.ts +9 -0
- package/dist/types/components/secret-create.d.ts.map +1 -0
- package/dist/types/components/secret-delete.d.ts +8 -0
- package/dist/types/components/secret-delete.d.ts.map +1 -0
- package/dist/types/components/secret-list.d.ts +7 -0
- package/dist/types/components/secret-list.d.ts.map +1 -0
- package/dist/types/components/secret-sync.d.ts +9 -0
- package/dist/types/components/secret-sync.d.ts.map +1 -0
- package/dist/types/components/watch.d.ts +7 -0
- package/dist/types/components/watch.d.ts.map +1 -0
- package/dist/types/hooks/useApi.d.ts +29 -0
- package/dist/types/hooks/useApi.d.ts.map +1 -0
- package/dist/types/positronic.d.ts +3 -0
- package/dist/types/positronic.d.ts.map +1 -0
- package/dist/types/test/mock-api-client.d.ts +25 -0
- package/dist/types/test/mock-api-client.d.ts.map +1 -0
- package/dist/types/test/test-dev-server.d.ts +129 -0
- package/dist/types/test/test-dev-server.d.ts.map +1 -0
- package/package.json +37 -0
- package/src/cli.ts +981 -0
- package/src/commands/backend.ts +63 -0
- package/src/commands/brain.test.ts +1004 -0
- package/src/commands/brain.ts +215 -0
- package/src/commands/helpers.test.ts +487 -0
- package/src/commands/helpers.ts +870 -0
- package/src/commands/project-config-manager.ts +152 -0
- package/src/commands/project.test.ts +502 -0
- package/src/commands/project.ts +109 -0
- package/src/commands/resources.test.ts +1052 -0
- package/src/commands/resources.ts +97 -0
- package/src/commands/schedule.test.ts +481 -0
- package/src/commands/schedule.ts +65 -0
- package/src/commands/secret.test.ts +210 -0
- package/src/commands/secret.ts +50 -0
- package/src/commands/server.test.ts +493 -0
- package/src/commands/server.ts +353 -0
- package/src/commands/test-utils.ts +324 -0
- package/src/components/brain-history.tsx +198 -0
- package/src/components/brain-list.tsx +105 -0
- package/src/components/brain-rerun.tsx +111 -0
- package/src/components/brain-show.tsx +92 -0
- package/src/components/error.tsx +24 -0
- package/src/components/project-add.tsx +59 -0
- package/src/components/project-create.tsx +83 -0
- package/src/components/project-list.tsx +83 -0
- package/src/components/project-remove.tsx +55 -0
- package/src/components/project-select.tsx +200 -0
- package/src/components/project-show.tsx +58 -0
- package/src/components/resource-clear.tsx +127 -0
- package/src/components/resource-delete.tsx +160 -0
- package/src/components/resource-list.tsx +177 -0
- package/src/components/resource-sync.tsx +170 -0
- package/src/components/resource-types.tsx +55 -0
- package/src/components/resource-upload.tsx +182 -0
- package/src/components/schedule-create.tsx +90 -0
- package/src/components/schedule-delete.tsx +116 -0
- package/src/components/schedule-list.tsx +186 -0
- package/src/components/schedule-runs.tsx +151 -0
- package/src/components/secret-bulk.tsx +79 -0
- package/src/components/secret-create.tsx +49 -0
- package/src/components/secret-delete.tsx +41 -0
- package/src/components/secret-list.tsx +41 -0
- package/src/components/watch.tsx +155 -0
- package/src/hooks/useApi.ts +183 -0
- package/src/positronic.ts +40 -0
- package/src/test/data/resources/config.json +1 -0
- package/src/test/data/resources/data/config.json +1 -0
- package/src/test/data/resources/data/logo.png +2 -0
- package/src/test/data/resources/docs/api.md +3 -0
- package/src/test/data/resources/docs/readme.md +3 -0
- package/src/test/data/resources/example.md +3 -0
- package/src/test/data/resources/file with spaces.txt +1 -0
- package/src/test/data/resources/readme.md +3 -0
- package/src/test/data/resources/test.txt +1 -0
- package/src/test/mock-api-client.ts +145 -0
- package/src/test/test-dev-server.ts +1003 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,1315 @@
|
|
|
1
|
+
function _array_like_to_array(arr, len) {
|
|
2
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
3
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
4
|
+
return arr2;
|
|
5
|
+
}
|
|
6
|
+
function _array_with_holes(arr) {
|
|
7
|
+
if (Array.isArray(arr)) return arr;
|
|
8
|
+
}
|
|
9
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
10
|
+
try {
|
|
11
|
+
var info = gen[key](arg);
|
|
12
|
+
var value = info.value;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
reject(error);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (info.done) {
|
|
18
|
+
resolve(value);
|
|
19
|
+
} else {
|
|
20
|
+
Promise.resolve(value).then(_next, _throw);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function _async_to_generator(fn) {
|
|
24
|
+
return function() {
|
|
25
|
+
var self = this, args = arguments;
|
|
26
|
+
return new Promise(function(resolve, reject) {
|
|
27
|
+
var gen = fn.apply(self, args);
|
|
28
|
+
function _next(value) {
|
|
29
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
30
|
+
}
|
|
31
|
+
function _throw(err) {
|
|
32
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
33
|
+
}
|
|
34
|
+
_next(undefined);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function _define_property(obj, key, value) {
|
|
39
|
+
if (key in obj) {
|
|
40
|
+
Object.defineProperty(obj, key, {
|
|
41
|
+
value: value,
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: true
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
obj[key] = value;
|
|
48
|
+
}
|
|
49
|
+
return obj;
|
|
50
|
+
}
|
|
51
|
+
function _iterable_to_array_limit(arr, i) {
|
|
52
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
53
|
+
if (_i == null) return;
|
|
54
|
+
var _arr = [];
|
|
55
|
+
var _n = true;
|
|
56
|
+
var _d = false;
|
|
57
|
+
var _s, _e;
|
|
58
|
+
try {
|
|
59
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
60
|
+
_arr.push(_s.value);
|
|
61
|
+
if (i && _arr.length === i) break;
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
_d = true;
|
|
65
|
+
_e = err;
|
|
66
|
+
} finally{
|
|
67
|
+
try {
|
|
68
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
69
|
+
} finally{
|
|
70
|
+
if (_d) throw _e;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return _arr;
|
|
74
|
+
}
|
|
75
|
+
function _non_iterable_rest() {
|
|
76
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
77
|
+
}
|
|
78
|
+
function _object_spread(target) {
|
|
79
|
+
for(var i = 1; i < arguments.length; i++){
|
|
80
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
81
|
+
var ownKeys = Object.keys(source);
|
|
82
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
83
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
84
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
ownKeys.forEach(function(key) {
|
|
88
|
+
_define_property(target, key, source[key]);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return target;
|
|
92
|
+
}
|
|
93
|
+
function ownKeys(object, enumerableOnly) {
|
|
94
|
+
var keys = Object.keys(object);
|
|
95
|
+
if (Object.getOwnPropertySymbols) {
|
|
96
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
97
|
+
if (enumerableOnly) {
|
|
98
|
+
symbols = symbols.filter(function(sym) {
|
|
99
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
keys.push.apply(keys, symbols);
|
|
103
|
+
}
|
|
104
|
+
return keys;
|
|
105
|
+
}
|
|
106
|
+
function _object_spread_props(target, source) {
|
|
107
|
+
source = source != null ? source : {};
|
|
108
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
109
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
110
|
+
} else {
|
|
111
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
112
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return target;
|
|
116
|
+
}
|
|
117
|
+
function _sliced_to_array(arr, i) {
|
|
118
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
119
|
+
}
|
|
120
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
121
|
+
if (!o) return;
|
|
122
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
123
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
124
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
125
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
126
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
127
|
+
}
|
|
128
|
+
function _ts_generator(thisArg, body) {
|
|
129
|
+
var f, y, t, _ = {
|
|
130
|
+
label: 0,
|
|
131
|
+
sent: function() {
|
|
132
|
+
if (t[0] & 1) throw t[1];
|
|
133
|
+
return t[1];
|
|
134
|
+
},
|
|
135
|
+
trys: [],
|
|
136
|
+
ops: []
|
|
137
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
138
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
139
|
+
return this;
|
|
140
|
+
}), g;
|
|
141
|
+
function verb(n) {
|
|
142
|
+
return function(v) {
|
|
143
|
+
return step([
|
|
144
|
+
n,
|
|
145
|
+
v
|
|
146
|
+
]);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function step(op) {
|
|
150
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
151
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
152
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
153
|
+
if (y = 0, t) op = [
|
|
154
|
+
op[0] & 2,
|
|
155
|
+
t.value
|
|
156
|
+
];
|
|
157
|
+
switch(op[0]){
|
|
158
|
+
case 0:
|
|
159
|
+
case 1:
|
|
160
|
+
t = op;
|
|
161
|
+
break;
|
|
162
|
+
case 4:
|
|
163
|
+
_.label++;
|
|
164
|
+
return {
|
|
165
|
+
value: op[1],
|
|
166
|
+
done: false
|
|
167
|
+
};
|
|
168
|
+
case 5:
|
|
169
|
+
_.label++;
|
|
170
|
+
y = op[1];
|
|
171
|
+
op = [
|
|
172
|
+
0
|
|
173
|
+
];
|
|
174
|
+
continue;
|
|
175
|
+
case 7:
|
|
176
|
+
op = _.ops.pop();
|
|
177
|
+
_.trys.pop();
|
|
178
|
+
continue;
|
|
179
|
+
default:
|
|
180
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
181
|
+
_ = 0;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
185
|
+
_.label = op[1];
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
189
|
+
_.label = t[1];
|
|
190
|
+
t = op;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
if (t && _.label < t[2]) {
|
|
194
|
+
_.label = t[2];
|
|
195
|
+
_.ops.push(op);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
if (t[2]) _.ops.pop();
|
|
199
|
+
_.trys.pop();
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
op = body.call(thisArg, _);
|
|
203
|
+
} catch (e) {
|
|
204
|
+
op = [
|
|
205
|
+
6,
|
|
206
|
+
e
|
|
207
|
+
];
|
|
208
|
+
y = 0;
|
|
209
|
+
} finally{
|
|
210
|
+
f = t = 0;
|
|
211
|
+
}
|
|
212
|
+
if (op[0] & 5) throw op[1];
|
|
213
|
+
return {
|
|
214
|
+
value: op[0] ? op[1] : void 0,
|
|
215
|
+
done: true
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
import process from 'process';
|
|
220
|
+
import * as fs from 'fs';
|
|
221
|
+
import * as path from 'path';
|
|
222
|
+
import * as os from 'os';
|
|
223
|
+
import caz from 'caz';
|
|
224
|
+
import { isText } from 'istextorbinary';
|
|
225
|
+
import * as http from 'http';
|
|
226
|
+
import * as https from 'https';
|
|
227
|
+
import { URL } from 'url';
|
|
228
|
+
import { createMinimalProject } from './test-utils.js';
|
|
229
|
+
// Singleton API client instance
|
|
230
|
+
export var apiClient = {
|
|
231
|
+
fetch: function(apiPath, options) {
|
|
232
|
+
return _async_to_generator(function() {
|
|
233
|
+
var port, baseUrl, fullUrl;
|
|
234
|
+
return _ts_generator(this, function(_state) {
|
|
235
|
+
port = process.env.POSITRONIC_PORT || '8787';
|
|
236
|
+
baseUrl = "http://localhost:".concat(port);
|
|
237
|
+
fullUrl = "".concat(baseUrl).concat(apiPath.startsWith('/') ? apiPath : '/' + apiPath);
|
|
238
|
+
return [
|
|
239
|
+
2,
|
|
240
|
+
fetch(fullUrl, options)
|
|
241
|
+
];
|
|
242
|
+
});
|
|
243
|
+
})();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
export function generateProject(projectName, projectDir) {
|
|
247
|
+
return _async_to_generator(function() {
|
|
248
|
+
var devPath, newProjectTemplatePath, cazOptions, originalNewProjectPkg, copiedNewProjectPkg;
|
|
249
|
+
return _ts_generator(this, function(_state) {
|
|
250
|
+
switch(_state.label){
|
|
251
|
+
case 0:
|
|
252
|
+
if (!(process.env.NODE_ENV === 'test')) return [
|
|
253
|
+
3,
|
|
254
|
+
2
|
|
255
|
+
];
|
|
256
|
+
return [
|
|
257
|
+
4,
|
|
258
|
+
createMinimalProject(projectDir)
|
|
259
|
+
];
|
|
260
|
+
case 1:
|
|
261
|
+
_state.sent();
|
|
262
|
+
return [
|
|
263
|
+
2
|
|
264
|
+
];
|
|
265
|
+
case 2:
|
|
266
|
+
devPath = process.env.POSITRONIC_LOCAL_PATH;
|
|
267
|
+
newProjectTemplatePath = '@positronic/template-new-project';
|
|
268
|
+
cazOptions = {
|
|
269
|
+
name: projectName
|
|
270
|
+
};
|
|
271
|
+
_state.label = 3;
|
|
272
|
+
case 3:
|
|
273
|
+
_state.trys.push([
|
|
274
|
+
3,
|
|
275
|
+
,
|
|
276
|
+
5,
|
|
277
|
+
6
|
|
278
|
+
]);
|
|
279
|
+
if (devPath) {
|
|
280
|
+
// Copying templates, why you ask?
|
|
281
|
+
// Well because when caz runs if you pass it a path to the template module
|
|
282
|
+
// (e.g. for development environment setting POSITRONIC_LOCAL_PATH)
|
|
283
|
+
// it runs npm install --production in the template directory. This is a problem
|
|
284
|
+
// in our monorepo because this messes up the node_modules at the root of the
|
|
285
|
+
// monorepo which then causes the tests to fail. Also ny time I was generating a new
|
|
286
|
+
// project it was a pain to have to run npm install over and over again just
|
|
287
|
+
// to get back to a good state.
|
|
288
|
+
originalNewProjectPkg = path.resolve(devPath, 'packages', 'template-new-project');
|
|
289
|
+
copiedNewProjectPkg = fs.mkdtempSync(path.join(os.tmpdir(), 'positronic-newproj-'));
|
|
290
|
+
fs.cpSync(originalNewProjectPkg, copiedNewProjectPkg, {
|
|
291
|
+
recursive: true
|
|
292
|
+
});
|
|
293
|
+
newProjectTemplatePath = copiedNewProjectPkg;
|
|
294
|
+
cazOptions = {
|
|
295
|
+
name: projectName,
|
|
296
|
+
install: true,
|
|
297
|
+
pm: 'npm'
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
// In test or CI environments, skip interactive prompts and dependency installation
|
|
301
|
+
if (process.env.NODE_ENV === 'test') {
|
|
302
|
+
cazOptions = _object_spread_props(_object_spread({}, cazOptions), {
|
|
303
|
+
backend: 'none',
|
|
304
|
+
install: false,
|
|
305
|
+
pm: 'npm'
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return [
|
|
309
|
+
4,
|
|
310
|
+
caz.default(newProjectTemplatePath, projectDir, _object_spread_props(_object_spread({}, cazOptions), {
|
|
311
|
+
force: false
|
|
312
|
+
}))
|
|
313
|
+
];
|
|
314
|
+
case 4:
|
|
315
|
+
_state.sent();
|
|
316
|
+
return [
|
|
317
|
+
3,
|
|
318
|
+
6
|
|
319
|
+
];
|
|
320
|
+
case 5:
|
|
321
|
+
// Clean up the temporary copied new project package
|
|
322
|
+
if (devPath) {
|
|
323
|
+
fs.rmSync(newProjectTemplatePath, {
|
|
324
|
+
recursive: true,
|
|
325
|
+
force: true,
|
|
326
|
+
maxRetries: 3
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return [
|
|
330
|
+
7
|
|
331
|
+
];
|
|
332
|
+
case 6:
|
|
333
|
+
return [
|
|
334
|
+
2
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
})();
|
|
339
|
+
}
|
|
340
|
+
export function scanLocalResources(resourcesDir) {
|
|
341
|
+
var localResources = [];
|
|
342
|
+
var scanDirectory = function(dir, baseDir) {
|
|
343
|
+
var entries = fs.readdirSync(dir, {
|
|
344
|
+
withFileTypes: true
|
|
345
|
+
});
|
|
346
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
347
|
+
try {
|
|
348
|
+
for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
349
|
+
var entry = _step.value;
|
|
350
|
+
var fullPath = path.join(dir, entry.name);
|
|
351
|
+
if (entry.isDirectory()) {
|
|
352
|
+
// Recursively scan subdirectories
|
|
353
|
+
scanDirectory(fullPath, baseDir);
|
|
354
|
+
} else if (entry.isFile()) {
|
|
355
|
+
// Calculate relative path from resources directory
|
|
356
|
+
var relativePath = path.relative(baseDir, fullPath);
|
|
357
|
+
// Use forward slashes for consistency across platforms
|
|
358
|
+
var key = relativePath.replace(/\\/g, '/');
|
|
359
|
+
// Determine file type using istextorbinary
|
|
360
|
+
// It checks both filename and content (first few bytes)
|
|
361
|
+
var type = isText(entry.name, fs.readFileSync(fullPath)) ? 'text' : 'binary';
|
|
362
|
+
localResources.push({
|
|
363
|
+
key: key,
|
|
364
|
+
path: fullPath,
|
|
365
|
+
type: type
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
} catch (err) {
|
|
370
|
+
_didIteratorError = true;
|
|
371
|
+
_iteratorError = err;
|
|
372
|
+
} finally{
|
|
373
|
+
try {
|
|
374
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
375
|
+
_iterator.return();
|
|
376
|
+
}
|
|
377
|
+
} finally{
|
|
378
|
+
if (_didIteratorError) {
|
|
379
|
+
throw _iteratorError;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
scanDirectory(resourcesDir, resourcesDir);
|
|
385
|
+
return localResources;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Core resource sync logic without UI dependencies
|
|
389
|
+
*/ export function syncResources(_0, _1) {
|
|
390
|
+
return _async_to_generator(function(projectRootPath) {
|
|
391
|
+
var client, onProgress, resourcesDir, localResources, response, errorText, data, serverResourceMap, localResourceKeys, uploadCount, skipCount, errorCount, deleteCount, errors, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, resource, fileStats, serverResource, shouldUpload, localModTime, fileContent, formData, uploadResponse, errorText1, error, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, _step_value, key, serverResource1, deleteResponse, errorText2, error1, err;
|
|
392
|
+
var _arguments = arguments;
|
|
393
|
+
return _ts_generator(this, function(_state) {
|
|
394
|
+
switch(_state.label){
|
|
395
|
+
case 0:
|
|
396
|
+
client = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : apiClient, onProgress = _arguments.length > 2 ? _arguments[2] : void 0;
|
|
397
|
+
resourcesDir = path.join(projectRootPath, 'resources');
|
|
398
|
+
// Ensure resources directory exists
|
|
399
|
+
if (!fs.existsSync(resourcesDir)) {
|
|
400
|
+
fs.mkdirSync(resourcesDir, {
|
|
401
|
+
recursive: true
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
localResources = scanLocalResources(resourcesDir);
|
|
405
|
+
return [
|
|
406
|
+
4,
|
|
407
|
+
client.fetch('/resources')
|
|
408
|
+
];
|
|
409
|
+
case 1:
|
|
410
|
+
response = _state.sent();
|
|
411
|
+
if (!!response.ok) return [
|
|
412
|
+
3,
|
|
413
|
+
3
|
|
414
|
+
];
|
|
415
|
+
return [
|
|
416
|
+
4,
|
|
417
|
+
response.text()
|
|
418
|
+
];
|
|
419
|
+
case 2:
|
|
420
|
+
errorText = _state.sent();
|
|
421
|
+
throw new Error("Failed to fetch resources: ".concat(response.status, " ").concat(errorText));
|
|
422
|
+
case 3:
|
|
423
|
+
return [
|
|
424
|
+
4,
|
|
425
|
+
response.json()
|
|
426
|
+
];
|
|
427
|
+
case 4:
|
|
428
|
+
data = _state.sent();
|
|
429
|
+
serverResourceMap = new Map(data.resources.map(function(r) {
|
|
430
|
+
return [
|
|
431
|
+
r.key,
|
|
432
|
+
r
|
|
433
|
+
];
|
|
434
|
+
}));
|
|
435
|
+
// Create a set of local resource keys for easy lookup
|
|
436
|
+
localResourceKeys = new Set(localResources.map(function(r) {
|
|
437
|
+
return r.key;
|
|
438
|
+
}));
|
|
439
|
+
uploadCount = 0;
|
|
440
|
+
skipCount = 0;
|
|
441
|
+
errorCount = 0;
|
|
442
|
+
deleteCount = 0;
|
|
443
|
+
errors = [];
|
|
444
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
445
|
+
_state.label = 5;
|
|
446
|
+
case 5:
|
|
447
|
+
_state.trys.push([
|
|
448
|
+
5,
|
|
449
|
+
16,
|
|
450
|
+
17,
|
|
451
|
+
18
|
|
452
|
+
]);
|
|
453
|
+
_iterator = localResources[Symbol.iterator]();
|
|
454
|
+
_state.label = 6;
|
|
455
|
+
case 6:
|
|
456
|
+
if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
|
|
457
|
+
3,
|
|
458
|
+
15
|
|
459
|
+
];
|
|
460
|
+
resource = _step.value;
|
|
461
|
+
// Report progress for checking
|
|
462
|
+
if (onProgress) {
|
|
463
|
+
onProgress({
|
|
464
|
+
currentFile: resource.key,
|
|
465
|
+
action: 'checking',
|
|
466
|
+
stats: {
|
|
467
|
+
uploadCount: uploadCount,
|
|
468
|
+
skipCount: skipCount,
|
|
469
|
+
errorCount: errorCount,
|
|
470
|
+
totalCount: localResources.length,
|
|
471
|
+
deleteCount: deleteCount,
|
|
472
|
+
errors: errors
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
fileStats = fs.statSync(resource.path);
|
|
477
|
+
serverResource = serverResourceMap.get(resource.key);
|
|
478
|
+
// Check if we need to upload (new or modified)
|
|
479
|
+
shouldUpload = !serverResource;
|
|
480
|
+
if (serverResource && serverResource.size !== fileStats.size) {
|
|
481
|
+
// Size mismatch indicates file has changed
|
|
482
|
+
shouldUpload = true;
|
|
483
|
+
} else if (serverResource) {
|
|
484
|
+
// For same-size files, check modification time if available
|
|
485
|
+
localModTime = fileStats.mtime.toISOString();
|
|
486
|
+
if (localModTime > serverResource.lastModified) {
|
|
487
|
+
shouldUpload = true;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (!shouldUpload) return [
|
|
491
|
+
3,
|
|
492
|
+
13
|
|
493
|
+
];
|
|
494
|
+
_state.label = 7;
|
|
495
|
+
case 7:
|
|
496
|
+
_state.trys.push([
|
|
497
|
+
7,
|
|
498
|
+
11,
|
|
499
|
+
,
|
|
500
|
+
12
|
|
501
|
+
]);
|
|
502
|
+
// Report progress for uploading
|
|
503
|
+
if (onProgress) {
|
|
504
|
+
onProgress({
|
|
505
|
+
currentFile: resource.key,
|
|
506
|
+
action: 'uploading',
|
|
507
|
+
stats: {
|
|
508
|
+
uploadCount: uploadCount,
|
|
509
|
+
skipCount: skipCount,
|
|
510
|
+
errorCount: errorCount,
|
|
511
|
+
totalCount: localResources.length,
|
|
512
|
+
deleteCount: deleteCount,
|
|
513
|
+
errors: errors
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
fileContent = fs.readFileSync(resource.path);
|
|
518
|
+
formData = new FormData();
|
|
519
|
+
formData.append('file', new Blob([
|
|
520
|
+
fileContent
|
|
521
|
+
]), path.basename(resource.path));
|
|
522
|
+
formData.append('type', resource.type);
|
|
523
|
+
formData.append('path', resource.key);
|
|
524
|
+
formData.append('key', resource.key);
|
|
525
|
+
formData.append('local', 'true');
|
|
526
|
+
return [
|
|
527
|
+
4,
|
|
528
|
+
client.fetch('/resources', {
|
|
529
|
+
method: 'POST',
|
|
530
|
+
body: formData
|
|
531
|
+
})
|
|
532
|
+
];
|
|
533
|
+
case 8:
|
|
534
|
+
uploadResponse = _state.sent();
|
|
535
|
+
if (!!uploadResponse.ok) return [
|
|
536
|
+
3,
|
|
537
|
+
10
|
|
538
|
+
];
|
|
539
|
+
return [
|
|
540
|
+
4,
|
|
541
|
+
uploadResponse.text()
|
|
542
|
+
];
|
|
543
|
+
case 9:
|
|
544
|
+
errorText1 = _state.sent();
|
|
545
|
+
throw new Error("Upload failed: ".concat(uploadResponse.status, " ").concat(errorText1));
|
|
546
|
+
case 10:
|
|
547
|
+
uploadCount++;
|
|
548
|
+
return [
|
|
549
|
+
3,
|
|
550
|
+
12
|
|
551
|
+
];
|
|
552
|
+
case 11:
|
|
553
|
+
error = _state.sent();
|
|
554
|
+
errorCount++;
|
|
555
|
+
errors.push({
|
|
556
|
+
file: resource.key,
|
|
557
|
+
message: error.message || 'Unknown error'
|
|
558
|
+
});
|
|
559
|
+
return [
|
|
560
|
+
3,
|
|
561
|
+
12
|
|
562
|
+
];
|
|
563
|
+
case 12:
|
|
564
|
+
return [
|
|
565
|
+
3,
|
|
566
|
+
14
|
|
567
|
+
];
|
|
568
|
+
case 13:
|
|
569
|
+
skipCount++;
|
|
570
|
+
_state.label = 14;
|
|
571
|
+
case 14:
|
|
572
|
+
_iteratorNormalCompletion = true;
|
|
573
|
+
return [
|
|
574
|
+
3,
|
|
575
|
+
6
|
|
576
|
+
];
|
|
577
|
+
case 15:
|
|
578
|
+
return [
|
|
579
|
+
3,
|
|
580
|
+
18
|
|
581
|
+
];
|
|
582
|
+
case 16:
|
|
583
|
+
err = _state.sent();
|
|
584
|
+
_didIteratorError = true;
|
|
585
|
+
_iteratorError = err;
|
|
586
|
+
return [
|
|
587
|
+
3,
|
|
588
|
+
18
|
|
589
|
+
];
|
|
590
|
+
case 17:
|
|
591
|
+
try {
|
|
592
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
593
|
+
_iterator.return();
|
|
594
|
+
}
|
|
595
|
+
} finally{
|
|
596
|
+
if (_didIteratorError) {
|
|
597
|
+
throw _iteratorError;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return [
|
|
601
|
+
7
|
|
602
|
+
];
|
|
603
|
+
case 18:
|
|
604
|
+
_iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
605
|
+
_state.label = 19;
|
|
606
|
+
case 19:
|
|
607
|
+
_state.trys.push([
|
|
608
|
+
19,
|
|
609
|
+
28,
|
|
610
|
+
29,
|
|
611
|
+
30
|
|
612
|
+
]);
|
|
613
|
+
_iterator1 = serverResourceMap[Symbol.iterator]();
|
|
614
|
+
_state.label = 20;
|
|
615
|
+
case 20:
|
|
616
|
+
if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
|
|
617
|
+
3,
|
|
618
|
+
27
|
|
619
|
+
];
|
|
620
|
+
_step_value = _sliced_to_array(_step1.value, 2), key = _step_value[0], serverResource1 = _step_value[1];
|
|
621
|
+
if (!(serverResource1.local && !localResourceKeys.has(key))) return [
|
|
622
|
+
3,
|
|
623
|
+
26
|
|
624
|
+
];
|
|
625
|
+
_state.label = 21;
|
|
626
|
+
case 21:
|
|
627
|
+
_state.trys.push([
|
|
628
|
+
21,
|
|
629
|
+
25,
|
|
630
|
+
,
|
|
631
|
+
26
|
|
632
|
+
]);
|
|
633
|
+
// Report progress for deleting
|
|
634
|
+
if (onProgress) {
|
|
635
|
+
onProgress({
|
|
636
|
+
currentFile: key,
|
|
637
|
+
action: 'deleting',
|
|
638
|
+
stats: {
|
|
639
|
+
uploadCount: uploadCount,
|
|
640
|
+
skipCount: skipCount,
|
|
641
|
+
errorCount: errorCount,
|
|
642
|
+
totalCount: localResources.length,
|
|
643
|
+
deleteCount: deleteCount,
|
|
644
|
+
errors: errors
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
return [
|
|
649
|
+
4,
|
|
650
|
+
client.fetch("/resources/".concat(encodeURIComponent(key)), {
|
|
651
|
+
method: 'DELETE'
|
|
652
|
+
})
|
|
653
|
+
];
|
|
654
|
+
case 22:
|
|
655
|
+
deleteResponse = _state.sent();
|
|
656
|
+
if (!(!deleteResponse.ok && deleteResponse.status !== 404)) return [
|
|
657
|
+
3,
|
|
658
|
+
24
|
|
659
|
+
];
|
|
660
|
+
return [
|
|
661
|
+
4,
|
|
662
|
+
deleteResponse.text()
|
|
663
|
+
];
|
|
664
|
+
case 23:
|
|
665
|
+
errorText2 = _state.sent();
|
|
666
|
+
throw new Error("Delete failed: ".concat(deleteResponse.status, " ").concat(errorText2));
|
|
667
|
+
case 24:
|
|
668
|
+
deleteCount++;
|
|
669
|
+
return [
|
|
670
|
+
3,
|
|
671
|
+
26
|
|
672
|
+
];
|
|
673
|
+
case 25:
|
|
674
|
+
error1 = _state.sent();
|
|
675
|
+
errorCount++;
|
|
676
|
+
errors.push({
|
|
677
|
+
file: key,
|
|
678
|
+
message: "Failed to delete: ".concat(error1.message || 'Unknown error')
|
|
679
|
+
});
|
|
680
|
+
return [
|
|
681
|
+
3,
|
|
682
|
+
26
|
|
683
|
+
];
|
|
684
|
+
case 26:
|
|
685
|
+
_iteratorNormalCompletion1 = true;
|
|
686
|
+
return [
|
|
687
|
+
3,
|
|
688
|
+
20
|
|
689
|
+
];
|
|
690
|
+
case 27:
|
|
691
|
+
return [
|
|
692
|
+
3,
|
|
693
|
+
30
|
|
694
|
+
];
|
|
695
|
+
case 28:
|
|
696
|
+
err = _state.sent();
|
|
697
|
+
_didIteratorError1 = true;
|
|
698
|
+
_iteratorError1 = err;
|
|
699
|
+
return [
|
|
700
|
+
3,
|
|
701
|
+
30
|
|
702
|
+
];
|
|
703
|
+
case 29:
|
|
704
|
+
try {
|
|
705
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
706
|
+
_iterator1.return();
|
|
707
|
+
}
|
|
708
|
+
} finally{
|
|
709
|
+
if (_didIteratorError1) {
|
|
710
|
+
throw _iteratorError1;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return [
|
|
714
|
+
7
|
|
715
|
+
];
|
|
716
|
+
case 30:
|
|
717
|
+
return [
|
|
718
|
+
2,
|
|
719
|
+
{
|
|
720
|
+
uploadCount: uploadCount,
|
|
721
|
+
skipCount: skipCount,
|
|
722
|
+
errorCount: errorCount,
|
|
723
|
+
totalCount: localResources.length,
|
|
724
|
+
deleteCount: deleteCount,
|
|
725
|
+
errors: errors
|
|
726
|
+
}
|
|
727
|
+
];
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
}).apply(this, arguments);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Check if a string is a valid JavaScript identifier
|
|
734
|
+
*/ function isValidJSIdentifier(name) {
|
|
735
|
+
// Must start with letter, underscore, or dollar sign
|
|
736
|
+
// Can contain letters, digits, underscores, dollar signs
|
|
737
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Build TypeScript structure from resource tree
|
|
741
|
+
*/ function buildTypeStructure(node) {
|
|
742
|
+
if (!node.children) return [];
|
|
743
|
+
var properties = [];
|
|
744
|
+
var processedNames = new Set();
|
|
745
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
746
|
+
try {
|
|
747
|
+
for(var _iterator = Object.entries(node.children)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
748
|
+
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], child = _step_value[1];
|
|
749
|
+
if (processedNames.has(name)) continue;
|
|
750
|
+
if (child.type) {
|
|
751
|
+
// File resource
|
|
752
|
+
var resourceType = child.type === 'text' ? 'TextResource' : 'BinaryResource';
|
|
753
|
+
properties.push({
|
|
754
|
+
name: name,
|
|
755
|
+
type: resourceType
|
|
756
|
+
});
|
|
757
|
+
processedNames.add(name);
|
|
758
|
+
if (child.fullName) {
|
|
759
|
+
processedNames.add(child.fullName);
|
|
760
|
+
}
|
|
761
|
+
} else if (child.children) {
|
|
762
|
+
// Directory with nested resources
|
|
763
|
+
var nestedProps = buildTypeStructure(child);
|
|
764
|
+
if (nestedProps.length > 0) {
|
|
765
|
+
properties.push({
|
|
766
|
+
name: name,
|
|
767
|
+
type: {
|
|
768
|
+
properties: nestedProps
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
processedNames.add(name);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
} catch (err) {
|
|
776
|
+
_didIteratorError = true;
|
|
777
|
+
_iteratorError = err;
|
|
778
|
+
} finally{
|
|
779
|
+
try {
|
|
780
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
781
|
+
_iterator.return();
|
|
782
|
+
}
|
|
783
|
+
} finally{
|
|
784
|
+
if (_didIteratorError) {
|
|
785
|
+
throw _iteratorError;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
return properties;
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Render TypeScript from structure
|
|
793
|
+
*/ function renderTypeScript(properties) {
|
|
794
|
+
var indent = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : ' ';
|
|
795
|
+
return properties.map(function(prop) {
|
|
796
|
+
if (typeof prop.type === 'string') {
|
|
797
|
+
return "".concat(indent).concat(prop.name, ": ").concat(prop.type, ";");
|
|
798
|
+
} else {
|
|
799
|
+
var nestedContent = renderTypeScript(prop.type.properties, indent + ' ');
|
|
800
|
+
return "".concat(indent).concat(prop.name, ": {\n").concat(nestedContent, "\n").concat(indent, "};");
|
|
801
|
+
}
|
|
802
|
+
}).join('\n');
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Generate TypeScript declarations for resources
|
|
806
|
+
*/ function generateResourceTypes(resources) {
|
|
807
|
+
var root = {
|
|
808
|
+
children: {}
|
|
809
|
+
};
|
|
810
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
811
|
+
try {
|
|
812
|
+
// Build the tree structure
|
|
813
|
+
for(var _iterator = resources[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
814
|
+
var resource = _step.value;
|
|
815
|
+
var parts = resource.key.split('/');
|
|
816
|
+
var current = root;
|
|
817
|
+
for(var i = 0; i < parts.length; i++){
|
|
818
|
+
var part = parts[i];
|
|
819
|
+
var isLeaf = i === parts.length - 1;
|
|
820
|
+
if (!current.children) {
|
|
821
|
+
current.children = {};
|
|
822
|
+
}
|
|
823
|
+
if (isLeaf) {
|
|
824
|
+
var resourceNode = {
|
|
825
|
+
type: resource.type,
|
|
826
|
+
fullName: part
|
|
827
|
+
};
|
|
828
|
+
if (isValidJSIdentifier(part)) {
|
|
829
|
+
current.children[part] = resourceNode;
|
|
830
|
+
}
|
|
831
|
+
var withoutExt = part.replace(/\.[^/.]+$/, '');
|
|
832
|
+
if (withoutExt !== part && isValidJSIdentifier(withoutExt)) {
|
|
833
|
+
if (!current.children[withoutExt]) {
|
|
834
|
+
current.children[withoutExt] = resourceNode;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
} else {
|
|
838
|
+
if (isValidJSIdentifier(part)) {
|
|
839
|
+
if (!current.children[part]) {
|
|
840
|
+
current.children[part] = {
|
|
841
|
+
children: {}
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
current = current.children[part];
|
|
845
|
+
} else {
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
} catch (err) {
|
|
852
|
+
_didIteratorError = true;
|
|
853
|
+
_iteratorError = err;
|
|
854
|
+
} finally{
|
|
855
|
+
try {
|
|
856
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
857
|
+
_iterator.return();
|
|
858
|
+
}
|
|
859
|
+
} finally{
|
|
860
|
+
if (_didIteratorError) {
|
|
861
|
+
throw _iteratorError;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
var typeStructure = buildTypeStructure(root);
|
|
866
|
+
var interfaceContent = renderTypeScript(typeStructure);
|
|
867
|
+
return "// Generated by Positronic CLI\n// This file provides TypeScript types for your resources\n\ndeclare module '@positronic/core' {\n interface TextResource {\n load(): Promise<string>;\n }\n\n interface BinaryResource {\n load(): Promise<Buffer>;\n }\n\n interface Resources {\n // Method signatures for loading resources by path\n loadText(path: string): Promise<string>;\n loadBinary(path: string): Promise<Buffer>;\n\n // Resource properties accessible via dot notation\n".concat(interfaceContent, "\n }\n}\n\nexport {}; // Make this a module\n");
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Core type generation logic without UI dependencies
|
|
871
|
+
*/ export function generateTypes(_0) {
|
|
872
|
+
return _async_to_generator(function(projectRootPath) {
|
|
873
|
+
var client, typesFilePath, response, errorText, data, typeDefinitions;
|
|
874
|
+
var _arguments = arguments;
|
|
875
|
+
return _ts_generator(this, function(_state) {
|
|
876
|
+
switch(_state.label){
|
|
877
|
+
case 0:
|
|
878
|
+
client = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : apiClient;
|
|
879
|
+
typesFilePath = path.join(projectRootPath, 'resources.d.ts');
|
|
880
|
+
return [
|
|
881
|
+
4,
|
|
882
|
+
client.fetch('/resources')
|
|
883
|
+
];
|
|
884
|
+
case 1:
|
|
885
|
+
response = _state.sent();
|
|
886
|
+
if (!!response.ok) return [
|
|
887
|
+
3,
|
|
888
|
+
3
|
|
889
|
+
];
|
|
890
|
+
return [
|
|
891
|
+
4,
|
|
892
|
+
response.text()
|
|
893
|
+
];
|
|
894
|
+
case 2:
|
|
895
|
+
errorText = _state.sent();
|
|
896
|
+
throw new Error("Failed to fetch resources: ".concat(response.status, " ").concat(errorText));
|
|
897
|
+
case 3:
|
|
898
|
+
return [
|
|
899
|
+
4,
|
|
900
|
+
response.json()
|
|
901
|
+
];
|
|
902
|
+
case 4:
|
|
903
|
+
data = _state.sent();
|
|
904
|
+
typeDefinitions = generateResourceTypes(data.resources);
|
|
905
|
+
fs.writeFileSync(typesFilePath, typeDefinitions, 'utf-8');
|
|
906
|
+
return [
|
|
907
|
+
2,
|
|
908
|
+
path.relative(process.cwd(), typesFilePath)
|
|
909
|
+
];
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
}).apply(this, arguments);
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Wait for resources to stabilize (indicating initial sync is complete)
|
|
916
|
+
*/ function waitForResources(maxWaitMs, startTime) {
|
|
917
|
+
return _async_to_generator(function() {
|
|
918
|
+
var lastCount, stableCount, response, data, e;
|
|
919
|
+
return _ts_generator(this, function(_state) {
|
|
920
|
+
switch(_state.label){
|
|
921
|
+
case 0:
|
|
922
|
+
lastCount = -1;
|
|
923
|
+
stableCount = 0;
|
|
924
|
+
_state.label = 1;
|
|
925
|
+
case 1:
|
|
926
|
+
if (!(Date.now() - startTime < maxWaitMs)) return [
|
|
927
|
+
3,
|
|
928
|
+
9
|
|
929
|
+
];
|
|
930
|
+
_state.label = 2;
|
|
931
|
+
case 2:
|
|
932
|
+
_state.trys.push([
|
|
933
|
+
2,
|
|
934
|
+
6,
|
|
935
|
+
,
|
|
936
|
+
7
|
|
937
|
+
]);
|
|
938
|
+
return [
|
|
939
|
+
4,
|
|
940
|
+
apiClient.fetch("/resources")
|
|
941
|
+
];
|
|
942
|
+
case 3:
|
|
943
|
+
response = _state.sent();
|
|
944
|
+
if (!response.ok) return [
|
|
945
|
+
3,
|
|
946
|
+
5
|
|
947
|
+
];
|
|
948
|
+
return [
|
|
949
|
+
4,
|
|
950
|
+
response.json()
|
|
951
|
+
];
|
|
952
|
+
case 4:
|
|
953
|
+
data = _state.sent();
|
|
954
|
+
// If the count hasn't changed for 3 checks, we consider it stable
|
|
955
|
+
if (data.count === lastCount) {
|
|
956
|
+
stableCount++;
|
|
957
|
+
if (stableCount >= 3) {
|
|
958
|
+
return [
|
|
959
|
+
2,
|
|
960
|
+
true
|
|
961
|
+
]; // Resources are stable
|
|
962
|
+
}
|
|
963
|
+
} else {
|
|
964
|
+
lastCount = data.count;
|
|
965
|
+
stableCount = 0;
|
|
966
|
+
}
|
|
967
|
+
_state.label = 5;
|
|
968
|
+
case 5:
|
|
969
|
+
return [
|
|
970
|
+
3,
|
|
971
|
+
7
|
|
972
|
+
];
|
|
973
|
+
case 6:
|
|
974
|
+
e = _state.sent();
|
|
975
|
+
return [
|
|
976
|
+
3,
|
|
977
|
+
7
|
|
978
|
+
];
|
|
979
|
+
case 7:
|
|
980
|
+
return [
|
|
981
|
+
4,
|
|
982
|
+
new Promise(function(resolve) {
|
|
983
|
+
return setTimeout(resolve, 100);
|
|
984
|
+
})
|
|
985
|
+
];
|
|
986
|
+
case 8:
|
|
987
|
+
_state.sent();
|
|
988
|
+
return [
|
|
989
|
+
3,
|
|
990
|
+
1
|
|
991
|
+
];
|
|
992
|
+
case 9:
|
|
993
|
+
return [
|
|
994
|
+
2,
|
|
995
|
+
false
|
|
996
|
+
];
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
})();
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Helper function to wait for server to be ready
|
|
1003
|
+
*/ export function waitUntilReady(port) {
|
|
1004
|
+
var maxWaitMs = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 5000;
|
|
1005
|
+
return _async_to_generator(function() {
|
|
1006
|
+
var serverPort, startTime, response, status, e;
|
|
1007
|
+
return _ts_generator(this, function(_state) {
|
|
1008
|
+
switch(_state.label){
|
|
1009
|
+
case 0:
|
|
1010
|
+
serverPort = port || Number(process.env.POSITRONIC_PORT) || 8787;
|
|
1011
|
+
startTime = Date.now();
|
|
1012
|
+
_state.label = 1;
|
|
1013
|
+
case 1:
|
|
1014
|
+
if (!(Date.now() - startTime < maxWaitMs)) return [
|
|
1015
|
+
3,
|
|
1016
|
+
9
|
|
1017
|
+
];
|
|
1018
|
+
_state.label = 2;
|
|
1019
|
+
case 2:
|
|
1020
|
+
_state.trys.push([
|
|
1021
|
+
2,
|
|
1022
|
+
6,
|
|
1023
|
+
,
|
|
1024
|
+
7
|
|
1025
|
+
]);
|
|
1026
|
+
return [
|
|
1027
|
+
4,
|
|
1028
|
+
apiClient.fetch("/status")
|
|
1029
|
+
];
|
|
1030
|
+
case 3:
|
|
1031
|
+
response = _state.sent();
|
|
1032
|
+
if (!response.ok) return [
|
|
1033
|
+
3,
|
|
1034
|
+
5
|
|
1035
|
+
];
|
|
1036
|
+
return [
|
|
1037
|
+
4,
|
|
1038
|
+
response.json()
|
|
1039
|
+
];
|
|
1040
|
+
case 4:
|
|
1041
|
+
status = _state.sent();
|
|
1042
|
+
if (status.ready) {
|
|
1043
|
+
return [
|
|
1044
|
+
3,
|
|
1045
|
+
9
|
|
1046
|
+
]; // HTTP server is ready
|
|
1047
|
+
}
|
|
1048
|
+
_state.label = 5;
|
|
1049
|
+
case 5:
|
|
1050
|
+
return [
|
|
1051
|
+
3,
|
|
1052
|
+
7
|
|
1053
|
+
];
|
|
1054
|
+
case 6:
|
|
1055
|
+
e = _state.sent();
|
|
1056
|
+
return [
|
|
1057
|
+
3,
|
|
1058
|
+
7
|
|
1059
|
+
];
|
|
1060
|
+
case 7:
|
|
1061
|
+
return [
|
|
1062
|
+
4,
|
|
1063
|
+
new Promise(function(resolve) {
|
|
1064
|
+
return setTimeout(resolve, 100);
|
|
1065
|
+
})
|
|
1066
|
+
];
|
|
1067
|
+
case 8:
|
|
1068
|
+
_state.sent();
|
|
1069
|
+
return [
|
|
1070
|
+
3,
|
|
1071
|
+
1
|
|
1072
|
+
];
|
|
1073
|
+
case 9:
|
|
1074
|
+
// Now wait for resources to stabilize (indicating initial sync is done)
|
|
1075
|
+
return [
|
|
1076
|
+
2,
|
|
1077
|
+
waitForResources(maxWaitMs, startTime)
|
|
1078
|
+
];
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
})();
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Upload a file using presigned URL for large files
|
|
1085
|
+
* This function is used by the `px resources upload` command to upload files
|
|
1086
|
+
* directly to R2 storage, bypassing the 100MB Worker limit.
|
|
1087
|
+
*
|
|
1088
|
+
* @param filePath - Path to the file to upload
|
|
1089
|
+
* @param customKey - The key (path) where the file will be stored in R2
|
|
1090
|
+
* @param client - Optional API client (defaults to singleton)
|
|
1091
|
+
* @param onProgress - Optional progress callback
|
|
1092
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
1093
|
+
*/ export function uploadFileWithPresignedUrl(_0, _1, _2, _3) {
|
|
1094
|
+
return _async_to_generator(function(filePath, customKey) {
|
|
1095
|
+
var client, onProgress, signal, stats, fileName, fileType, fileContent, presignedResponse, errorText, errorMessage, errorData, _ref, url, method, requiredHeaders, fileContent1, parsedUrl, httpModule, uploadResponse;
|
|
1096
|
+
var _arguments = arguments;
|
|
1097
|
+
return _ts_generator(this, function(_state) {
|
|
1098
|
+
switch(_state.label){
|
|
1099
|
+
case 0:
|
|
1100
|
+
client = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : apiClient, onProgress = _arguments.length > 3 ? _arguments[3] : void 0, signal = _arguments.length > 4 ? _arguments[4] : void 0;
|
|
1101
|
+
// Get file info
|
|
1102
|
+
stats = fs.statSync(filePath);
|
|
1103
|
+
fileName = path.basename(filePath);
|
|
1104
|
+
if (stats.size < 1024 * 1024) {
|
|
1105
|
+
// 1MB
|
|
1106
|
+
fileContent = fs.readFileSync(filePath);
|
|
1107
|
+
fileType = isText(fileName, fileContent) ? 'text' : 'binary';
|
|
1108
|
+
} else {
|
|
1109
|
+
// For large files, use extension-based detection
|
|
1110
|
+
fileType = isText(fileName) ? 'text' : 'binary';
|
|
1111
|
+
}
|
|
1112
|
+
return [
|
|
1113
|
+
4,
|
|
1114
|
+
client.fetch('/resources/presigned-link', {
|
|
1115
|
+
method: 'POST',
|
|
1116
|
+
headers: {
|
|
1117
|
+
'Content-Type': 'application/json'
|
|
1118
|
+
},
|
|
1119
|
+
body: JSON.stringify({
|
|
1120
|
+
key: customKey,
|
|
1121
|
+
type: fileType,
|
|
1122
|
+
size: stats.size
|
|
1123
|
+
})
|
|
1124
|
+
})
|
|
1125
|
+
];
|
|
1126
|
+
case 1:
|
|
1127
|
+
presignedResponse = _state.sent();
|
|
1128
|
+
if (!!presignedResponse.ok) return [
|
|
1129
|
+
3,
|
|
1130
|
+
3
|
|
1131
|
+
];
|
|
1132
|
+
return [
|
|
1133
|
+
4,
|
|
1134
|
+
presignedResponse.text()
|
|
1135
|
+
];
|
|
1136
|
+
case 2:
|
|
1137
|
+
errorText = _state.sent();
|
|
1138
|
+
errorMessage = "Failed to get presigned URL: ".concat(presignedResponse.status);
|
|
1139
|
+
// Parse error response if it's JSON
|
|
1140
|
+
try {
|
|
1141
|
+
errorData = JSON.parse(errorText);
|
|
1142
|
+
if (errorData.error) {
|
|
1143
|
+
errorMessage = errorData.error;
|
|
1144
|
+
}
|
|
1145
|
+
} catch (e) {
|
|
1146
|
+
errorMessage += " ".concat(errorText);
|
|
1147
|
+
}
|
|
1148
|
+
throw new Error(errorMessage);
|
|
1149
|
+
case 3:
|
|
1150
|
+
return [
|
|
1151
|
+
4,
|
|
1152
|
+
presignedResponse.json()
|
|
1153
|
+
];
|
|
1154
|
+
case 4:
|
|
1155
|
+
_ref = _state.sent(), url = _ref.url, method = _ref.method;
|
|
1156
|
+
// Headers that must be included in the upload to match the presigned URL signature
|
|
1157
|
+
requiredHeaders = {
|
|
1158
|
+
'x-amz-meta-type': fileType,
|
|
1159
|
+
'x-amz-meta-local': 'false'
|
|
1160
|
+
};
|
|
1161
|
+
if (!(stats.size > 10 * 1024 * 1024)) return [
|
|
1162
|
+
3,
|
|
1163
|
+
6
|
|
1164
|
+
];
|
|
1165
|
+
// 10MB
|
|
1166
|
+
return [
|
|
1167
|
+
4,
|
|
1168
|
+
uploadLargeFileWithProgress(filePath, url, method, stats.size, requiredHeaders, onProgress, signal)
|
|
1169
|
+
];
|
|
1170
|
+
case 5:
|
|
1171
|
+
_state.sent();
|
|
1172
|
+
return [
|
|
1173
|
+
3,
|
|
1174
|
+
8
|
|
1175
|
+
];
|
|
1176
|
+
case 6:
|
|
1177
|
+
// For small files, use simple upload
|
|
1178
|
+
fileContent1 = fs.readFileSync(filePath);
|
|
1179
|
+
// Use native http/https for the upload
|
|
1180
|
+
parsedUrl = new URL(url);
|
|
1181
|
+
httpModule = parsedUrl.protocol === 'https:' ? https : http;
|
|
1182
|
+
return [
|
|
1183
|
+
4,
|
|
1184
|
+
new Promise(function(resolve, reject) {
|
|
1185
|
+
var requestOptions = {
|
|
1186
|
+
hostname: parsedUrl.hostname,
|
|
1187
|
+
port: parseInt(parsedUrl.port || (parsedUrl.protocol === 'https:' ? '443' : '80'), 10),
|
|
1188
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
1189
|
+
method: method,
|
|
1190
|
+
headers: _object_spread_props(_object_spread({}, requiredHeaders), {
|
|
1191
|
+
'Content-Length': fileContent1.length.toString()
|
|
1192
|
+
})
|
|
1193
|
+
};
|
|
1194
|
+
var req = httpModule.request(requestOptions, function(res) {
|
|
1195
|
+
var chunks = [];
|
|
1196
|
+
res.on('data', function(chunk) {
|
|
1197
|
+
chunks.push(chunk);
|
|
1198
|
+
});
|
|
1199
|
+
res.on('end', function() {
|
|
1200
|
+
var responseBody = Buffer.concat(chunks);
|
|
1201
|
+
resolve(new Response(responseBody, {
|
|
1202
|
+
status: res.statusCode,
|
|
1203
|
+
statusText: res.statusMessage,
|
|
1204
|
+
headers: Object.fromEntries(Object.entries(res.headers).map(function(param) {
|
|
1205
|
+
var _param = _sliced_to_array(param, 2), key = _param[0], value = _param[1];
|
|
1206
|
+
return [
|
|
1207
|
+
key,
|
|
1208
|
+
Array.isArray(value) ? value.join(', ') : value || ''
|
|
1209
|
+
];
|
|
1210
|
+
}))
|
|
1211
|
+
}));
|
|
1212
|
+
});
|
|
1213
|
+
res.on('error', reject);
|
|
1214
|
+
});
|
|
1215
|
+
req.on('error', reject);
|
|
1216
|
+
if (signal) {
|
|
1217
|
+
signal.addEventListener('abort', function() {
|
|
1218
|
+
req.destroy();
|
|
1219
|
+
reject(new Error('AbortError'));
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
req.write(fileContent1);
|
|
1223
|
+
req.end();
|
|
1224
|
+
})
|
|
1225
|
+
];
|
|
1226
|
+
case 7:
|
|
1227
|
+
uploadResponse = _state.sent();
|
|
1228
|
+
if (!uploadResponse.ok) {
|
|
1229
|
+
throw new Error("Failed to upload file: ".concat(uploadResponse.status, " ").concat(uploadResponse.statusText));
|
|
1230
|
+
}
|
|
1231
|
+
_state.label = 8;
|
|
1232
|
+
case 8:
|
|
1233
|
+
return [
|
|
1234
|
+
2
|
|
1235
|
+
];
|
|
1236
|
+
}
|
|
1237
|
+
});
|
|
1238
|
+
}).apply(this, arguments);
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Stream upload large file with progress tracking
|
|
1242
|
+
* Uses Node.js https module for true streaming without loading entire file into memory
|
|
1243
|
+
*/ function uploadLargeFileWithProgress(filePath, url, method, totalSize, requiredHeaders, onProgress, signal) {
|
|
1244
|
+
return _async_to_generator(function() {
|
|
1245
|
+
var parsedUrl, httpModule;
|
|
1246
|
+
return _ts_generator(this, function(_state) {
|
|
1247
|
+
parsedUrl = new URL(url);
|
|
1248
|
+
httpModule = parsedUrl.protocol === 'https:' ? https : http;
|
|
1249
|
+
return [
|
|
1250
|
+
2,
|
|
1251
|
+
new Promise(function(resolve, reject) {
|
|
1252
|
+
// Abort handler
|
|
1253
|
+
var onAbort = function() {
|
|
1254
|
+
req.destroy();
|
|
1255
|
+
reject(new Error('AbortError'));
|
|
1256
|
+
};
|
|
1257
|
+
if (signal) {
|
|
1258
|
+
signal.addEventListener('abort', onAbort);
|
|
1259
|
+
}
|
|
1260
|
+
var options = {
|
|
1261
|
+
hostname: parsedUrl.hostname,
|
|
1262
|
+
port: parsedUrl.port ? parseInt(parsedUrl.port, 10) : undefined,
|
|
1263
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
1264
|
+
method: method,
|
|
1265
|
+
headers: _object_spread_props(_object_spread({}, requiredHeaders), {
|
|
1266
|
+
'Content-Length': totalSize.toString()
|
|
1267
|
+
})
|
|
1268
|
+
};
|
|
1269
|
+
var req = httpModule.request(options, function(res) {
|
|
1270
|
+
var responseBody = '';
|
|
1271
|
+
res.on('data', function(chunk) {
|
|
1272
|
+
responseBody += chunk.toString();
|
|
1273
|
+
});
|
|
1274
|
+
res.on('end', function() {
|
|
1275
|
+
if (signal) {
|
|
1276
|
+
signal.removeEventListener('abort', onAbort);
|
|
1277
|
+
}
|
|
1278
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
1279
|
+
resolve();
|
|
1280
|
+
} else {
|
|
1281
|
+
reject(new Error("Failed to upload file: ".concat(res.statusCode, " ").concat(res.statusMessage, ". Response: ").concat(responseBody)));
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
});
|
|
1285
|
+
req.on('error', function(err) {
|
|
1286
|
+
if (signal) {
|
|
1287
|
+
signal.removeEventListener('abort', onAbort);
|
|
1288
|
+
}
|
|
1289
|
+
reject(err);
|
|
1290
|
+
});
|
|
1291
|
+
// Stream the file directly to the request
|
|
1292
|
+
var fileStream = fs.createReadStream(filePath);
|
|
1293
|
+
var uploadedBytes = 0;
|
|
1294
|
+
fileStream.on('data', function(chunk) {
|
|
1295
|
+
var chunkLength = Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(chunk);
|
|
1296
|
+
uploadedBytes += chunkLength;
|
|
1297
|
+
if (onProgress) {
|
|
1298
|
+
onProgress({
|
|
1299
|
+
loaded: uploadedBytes,
|
|
1300
|
+
total: totalSize,
|
|
1301
|
+
percentage: Math.round(uploadedBytes / totalSize * 100)
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
fileStream.on('error', function(err) {
|
|
1306
|
+
req.destroy();
|
|
1307
|
+
reject(err);
|
|
1308
|
+
});
|
|
1309
|
+
// Pipe the file stream to the request
|
|
1310
|
+
fileStream.pipe(req);
|
|
1311
|
+
})
|
|
1312
|
+
];
|
|
1313
|
+
});
|
|
1314
|
+
})();
|
|
1315
|
+
}
|