@limrun/ui 0.14.0-rc.4 → 0.14.0

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.
Files changed (115) hide show
  1. package/README.md +9 -26
  2. package/dist/components/remote-control.d.ts +36 -0
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1189 -1089
  6. package/package.json +10 -51
  7. package/src/components/remote-control.tsx +267 -0
  8. package/src/index.ts +1 -1
  9. package/vite.config.ts +0 -9
  10. package/dist/app-store-relay/index.cjs +0 -9
  11. package/dist/app-store-relay/index.d.ts +0 -100
  12. package/dist/app-store-relay/index.js +0 -484
  13. package/dist/app-store-relay/react.cjs +0 -1
  14. package/dist/app-store-relay/react.d.ts +0 -15
  15. package/dist/app-store-relay/react.js +0 -69
  16. package/dist/apple-credentials/index.cjs +0 -1
  17. package/dist/apple-credentials/index.d.ts +0 -59
  18. package/dist/apple-credentials/index.js +0 -227
  19. package/dist/browser-storage-BnO-Ma-e.mjs +0 -219
  20. package/dist/browser-storage-DLxIqZk5.js +0 -1
  21. package/dist/client-D1drDXxE.js +0 -1
  22. package/dist/client-DSuNtWDv.mjs +0 -184
  23. package/dist/core/device-install/apple/client.d.ts +0 -18
  24. package/dist/core/device-install/apple/crypto.d.ts +0 -20
  25. package/dist/core/device-install/apple/gsa-srp.d.ts +0 -26
  26. package/dist/core/device-install/apple/index.d.ts +0 -5
  27. package/dist/core/device-install/apple/provisioning.d.ts +0 -212
  28. package/dist/core/device-install/apple/relay.d.ts +0 -40
  29. package/dist/core/device-install/index.d.ts +0 -4
  30. package/dist/core/device-install/operations/index.d.ts +0 -6
  31. package/dist/core/device-install/operations/limbuild-client.d.ts +0 -43
  32. package/dist/core/device-install/operations/operations.d.ts +0 -47
  33. package/dist/core/device-install/operations/relay-client.d.ts +0 -26
  34. package/dist/core/device-install/operations/relay-protocol.d.ts +0 -27
  35. package/dist/core/device-install/operations/usbmux.d.ts +0 -32
  36. package/dist/core/device-install/operations/webusb.d.ts +0 -21
  37. package/dist/core/device-install/storage/browser-storage.d.ts +0 -56
  38. package/dist/core/device-install/storage/index.d.ts +0 -2
  39. package/dist/core/device-install/storage/secret-store.d.ts +0 -101
  40. package/dist/core/device-install/types.d.ts +0 -57
  41. package/dist/core/errors.d.ts +0 -1
  42. package/dist/core/play-publish/google.d.ts +0 -13
  43. package/dist/core/play-publish/publish.d.ts +0 -34
  44. package/dist/device-build/index.cjs +0 -1
  45. package/dist/device-build/index.d.ts +0 -4
  46. package/dist/device-build/index.js +0 -85
  47. package/dist/device-build/react.cjs +0 -1
  48. package/dist/device-build/react.d.ts +0 -21
  49. package/dist/device-build/react.js +0 -68
  50. package/dist/device-build/signing.d.ts +0 -20
  51. package/dist/device-install/demo/demo.d.ts +0 -0
  52. package/dist/device-install/index.cjs +0 -1
  53. package/dist/device-install/index.d.ts +0 -18
  54. package/dist/device-install/index.js +0 -591
  55. package/dist/device-install/react.cjs +0 -1
  56. package/dist/device-install/react.d.ts +0 -24
  57. package/dist/device-install/react.js +0 -105
  58. package/dist/errors-BSkqS7U-.js +0 -1
  59. package/dist/errors-gy8yQJos.mjs +0 -6
  60. package/dist/gsa-srp-Bme3JLEi.mjs +0 -266
  61. package/dist/gsa-srp-CCIfUz7Y.js +0 -1
  62. package/dist/index-ChhtuQ7e.js +0 -22
  63. package/dist/index-YDu8K9a4.mjs +0 -11279
  64. package/dist/limbuild-client-BagK_FWE.mjs +0 -83
  65. package/dist/limbuild-client-CVDwq54z.js +0 -1
  66. package/dist/play-publish/index.cjs +0 -1
  67. package/dist/play-publish/index.d.ts +0 -2
  68. package/dist/play-publish/index.js +0 -109
  69. package/dist/play-publish/react.cjs +0 -1
  70. package/dist/play-publish/react.d.ts +0 -31
  71. package/dist/play-publish/react.js +0 -91
  72. package/dist/provisioning-B_DefBEp.mjs +0 -239
  73. package/dist/provisioning-BlQMccX_.js +0 -1
  74. package/src/app-store-relay/index.test.ts +0 -60
  75. package/src/app-store-relay/index.ts +0 -511
  76. package/src/app-store-relay/react.ts +0 -131
  77. package/src/apple-credentials/index.test.ts +0 -158
  78. package/src/apple-credentials/index.ts +0 -241
  79. package/src/core/device-install/apple/client.ts +0 -143
  80. package/src/core/device-install/apple/crypto.ts +0 -205
  81. package/src/core/device-install/apple/gsa-srp.ts +0 -123
  82. package/src/core/device-install/apple/index.ts +0 -5
  83. package/src/core/device-install/apple/provisioning.test.ts +0 -84
  84. package/src/core/device-install/apple/provisioning.ts +0 -380
  85. package/src/core/device-install/apple/relay.ts +0 -182
  86. package/src/core/device-install/index.ts +0 -4
  87. package/src/core/device-install/operations/index.ts +0 -6
  88. package/src/core/device-install/operations/limbuild-client.ts +0 -144
  89. package/src/core/device-install/operations/operations.ts +0 -234
  90. package/src/core/device-install/operations/relay-client.ts +0 -286
  91. package/src/core/device-install/operations/relay-protocol.ts +0 -71
  92. package/src/core/device-install/operations/usbmux.ts +0 -270
  93. package/src/core/device-install/operations/webusb-dom.d.ts +0 -54
  94. package/src/core/device-install/operations/webusb.ts +0 -110
  95. package/src/core/device-install/storage/browser-storage.test.ts +0 -65
  96. package/src/core/device-install/storage/browser-storage.ts +0 -325
  97. package/src/core/device-install/storage/index.ts +0 -2
  98. package/src/core/device-install/storage/secret-store.ts +0 -298
  99. package/src/core/device-install/types.ts +0 -69
  100. package/src/core/errors.ts +0 -3
  101. package/src/core/play-publish/google.ts +0 -113
  102. package/src/core/play-publish/publish.test.ts +0 -68
  103. package/src/core/play-publish/publish.ts +0 -89
  104. package/src/device-build/index.ts +0 -42
  105. package/src/device-build/react.ts +0 -130
  106. package/src/device-build/signing.ts +0 -94
  107. package/src/device-install/README.md +0 -423
  108. package/src/device-install/demo/demo.css +0 -493
  109. package/src/device-install/demo/demo.tsx +0 -1061
  110. package/src/device-install/demo/index.html +0 -12
  111. package/src/device-install/index.ts +0 -50
  112. package/src/device-install/react.ts +0 -195
  113. package/src/play-publish/README.md +0 -66
  114. package/src/play-publish/index.ts +0 -12
  115. package/src/play-publish/react.ts +0 -208
