@mcesystems/apple-kit 1.0.58 → 1.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +306 -306
- package/dist/index.js +760 -735
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +755 -730
- package/dist/index.mjs.map +4 -4
- package/dist/resources/plist/ddm-managed-app.xml +55 -0
- package/dist/types/logic/actions/device.d.ts +1 -0
- package/dist/types/logic/actions/device.d.ts.map +1 -1
- package/dist/types/logic/actions/install.d.ts +1 -1
- package/dist/types/logic/actions/install.d.ts.map +1 -1
- package/dist/types/logic/appleDeviceKit.d.ts +2 -1
- package/dist/types/logic/appleDeviceKit.d.ts.map +1 -1
- package/dist/types/logic/iosCli.d.ts.map +1 -1
- package/dist/types/utils/ddmDeclaration.d.ts +8 -0
- package/dist/types/utils/ddmDeclaration.d.ts.map +1 -0
- package/dist/types/utils/installRawProfileRetry.d.ts +7 -0
- package/dist/types/utils/installRawProfileRetry.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15027,19 +15027,19 @@ var require_printer = __commonJS({
|
|
|
15027
15027
|
},
|
|
15028
15028
|
// Document
|
|
15029
15029
|
Document: function Document(node) {
|
|
15030
|
-
return
|
|
15030
|
+
return join9(node.definitions, "\n\n") + "\n";
|
|
15031
15031
|
},
|
|
15032
15032
|
OperationDefinition: function OperationDefinition(node) {
|
|
15033
15033
|
var op = node.operation;
|
|
15034
15034
|
var name = node.name;
|
|
15035
|
-
var varDefs = wrap("(",
|
|
15036
|
-
var directives =
|
|
15035
|
+
var varDefs = wrap("(", join9(node.variableDefinitions, ", "), ")");
|
|
15036
|
+
var directives = join9(node.directives, " ");
|
|
15037
15037
|
var selectionSet = node.selectionSet;
|
|
15038
|
-
return !name && !directives && !varDefs && op === "query" ? selectionSet :
|
|
15038
|
+
return !name && !directives && !varDefs && op === "query" ? selectionSet : join9([op, join9([name, varDefs]), directives, selectionSet], " ");
|
|
15039
15039
|
},
|
|
15040
15040
|
VariableDefinition: function VariableDefinition(_ref) {
|
|
15041
15041
|
var variable = _ref.variable, type = _ref.type, defaultValue = _ref.defaultValue, directives = _ref.directives;
|
|
15042
|
-
return variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ",
|
|
15042
|
+
return variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ", join9(directives, " "));
|
|
15043
15043
|
},
|
|
15044
15044
|
SelectionSet: function SelectionSet(_ref2) {
|
|
15045
15045
|
var selections = _ref2.selections;
|
|
@@ -15047,7 +15047,7 @@ var require_printer = __commonJS({
|
|
|
15047
15047
|
},
|
|
15048
15048
|
Field: function Field(_ref3) {
|
|
15049
15049
|
var alias = _ref3.alias, name = _ref3.name, args = _ref3.arguments, directives = _ref3.directives, selectionSet = _ref3.selectionSet;
|
|
15050
|
-
return
|
|
15050
|
+
return join9([wrap("", alias, ": ") + name + wrap("(", join9(args, ", "), ")"), join9(directives, " "), selectionSet], " ");
|
|
15051
15051
|
},
|
|
15052
15052
|
Argument: function Argument(_ref4) {
|
|
15053
15053
|
var name = _ref4.name, value = _ref4.value;
|
|
@@ -15056,18 +15056,18 @@ var require_printer = __commonJS({
|
|
|
15056
15056
|
// Fragments
|
|
15057
15057
|
FragmentSpread: function FragmentSpread(_ref5) {
|
|
15058
15058
|
var name = _ref5.name, directives = _ref5.directives;
|
|
15059
|
-
return "..." + name + wrap(" ",
|
|
15059
|
+
return "..." + name + wrap(" ", join9(directives, " "));
|
|
15060
15060
|
},
|
|
15061
15061
|
InlineFragment: function InlineFragment(_ref6) {
|
|
15062
15062
|
var typeCondition = _ref6.typeCondition, directives = _ref6.directives, selectionSet = _ref6.selectionSet;
|
|
15063
|
-
return
|
|
15063
|
+
return join9(["...", wrap("on ", typeCondition), join9(directives, " "), selectionSet], " ");
|
|
15064
15064
|
},
|
|
15065
15065
|
FragmentDefinition: function FragmentDefinition(_ref7) {
|
|
15066
15066
|
var name = _ref7.name, typeCondition = _ref7.typeCondition, variableDefinitions = _ref7.variableDefinitions, directives = _ref7.directives, selectionSet = _ref7.selectionSet;
|
|
15067
15067
|
return (
|
|
15068
15068
|
// Note: fragment variable definitions are experimental and may be changed
|
|
15069
15069
|
// or removed in the future.
|
|
15070
|
-
"fragment ".concat(name).concat(wrap("(",
|
|
15070
|
+
"fragment ".concat(name).concat(wrap("(", join9(variableDefinitions, ", "), ")"), " ") + "on ".concat(typeCondition, " ").concat(wrap("", join9(directives, " "), " ")) + selectionSet
|
|
15071
15071
|
);
|
|
15072
15072
|
},
|
|
15073
15073
|
// Value
|
|
@@ -15096,11 +15096,11 @@ var require_printer = __commonJS({
|
|
|
15096
15096
|
},
|
|
15097
15097
|
ListValue: function ListValue(_ref13) {
|
|
15098
15098
|
var values = _ref13.values;
|
|
15099
|
-
return "[" +
|
|
15099
|
+
return "[" + join9(values, ", ") + "]";
|
|
15100
15100
|
},
|
|
15101
15101
|
ObjectValue: function ObjectValue(_ref14) {
|
|
15102
15102
|
var fields = _ref14.fields;
|
|
15103
|
-
return "{" +
|
|
15103
|
+
return "{" + join9(fields, ", ") + "}";
|
|
15104
15104
|
},
|
|
15105
15105
|
ObjectField: function ObjectField(_ref15) {
|
|
15106
15106
|
var name = _ref15.name, value = _ref15.value;
|
|
@@ -15109,7 +15109,7 @@ var require_printer = __commonJS({
|
|
|
15109
15109
|
// Directive
|
|
15110
15110
|
Directive: function Directive(_ref16) {
|
|
15111
15111
|
var name = _ref16.name, args = _ref16.arguments;
|
|
15112
|
-
return "@" + name + wrap("(",
|
|
15112
|
+
return "@" + name + wrap("(", join9(args, ", "), ")");
|
|
15113
15113
|
},
|
|
15114
15114
|
// Type
|
|
15115
15115
|
NamedType: function NamedType(_ref17) {
|
|
@@ -15127,7 +15127,7 @@ var require_printer = __commonJS({
|
|
|
15127
15127
|
// Type System Definitions
|
|
15128
15128
|
SchemaDefinition: function SchemaDefinition(_ref20) {
|
|
15129
15129
|
var directives = _ref20.directives, operationTypes = _ref20.operationTypes;
|
|
15130
|
-
return
|
|
15130
|
+
return join9(["schema", join9(directives, " "), block(operationTypes)], " ");
|
|
15131
15131
|
},
|
|
15132
15132
|
OperationTypeDefinition: function OperationTypeDefinition(_ref21) {
|
|
15133
15133
|
var operation = _ref21.operation, type = _ref21.type;
|
|
@@ -15135,85 +15135,85 @@ var require_printer = __commonJS({
|
|
|
15135
15135
|
},
|
|
15136
15136
|
ScalarTypeDefinition: addDescription(function(_ref22) {
|
|
15137
15137
|
var name = _ref22.name, directives = _ref22.directives;
|
|
15138
|
-
return
|
|
15138
|
+
return join9(["scalar", name, join9(directives, " ")], " ");
|
|
15139
15139
|
}),
|
|
15140
15140
|
ObjectTypeDefinition: addDescription(function(_ref23) {
|
|
15141
15141
|
var name = _ref23.name, interfaces = _ref23.interfaces, directives = _ref23.directives, fields = _ref23.fields;
|
|
15142
|
-
return
|
|
15142
|
+
return join9(["type", name, wrap("implements ", join9(interfaces, " & ")), join9(directives, " "), block(fields)], " ");
|
|
15143
15143
|
}),
|
|
15144
15144
|
FieldDefinition: addDescription(function(_ref24) {
|
|
15145
15145
|
var name = _ref24.name, args = _ref24.arguments, type = _ref24.type, directives = _ref24.directives;
|
|
15146
|
-
return name + (hasMultilineItems(args) ? wrap("(\n", indent(
|
|
15146
|
+
return name + (hasMultilineItems(args) ? wrap("(\n", indent(join9(args, "\n")), "\n)") : wrap("(", join9(args, ", "), ")")) + ": " + type + wrap(" ", join9(directives, " "));
|
|
15147
15147
|
}),
|
|
15148
15148
|
InputValueDefinition: addDescription(function(_ref25) {
|
|
15149
15149
|
var name = _ref25.name, type = _ref25.type, defaultValue = _ref25.defaultValue, directives = _ref25.directives;
|
|
15150
|
-
return
|
|
15150
|
+
return join9([name + ": " + type, wrap("= ", defaultValue), join9(directives, " ")], " ");
|
|
15151
15151
|
}),
|
|
15152
15152
|
InterfaceTypeDefinition: addDescription(function(_ref26) {
|
|
15153
15153
|
var name = _ref26.name, directives = _ref26.directives, fields = _ref26.fields;
|
|
15154
|
-
return
|
|
15154
|
+
return join9(["interface", name, join9(directives, " "), block(fields)], " ");
|
|
15155
15155
|
}),
|
|
15156
15156
|
UnionTypeDefinition: addDescription(function(_ref27) {
|
|
15157
15157
|
var name = _ref27.name, directives = _ref27.directives, types = _ref27.types;
|
|
15158
|
-
return
|
|
15158
|
+
return join9(["union", name, join9(directives, " "), types && types.length !== 0 ? "= " + join9(types, " | ") : ""], " ");
|
|
15159
15159
|
}),
|
|
15160
15160
|
EnumTypeDefinition: addDescription(function(_ref28) {
|
|
15161
15161
|
var name = _ref28.name, directives = _ref28.directives, values = _ref28.values;
|
|
15162
|
-
return
|
|
15162
|
+
return join9(["enum", name, join9(directives, " "), block(values)], " ");
|
|
15163
15163
|
}),
|
|
15164
15164
|
EnumValueDefinition: addDescription(function(_ref29) {
|
|
15165
15165
|
var name = _ref29.name, directives = _ref29.directives;
|
|
15166
|
-
return
|
|
15166
|
+
return join9([name, join9(directives, " ")], " ");
|
|
15167
15167
|
}),
|
|
15168
15168
|
InputObjectTypeDefinition: addDescription(function(_ref30) {
|
|
15169
15169
|
var name = _ref30.name, directives = _ref30.directives, fields = _ref30.fields;
|
|
15170
|
-
return
|
|
15170
|
+
return join9(["input", name, join9(directives, " "), block(fields)], " ");
|
|
15171
15171
|
}),
|
|
15172
15172
|
DirectiveDefinition: addDescription(function(_ref31) {
|
|
15173
15173
|
var name = _ref31.name, args = _ref31.arguments, repeatable = _ref31.repeatable, locations = _ref31.locations;
|
|
15174
|
-
return "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(
|
|
15174
|
+
return "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join9(args, "\n")), "\n)") : wrap("(", join9(args, ", "), ")")) + (repeatable ? " repeatable" : "") + " on " + join9(locations, " | ");
|
|
15175
15175
|
}),
|
|
15176
15176
|
SchemaExtension: function SchemaExtension(_ref32) {
|
|
15177
15177
|
var directives = _ref32.directives, operationTypes = _ref32.operationTypes;
|
|
15178
|
-
return
|
|
15178
|
+
return join9(["extend schema", join9(directives, " "), block(operationTypes)], " ");
|
|
15179
15179
|
},
|
|
15180
15180
|
ScalarTypeExtension: function ScalarTypeExtension(_ref33) {
|
|
15181
15181
|
var name = _ref33.name, directives = _ref33.directives;
|
|
15182
|
-
return
|
|
15182
|
+
return join9(["extend scalar", name, join9(directives, " ")], " ");
|
|
15183
15183
|
},
|
|
15184
15184
|
ObjectTypeExtension: function ObjectTypeExtension(_ref34) {
|
|
15185
15185
|
var name = _ref34.name, interfaces = _ref34.interfaces, directives = _ref34.directives, fields = _ref34.fields;
|
|
15186
|
-
return
|
|
15186
|
+
return join9(["extend type", name, wrap("implements ", join9(interfaces, " & ")), join9(directives, " "), block(fields)], " ");
|
|
15187
15187
|
},
|
|
15188
15188
|
InterfaceTypeExtension: function InterfaceTypeExtension(_ref35) {
|
|
15189
15189
|
var name = _ref35.name, directives = _ref35.directives, fields = _ref35.fields;
|
|
15190
|
-
return
|
|
15190
|
+
return join9(["extend interface", name, join9(directives, " "), block(fields)], " ");
|
|
15191
15191
|
},
|
|
15192
15192
|
UnionTypeExtension: function UnionTypeExtension(_ref36) {
|
|
15193
15193
|
var name = _ref36.name, directives = _ref36.directives, types = _ref36.types;
|
|
15194
|
-
return
|
|
15194
|
+
return join9(["extend union", name, join9(directives, " "), types && types.length !== 0 ? "= " + join9(types, " | ") : ""], " ");
|
|
15195
15195
|
},
|
|
15196
15196
|
EnumTypeExtension: function EnumTypeExtension(_ref37) {
|
|
15197
15197
|
var name = _ref37.name, directives = _ref37.directives, values = _ref37.values;
|
|
15198
|
-
return
|
|
15198
|
+
return join9(["extend enum", name, join9(directives, " "), block(values)], " ");
|
|
15199
15199
|
},
|
|
15200
15200
|
InputObjectTypeExtension: function InputObjectTypeExtension(_ref38) {
|
|
15201
15201
|
var name = _ref38.name, directives = _ref38.directives, fields = _ref38.fields;
|
|
15202
|
-
return
|
|
15202
|
+
return join9(["extend input", name, join9(directives, " "), block(fields)], " ");
|
|
15203
15203
|
}
|
|
15204
15204
|
};
|
|
15205
15205
|
function addDescription(cb) {
|
|
15206
15206
|
return function(node) {
|
|
15207
|
-
return
|
|
15207
|
+
return join9([node.description, cb(node)], "\n");
|
|
15208
15208
|
};
|
|
15209
15209
|
}
|
|
15210
|
-
function
|
|
15210
|
+
function join9(maybeArray, separator) {
|
|
15211
15211
|
return maybeArray ? maybeArray.filter(function(x) {
|
|
15212
15212
|
return x;
|
|
15213
15213
|
}).join(separator || "") : "";
|
|
15214
15214
|
}
|
|
15215
15215
|
function block(array) {
|
|
15216
|
-
return array && array.length !== 0 ? "{\n" + indent(
|
|
15216
|
+
return array && array.length !== 0 ? "{\n" + indent(join9(array, "\n")) + "\n}" : "";
|
|
15217
15217
|
}
|
|
15218
15218
|
function wrap(start, maybeString, end) {
|
|
15219
15219
|
return maybeString ? start + maybeString + (end || "") : "";
|
|
@@ -20304,9 +20304,9 @@ var require_execute = __commonJS({
|
|
|
20304
20304
|
return;
|
|
20305
20305
|
}
|
|
20306
20306
|
var resolveFn = fieldDef.resolve || exeContext.fieldResolver;
|
|
20307
|
-
var
|
|
20308
|
-
var result = resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source,
|
|
20309
|
-
return completeValueCatchingError(exeContext, fieldDef.type, fieldNodes,
|
|
20307
|
+
var info2 = buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path);
|
|
20308
|
+
var result = resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source, info2);
|
|
20309
|
+
return completeValueCatchingError(exeContext, fieldDef.type, fieldNodes, info2, path, result);
|
|
20310
20310
|
}
|
|
20311
20311
|
function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) {
|
|
20312
20312
|
return {
|
|
@@ -20322,11 +20322,11 @@ var require_execute = __commonJS({
|
|
|
20322
20322
|
variableValues: exeContext.variableValues
|
|
20323
20323
|
};
|
|
20324
20324
|
}
|
|
20325
|
-
function resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source,
|
|
20325
|
+
function resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source, info2) {
|
|
20326
20326
|
try {
|
|
20327
20327
|
var args = (0, _values.getArgumentValues)(fieldDef, fieldNodes[0], exeContext.variableValues);
|
|
20328
20328
|
var _contextValue = exeContext.contextValue;
|
|
20329
|
-
var result = resolveFn(source, args, _contextValue,
|
|
20329
|
+
var result = resolveFn(source, args, _contextValue, info2);
|
|
20330
20330
|
return (0, _isPromise.default)(result) ? result.then(void 0, asErrorInstance) : result;
|
|
20331
20331
|
} catch (error) {
|
|
20332
20332
|
return asErrorInstance(error);
|
|
@@ -20338,15 +20338,15 @@ var require_execute = __commonJS({
|
|
|
20338
20338
|
}
|
|
20339
20339
|
return new Error("Unexpected error value: " + (0, _inspect.default)(error));
|
|
20340
20340
|
}
|
|
20341
|
-
function completeValueCatchingError(exeContext, returnType, fieldNodes,
|
|
20341
|
+
function completeValueCatchingError(exeContext, returnType, fieldNodes, info2, path, result) {
|
|
20342
20342
|
try {
|
|
20343
20343
|
var completed;
|
|
20344
20344
|
if ((0, _isPromise.default)(result)) {
|
|
20345
20345
|
completed = result.then(function(resolved) {
|
|
20346
|
-
return completeValue(exeContext, returnType, fieldNodes,
|
|
20346
|
+
return completeValue(exeContext, returnType, fieldNodes, info2, path, resolved);
|
|
20347
20347
|
});
|
|
20348
20348
|
} else {
|
|
20349
|
-
completed = completeValue(exeContext, returnType, fieldNodes,
|
|
20349
|
+
completed = completeValue(exeContext, returnType, fieldNodes, info2, path, result);
|
|
20350
20350
|
}
|
|
20351
20351
|
if ((0, _isPromise.default)(completed)) {
|
|
20352
20352
|
return completed.then(void 0, function(error) {
|
|
@@ -20366,14 +20366,14 @@ var require_execute = __commonJS({
|
|
|
20366
20366
|
exeContext.errors.push(error);
|
|
20367
20367
|
return null;
|
|
20368
20368
|
}
|
|
20369
|
-
function completeValue(exeContext, returnType, fieldNodes,
|
|
20369
|
+
function completeValue(exeContext, returnType, fieldNodes, info2, path, result) {
|
|
20370
20370
|
if (result instanceof Error) {
|
|
20371
20371
|
throw result;
|
|
20372
20372
|
}
|
|
20373
20373
|
if ((0, _definition.isNonNullType)(returnType)) {
|
|
20374
|
-
var completed = completeValue(exeContext, returnType.ofType, fieldNodes,
|
|
20374
|
+
var completed = completeValue(exeContext, returnType.ofType, fieldNodes, info2, path, result);
|
|
20375
20375
|
if (completed === null) {
|
|
20376
|
-
throw new Error("Cannot return null for non-nullable field ".concat(
|
|
20376
|
+
throw new Error("Cannot return null for non-nullable field ".concat(info2.parentType.name, ".").concat(info2.fieldName, "."));
|
|
20377
20377
|
}
|
|
20378
20378
|
return completed;
|
|
20379
20379
|
}
|
|
@@ -20381,29 +20381,29 @@ var require_execute = __commonJS({
|
|
|
20381
20381
|
return null;
|
|
20382
20382
|
}
|
|
20383
20383
|
if ((0, _definition.isListType)(returnType)) {
|
|
20384
|
-
return completeListValue(exeContext, returnType, fieldNodes,
|
|
20384
|
+
return completeListValue(exeContext, returnType, fieldNodes, info2, path, result);
|
|
20385
20385
|
}
|
|
20386
20386
|
if ((0, _definition.isLeafType)(returnType)) {
|
|
20387
20387
|
return completeLeafValue(returnType, result);
|
|
20388
20388
|
}
|
|
20389
20389
|
if ((0, _definition.isAbstractType)(returnType)) {
|
|
20390
|
-
return completeAbstractValue(exeContext, returnType, fieldNodes,
|
|
20390
|
+
return completeAbstractValue(exeContext, returnType, fieldNodes, info2, path, result);
|
|
20391
20391
|
}
|
|
20392
20392
|
if ((0, _definition.isObjectType)(returnType)) {
|
|
20393
|
-
return completeObjectValue(exeContext, returnType, fieldNodes,
|
|
20393
|
+
return completeObjectValue(exeContext, returnType, fieldNodes, info2, path, result);
|
|
20394
20394
|
}
|
|
20395
20395
|
(0, _invariant.default)(false, "Cannot complete value of unexpected output type: " + (0, _inspect.default)(returnType));
|
|
20396
20396
|
}
|
|
20397
|
-
function completeListValue(exeContext, returnType, fieldNodes,
|
|
20397
|
+
function completeListValue(exeContext, returnType, fieldNodes, info2, path, result) {
|
|
20398
20398
|
if (!(0, _iterall.isCollection)(result)) {
|
|
20399
|
-
throw new _GraphQLError.GraphQLError("Expected Iterable, but did not find one for field ".concat(
|
|
20399
|
+
throw new _GraphQLError.GraphQLError("Expected Iterable, but did not find one for field ".concat(info2.parentType.name, ".").concat(info2.fieldName, "."));
|
|
20400
20400
|
}
|
|
20401
20401
|
var itemType = returnType.ofType;
|
|
20402
20402
|
var containsPromise = false;
|
|
20403
20403
|
var completedResults = [];
|
|
20404
20404
|
(0, _iterall.forEach)(result, function(item, index) {
|
|
20405
20405
|
var fieldPath = (0, _Path.addPath)(path, index);
|
|
20406
|
-
var completedItem = completeValueCatchingError(exeContext, itemType, fieldNodes,
|
|
20406
|
+
var completedItem = completeValueCatchingError(exeContext, itemType, fieldNodes, info2, fieldPath, item);
|
|
20407
20407
|
if (!containsPromise && (0, _isPromise.default)(completedItem)) {
|
|
20408
20408
|
containsPromise = true;
|
|
20409
20409
|
}
|
|
@@ -20418,30 +20418,30 @@ var require_execute = __commonJS({
|
|
|
20418
20418
|
}
|
|
20419
20419
|
return serializedResult;
|
|
20420
20420
|
}
|
|
20421
|
-
function completeAbstractValue(exeContext, returnType, fieldNodes,
|
|
20421
|
+
function completeAbstractValue(exeContext, returnType, fieldNodes, info2, path, result) {
|
|
20422
20422
|
var resolveTypeFn = returnType.resolveType || exeContext.typeResolver;
|
|
20423
20423
|
var contextValue = exeContext.contextValue;
|
|
20424
|
-
var runtimeType = resolveTypeFn(result, contextValue,
|
|
20424
|
+
var runtimeType = resolveTypeFn(result, contextValue, info2, returnType);
|
|
20425
20425
|
if ((0, _isPromise.default)(runtimeType)) {
|
|
20426
20426
|
return runtimeType.then(function(resolvedRuntimeType) {
|
|
20427
|
-
return completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes,
|
|
20427
|
+
return completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes, info2, result), fieldNodes, info2, path, result);
|
|
20428
20428
|
});
|
|
20429
20429
|
}
|
|
20430
|
-
return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes,
|
|
20430
|
+
return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info2, result), fieldNodes, info2, path, result);
|
|
20431
20431
|
}
|
|
20432
|
-
function ensureValidRuntimeType(runtimeTypeOrName, exeContext, returnType, fieldNodes,
|
|
20432
|
+
function ensureValidRuntimeType(runtimeTypeOrName, exeContext, returnType, fieldNodes, info2, result) {
|
|
20433
20433
|
var runtimeType = typeof runtimeTypeOrName === "string" ? exeContext.schema.getType(runtimeTypeOrName) : runtimeTypeOrName;
|
|
20434
20434
|
if (!(0, _definition.isObjectType)(runtimeType)) {
|
|
20435
|
-
throw new _GraphQLError.GraphQLError("Abstract type ".concat(returnType.name, " must resolve to an Object type at runtime for field ").concat(
|
|
20435
|
+
throw new _GraphQLError.GraphQLError("Abstract type ".concat(returnType.name, " must resolve to an Object type at runtime for field ").concat(info2.parentType.name, ".").concat(info2.fieldName, " with ") + "value ".concat((0, _inspect.default)(result), ', received "').concat((0, _inspect.default)(runtimeType), '". ') + "Either the ".concat(returnType.name, ' type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.'), fieldNodes);
|
|
20436
20436
|
}
|
|
20437
20437
|
if (!exeContext.schema.isPossibleType(returnType, runtimeType)) {
|
|
20438
20438
|
throw new _GraphQLError.GraphQLError('Runtime Object type "'.concat(runtimeType.name, '" is not a possible type for "').concat(returnType.name, '".'), fieldNodes);
|
|
20439
20439
|
}
|
|
20440
20440
|
return runtimeType;
|
|
20441
20441
|
}
|
|
20442
|
-
function completeObjectValue(exeContext, returnType, fieldNodes,
|
|
20442
|
+
function completeObjectValue(exeContext, returnType, fieldNodes, info2, path, result) {
|
|
20443
20443
|
if (returnType.isTypeOf) {
|
|
20444
|
-
var isTypeOf = returnType.isTypeOf(result, exeContext.contextValue,
|
|
20444
|
+
var isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info2);
|
|
20445
20445
|
if ((0, _isPromise.default)(isTypeOf)) {
|
|
20446
20446
|
return isTypeOf.then(function(resolvedIsTypeOf) {
|
|
20447
20447
|
if (!resolvedIsTypeOf) {
|
|
@@ -20475,16 +20475,16 @@ var require_execute = __commonJS({
|
|
|
20475
20475
|
}
|
|
20476
20476
|
return subFieldNodes;
|
|
20477
20477
|
}
|
|
20478
|
-
var defaultTypeResolver = function defaultTypeResolver2(value, contextValue,
|
|
20478
|
+
var defaultTypeResolver = function defaultTypeResolver2(value, contextValue, info2, abstractType) {
|
|
20479
20479
|
if ((0, _isObjectLike.default)(value) && typeof value.__typename === "string") {
|
|
20480
20480
|
return value.__typename;
|
|
20481
20481
|
}
|
|
20482
|
-
var possibleTypes =
|
|
20482
|
+
var possibleTypes = info2.schema.getPossibleTypes(abstractType);
|
|
20483
20483
|
var promisedIsTypeOfResults = [];
|
|
20484
20484
|
for (var i = 0; i < possibleTypes.length; i++) {
|
|
20485
20485
|
var type = possibleTypes[i];
|
|
20486
20486
|
if (type.isTypeOf) {
|
|
20487
|
-
var isTypeOfResult = type.isTypeOf(value, contextValue,
|
|
20487
|
+
var isTypeOfResult = type.isTypeOf(value, contextValue, info2);
|
|
20488
20488
|
if ((0, _isPromise.default)(isTypeOfResult)) {
|
|
20489
20489
|
promisedIsTypeOfResults[i] = isTypeOfResult;
|
|
20490
20490
|
} else if (isTypeOfResult) {
|
|
@@ -20503,11 +20503,11 @@ var require_execute = __commonJS({
|
|
|
20503
20503
|
}
|
|
20504
20504
|
};
|
|
20505
20505
|
exports2.defaultTypeResolver = defaultTypeResolver;
|
|
20506
|
-
var defaultFieldResolver = function defaultFieldResolver2(source, args, contextValue,
|
|
20506
|
+
var defaultFieldResolver = function defaultFieldResolver2(source, args, contextValue, info2) {
|
|
20507
20507
|
if ((0, _isObjectLike.default)(source) || typeof source === "function") {
|
|
20508
|
-
var property = source[
|
|
20508
|
+
var property = source[info2.fieldName];
|
|
20509
20509
|
if (typeof property === "function") {
|
|
20510
|
-
return source[
|
|
20510
|
+
return source[info2.fieldName](args, contextValue, info2);
|
|
20511
20511
|
}
|
|
20512
20512
|
return property;
|
|
20513
20513
|
}
|
|
@@ -21484,8 +21484,8 @@ var require_subscribe = __commonJS({
|
|
|
21484
21484
|
}
|
|
21485
21485
|
var resolveFn = fieldDef.subscribe || exeContext.fieldResolver;
|
|
21486
21486
|
var path = (0, _Path.addPath)(void 0, responseName);
|
|
21487
|
-
var
|
|
21488
|
-
var result = (0, _execute.resolveFieldValueOrError)(exeContext, fieldDef, fieldNodes, resolveFn, rootValue,
|
|
21487
|
+
var info2 = (0, _execute.buildResolveInfo)(exeContext, fieldDef, fieldNodes, type, path);
|
|
21488
|
+
var result = (0, _execute.resolveFieldValueOrError)(exeContext, fieldDef, fieldNodes, resolveFn, rootValue, info2);
|
|
21489
21489
|
return Promise.resolve(result).then(function(eventStream) {
|
|
21490
21490
|
if (eventStream instanceof Error) {
|
|
21491
21491
|
return {
|
|
@@ -32389,71 +32389,16 @@ async function getActivationState(udid) {
|
|
|
32389
32389
|
}
|
|
32390
32390
|
|
|
32391
32391
|
// src/logic/actions/device.ts
|
|
32392
|
-
var
|
|
32393
|
-
var
|
|
32394
|
-
|
|
32395
|
-
// src/logic/dataParser.ts
|
|
32396
|
-
function parsePlistOutput(output) {
|
|
32397
|
-
const result = {};
|
|
32398
|
-
const lines = output.split("\n");
|
|
32399
|
-
for (const line of lines) {
|
|
32400
|
-
const colonIndex = line.indexOf(":");
|
|
32401
|
-
if (colonIndex > 0) {
|
|
32402
|
-
const key = line.substring(0, colonIndex).trim();
|
|
32403
|
-
const value = line.substring(colonIndex + 1).trim();
|
|
32404
|
-
result[key] = value;
|
|
32405
|
-
}
|
|
32406
|
-
}
|
|
32407
|
-
return result;
|
|
32408
|
-
}
|
|
32409
|
-
function parseAppList(output) {
|
|
32410
|
-
const apps = [];
|
|
32411
|
-
const lines = output.trim().split("\n");
|
|
32412
|
-
for (const line of lines) {
|
|
32413
|
-
const match = line.match(/^([^,]+),\s*([^,]+),\s*"?([^"]+)"?/);
|
|
32414
|
-
if (match) {
|
|
32415
|
-
apps.push({
|
|
32416
|
-
bundleId: match[1].trim(),
|
|
32417
|
-
version: match[2].trim(),
|
|
32418
|
-
displayName: match[3].trim(),
|
|
32419
|
-
bundleVersion: ""
|
|
32420
|
-
});
|
|
32421
|
-
}
|
|
32422
|
-
}
|
|
32423
|
-
return apps;
|
|
32424
|
-
}
|
|
32392
|
+
var import_node_fs3 = require("node:fs");
|
|
32393
|
+
var import_node_path7 = require("node:path");
|
|
32425
32394
|
|
|
32426
|
-
// src/logic/
|
|
32427
|
-
|
|
32428
|
-
|
|
32429
|
-
|
|
32430
|
-
if (!result) {
|
|
32431
|
-
throw new Error("Failed to get device info");
|
|
32432
|
-
}
|
|
32433
|
-
const props = parsePlistOutput(result.stdout);
|
|
32434
|
-
return {
|
|
32435
|
-
deviceName: props.DeviceName || "",
|
|
32436
|
-
productType: props.ProductType || "",
|
|
32437
|
-
productVersion: props.ProductVersion || "",
|
|
32438
|
-
buildVersion: props.BuildVersion || "",
|
|
32439
|
-
serialNumber: props.SerialNumber || "",
|
|
32440
|
-
udid: props.UniqueDeviceID || udid,
|
|
32441
|
-
wifiAddress: props.WiFiAddress || "",
|
|
32442
|
-
bluetoothAddress: props.BluetoothAddress || "",
|
|
32443
|
-
phoneNumber: props.PhoneNumber || "",
|
|
32444
|
-
cpuArchitecture: props.CPUArchitecture || "",
|
|
32445
|
-
hardwareModel: props.HardwareModel || "",
|
|
32446
|
-
modelNumber: props.ModelNumber || "",
|
|
32447
|
-
regionInfo: props.RegionInfo || "",
|
|
32448
|
-
timeZone: props.TimeZone || "",
|
|
32449
|
-
uniqueChipID: props.UniqueChipID || "",
|
|
32450
|
-
isPaired: true
|
|
32451
|
-
// If we can get info, device is paired
|
|
32452
|
-
};
|
|
32453
|
-
}
|
|
32395
|
+
// src/logic/activationFlow.ts
|
|
32396
|
+
var import_promises2 = require("node:fs/promises");
|
|
32397
|
+
var import_node_os2 = require("node:os");
|
|
32398
|
+
var import_node_path6 = require("node:path");
|
|
32454
32399
|
|
|
32455
32400
|
// src/utils/mdmClient.ts
|
|
32456
|
-
var
|
|
32401
|
+
var import_node_path3 = require("node:path");
|
|
32457
32402
|
|
|
32458
32403
|
// ../../node_modules/.pnpm/graphql-request@5.2.0_encoding@0.1.13_graphql@14.7.0/node_modules/graphql-request/build/esm/defaultJsonSerializer.js
|
|
32459
32404
|
var defaultJsonSerializer = {
|
|
@@ -33223,7 +33168,7 @@ function createMdmClient(config) {
|
|
|
33223
33168
|
}
|
|
33224
33169
|
async function createMDMClient() {
|
|
33225
33170
|
const endpoint = process.env.MDM_ENDPOINT;
|
|
33226
|
-
const credPath = (0,
|
|
33171
|
+
const credPath = (0, import_node_path3.join)(getResourcesPath(), "@clientLocal.json");
|
|
33227
33172
|
if (!endpoint || !credPath) {
|
|
33228
33173
|
return void 0;
|
|
33229
33174
|
}
|
|
@@ -33236,451 +33181,92 @@ async function createMDMClient() {
|
|
|
33236
33181
|
});
|
|
33237
33182
|
}
|
|
33238
33183
|
|
|
33239
|
-
// src/
|
|
33240
|
-
|
|
33241
|
-
|
|
33242
|
-
|
|
33243
|
-
|
|
33244
|
-
|
|
33245
|
-
|
|
33246
|
-
|
|
33247
|
-
|
|
33248
|
-
|
|
33249
|
-
|
|
33250
|
-
|
|
33251
|
-
|
|
33252
|
-
async function trustDevice(udid, timeout2 = 6e4, onWaitingForTrust) {
|
|
33253
|
-
logTask(`Trusting device ${udid}`);
|
|
33254
|
-
if (await isPaired(udid)) {
|
|
33255
|
-
logInfo(`Device ${udid} is already trusted`);
|
|
33256
|
-
return true;
|
|
33257
|
-
}
|
|
33258
|
-
logInfo(`Initiating pairing for device ${udid}`);
|
|
33259
|
-
try {
|
|
33260
|
-
const pairResult = await pair(udid);
|
|
33261
|
-
if (pairResult) {
|
|
33262
|
-
logInfo(`Device ${udid} paired successfully`);
|
|
33263
|
-
return true;
|
|
33264
|
-
}
|
|
33265
|
-
} catch (error) {
|
|
33266
|
-
logError(`Pairing failed with ${udid}: ${error}`);
|
|
33184
|
+
// src/utils/wifiProfile.ts
|
|
33185
|
+
var import_node_crypto2 = require("node:crypto");
|
|
33186
|
+
|
|
33187
|
+
// src/utils/templateLoader.ts
|
|
33188
|
+
var import_node_fs2 = require("node:fs");
|
|
33189
|
+
var import_promises = require("node:fs/promises");
|
|
33190
|
+
var import_node_path4 = require("node:path");
|
|
33191
|
+
var import_node_url = require("node:url");
|
|
33192
|
+
var import_meta = {};
|
|
33193
|
+
function resolveEnvPlistDir() {
|
|
33194
|
+
const envPath = (0, import_node_path4.join)(getResourcesPath(), "plist");
|
|
33195
|
+
if (!(0, import_node_fs2.existsSync)(envPath)) {
|
|
33196
|
+
return null;
|
|
33267
33197
|
}
|
|
33268
|
-
|
|
33269
|
-
|
|
33270
|
-
|
|
33271
|
-
await waitForPairing(udid, timeout2, 1e3);
|
|
33272
|
-
logInfo(`Device ${udid} is now trusted`);
|
|
33273
|
-
return true;
|
|
33274
|
-
} catch {
|
|
33275
|
-
logInfo(`Timeout waiting for trust acceptance on device ${udid}`);
|
|
33276
|
-
return false;
|
|
33198
|
+
const absolutePath = (0, import_node_path4.isAbsolute)(envPath) ? envPath : (0, import_node_path4.join)(process.cwd(), envPath);
|
|
33199
|
+
if ((0, import_node_fs2.existsSync)(absolutePath)) {
|
|
33200
|
+
return absolutePath;
|
|
33277
33201
|
}
|
|
33202
|
+
return null;
|
|
33278
33203
|
}
|
|
33279
|
-
|
|
33280
|
-
|
|
33281
|
-
|
|
33282
|
-
while (Date.now() - startTime < timeout2) {
|
|
33283
|
-
if (await isPaired(udid)) {
|
|
33284
|
-
logInfo(`Device ${udid} is now paired`);
|
|
33285
|
-
return true;
|
|
33286
|
-
}
|
|
33287
|
-
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
33204
|
+
function getPlistDir(overrideDir) {
|
|
33205
|
+
if (overrideDir) {
|
|
33206
|
+
return (0, import_node_path4.resolve)(overrideDir);
|
|
33288
33207
|
}
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
|
|
33292
|
-
logTask(`Initiating pairing for device ${udid}`);
|
|
33293
|
-
try {
|
|
33294
|
-
const result = await runIDeviceTool("idevicepair", ["-u", udid, "pair"]);
|
|
33295
|
-
if (!result) {
|
|
33296
|
-
return false;
|
|
33297
|
-
}
|
|
33298
|
-
return result.stdout.toLowerCase().includes("success");
|
|
33299
|
-
} catch (error) {
|
|
33300
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33301
|
-
if (errorMsg.includes("Please accept the trust dialog")) {
|
|
33302
|
-
return false;
|
|
33303
|
-
}
|
|
33304
|
-
throw error;
|
|
33208
|
+
const envPlistDir = resolveEnvPlistDir();
|
|
33209
|
+
if (envPlistDir) {
|
|
33210
|
+
return envPlistDir;
|
|
33305
33211
|
}
|
|
33306
|
-
|
|
33307
|
-
async function unpair(udid) {
|
|
33308
|
-
logTask(`Un-pairing device ${udid}`);
|
|
33212
|
+
let baseDir;
|
|
33309
33213
|
try {
|
|
33310
|
-
|
|
33311
|
-
|
|
33312
|
-
|
|
33214
|
+
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
33215
|
+
const currentFile = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
33216
|
+
baseDir = (0, import_node_path4.dirname)(currentFile);
|
|
33217
|
+
} else {
|
|
33218
|
+
baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
33313
33219
|
}
|
|
33314
|
-
return result.stdout.toLowerCase().includes("success");
|
|
33315
33220
|
} catch {
|
|
33316
|
-
|
|
33221
|
+
baseDir = process.cwd();
|
|
33317
33222
|
}
|
|
33318
|
-
|
|
33319
|
-
|
|
33320
|
-
|
|
33321
|
-
async function installLocalApp(ipaPath, udid) {
|
|
33322
|
-
logTask(`Installing app ${ipaPath} on device ${udid}`);
|
|
33323
|
-
await runIDeviceTool("ideviceinstaller", ["-u", udid, "install", ipaPath]);
|
|
33324
|
-
}
|
|
33325
|
-
async function installManagedApp(ipaPath, udid, timeBetweenInstalls, options) {
|
|
33326
|
-
await installLocalApp(ipaPath, udid);
|
|
33327
|
-
const client = await createMDMClient();
|
|
33328
|
-
logTask("Installing app via MDM for management takeover");
|
|
33329
|
-
await new Promise((resolve2) => setTimeout(resolve2, timeBetweenInstalls));
|
|
33330
|
-
if (client) {
|
|
33331
|
-
client.installApp(udid, options);
|
|
33223
|
+
const sourcePlistDir = (0, import_node_path4.join)(baseDir, "../plist");
|
|
33224
|
+
if ((0, import_node_fs2.existsSync)(sourcePlistDir)) {
|
|
33225
|
+
return sourcePlistDir;
|
|
33332
33226
|
}
|
|
33333
|
-
|
|
33334
|
-
|
|
33335
|
-
|
|
33336
|
-
if (!await isPaired(udid)) {
|
|
33337
|
-
await waitForPairing(udid, 1e4);
|
|
33227
|
+
const distPlistDir = (0, import_node_path4.join)(baseDir, "../plist");
|
|
33228
|
+
if ((0, import_node_fs2.existsSync)(distPlistDir)) {
|
|
33229
|
+
return distPlistDir;
|
|
33338
33230
|
}
|
|
33339
|
-
|
|
33340
|
-
|
|
33341
|
-
|
|
33342
|
-
logTask(`Listing apps on device ${udid}`);
|
|
33343
|
-
if (!await isPaired(udid)) {
|
|
33344
|
-
await waitForPairing(udid, 1e4);
|
|
33231
|
+
const distPlistDir2 = (0, import_node_path4.join)(baseDir, "../dist/plist");
|
|
33232
|
+
if ((0, import_node_fs2.existsSync)(distPlistDir2)) {
|
|
33233
|
+
return distPlistDir2;
|
|
33345
33234
|
}
|
|
33346
|
-
|
|
33347
|
-
|
|
33348
|
-
|
|
33349
|
-
|
|
33350
|
-
|
|
33351
|
-
|
|
33352
|
-
return
|
|
33353
|
-
} catch {
|
|
33354
|
-
return [];
|
|
33235
|
+
const srcPlistFallback = (0, import_node_path4.join)(process.cwd(), "src/plist");
|
|
33236
|
+
if ((0, import_node_fs2.existsSync)(srcPlistFallback)) {
|
|
33237
|
+
return srcPlistFallback;
|
|
33238
|
+
}
|
|
33239
|
+
const distPlistFallback = (0, import_node_path4.join)(process.cwd(), "dist/plist");
|
|
33240
|
+
if ((0, import_node_fs2.existsSync)(distPlistFallback)) {
|
|
33241
|
+
return distPlistFallback;
|
|
33355
33242
|
}
|
|
33243
|
+
return (0, import_node_path4.join)(process.cwd(), "src/plist");
|
|
33356
33244
|
}
|
|
33357
|
-
async function
|
|
33358
|
-
|
|
33359
|
-
const
|
|
33360
|
-
return
|
|
33245
|
+
async function loadTemplate(templateName, plistDir) {
|
|
33246
|
+
const templatePath = (0, import_node_path4.join)(getPlistDir(plistDir), templateName);
|
|
33247
|
+
const content = await (0, import_promises.readFile)(templatePath, "utf-8");
|
|
33248
|
+
return content;
|
|
33361
33249
|
}
|
|
33362
|
-
|
|
33363
|
-
|
|
33364
|
-
|
|
33365
|
-
|
|
33366
|
-
|
|
33367
|
-
|
|
33368
|
-
} catch {
|
|
33250
|
+
function processTemplate(template, variables) {
|
|
33251
|
+
let result = template;
|
|
33252
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_match, key, content) => {
|
|
33253
|
+
const value = variables[key];
|
|
33254
|
+
if (value && value !== false && value !== "" && value !== null && value !== void 0) {
|
|
33255
|
+
return processTemplate(content, variables);
|
|
33369
33256
|
}
|
|
33370
|
-
|
|
33371
|
-
|
|
33372
|
-
|
|
33257
|
+
return "";
|
|
33258
|
+
});
|
|
33259
|
+
result = result.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
33260
|
+
const value = variables[key];
|
|
33261
|
+
if (value === void 0 || value === null) {
|
|
33262
|
+
return "";
|
|
33373
33263
|
}
|
|
33374
|
-
|
|
33375
|
-
|
|
33376
|
-
|
|
33377
|
-
|
|
33378
|
-
|
|
33379
|
-
|
|
33380
|
-
}
|
|
33381
|
-
}
|
|
33382
|
-
async function launchApp(bundleId, args, udid) {
|
|
33383
|
-
logTask(`Launching app ${bundleId} on device ${udid}`);
|
|
33384
|
-
if (!await isPaired(udid)) {
|
|
33385
|
-
await waitForPairing(udid, 1e4);
|
|
33386
|
-
}
|
|
33387
|
-
const installed = await isAppInstalled(bundleId, udid);
|
|
33388
|
-
if (!installed) {
|
|
33389
|
-
throw new Error(
|
|
33390
|
-
`App "${bundleId}" is not installed on the device. Install the app first or verify the bundle identifier is correct.`
|
|
33391
|
-
);
|
|
33392
|
-
}
|
|
33393
|
-
await wakeDevice(udid);
|
|
33394
|
-
try {
|
|
33395
|
-
logInfo(`Attempting to launch ${bundleId} using idevicedebug...`);
|
|
33396
|
-
const result = await runIDeviceTool("idevicedebug", ["-u", udid, "run", bundleId, ...args]);
|
|
33397
|
-
const output = (result?.stdout ?? "") + (result?.stderr ?? "");
|
|
33398
|
-
if (output.trim()) {
|
|
33399
|
-
logInfo(`idevicedebug output: ${output.substring(0, 200)}`);
|
|
33400
|
-
}
|
|
33401
|
-
if (output.toLowerCase().includes("could not start") && output.toLowerCase().includes("debugserver")) {
|
|
33402
|
-
logInfo("idevicedebug requires debugserver, falling back to pymobiledevice3...");
|
|
33403
|
-
throw new Error("debugserver_not_available");
|
|
33404
|
-
}
|
|
33405
|
-
logInfo(`App ${bundleId} launched successfully using idevicedebug`);
|
|
33406
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
33407
|
-
return;
|
|
33408
|
-
} catch (error) {
|
|
33409
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33410
|
-
if (errorMsg.includes("debugserver_not_available") || errorMsg.toLowerCase().includes("could not start") || errorMsg.toLowerCase().includes("debugserver")) {
|
|
33411
|
-
logInfo("idevicedebug failed, trying pymobiledevice3 for iOS 17+...");
|
|
33412
|
-
await launchAppWithPymobiledevice3(bundleId, args, udid);
|
|
33413
|
-
return;
|
|
33414
|
-
}
|
|
33415
|
-
throw error;
|
|
33416
|
-
}
|
|
33417
|
-
}
|
|
33418
|
-
async function launchAppWithPymobiledevice3(bundleId, args, udid) {
|
|
33419
|
-
logTask(`Launching app ${bundleId} using pymobiledevice3`);
|
|
33420
|
-
const { exec } = await import("node:child_process");
|
|
33421
|
-
const { promisify: promisify3 } = await import("node:util");
|
|
33422
|
-
const execAsync2 = promisify3(exec);
|
|
33423
|
-
try {
|
|
33424
|
-
let cmdArgs = [
|
|
33425
|
-
"-m",
|
|
33426
|
-
"pymobiledevice3",
|
|
33427
|
-
"developer",
|
|
33428
|
-
"dvt",
|
|
33429
|
-
"launch",
|
|
33430
|
-
"--udid",
|
|
33431
|
-
udid,
|
|
33432
|
-
"--kill-existing",
|
|
33433
|
-
// Kill existing instance to bring app to foreground
|
|
33434
|
-
bundleId,
|
|
33435
|
-
...args
|
|
33436
|
-
];
|
|
33437
|
-
let command = `python ${cmdArgs.map((a) => `"${a}"`).join(" ")}`;
|
|
33438
|
-
logInfo(`Executing: ${command}`);
|
|
33439
|
-
const result = await execAsync2(command, {
|
|
33440
|
-
windowsHide: true,
|
|
33441
|
-
encoding: "utf8",
|
|
33442
|
-
timeout: 3e4
|
|
33443
|
-
// 30 second timeout
|
|
33444
|
-
});
|
|
33445
|
-
const output = result.stdout.toString() + result.stderr.toString();
|
|
33446
|
-
if (output.trim()) {
|
|
33447
|
-
logInfo(`pymobiledevice3 output: ${output.substring(0, 200)}`);
|
|
33448
|
-
}
|
|
33449
|
-
if (output.toLowerCase().includes("developer mode") && output.toLowerCase().includes("not enabled")) {
|
|
33450
|
-
throw new Error(
|
|
33451
|
-
"Developer Mode is not enabled on the device.\nPlease enable it: Settings \u2192 Privacy & Security \u2192 Developer Mode \u2192 Enable"
|
|
33452
|
-
);
|
|
33453
|
-
}
|
|
33454
|
-
if (output.toLowerCase().includes("tunneld") && (output.toLowerCase().includes("unable to connect") || output.toLowerCase().includes("invalidserviceerror"))) {
|
|
33455
|
-
logInfo("Tunnel required, retrying with tunnel option...");
|
|
33456
|
-
cmdArgs = [
|
|
33457
|
-
"-m",
|
|
33458
|
-
"pymobiledevice3",
|
|
33459
|
-
"developer",
|
|
33460
|
-
"dvt",
|
|
33461
|
-
"launch",
|
|
33462
|
-
"--udid",
|
|
33463
|
-
udid,
|
|
33464
|
-
"--tunnel",
|
|
33465
|
-
udid,
|
|
33466
|
-
// Use UDID for tunnel
|
|
33467
|
-
"--kill-existing",
|
|
33468
|
-
bundleId,
|
|
33469
|
-
...args
|
|
33470
|
-
];
|
|
33471
|
-
command = `python ${cmdArgs.map((a) => `"${a}"`).join(" ")}`;
|
|
33472
|
-
logInfo(`Retrying with tunnel: ${command}`);
|
|
33473
|
-
try {
|
|
33474
|
-
const retryResult = await execAsync2(command, {
|
|
33475
|
-
windowsHide: true,
|
|
33476
|
-
encoding: "utf8",
|
|
33477
|
-
timeout: 3e4
|
|
33478
|
-
});
|
|
33479
|
-
const retryOutput = retryResult.stdout.toString() + retryResult.stderr.toString();
|
|
33480
|
-
if (retryOutput.trim()) {
|
|
33481
|
-
logInfo(`pymobiledevice3 retry output: ${retryOutput.substring(0, 200)}`);
|
|
33482
|
-
}
|
|
33483
|
-
if (retryOutput.toLowerCase().includes("tunneld") && retryOutput.toLowerCase().includes("unable to connect")) {
|
|
33484
|
-
throw new Error(
|
|
33485
|
-
"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\n python -m pymobiledevice3 remote tunneld\nOr ensure Developer Mode is enabled and device is unlocked."
|
|
33486
|
-
);
|
|
33487
|
-
}
|
|
33488
|
-
logInfo(`App ${bundleId} launched successfully using pymobiledevice3 with tunnel`);
|
|
33489
|
-
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
33490
|
-
return;
|
|
33491
|
-
} catch {
|
|
33492
|
-
throw new Error(
|
|
33493
|
-
"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\n python -m pymobiledevice3 remote tunneld\nOr ensure Developer Mode is enabled and device is unlocked."
|
|
33494
|
-
);
|
|
33495
|
-
}
|
|
33496
|
-
}
|
|
33497
|
-
if (output.toLowerCase().includes("not found") || output.toLowerCase().includes("command not found") || output.toLowerCase().includes("cannot find")) {
|
|
33498
|
-
throw new Error(
|
|
33499
|
-
"pymobiledevice3 is not installed.\nInstall it with: python -m pip install --user pymobiledevice3"
|
|
33500
|
-
);
|
|
33501
|
-
}
|
|
33502
|
-
if (output.toLowerCase().includes("error") && !output.toLowerCase().includes("warning")) {
|
|
33503
|
-
logInfo(`Warning: pymobiledevice3 reported errors: ${output.substring(0, 300)}`);
|
|
33504
|
-
}
|
|
33505
|
-
logInfo(`App ${bundleId} launched successfully using pymobiledevice3`);
|
|
33506
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
33507
|
-
} catch (error) {
|
|
33508
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33509
|
-
if (errorMsg.includes("not found") || errorMsg.includes("command not found") || errorMsg.includes("cannot find") || errorMsg.includes("No module named")) {
|
|
33510
|
-
throw new Error(
|
|
33511
|
-
"pymobiledevice3 is not installed or Python is not available.\nInstall it with: python -m pip install --user pymobiledevice3\nFor iOS 17+, Developer Mode must also be enabled on the device."
|
|
33512
|
-
);
|
|
33513
|
-
}
|
|
33514
|
-
throw error;
|
|
33515
|
-
}
|
|
33516
|
-
}
|
|
33517
|
-
|
|
33518
|
-
// src/logic/actions/proxy.ts
|
|
33519
|
-
var import_node_child_process2 = require("node:child_process");
|
|
33520
|
-
var import_node_path5 = require("node:path");
|
|
33521
|
-
function startPortForward(localPort, devicePort, udid, startupTimeout = 500) {
|
|
33522
|
-
return new Promise((resolve2, reject) => {
|
|
33523
|
-
logTask(`Starting port forward ${localPort} -> ${devicePort} for device ${udid}`);
|
|
33524
|
-
const binPath = getResourcesBinPath();
|
|
33525
|
-
const ext = process.platform === "win32" ? ".exe" : "";
|
|
33526
|
-
const toolPath = binPath ? (0, import_node_path5.join)(binPath, `iproxy${ext}`) : `iproxy${ext}`;
|
|
33527
|
-
const spawnOptions = {
|
|
33528
|
-
windowsHide: true,
|
|
33529
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
33530
|
-
};
|
|
33531
|
-
if (binPath) {
|
|
33532
|
-
spawnOptions.cwd = binPath;
|
|
33533
|
-
}
|
|
33534
|
-
logInfo(`Spawning iproxy with path: ${toolPath}`);
|
|
33535
|
-
logInfo(`Arguments: ${[localPort.toString(), devicePort.toString(), "-u", udid].join(" ")}`);
|
|
33536
|
-
logInfo(`Options: ${JSON.stringify(spawnOptions)}`);
|
|
33537
|
-
const child = (0, import_node_child_process2.spawn)(
|
|
33538
|
-
toolPath,
|
|
33539
|
-
[localPort.toString(), devicePort.toString(), "-u", udid],
|
|
33540
|
-
spawnOptions
|
|
33541
|
-
);
|
|
33542
|
-
let hasResolved = false;
|
|
33543
|
-
let stderrOutput = "";
|
|
33544
|
-
child.stdout?.on("data", (data) => {
|
|
33545
|
-
logTask(`${data.toString()}`);
|
|
33546
|
-
});
|
|
33547
|
-
child.stderr?.on("data", (data) => {
|
|
33548
|
-
logError(`${data.toString()}`);
|
|
33549
|
-
const msg = data.toString();
|
|
33550
|
-
stderrOutput += msg;
|
|
33551
|
-
if (msg.toLowerCase().includes("error") && !hasResolved) {
|
|
33552
|
-
hasResolved = true;
|
|
33553
|
-
child.kill();
|
|
33554
|
-
reject(new Error(`Port forwarding failed: ${msg}`));
|
|
33555
|
-
}
|
|
33556
|
-
});
|
|
33557
|
-
child.on("error", (error) => {
|
|
33558
|
-
if (!hasResolved) {
|
|
33559
|
-
hasResolved = true;
|
|
33560
|
-
reject(new Error(`Failed to start iproxy: ${error.message}`));
|
|
33561
|
-
}
|
|
33562
|
-
});
|
|
33563
|
-
child.on("exit", (code) => {
|
|
33564
|
-
if (!hasResolved) {
|
|
33565
|
-
hasResolved = true;
|
|
33566
|
-
if (code !== 0 && code !== null) {
|
|
33567
|
-
reject(new Error(`iproxy exited with code ${code}: ${stderrOutput}`));
|
|
33568
|
-
}
|
|
33569
|
-
}
|
|
33570
|
-
});
|
|
33571
|
-
setTimeout(() => {
|
|
33572
|
-
if (!hasResolved) {
|
|
33573
|
-
hasResolved = true;
|
|
33574
|
-
logTask(`Port forward started: ${localPort} -> ${devicePort} for device ${udid}`);
|
|
33575
|
-
resolve2({
|
|
33576
|
-
result: {
|
|
33577
|
-
localPort,
|
|
33578
|
-
devicePort
|
|
33579
|
-
},
|
|
33580
|
-
process: child
|
|
33581
|
-
});
|
|
33582
|
-
}
|
|
33583
|
-
}, startupTimeout);
|
|
33584
|
-
});
|
|
33585
|
-
}
|
|
33586
|
-
function killPortForwardProcess(process2) {
|
|
33587
|
-
if (process2 && !process2.killed) {
|
|
33588
|
-
logTask("Killing port forward process");
|
|
33589
|
-
process2.kill();
|
|
33590
|
-
}
|
|
33591
|
-
}
|
|
33592
|
-
|
|
33593
|
-
// src/logic/activationFlow.ts
|
|
33594
|
-
var import_promises2 = require("node:fs/promises");
|
|
33595
|
-
var import_node_os2 = require("node:os");
|
|
33596
|
-
var import_node_path7 = require("node:path");
|
|
33597
|
-
|
|
33598
|
-
// src/utils/wifiProfile.ts
|
|
33599
|
-
var import_node_crypto2 = require("node:crypto");
|
|
33600
|
-
|
|
33601
|
-
// src/utils/templateLoader.ts
|
|
33602
|
-
var import_node_fs3 = require("node:fs");
|
|
33603
|
-
var import_promises = require("node:fs/promises");
|
|
33604
|
-
var import_node_path6 = require("node:path");
|
|
33605
|
-
var import_node_url = require("node:url");
|
|
33606
|
-
var import_meta = {};
|
|
33607
|
-
function resolveEnvPlistDir() {
|
|
33608
|
-
const envPath = (0, import_node_path6.join)(getResourcesPath(), "plist");
|
|
33609
|
-
if (!(0, import_node_fs3.existsSync)(envPath)) {
|
|
33610
|
-
return null;
|
|
33611
|
-
}
|
|
33612
|
-
const absolutePath = (0, import_node_path6.isAbsolute)(envPath) ? envPath : (0, import_node_path6.join)(process.cwd(), envPath);
|
|
33613
|
-
if ((0, import_node_fs3.existsSync)(absolutePath)) {
|
|
33614
|
-
return absolutePath;
|
|
33615
|
-
}
|
|
33616
|
-
return null;
|
|
33617
|
-
}
|
|
33618
|
-
function getPlistDir(overrideDir) {
|
|
33619
|
-
if (overrideDir) {
|
|
33620
|
-
return (0, import_node_path6.resolve)(overrideDir);
|
|
33621
|
-
}
|
|
33622
|
-
const envPlistDir = resolveEnvPlistDir();
|
|
33623
|
-
if (envPlistDir) {
|
|
33624
|
-
return envPlistDir;
|
|
33625
|
-
}
|
|
33626
|
-
let baseDir;
|
|
33627
|
-
try {
|
|
33628
|
-
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
33629
|
-
const currentFile = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
33630
|
-
baseDir = (0, import_node_path6.dirname)(currentFile);
|
|
33631
|
-
} else {
|
|
33632
|
-
baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
33633
|
-
}
|
|
33634
|
-
} catch {
|
|
33635
|
-
baseDir = process.cwd();
|
|
33636
|
-
}
|
|
33637
|
-
const sourcePlistDir = (0, import_node_path6.join)(baseDir, "../plist");
|
|
33638
|
-
if ((0, import_node_fs3.existsSync)(sourcePlistDir)) {
|
|
33639
|
-
return sourcePlistDir;
|
|
33640
|
-
}
|
|
33641
|
-
const distPlistDir = (0, import_node_path6.join)(baseDir, "../plist");
|
|
33642
|
-
if ((0, import_node_fs3.existsSync)(distPlistDir)) {
|
|
33643
|
-
return distPlistDir;
|
|
33644
|
-
}
|
|
33645
|
-
const distPlistDir2 = (0, import_node_path6.join)(baseDir, "../dist/plist");
|
|
33646
|
-
if ((0, import_node_fs3.existsSync)(distPlistDir2)) {
|
|
33647
|
-
return distPlistDir2;
|
|
33648
|
-
}
|
|
33649
|
-
const srcPlistFallback = (0, import_node_path6.join)(process.cwd(), "src/plist");
|
|
33650
|
-
if ((0, import_node_fs3.existsSync)(srcPlistFallback)) {
|
|
33651
|
-
return srcPlistFallback;
|
|
33652
|
-
}
|
|
33653
|
-
const distPlistFallback = (0, import_node_path6.join)(process.cwd(), "dist/plist");
|
|
33654
|
-
if ((0, import_node_fs3.existsSync)(distPlistFallback)) {
|
|
33655
|
-
return distPlistFallback;
|
|
33656
|
-
}
|
|
33657
|
-
return (0, import_node_path6.join)(process.cwd(), "src/plist");
|
|
33658
|
-
}
|
|
33659
|
-
async function loadTemplate(templateName, plistDir) {
|
|
33660
|
-
const templatePath = (0, import_node_path6.join)(getPlistDir(plistDir), templateName);
|
|
33661
|
-
const content = await (0, import_promises.readFile)(templatePath, "utf-8");
|
|
33662
|
-
return content;
|
|
33663
|
-
}
|
|
33664
|
-
function processTemplate(template, variables) {
|
|
33665
|
-
let result = template;
|
|
33666
|
-
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_match, key, content) => {
|
|
33667
|
-
const value = variables[key];
|
|
33668
|
-
if (value && value !== false && value !== "" && value !== null && value !== void 0) {
|
|
33669
|
-
return processTemplate(content, variables);
|
|
33670
|
-
}
|
|
33671
|
-
return "";
|
|
33672
|
-
});
|
|
33673
|
-
result = result.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
33674
|
-
const value = variables[key];
|
|
33675
|
-
if (value === void 0 || value === null) {
|
|
33676
|
-
return "";
|
|
33677
|
-
}
|
|
33678
|
-
if (typeof value === "boolean") {
|
|
33679
|
-
return value ? "true" : "false";
|
|
33680
|
-
}
|
|
33681
|
-
return escapeXml(String(value));
|
|
33682
|
-
});
|
|
33683
|
-
return result;
|
|
33264
|
+
if (typeof value === "boolean") {
|
|
33265
|
+
return value ? "true" : "false";
|
|
33266
|
+
}
|
|
33267
|
+
return escapeXml(String(value));
|
|
33268
|
+
});
|
|
33269
|
+
return result;
|
|
33684
33270
|
}
|
|
33685
33271
|
function escapeXml(str) {
|
|
33686
33272
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -33811,10 +33397,11 @@ function parseWifiEapType(value) {
|
|
|
33811
33397
|
}
|
|
33812
33398
|
|
|
33813
33399
|
// src/logic/iosCli.ts
|
|
33814
|
-
var
|
|
33400
|
+
var import_node_child_process2 = require("node:child_process");
|
|
33401
|
+
var import_node_path5 = require("node:path");
|
|
33815
33402
|
function runIosCommand(iosBinaryPath, args) {
|
|
33816
33403
|
return new Promise((resolve2, reject) => {
|
|
33817
|
-
const child = (0,
|
|
33404
|
+
const child = (0, import_node_child_process2.spawn)(iosBinaryPath, args, {
|
|
33818
33405
|
windowsHide: true,
|
|
33819
33406
|
stdio: ["ignore", "pipe", "pipe"]
|
|
33820
33407
|
});
|
|
@@ -33970,7 +33557,15 @@ function createIosCli(iosBinaryPath) {
|
|
|
33970
33557
|
return runIosCommand(iosBinaryPath, ["profile", "remove", profileName, "--udid", deviceId]);
|
|
33971
33558
|
},
|
|
33972
33559
|
async skipSteps(deviceId) {
|
|
33973
|
-
|
|
33560
|
+
const resourcesDir2 = getResourcesPath();
|
|
33561
|
+
return runIosCommand(iosBinaryPath, [
|
|
33562
|
+
"prepare",
|
|
33563
|
+
"--skip-all",
|
|
33564
|
+
`--certfile=${(0, import_node_path5.join)(resourcesDir2, "cert.der")}`,
|
|
33565
|
+
`--orgname=${process.env.ORGANIZATION_NAME}`,
|
|
33566
|
+
"--udid",
|
|
33567
|
+
deviceId
|
|
33568
|
+
]);
|
|
33974
33569
|
},
|
|
33975
33570
|
async activate(deviceId) {
|
|
33976
33571
|
return runIosCommand(iosBinaryPath, ["activate", "--udid", deviceId]);
|
|
@@ -33999,209 +33594,635 @@ function createIosCli(iosBinaryPath) {
|
|
|
33999
33594
|
};
|
|
34000
33595
|
}
|
|
34001
33596
|
|
|
34002
|
-
// src/logic/activationFlow.ts
|
|
34003
|
-
var DEFAULT_RETRIES = 150;
|
|
34004
|
-
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
34005
|
-
var MCE_MDM_PROFILE_PREFIX = "com.mce.mdm";
|
|
34006
|
-
var ActivationFlow = class {
|
|
34007
|
-
iosCli;
|
|
34008
|
-
mdmClientPromise;
|
|
34009
|
-
constructor() {
|
|
34010
|
-
const iosBinaryPath = resolveIosBinaryPath();
|
|
34011
|
-
if (!iosBinaryPath) {
|
|
34012
|
-
throw new Error("iosBinaryPath is required. Provide iosBinaryPath or resourcesDir.");
|
|
33597
|
+
// src/logic/activationFlow.ts
|
|
33598
|
+
var DEFAULT_RETRIES = 150;
|
|
33599
|
+
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
33600
|
+
var MCE_MDM_PROFILE_PREFIX = "com.mce.mdm";
|
|
33601
|
+
var ActivationFlow = class {
|
|
33602
|
+
iosCli;
|
|
33603
|
+
mdmClientPromise;
|
|
33604
|
+
constructor() {
|
|
33605
|
+
const iosBinaryPath = resolveIosBinaryPath();
|
|
33606
|
+
if (!iosBinaryPath) {
|
|
33607
|
+
throw new Error("iosBinaryPath is required. Provide iosBinaryPath or resourcesDir.");
|
|
33608
|
+
}
|
|
33609
|
+
this.iosCli = createIosCli(iosBinaryPath);
|
|
33610
|
+
this.mdmClientPromise = createMDMClient();
|
|
33611
|
+
}
|
|
33612
|
+
async run(udid) {
|
|
33613
|
+
logTask(`Starting activation flow for device ${udid}`);
|
|
33614
|
+
const activationState = await this.getActivationState(udid);
|
|
33615
|
+
if (activationState === "Activated") {
|
|
33616
|
+
const isEnrolled = await this.isEnrolledToMceMdm(udid);
|
|
33617
|
+
if (isEnrolled) {
|
|
33618
|
+
logInfo("Device already activated and enrolled to MCE MDM. Skipping activation flow.");
|
|
33619
|
+
return async () => {
|
|
33620
|
+
};
|
|
33621
|
+
}
|
|
33622
|
+
} else if (activationState) {
|
|
33623
|
+
logInfo(`Activation state is ${activationState}, activating device`);
|
|
33624
|
+
await this.retryActivateCommand("activate device", () => this.iosCli.activate(udid));
|
|
33625
|
+
} else {
|
|
33626
|
+
await this.retryIosCommand("wipe", () => this.iosCli.wipe(udid));
|
|
33627
|
+
return void 0;
|
|
33628
|
+
}
|
|
33629
|
+
const wifiProfileIdentifier = await this.installWifiProfile(udid);
|
|
33630
|
+
await this.installMdmProfile(udid);
|
|
33631
|
+
await this.retryIosCommand("skip steps", () => this.iosCli.skipSteps(udid));
|
|
33632
|
+
return () => this.removeWifiProfile(udid, wifiProfileIdentifier);
|
|
33633
|
+
}
|
|
33634
|
+
async isEnrolledToMceMdm(udid) {
|
|
33635
|
+
const profiles = await this.listProfiles(udid);
|
|
33636
|
+
return profiles.some((profile) => isMceMdmProfile(profile));
|
|
33637
|
+
}
|
|
33638
|
+
async listProfiles(udid) {
|
|
33639
|
+
const result = await this.retry(
|
|
33640
|
+
"list profiles",
|
|
33641
|
+
() => this.iosCli.listProfiles(udid),
|
|
33642
|
+
(response) => response.raw.exitCode === 0
|
|
33643
|
+
);
|
|
33644
|
+
return result.profiles;
|
|
33645
|
+
}
|
|
33646
|
+
async installWifiProfile(udid) {
|
|
33647
|
+
const wifiProfile = await generateWifiProfileFromEnv();
|
|
33648
|
+
if (!wifiProfile) {
|
|
33649
|
+
return void 0;
|
|
33650
|
+
}
|
|
33651
|
+
const wifiProfilePath = await saveWifiProfileToTemp(wifiProfile);
|
|
33652
|
+
const wifiProfileIdentifier = getProfileIdentifierFromProfile(wifiProfile);
|
|
33653
|
+
await this.retryIosCommand(
|
|
33654
|
+
"install wifi profile",
|
|
33655
|
+
() => this.iosCli.installProfile(udid, wifiProfilePath)
|
|
33656
|
+
);
|
|
33657
|
+
await removeTempFile(wifiProfilePath, "wifi profile");
|
|
33658
|
+
return wifiProfileIdentifier;
|
|
33659
|
+
}
|
|
33660
|
+
async getActivationState(udid) {
|
|
33661
|
+
const infoResult = await this.retryIosCommand("device info", () => this.iosCli.info(udid));
|
|
33662
|
+
const activationState = getActivationState2(infoResult.output);
|
|
33663
|
+
if (!activationState) {
|
|
33664
|
+
logInfo("Activation state not found");
|
|
33665
|
+
}
|
|
33666
|
+
return activationState;
|
|
33667
|
+
}
|
|
33668
|
+
async installMdmProfile(udid) {
|
|
33669
|
+
const client = await this.requireMdmClient();
|
|
33670
|
+
logTask("Installing MDM enrollment profile");
|
|
33671
|
+
const enrollmentProfile = await this.retry(
|
|
33672
|
+
"generate mdm enrollment profile",
|
|
33673
|
+
() => client.generateEnrollmentProfile(udid),
|
|
33674
|
+
(result) => result.status === "OK" && Boolean(result.profile)
|
|
33675
|
+
);
|
|
33676
|
+
if (!enrollmentProfile.profile) {
|
|
33677
|
+
throw new Error("MDM enrollment profile missing from response");
|
|
33678
|
+
}
|
|
33679
|
+
const profilePath = await saveProfileToTemp(enrollmentProfile.profile, "mdm_profile");
|
|
33680
|
+
await this.retryIosCommand(
|
|
33681
|
+
"install mdm profile",
|
|
33682
|
+
() => this.iosCli.installProfile(udid, profilePath)
|
|
33683
|
+
);
|
|
33684
|
+
await removeTempFile(profilePath, "mdm profile");
|
|
33685
|
+
}
|
|
33686
|
+
async removeWifiProfile(udid, profileIdentifier) {
|
|
33687
|
+
if (!profileIdentifier) {
|
|
33688
|
+
return;
|
|
33689
|
+
}
|
|
33690
|
+
logTask("Removing WiFi profile");
|
|
33691
|
+
await this.retryIosCommand(
|
|
33692
|
+
"remove wifi profile",
|
|
33693
|
+
() => this.iosCli.removeProfile(udid, profileIdentifier)
|
|
33694
|
+
);
|
|
33695
|
+
}
|
|
33696
|
+
async requireMdmClient() {
|
|
33697
|
+
const client = await this.mdmClientPromise;
|
|
33698
|
+
if (!client) {
|
|
33699
|
+
throw new Error("MDM client not configured. Set mdm endpoint and credential path.");
|
|
33700
|
+
}
|
|
33701
|
+
return client;
|
|
33702
|
+
}
|
|
33703
|
+
async retryIosCommand(label, command) {
|
|
33704
|
+
return this.retry(label, command, (result) => result.exitCode === 0);
|
|
33705
|
+
}
|
|
33706
|
+
async retryActivateCommand(label, command) {
|
|
33707
|
+
return this.retry(label, command, (result) => isActivationSuccess(result));
|
|
33708
|
+
}
|
|
33709
|
+
async retry(label, command, isSuccess, retries = DEFAULT_RETRIES, retryDelayMs = DEFAULT_RETRY_DELAY_MS) {
|
|
33710
|
+
for (let attempt = 0; attempt < retries; attempt += 1) {
|
|
33711
|
+
try {
|
|
33712
|
+
const result = await command();
|
|
33713
|
+
if (isSuccess(result)) {
|
|
33714
|
+
return result;
|
|
33715
|
+
}
|
|
33716
|
+
} catch (error) {
|
|
33717
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33718
|
+
logError(`${label} failed: ${errorMsg}`);
|
|
33719
|
+
}
|
|
33720
|
+
logInfo(`Retrying ${label}... ${attempt + 1} of ${retries}`);
|
|
33721
|
+
await new Promise((resolve2) => setTimeout(resolve2, retryDelayMs));
|
|
33722
|
+
}
|
|
33723
|
+
throw new Error(`Failed to ${label} after ${retries} attempts`);
|
|
33724
|
+
}
|
|
33725
|
+
};
|
|
33726
|
+
async function saveProfileToTemp(profile, prefix) {
|
|
33727
|
+
const tempFilePath = (0, import_node_path6.join)((0, import_node_os2.tmpdir)(), `mce_${prefix}_${Date.now()}.mobileconfig`);
|
|
33728
|
+
await (0, import_promises2.writeFile)(tempFilePath, profile, "utf-8");
|
|
33729
|
+
logInfo(`Profile saved to: ${tempFilePath}`);
|
|
33730
|
+
return tempFilePath;
|
|
33731
|
+
}
|
|
33732
|
+
async function removeTempFile(filePath, label) {
|
|
33733
|
+
try {
|
|
33734
|
+
await (0, import_promises2.unlink)(filePath);
|
|
33735
|
+
logInfo(`Removed ${label} temp file: ${filePath}`);
|
|
33736
|
+
} catch (error) {
|
|
33737
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33738
|
+
logError(`Failed to remove ${label} temp file: ${errorMsg}`);
|
|
33739
|
+
}
|
|
33740
|
+
}
|
|
33741
|
+
function getProfileIdentifierFromProfile(profile) {
|
|
33742
|
+
const pattern = /<key>PayloadIdentifier<\/key>\s*<string>([^<]+)<\/string>/g;
|
|
33743
|
+
const matches = [];
|
|
33744
|
+
let match = pattern.exec(profile);
|
|
33745
|
+
while (match) {
|
|
33746
|
+
matches.push(match[1].trim());
|
|
33747
|
+
match = pattern.exec(profile);
|
|
33748
|
+
}
|
|
33749
|
+
if (matches.length === 0) {
|
|
33750
|
+
return void 0;
|
|
33751
|
+
}
|
|
33752
|
+
return matches[matches.length - 1];
|
|
33753
|
+
}
|
|
33754
|
+
function resolveIosBinaryPath() {
|
|
33755
|
+
const platform = process.platform;
|
|
33756
|
+
const binaryName = platform === "win32" ? "ios.exe" : "ios";
|
|
33757
|
+
return (0, import_node_path6.join)(getResourcesBinPath(), binaryName);
|
|
33758
|
+
}
|
|
33759
|
+
function getActivationState2(output) {
|
|
33760
|
+
if (!Array.isArray(output) || output.length === 0) {
|
|
33761
|
+
return void 0;
|
|
33762
|
+
}
|
|
33763
|
+
for (const item of output) {
|
|
33764
|
+
if (!item || typeof item !== "object") {
|
|
33765
|
+
continue;
|
|
33766
|
+
}
|
|
33767
|
+
if ("ActivationState" in item) {
|
|
33768
|
+
const value = item.ActivationState;
|
|
33769
|
+
return typeof value === "string" ? value : void 0;
|
|
33770
|
+
}
|
|
33771
|
+
if ("activationState" in item) {
|
|
33772
|
+
const value = item.activationState;
|
|
33773
|
+
return typeof value === "string" ? value : void 0;
|
|
33774
|
+
}
|
|
33775
|
+
}
|
|
33776
|
+
return void 0;
|
|
33777
|
+
}
|
|
33778
|
+
function isActivationSuccess(result) {
|
|
33779
|
+
if (result.exitCode !== 0) {
|
|
33780
|
+
return false;
|
|
33781
|
+
}
|
|
33782
|
+
if (result.logMessages.length === 0) {
|
|
33783
|
+
return true;
|
|
33784
|
+
}
|
|
33785
|
+
const hasFatal = result.logMessages.some((log) => log.level === "error");
|
|
33786
|
+
return !hasFatal;
|
|
33787
|
+
}
|
|
33788
|
+
function isMceMdmProfile(profile) {
|
|
33789
|
+
const identifier = profile.Identifier;
|
|
33790
|
+
if (!identifier) {
|
|
33791
|
+
return false;
|
|
33792
|
+
}
|
|
33793
|
+
if (!identifier.startsWith(MCE_MDM_PROFILE_PREFIX)) {
|
|
33794
|
+
return false;
|
|
33795
|
+
}
|
|
33796
|
+
if (profile.Manifest?.IsActive === false) {
|
|
33797
|
+
return false;
|
|
33798
|
+
}
|
|
33799
|
+
return true;
|
|
33800
|
+
}
|
|
33801
|
+
|
|
33802
|
+
// src/logic/dataParser.ts
|
|
33803
|
+
function parsePlistOutput(output) {
|
|
33804
|
+
const result = {};
|
|
33805
|
+
const lines = output.split("\n");
|
|
33806
|
+
for (const line of lines) {
|
|
33807
|
+
const colonIndex = line.indexOf(":");
|
|
33808
|
+
if (colonIndex > 0) {
|
|
33809
|
+
const key = line.substring(0, colonIndex).trim();
|
|
33810
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
33811
|
+
result[key] = value;
|
|
33812
|
+
}
|
|
33813
|
+
}
|
|
33814
|
+
return result;
|
|
33815
|
+
}
|
|
33816
|
+
function parseAppList(output) {
|
|
33817
|
+
const apps = [];
|
|
33818
|
+
const lines = output.trim().split("\n");
|
|
33819
|
+
for (const line of lines) {
|
|
33820
|
+
const match = line.match(/^([^,]+),\s*([^,]+),\s*"?([^"]+)"?/);
|
|
33821
|
+
if (match) {
|
|
33822
|
+
apps.push({
|
|
33823
|
+
bundleId: match[1].trim(),
|
|
33824
|
+
version: match[2].trim(),
|
|
33825
|
+
displayName: match[3].trim(),
|
|
33826
|
+
bundleVersion: ""
|
|
33827
|
+
});
|
|
33828
|
+
}
|
|
33829
|
+
}
|
|
33830
|
+
return apps;
|
|
33831
|
+
}
|
|
33832
|
+
|
|
33833
|
+
// src/logic/actions/device.ts
|
|
33834
|
+
async function getDeviceInfo(udid) {
|
|
33835
|
+
logTask(`Getting device info for ${udid}`);
|
|
33836
|
+
const result = await runIDeviceTool("ideviceinfo", ["-u", udid]);
|
|
33837
|
+
if (!result) {
|
|
33838
|
+
throw new Error("Failed to get device info");
|
|
33839
|
+
}
|
|
33840
|
+
const props = parsePlistOutput(result.stdout);
|
|
33841
|
+
return {
|
|
33842
|
+
deviceName: props.DeviceName || "",
|
|
33843
|
+
productType: props.ProductType || "",
|
|
33844
|
+
productVersion: props.ProductVersion || "",
|
|
33845
|
+
buildVersion: props.BuildVersion || "",
|
|
33846
|
+
serialNumber: props.SerialNumber || "",
|
|
33847
|
+
udid: props.UniqueDeviceID || udid,
|
|
33848
|
+
wifiAddress: props.WiFiAddress || "",
|
|
33849
|
+
bluetoothAddress: props.BluetoothAddress || "",
|
|
33850
|
+
phoneNumber: props.PhoneNumber || "",
|
|
33851
|
+
cpuArchitecture: props.CPUArchitecture || "",
|
|
33852
|
+
hardwareModel: props.HardwareModel || "",
|
|
33853
|
+
modelNumber: props.ModelNumber || "",
|
|
33854
|
+
regionInfo: props.RegionInfo || "",
|
|
33855
|
+
timeZone: props.TimeZone || "",
|
|
33856
|
+
uniqueChipID: props.UniqueChipID || "",
|
|
33857
|
+
isPaired: true
|
|
33858
|
+
// If we can get info, device is paired
|
|
33859
|
+
};
|
|
33860
|
+
}
|
|
33861
|
+
async function info(udid) {
|
|
33862
|
+
logTask(`Getting device info for ${udid}`);
|
|
33863
|
+
const iosBinaryPath = resolveIosBinaryPath();
|
|
33864
|
+
if (!iosBinaryPath) {
|
|
33865
|
+
throw new Error("iosBinaryPath is required. Provide iosBinaryPath or resourcesDir.");
|
|
33866
|
+
}
|
|
33867
|
+
const iosCli = createIosCli(iosBinaryPath);
|
|
33868
|
+
const result = await iosCli.info(udid);
|
|
33869
|
+
if (!result) {
|
|
33870
|
+
throw new Error("Failed to get device info");
|
|
33871
|
+
}
|
|
33872
|
+
return result.output[0];
|
|
33873
|
+
}
|
|
33874
|
+
|
|
33875
|
+
// src/logic/actions/pair.ts
|
|
33876
|
+
async function isPaired(udid) {
|
|
33877
|
+
logTask(`Checking pairing status for ${udid}`);
|
|
33878
|
+
try {
|
|
33879
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "validate"]);
|
|
33880
|
+
if (!result) {
|
|
33881
|
+
return false;
|
|
34013
33882
|
}
|
|
34014
|
-
|
|
34015
|
-
|
|
33883
|
+
return result.stdout.toLowerCase().includes("success");
|
|
33884
|
+
} catch {
|
|
33885
|
+
return false;
|
|
34016
33886
|
}
|
|
34017
|
-
|
|
34018
|
-
|
|
34019
|
-
|
|
34020
|
-
|
|
34021
|
-
|
|
34022
|
-
|
|
34023
|
-
logInfo("Device already activated and enrolled to MCE MDM. Skipping activation flow.");
|
|
34024
|
-
return async () => {
|
|
34025
|
-
};
|
|
34026
|
-
}
|
|
34027
|
-
} else if (activationState) {
|
|
34028
|
-
logInfo(`Activation state is ${activationState}, activating device`);
|
|
34029
|
-
await this.retryActivateCommand("activate device", () => this.iosCli.activate(udid));
|
|
34030
|
-
} else {
|
|
34031
|
-
await this.retryIosCommand("wipe", () => this.iosCli.wipe(udid));
|
|
34032
|
-
return void 0;
|
|
34033
|
-
}
|
|
34034
|
-
const wifiProfileIdentifier = await this.installWifiProfile(udid);
|
|
34035
|
-
await this.installMdmProfile(udid);
|
|
34036
|
-
await this.retryIosCommand("skip steps", () => this.iosCli.skipSteps(udid));
|
|
34037
|
-
return () => this.removeWifiProfile(udid, wifiProfileIdentifier);
|
|
33887
|
+
}
|
|
33888
|
+
async function trustDevice(udid, timeout2 = 6e4, onWaitingForTrust) {
|
|
33889
|
+
logTask(`Trusting device ${udid}`);
|
|
33890
|
+
if (await isPaired(udid)) {
|
|
33891
|
+
logInfo(`Device ${udid} is already trusted`);
|
|
33892
|
+
return true;
|
|
34038
33893
|
}
|
|
34039
|
-
|
|
34040
|
-
|
|
34041
|
-
|
|
33894
|
+
logInfo(`Initiating pairing for device ${udid}`);
|
|
33895
|
+
try {
|
|
33896
|
+
const pairResult = await pair(udid);
|
|
33897
|
+
if (pairResult) {
|
|
33898
|
+
logInfo(`Device ${udid} paired successfully`);
|
|
33899
|
+
return true;
|
|
33900
|
+
}
|
|
33901
|
+
} catch (error) {
|
|
33902
|
+
logError(`Pairing failed with ${udid}: ${error}`);
|
|
34042
33903
|
}
|
|
34043
|
-
|
|
34044
|
-
|
|
34045
|
-
|
|
34046
|
-
|
|
34047
|
-
|
|
34048
|
-
|
|
34049
|
-
|
|
33904
|
+
logInfo("Please accept the trust dialog on the device...");
|
|
33905
|
+
onWaitingForTrust?.();
|
|
33906
|
+
try {
|
|
33907
|
+
await waitForPairing(udid, timeout2, 1e3);
|
|
33908
|
+
logInfo(`Device ${udid} is now trusted`);
|
|
33909
|
+
return true;
|
|
33910
|
+
} catch {
|
|
33911
|
+
logInfo(`Timeout waiting for trust acceptance on device ${udid}`);
|
|
33912
|
+
return false;
|
|
34050
33913
|
}
|
|
34051
|
-
|
|
34052
|
-
|
|
34053
|
-
|
|
34054
|
-
|
|
33914
|
+
}
|
|
33915
|
+
async function waitForPairing(udid, timeout2 = 12e4, pollInterval = 1e3) {
|
|
33916
|
+
logTask(`Waiting for pairing on device ${udid}`);
|
|
33917
|
+
const startTime = Date.now();
|
|
33918
|
+
while (Date.now() - startTime < timeout2) {
|
|
33919
|
+
if (await isPaired(udid)) {
|
|
33920
|
+
logInfo(`Device ${udid} is now paired`);
|
|
33921
|
+
return true;
|
|
34055
33922
|
}
|
|
34056
|
-
|
|
34057
|
-
const wifiProfileIdentifier = getProfileIdentifierFromProfile(wifiProfile);
|
|
34058
|
-
await this.retryIosCommand(
|
|
34059
|
-
"install wifi profile",
|
|
34060
|
-
() => this.iosCli.installProfile(udid, wifiProfilePath)
|
|
34061
|
-
);
|
|
34062
|
-
await removeTempFile(wifiProfilePath, "wifi profile");
|
|
34063
|
-
return wifiProfileIdentifier;
|
|
33923
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
34064
33924
|
}
|
|
34065
|
-
|
|
34066
|
-
|
|
34067
|
-
|
|
34068
|
-
|
|
34069
|
-
|
|
33925
|
+
throw new Error(`Timeout waiting for device pairing after ${timeout2}ms`);
|
|
33926
|
+
}
|
|
33927
|
+
async function pair(udid) {
|
|
33928
|
+
logTask(`Initiating pairing for device ${udid}`);
|
|
33929
|
+
try {
|
|
33930
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "pair"]);
|
|
33931
|
+
if (!result) {
|
|
33932
|
+
return false;
|
|
34070
33933
|
}
|
|
34071
|
-
return
|
|
34072
|
-
}
|
|
34073
|
-
|
|
34074
|
-
|
|
34075
|
-
|
|
34076
|
-
const enrollmentProfile = await this.retry(
|
|
34077
|
-
"generate mdm enrollment profile",
|
|
34078
|
-
() => client.generateEnrollmentProfile(udid),
|
|
34079
|
-
(result) => result.status === "OK" && Boolean(result.profile)
|
|
34080
|
-
);
|
|
34081
|
-
if (!enrollmentProfile.profile) {
|
|
34082
|
-
throw new Error("MDM enrollment profile missing from response");
|
|
33934
|
+
return result.stdout.toLowerCase().includes("success");
|
|
33935
|
+
} catch (error) {
|
|
33936
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33937
|
+
if (errorMsg.includes("Please accept the trust dialog")) {
|
|
33938
|
+
return false;
|
|
34083
33939
|
}
|
|
34084
|
-
|
|
34085
|
-
await this.retryIosCommand(
|
|
34086
|
-
"install mdm profile",
|
|
34087
|
-
() => this.iosCli.installProfile(udid, profilePath)
|
|
34088
|
-
);
|
|
34089
|
-
await removeTempFile(profilePath, "mdm profile");
|
|
33940
|
+
throw error;
|
|
34090
33941
|
}
|
|
34091
|
-
|
|
34092
|
-
|
|
34093
|
-
|
|
33942
|
+
}
|
|
33943
|
+
async function unpair(udid) {
|
|
33944
|
+
logTask(`Un-pairing device ${udid}`);
|
|
33945
|
+
try {
|
|
33946
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "unpair"]);
|
|
33947
|
+
if (!result) {
|
|
33948
|
+
return false;
|
|
34094
33949
|
}
|
|
34095
|
-
|
|
34096
|
-
|
|
34097
|
-
|
|
34098
|
-
() => this.iosCli.removeProfile(udid, profileIdentifier)
|
|
34099
|
-
);
|
|
33950
|
+
return result.stdout.toLowerCase().includes("success");
|
|
33951
|
+
} catch {
|
|
33952
|
+
return false;
|
|
34100
33953
|
}
|
|
34101
|
-
|
|
34102
|
-
|
|
34103
|
-
|
|
34104
|
-
|
|
34105
|
-
|
|
34106
|
-
|
|
33954
|
+
}
|
|
33955
|
+
|
|
33956
|
+
// src/logic/actions/install.ts
|
|
33957
|
+
async function installLocalApp(ipaPath, udid) {
|
|
33958
|
+
logTask(`Installing app ${ipaPath} on device ${udid}`);
|
|
33959
|
+
await runIDeviceTool("ideviceinstaller", ["-u", udid, "install", ipaPath]);
|
|
33960
|
+
}
|
|
33961
|
+
async function installManagedApp(ipaPath, udid, options) {
|
|
33962
|
+
await installLocalApp(ipaPath, udid);
|
|
33963
|
+
const client = await createMDMClient();
|
|
33964
|
+
logTask("Installing app via MDM for management takeover");
|
|
33965
|
+
if (client) {
|
|
33966
|
+
client.installApp(udid, options);
|
|
34107
33967
|
}
|
|
34108
|
-
|
|
34109
|
-
|
|
33968
|
+
}
|
|
33969
|
+
async function uninstallApp(bundleId, udid) {
|
|
33970
|
+
logTask(`Uninstalling app ${bundleId} from device ${udid}`);
|
|
33971
|
+
if (!await isPaired(udid)) {
|
|
33972
|
+
await waitForPairing(udid, 1e4);
|
|
34110
33973
|
}
|
|
34111
|
-
|
|
34112
|
-
|
|
33974
|
+
await runIDeviceTool("ideviceinstaller", ["-u", udid, "uninstall", bundleId]);
|
|
33975
|
+
}
|
|
33976
|
+
async function listApps(udid) {
|
|
33977
|
+
logTask(`Listing apps on device ${udid}`);
|
|
33978
|
+
if (!await isPaired(udid)) {
|
|
33979
|
+
await waitForPairing(udid, 1e4);
|
|
34113
33980
|
}
|
|
34114
|
-
|
|
34115
|
-
|
|
34116
|
-
|
|
34117
|
-
|
|
34118
|
-
if (isSuccess(result)) {
|
|
34119
|
-
return result;
|
|
34120
|
-
}
|
|
34121
|
-
} catch (error) {
|
|
34122
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
34123
|
-
logError(`${label} failed: ${errorMsg}`);
|
|
34124
|
-
}
|
|
34125
|
-
logInfo(`Retrying ${label}... ${attempt + 1} of ${retries}`);
|
|
34126
|
-
await new Promise((resolve2) => setTimeout(resolve2, retryDelayMs));
|
|
33981
|
+
try {
|
|
33982
|
+
const result = await runIDeviceTool("ideviceinstaller", ["-u", udid, "list"]);
|
|
33983
|
+
if (!result) {
|
|
33984
|
+
return [];
|
|
34127
33985
|
}
|
|
34128
|
-
|
|
33986
|
+
const { stdout } = result;
|
|
33987
|
+
return parseAppList(stdout);
|
|
33988
|
+
} catch {
|
|
33989
|
+
return [];
|
|
33990
|
+
}
|
|
33991
|
+
}
|
|
33992
|
+
async function isAppInstalled(bundleId, udid) {
|
|
33993
|
+
logTask(`Checking if app ${bundleId} is installed on device ${udid}`);
|
|
33994
|
+
const apps = await listApps(udid);
|
|
33995
|
+
return apps.some((app) => app.bundleId === bundleId);
|
|
33996
|
+
}
|
|
33997
|
+
async function wakeDevice(udid) {
|
|
33998
|
+
try {
|
|
33999
|
+
logInfo("Attempting to wake device screen...");
|
|
34000
|
+
await runIDeviceTool("ideviceinfo", ["-u", udid, "-k", "DeviceName"]);
|
|
34001
|
+
try {
|
|
34002
|
+
await runIDeviceTool("ideviceinfo", ["-u", udid, "-k", "ActivationState"]);
|
|
34003
|
+
} catch {
|
|
34004
|
+
}
|
|
34005
|
+
try {
|
|
34006
|
+
await runIDeviceTool("idevicepair", ["-u", udid, "validate"]);
|
|
34007
|
+
} catch {
|
|
34008
|
+
}
|
|
34009
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
34010
|
+
logInfo("Device wake attempt completed");
|
|
34011
|
+
} catch (error) {
|
|
34012
|
+
logInfo(
|
|
34013
|
+
`Device wake attempt failed (non-critical): ${error instanceof Error ? error.message : String(error)}`
|
|
34014
|
+
);
|
|
34129
34015
|
}
|
|
34130
|
-
};
|
|
34131
|
-
async function saveProfileToTemp(profile, prefix) {
|
|
34132
|
-
const tempFilePath = (0, import_node_path7.join)((0, import_node_os2.tmpdir)(), `mce_${prefix}_${Date.now()}.mobileconfig`);
|
|
34133
|
-
await (0, import_promises2.writeFile)(tempFilePath, profile, "utf-8");
|
|
34134
|
-
logInfo(`Profile saved to: ${tempFilePath}`);
|
|
34135
|
-
return tempFilePath;
|
|
34136
34016
|
}
|
|
34137
|
-
async function
|
|
34017
|
+
async function launchApp(bundleId, args, udid) {
|
|
34018
|
+
logTask(`Launching app ${bundleId} on device ${udid}`);
|
|
34019
|
+
if (!await isPaired(udid)) {
|
|
34020
|
+
await waitForPairing(udid, 1e4);
|
|
34021
|
+
}
|
|
34022
|
+
const installed = await isAppInstalled(bundleId, udid);
|
|
34023
|
+
if (!installed) {
|
|
34024
|
+
throw new Error(
|
|
34025
|
+
`App "${bundleId}" is not installed on the device. Install the app first or verify the bundle identifier is correct.`
|
|
34026
|
+
);
|
|
34027
|
+
}
|
|
34028
|
+
await wakeDevice(udid);
|
|
34138
34029
|
try {
|
|
34139
|
-
|
|
34140
|
-
|
|
34030
|
+
logInfo(`Attempting to launch ${bundleId} using idevicedebug...`);
|
|
34031
|
+
const result = await runIDeviceTool("idevicedebug", ["-u", udid, "run", bundleId, ...args]);
|
|
34032
|
+
const output = (result?.stdout ?? "") + (result?.stderr ?? "");
|
|
34033
|
+
if (output.trim()) {
|
|
34034
|
+
logInfo(`idevicedebug output: ${output.substring(0, 200)}`);
|
|
34035
|
+
}
|
|
34036
|
+
if (output.toLowerCase().includes("could not start") && output.toLowerCase().includes("debugserver")) {
|
|
34037
|
+
logInfo("idevicedebug requires debugserver, falling back to pymobiledevice3...");
|
|
34038
|
+
throw new Error("debugserver_not_available");
|
|
34039
|
+
}
|
|
34040
|
+
logInfo(`App ${bundleId} launched successfully using idevicedebug`);
|
|
34041
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
34042
|
+
return;
|
|
34141
34043
|
} catch (error) {
|
|
34142
34044
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
let match = pattern.exec(profile);
|
|
34150
|
-
while (match) {
|
|
34151
|
-
matches.push(match[1].trim());
|
|
34152
|
-
match = pattern.exec(profile);
|
|
34153
|
-
}
|
|
34154
|
-
if (matches.length === 0) {
|
|
34155
|
-
return void 0;
|
|
34045
|
+
if (errorMsg.includes("debugserver_not_available") || errorMsg.toLowerCase().includes("could not start") || errorMsg.toLowerCase().includes("debugserver")) {
|
|
34046
|
+
logInfo("idevicedebug failed, trying pymobiledevice3 for iOS 17+...");
|
|
34047
|
+
await launchAppWithPymobiledevice3(bundleId, args, udid);
|
|
34048
|
+
return;
|
|
34049
|
+
}
|
|
34050
|
+
throw error;
|
|
34156
34051
|
}
|
|
34157
|
-
return matches[matches.length - 1];
|
|
34158
|
-
}
|
|
34159
|
-
function resolveIosBinaryPath() {
|
|
34160
|
-
const platform = process.platform;
|
|
34161
|
-
const binaryName = platform === "win32" ? "ios.exe" : "ios";
|
|
34162
|
-
return (0, import_node_path7.join)(getResourcesBinPath(), binaryName);
|
|
34163
34052
|
}
|
|
34164
|
-
function
|
|
34165
|
-
|
|
34166
|
-
|
|
34167
|
-
}
|
|
34168
|
-
|
|
34169
|
-
|
|
34170
|
-
|
|
34053
|
+
async function launchAppWithPymobiledevice3(bundleId, args, udid) {
|
|
34054
|
+
logTask(`Launching app ${bundleId} using pymobiledevice3`);
|
|
34055
|
+
const { exec } = await import("node:child_process");
|
|
34056
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
34057
|
+
const execAsync2 = promisify3(exec);
|
|
34058
|
+
try {
|
|
34059
|
+
let cmdArgs = [
|
|
34060
|
+
"-m",
|
|
34061
|
+
"pymobiledevice3",
|
|
34062
|
+
"developer",
|
|
34063
|
+
"dvt",
|
|
34064
|
+
"launch",
|
|
34065
|
+
"--udid",
|
|
34066
|
+
udid,
|
|
34067
|
+
"--kill-existing",
|
|
34068
|
+
// Kill existing instance to bring app to foreground
|
|
34069
|
+
bundleId,
|
|
34070
|
+
...args
|
|
34071
|
+
];
|
|
34072
|
+
let command = `python ${cmdArgs.map((a) => `"${a}"`).join(" ")}`;
|
|
34073
|
+
logInfo(`Executing: ${command}`);
|
|
34074
|
+
const result = await execAsync2(command, {
|
|
34075
|
+
windowsHide: true,
|
|
34076
|
+
encoding: "utf8",
|
|
34077
|
+
timeout: 3e4
|
|
34078
|
+
// 30 second timeout
|
|
34079
|
+
});
|
|
34080
|
+
const output = result.stdout.toString() + result.stderr.toString();
|
|
34081
|
+
if (output.trim()) {
|
|
34082
|
+
logInfo(`pymobiledevice3 output: ${output.substring(0, 200)}`);
|
|
34171
34083
|
}
|
|
34172
|
-
if ("
|
|
34173
|
-
|
|
34174
|
-
|
|
34084
|
+
if (output.toLowerCase().includes("developer mode") && output.toLowerCase().includes("not enabled")) {
|
|
34085
|
+
throw new Error(
|
|
34086
|
+
"Developer Mode is not enabled on the device.\nPlease enable it: Settings \u2192 Privacy & Security \u2192 Developer Mode \u2192 Enable"
|
|
34087
|
+
);
|
|
34175
34088
|
}
|
|
34176
|
-
if ("
|
|
34177
|
-
|
|
34178
|
-
|
|
34089
|
+
if (output.toLowerCase().includes("tunneld") && (output.toLowerCase().includes("unable to connect") || output.toLowerCase().includes("invalidserviceerror"))) {
|
|
34090
|
+
logInfo("Tunnel required, retrying with tunnel option...");
|
|
34091
|
+
cmdArgs = [
|
|
34092
|
+
"-m",
|
|
34093
|
+
"pymobiledevice3",
|
|
34094
|
+
"developer",
|
|
34095
|
+
"dvt",
|
|
34096
|
+
"launch",
|
|
34097
|
+
"--udid",
|
|
34098
|
+
udid,
|
|
34099
|
+
"--tunnel",
|
|
34100
|
+
udid,
|
|
34101
|
+
// Use UDID for tunnel
|
|
34102
|
+
"--kill-existing",
|
|
34103
|
+
bundleId,
|
|
34104
|
+
...args
|
|
34105
|
+
];
|
|
34106
|
+
command = `python ${cmdArgs.map((a) => `"${a}"`).join(" ")}`;
|
|
34107
|
+
logInfo(`Retrying with tunnel: ${command}`);
|
|
34108
|
+
try {
|
|
34109
|
+
const retryResult = await execAsync2(command, {
|
|
34110
|
+
windowsHide: true,
|
|
34111
|
+
encoding: "utf8",
|
|
34112
|
+
timeout: 3e4
|
|
34113
|
+
});
|
|
34114
|
+
const retryOutput = retryResult.stdout.toString() + retryResult.stderr.toString();
|
|
34115
|
+
if (retryOutput.trim()) {
|
|
34116
|
+
logInfo(`pymobiledevice3 retry output: ${retryOutput.substring(0, 200)}`);
|
|
34117
|
+
}
|
|
34118
|
+
if (retryOutput.toLowerCase().includes("tunneld") && retryOutput.toLowerCase().includes("unable to connect")) {
|
|
34119
|
+
throw new Error(
|
|
34120
|
+
"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\n python -m pymobiledevice3 remote tunneld\nOr ensure Developer Mode is enabled and device is unlocked."
|
|
34121
|
+
);
|
|
34122
|
+
}
|
|
34123
|
+
logInfo(`App ${bundleId} launched successfully using pymobiledevice3 with tunnel`);
|
|
34124
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
34125
|
+
return;
|
|
34126
|
+
} catch {
|
|
34127
|
+
throw new Error(
|
|
34128
|
+
"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\n python -m pymobiledevice3 remote tunneld\nOr ensure Developer Mode is enabled and device is unlocked."
|
|
34129
|
+
);
|
|
34130
|
+
}
|
|
34131
|
+
}
|
|
34132
|
+
if (output.toLowerCase().includes("not found") || output.toLowerCase().includes("command not found") || output.toLowerCase().includes("cannot find")) {
|
|
34133
|
+
throw new Error(
|
|
34134
|
+
"pymobiledevice3 is not installed.\nInstall it with: python -m pip install --user pymobiledevice3"
|
|
34135
|
+
);
|
|
34136
|
+
}
|
|
34137
|
+
if (output.toLowerCase().includes("error") && !output.toLowerCase().includes("warning")) {
|
|
34138
|
+
logInfo(`Warning: pymobiledevice3 reported errors: ${output.substring(0, 300)}`);
|
|
34139
|
+
}
|
|
34140
|
+
logInfo(`App ${bundleId} launched successfully using pymobiledevice3`);
|
|
34141
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
34142
|
+
} catch (error) {
|
|
34143
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
34144
|
+
if (errorMsg.includes("not found") || errorMsg.includes("command not found") || errorMsg.includes("cannot find") || errorMsg.includes("No module named")) {
|
|
34145
|
+
throw new Error(
|
|
34146
|
+
"pymobiledevice3 is not installed or Python is not available.\nInstall it with: python -m pip install --user pymobiledevice3\nFor iOS 17+, Developer Mode must also be enabled on the device."
|
|
34147
|
+
);
|
|
34179
34148
|
}
|
|
34149
|
+
throw error;
|
|
34180
34150
|
}
|
|
34181
|
-
return void 0;
|
|
34182
34151
|
}
|
|
34183
|
-
|
|
34184
|
-
|
|
34185
|
-
|
|
34186
|
-
|
|
34187
|
-
|
|
34188
|
-
|
|
34189
|
-
|
|
34190
|
-
|
|
34191
|
-
|
|
34152
|
+
|
|
34153
|
+
// src/logic/actions/proxy.ts
|
|
34154
|
+
var import_node_child_process3 = require("node:child_process");
|
|
34155
|
+
var import_node_path8 = require("node:path");
|
|
34156
|
+
function startPortForward(localPort, devicePort, udid, startupTimeout = 500) {
|
|
34157
|
+
return new Promise((resolve2, reject) => {
|
|
34158
|
+
logTask(`Starting port forward ${localPort} -> ${devicePort} for device ${udid}`);
|
|
34159
|
+
const binPath = getResourcesBinPath();
|
|
34160
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
34161
|
+
const toolPath = binPath ? (0, import_node_path8.join)(binPath, `iproxy${ext}`) : `iproxy${ext}`;
|
|
34162
|
+
const spawnOptions = {
|
|
34163
|
+
windowsHide: true,
|
|
34164
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34165
|
+
};
|
|
34166
|
+
if (binPath) {
|
|
34167
|
+
spawnOptions.cwd = binPath;
|
|
34168
|
+
}
|
|
34169
|
+
logInfo(`Spawning iproxy with path: ${toolPath}`);
|
|
34170
|
+
logInfo(`Arguments: ${[localPort.toString(), devicePort.toString(), "-u", udid].join(" ")}`);
|
|
34171
|
+
logInfo(`Options: ${JSON.stringify(spawnOptions)}`);
|
|
34172
|
+
const child = (0, import_node_child_process3.spawn)(
|
|
34173
|
+
toolPath,
|
|
34174
|
+
[localPort.toString(), devicePort.toString(), "-u", udid],
|
|
34175
|
+
spawnOptions
|
|
34176
|
+
);
|
|
34177
|
+
let hasResolved = false;
|
|
34178
|
+
let stderrOutput = "";
|
|
34179
|
+
child.stdout?.on("data", (data) => {
|
|
34180
|
+
logTask(`${data.toString()}`);
|
|
34181
|
+
});
|
|
34182
|
+
child.stderr?.on("data", (data) => {
|
|
34183
|
+
logError(`${data.toString()}`);
|
|
34184
|
+
const msg = data.toString();
|
|
34185
|
+
stderrOutput += msg;
|
|
34186
|
+
if (msg.toLowerCase().includes("error") && !hasResolved) {
|
|
34187
|
+
hasResolved = true;
|
|
34188
|
+
child.kill();
|
|
34189
|
+
reject(new Error(`Port forwarding failed: ${msg}`));
|
|
34190
|
+
}
|
|
34191
|
+
});
|
|
34192
|
+
child.on("error", (error) => {
|
|
34193
|
+
if (!hasResolved) {
|
|
34194
|
+
hasResolved = true;
|
|
34195
|
+
reject(new Error(`Failed to start iproxy: ${error.message}`));
|
|
34196
|
+
}
|
|
34197
|
+
});
|
|
34198
|
+
child.on("exit", (code) => {
|
|
34199
|
+
if (!hasResolved) {
|
|
34200
|
+
hasResolved = true;
|
|
34201
|
+
if (code !== 0 && code !== null) {
|
|
34202
|
+
reject(new Error(`iproxy exited with code ${code}: ${stderrOutput}`));
|
|
34203
|
+
}
|
|
34204
|
+
}
|
|
34205
|
+
});
|
|
34206
|
+
setTimeout(() => {
|
|
34207
|
+
if (!hasResolved) {
|
|
34208
|
+
hasResolved = true;
|
|
34209
|
+
logTask(`Port forward started: ${localPort} -> ${devicePort} for device ${udid}`);
|
|
34210
|
+
resolve2({
|
|
34211
|
+
result: {
|
|
34212
|
+
localPort,
|
|
34213
|
+
devicePort
|
|
34214
|
+
},
|
|
34215
|
+
process: child
|
|
34216
|
+
});
|
|
34217
|
+
}
|
|
34218
|
+
}, startupTimeout);
|
|
34219
|
+
});
|
|
34192
34220
|
}
|
|
34193
|
-
function
|
|
34194
|
-
|
|
34195
|
-
|
|
34196
|
-
|
|
34197
|
-
}
|
|
34198
|
-
if (!identifier.startsWith(MCE_MDM_PROFILE_PREFIX)) {
|
|
34199
|
-
return false;
|
|
34200
|
-
}
|
|
34201
|
-
if (profile.Manifest?.IsActive === false) {
|
|
34202
|
-
return false;
|
|
34221
|
+
function killPortForwardProcess(process2) {
|
|
34222
|
+
if (process2 && !process2.killed) {
|
|
34223
|
+
logTask("Killing port forward process");
|
|
34224
|
+
process2.kill();
|
|
34203
34225
|
}
|
|
34204
|
-
return true;
|
|
34205
34226
|
}
|
|
34206
34227
|
|
|
34207
34228
|
// src/logic/appleDeviceKit.ts
|
|
@@ -34235,6 +34256,10 @@ var AppleDeviceKit = class {
|
|
|
34235
34256
|
this.ensureNotDisposed();
|
|
34236
34257
|
return getDeviceInfo(this.deviceId);
|
|
34237
34258
|
}
|
|
34259
|
+
async info() {
|
|
34260
|
+
this.ensureNotDisposed();
|
|
34261
|
+
return info(this.deviceId);
|
|
34262
|
+
}
|
|
34238
34263
|
/**
|
|
34239
34264
|
* Check if device is paired/trusted with this computer
|
|
34240
34265
|
*/
|
|
@@ -34290,9 +34315,9 @@ var AppleDeviceKit = class {
|
|
|
34290
34315
|
*
|
|
34291
34316
|
* @param ipaPath Path to the IPA file
|
|
34292
34317
|
*/
|
|
34293
|
-
async installApp(ipaPath, options
|
|
34318
|
+
async installApp(ipaPath, options) {
|
|
34294
34319
|
this.ensureNotDisposed();
|
|
34295
|
-
return installManagedApp(ipaPath, this.deviceId,
|
|
34320
|
+
return installManagedApp(ipaPath, this.deviceId, options);
|
|
34296
34321
|
}
|
|
34297
34322
|
/**
|
|
34298
34323
|
* Uninstall an app by bundle ID (uninstall agent)
|