@@ -1,205 +0,0 @@
1
- import forge from 'node-forge';
2
-
3
- export type AppleSigningKeyMaterial = {
4
- privateKey: CryptoKey;
5
- privateKeyPKCS8Base64: string;
6
- publicKeySPKIBase64: string;
7
- csrPEM: string;
8
- csrBase64: string;
9
- };
10
-
11
- export type AppleCSRInput = {
12
- commonName: string;
13
- emailAddress?: string;
14
- };
15
-
16
- export type ExportP12Input = {
17
- privateKeyPKCS8Base64: string;
18
- certificateBase64?: string;
19
- certificatePEM?: string;
20
- password: string;
21
- friendlyName?: string;
22
- };
23
-
24
- const rsaAlgorithm: RsaHashedKeyGenParams = {
25
- name: 'RSASSA-PKCS1-v1_5',
26
- modulusLength: 2048,
27
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
28
- hash: 'SHA-256',
29
- };
30
-
31
- export async function generateAppleSigningKeyAndCSR(input: AppleCSRInput): Promise<AppleSigningKeyMaterial> {
32
- if (!crypto.subtle) {
33
- throw new Error('WebCrypto is not available in this browser.');
34
- }
35
- const keyPair = await crypto.subtle.generateKey(rsaAlgorithm, true, ['sign', 'verify']);
36
- const publicKeySPKI = new Uint8Array(await crypto.subtle.exportKey('spki', keyPair.publicKey));
37
- const certificationRequestInfo = derSequence(
38
- derInteger(0),
39
- derName(input),
40
- publicKeySPKI,
41
- derContext(0, new Uint8Array()),
42
- );
43
- const signature = new Uint8Array(
44
- await crypto.subtle.sign(
45
- 'RSASSA-PKCS1-v1_5',
46
- keyPair.privateKey,
47
- toArrayBuffer(certificationRequestInfo),
48
- ),
49
- );
50
- const csrDER = derSequence(
51
- certificationRequestInfo,
52
- derSequence(derOID('1.2.840.113549.1.1.11'), derNull()),
53
- derBitString(signature),
54
- );
55
- const privateKeyPKCS8 = new Uint8Array(await crypto.subtle.exportKey('pkcs8', keyPair.privateKey));
56
- return {
57
- privateKey: keyPair.privateKey,
58
- privateKeyPKCS8Base64: bytesToBase64(privateKeyPKCS8),
59
- publicKeySPKIBase64: bytesToBase64(publicKeySPKI),
60
- csrPEM: pemBlock('CERTIFICATE REQUEST', csrDER),
61
- csrBase64: bytesToBase64(csrDER),
62
- };
63
- }
64
-
65
- export function exportAppleCertificateP12(input: ExportP12Input) {
66
- if (!input.certificateBase64 && !input.certificatePEM) {
67
- throw new Error('certificateBase64 or certificatePEM is required.');
68
- }
69
- const privateKey = forge.pki.privateKeyFromPem(pemFromBase64('PRIVATE KEY', input.privateKeyPKCS8Base64));
70
- const certificate =
71
- input.certificatePEM ?
72
- forge.pki.certificateFromPem(input.certificatePEM)
73
- : forge.pki.certificateFromAsn1(
74
- forge.asn1.fromDer(forge.util.createBuffer(base64ToBinary(input.certificateBase64!))),
75
- );
76
- const p12 = forge.pkcs12.toPkcs12Asn1(privateKey, [certificate], input.password, {
77
- algorithm: '3des',
78
- friendlyName: input.friendlyName,
79
- });
80
- const der = forge.asn1.toDer(p12).getBytes();
81
- return binaryToBase64(der);
82
- }
83
-
84
- function derName(input: AppleCSRInput) {
85
- const attributes = [derAttribute('2.5.4.3', derUTF8String(input.commonName))];
86
- if (input.emailAddress) {
87
- attributes.push(derAttribute('1.2.840.113549.1.9.1', derIA5String(input.emailAddress)));
88
- }
89
- return derSequence(...attributes);
90
- }
91
-
92
- function derAttribute(oid: string, value: Uint8Array) {
93
- return derSet(derSequence(derOID(oid), value));
94
- }
95
-
96
- function derSequence(...values: Uint8Array[]) {
97
- return derTLV(0x30, concatBytes(...values));
98
- }
99
-
100
- function derSet(...values: Uint8Array[]) {
101
- return derTLV(0x31, concatBytes(...values));
102
- }
103
-
104
- function derContext(tag: number, value: Uint8Array) {
105
- return derTLV(0xa0 + tag, value);
106
- }
107
-
108
- function derInteger(value: number) {
109
- return derTLV(0x02, new Uint8Array([value]));
110
- }
111
-
112
- function derNull() {
113
- return new Uint8Array([0x05, 0x00]);
114
- }
115
-
116
- function derUTF8String(value: string) {
117
- return derTLV(0x0c, new TextEncoder().encode(value));
118
- }
119
-
120
- function derIA5String(value: string) {
121
- return derTLV(0x16, new TextEncoder().encode(value));
122
- }
123
-
124
- function derBitString(value: Uint8Array) {
125
- return derTLV(0x03, concatBytes(new Uint8Array([0]), value));
126
- }
127
-
128
- function derOID(oid: string) {
129
- const parts = oid.split('.').map((part) => parseInt(part, 10));
130
- if (parts.length < 2 || parts.some((part) => !Number.isFinite(part))) {
131
- throw new Error(`Invalid OID: ${oid}`);
132
- }
133
- const encoded = [parts[0] * 40 + parts[1]];
134
- for (const part of parts.slice(2)) {
135
- const stack = [part & 0x7f];
136
- let value = part >> 7;
137
- while (value > 0) {
138
- stack.unshift((value & 0x7f) | 0x80);
139
- value >>= 7;
140
- }
141
- encoded.push(...stack);
142
- }
143
- return derTLV(0x06, new Uint8Array(encoded));
144
- }
145
-
146
- function derTLV(tag: number, value: Uint8Array) {
147
- return concatBytes(new Uint8Array([tag]), derLength(value.byteLength), value);
148
- }
149
-
150
- function derLength(length: number) {
151
- if (length < 0x80) {
152
- return new Uint8Array([length]);
153
- }
154
- const bytes: number[] = [];
155
- let value = length;
156
- while (value > 0) {
157
- bytes.unshift(value & 0xff);
158
- value >>= 8;
159
- }
160
- return new Uint8Array([0x80 | bytes.length, ...bytes]);
161
- }
162
-
163
- function concatBytes(...chunks: Uint8Array[]) {
164
- const length = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
165
- const out = new Uint8Array(length);
166
- let offset = 0;
167
- for (const chunk of chunks) {
168
- out.set(chunk, offset);
169
- offset += chunk.byteLength;
170
- }
171
- return out;
172
- }
173
-
174
- function pemBlock(label: string, der: Uint8Array) {
175
- const base64 = bytesToBase64(der);
176
- const lines = base64.match(/.{1,64}/g) ?? [];
177
- return `-----BEGIN ${label}-----\n${lines.join('\n')}\n-----END ${label}-----\n`;
178
- }
179
-
180
- function pemFromBase64(label: string, base64: string) {
181
- const lines = base64.match(/.{1,64}/g) ?? [];
182
- return `-----BEGIN ${label}-----\n${lines.join('\n')}\n-----END ${label}-----\n`;
183
- }
184
-
185
- function bytesToBase64(bytes: Uint8Array) {
186
- let binary = '';
187
- for (const byte of bytes) {
188
- binary += String.fromCharCode(byte);
189
- }
190
- return btoa(binary);
191
- }
192
-
193
- function binaryToBase64(binary: string) {
194
- return btoa(binary);
195
- }
196
-
197
- function base64ToBinary(value: string) {
198
- return atob(value);
199
- }
200
-
201
- function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {
202
- const copy = new Uint8Array(bytes.byteLength);
203
- copy.set(bytes);
204
- return copy.buffer;
205
- }
@@ -1,123 +0,0 @@
1
- import { Hash, Mode, Srp, util } from '@foxt/js-srp';
2
-
3
- export type AppleSRPProtocol = 's2k' | 's2k_fo';
4
-
5
- export type AppleSRPInitRequest = {
6
- a: string;
7
- accountName: string;
8
- protocols: AppleSRPProtocol[];
9
- };
10
-
11
- export type AppleSRPInitResponse = {
12
- iteration: number;
13
- salt: string;
14
- protocol: AppleSRPProtocol;
15
- b: string;
16
- c: string;
17
- };
18
-
19
- export type AppleSRPCompleteProof = {
20
- accountName: string;
21
- m1: string;
22
- m2: string;
23
- c: string;
24
- };
25
-
26
- const srp = new Srp(Mode.GSA, Hash.SHA256, 2048);
27
-
28
- export class AppleGsaSrpClient {
29
- private srpClient?: Awaited<ReturnType<typeof srp.newClient>>;
30
-
31
- constructor(private readonly accountName: string) {}
32
-
33
- async init(): Promise<AppleSRPInitRequest> {
34
- if (this.srpClient) {
35
- throw new Error('SRP client is already initialized.');
36
- }
37
- this.srpClient = await srp.newClient(stringToBytes(this.accountName), new Uint8Array());
38
- return {
39
- accountName: this.accountName,
40
- protocols: ['s2k', 's2k_fo'],
41
- a: bytesToBase64(util.bytesFromBigint(this.srpClient.A)),
42
- };
43
- }
44
-
45
- async complete(password: string, serverData: AppleSRPInitResponse): Promise<AppleSRPCompleteProof> {
46
- if (!this.srpClient) {
47
- throw new Error('SRP client is not initialized.');
48
- }
49
- if (serverData.protocol !== 's2k' && serverData.protocol !== 's2k_fo') {
50
- throw new Error(`Unsupported Apple SRP protocol ${serverData.protocol}.`);
51
- }
52
- const salt = base64ToBytes(serverData.salt);
53
- const serverPublicKey = base64ToBytes(serverData.b);
54
- const derivedPassword = await deriveApplePassword(
55
- serverData.protocol,
56
- password,
57
- salt,
58
- serverData.iteration,
59
- );
60
- this.srpClient.p = derivedPassword;
61
- await this.srpClient.generate(salt, serverPublicKey);
62
- const m2 = await this.srpClient.generateM2();
63
- return {
64
- accountName: this.accountName,
65
- c: serverData.c,
66
- m1: bytesToBase64(this.srpClient._M),
67
- m2: bytesToBase64(m2),
68
- };
69
- }
70
- }
71
-
72
- async function deriveApplePassword(
73
- protocol: AppleSRPProtocol,
74
- password: string,
75
- salt: Uint8Array,
76
- iterations: number,
77
- ) {
78
- let passHash = new Uint8Array(await util.hash(srp.h, toArrayBuffer(stringToBytes(password))));
79
- if (protocol === 's2k_fo') {
80
- passHash = stringToBytes(util.toHex(passHash));
81
- }
82
- const imported = await crypto.subtle.importKey('raw', toArrayBuffer(passHash), { name: 'PBKDF2' }, false, [
83
- 'deriveBits',
84
- ]);
85
- const derived = await crypto.subtle.deriveBits(
86
- {
87
- name: 'PBKDF2',
88
- hash: { name: 'SHA-256' },
89
- iterations,
90
- salt: toArrayBuffer(salt),
91
- },
92
- imported,
93
- 256,
94
- );
95
- return new Uint8Array(derived);
96
- }
97
-
98
- function stringToBytes(value: string) {
99
- return new TextEncoder().encode(value);
100
- }
101
-
102
- function bytesToBase64(bytes: Uint8Array) {
103
- let binary = '';
104
- for (const byte of bytes) {
105
- binary += String.fromCharCode(byte);
106
- }
107
- return btoa(binary);
108
- }
109
-
110
- function base64ToBytes(value: string) {
111
- const binary = atob(value);
112
- const bytes = new Uint8Array(binary.length);
113
- for (let index = 0; index < binary.length; index += 1) {
114
- bytes[index] = binary.charCodeAt(index);
115
- }
116
- return bytes;
117
- }
118
-
119
- function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {
120
- const copy = new Uint8Array(bytes.byteLength);
121
- copy.set(bytes);
122
- return copy.buffer;
123
- }
@@ -1,5 +0,0 @@
1
- export * from './client';
2
- export * from './crypto';
3
- export * from './gsa-srp';
4
- export * from './provisioning';
5
- export * from './relay';
@@ -1,84 +0,0 @@
1
- // @vitest-environment node
2
-
3
- import { describe, expect, test } from 'vitest';
4
- import {
5
- createAdHocProfileRequest,
6
- createDevelopmentProfileRequest,
7
- downloadDistributionCertificateRequest,
8
- findAdHocProfilesRequest,
9
- findDevelopmentCertificatesRequest,
10
- findDistributionCertificatesRequest,
11
- submitDistributionCSRRequest,
12
- } from './provisioning';
13
-
14
- describe('Apple provisioning request helpers', () => {
15
- test('keeps development certificate requests on Apple Development types', () => {
16
- expect(findDevelopmentCertificatesRequest('TEAM').payload).toMatchObject({
17
- teamId: 'TEAM',
18
- types: '83Q87W3TGH,5QPB9NHCEI',
19
- });
20
- });
21
-
22
- test('uses distribution certificate requests for Ad Hoc signing', () => {
23
- expect(findDistributionCertificatesRequest('TEAM').payload).toMatchObject({
24
- teamId: 'TEAM',
25
- types: 'WXV89964HE,R58UK2EWSO',
26
- });
27
- expect(submitDistributionCSRRequest({ csrPEM: 'csr', teamID: 'TEAM' }).payload).toMatchObject({
28
- teamId: 'TEAM',
29
- type: 'WXV89964HE',
30
- csrContent: 'csr',
31
- });
32
- expect(downloadDistributionCertificateRequest('CERT', 'TEAM').payload).toMatchObject({
33
- teamId: 'TEAM',
34
- certificateId: 'CERT',
35
- type: 'WXV89964HE',
36
- });
37
- });
38
-
39
- test('builds separate development and Ad Hoc profile payloads', () => {
40
- expect(
41
- createDevelopmentProfileRequest({
42
- bundleID: 'com.example.app',
43
- teamID: 'TEAM',
44
- appIDID: 'APP',
45
- certificateID: 'CERT',
46
- deviceIDs: ['DEVICE'],
47
- }).payload,
48
- ).toMatchObject({
49
- teamId: 'TEAM',
50
- provisioningProfileName: 'Limrun com.example.app',
51
- certificateIds: ['CERT'],
52
- appIdId: 'APP',
53
- deviceIds: ['DEVICE'],
54
- distributionType: 'limited',
55
- subPlatform: 'ios',
56
- });
57
-
58
- expect(
59
- createAdHocProfileRequest({
60
- bundleID: 'com.example.app',
61
- teamID: 'TEAM',
62
- appIDID: 'APP',
63
- certificateID: 'CERT',
64
- deviceIDs: ['DEVICE'],
65
- }).payload,
66
- ).toMatchObject({
67
- teamId: 'TEAM',
68
- provisioningProfileName: 'Limrun Ad Hoc com.example.app',
69
- certificateIds: ['CERT'],
70
- appIdId: 'APP',
71
- deviceIds: ['DEVICE'],
72
- distributionType: 'adhoc',
73
- subPlatform: 'ios',
74
- });
75
- });
76
-
77
- test('filters Ad Hoc profile list requests by Ad Hoc distribution type', () => {
78
- expect(findAdHocProfilesRequest({ bundleID: 'com.example.app', teamID: 'TEAM' }).payload).toMatchObject({
79
- teamId: 'TEAM',
80
- search: 'com.example.app',
81
- distributionType: 'adhoc',
82
- });
83
- });
84
- });