Skip to content

Commit 7ace171

Browse files
authored
Merge pull request #165 from 1Password/sdks-for-desktop-integrations
Prepare SDK beta release 0.4.0-beta.2
2 parents b24bdc0 + d712841 commit 7ace171

File tree

14 files changed

+227
-86
lines changed

14 files changed

+227
-86
lines changed

client/src/client_builder.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ export const createClientWithCore = async (
2222
core.setInner(new SharedLibCore(authConfig.accountName));
2323
}
2424
const clientId = await core.initClient(authConfig);
25-
const inner: InnerClient = {
26-
id: parseInt(clientId, 10),
27-
core,
28-
};
25+
const inner = new InnerClient(parseInt(clientId, 10), core, authConfig);
2926
const client = new Client(inner);
3027
// Cleans up associated memory from core when client instance goes out of scope.
3128
finalizationRegistry.register(client, inner);

client/src/core.ts

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from "@1password/sdk-core";
77

88
import { ReplacerFunc } from "./types";
9-
import { throwError } from "./errors";
9+
import { DesktopSessionExpiredError, throwError } from "./errors";
1010

1111
// In empirical tests, we determined that maximum message size that can cross the FFI boundary
1212
// is ~64MB. Past this limit, the wasm-bingen FFI will throw an error and the program will crash.
@@ -123,11 +123,7 @@ export class SharedCore {
123123

124124
public async initClient(config: ClientAuthConfig): Promise<string> {
125125
const serializedConfig = JSON.stringify(config);
126-
try {
127-
return await this.inner.initClient(serializedConfig);
128-
} catch (e) {
129-
throwError(e as string);
130-
}
126+
return this.inner.initClient(serializedConfig);
131127
}
132128

133129
public async invoke(config: InvokeConfig): Promise<string> {
@@ -139,11 +135,7 @@ export class SharedCore {
139135
`message size exceeds the limit of ${messageLimit} bytes, please contact 1Password at [email protected] or https://developer.1password.com/joinslack if you need help."`,
140136
);
141137
}
142-
try {
143-
return await this.inner.invoke(serializedConfig);
144-
} catch (e) {
145-
throwError(e as string);
146-
}
138+
return this.inner.invoke(serializedConfig);
147139
}
148140

149141
public invoke_sync(config: InvokeConfig): string {
@@ -155,11 +147,7 @@ export class SharedCore {
155147
`message size exceeds the limit of ${messageLimit} bytes, please contact 1Password at [email protected] or https://developer.1password.com/joinslack if you need help.`,
156148
);
157149
}
158-
try {
159-
return invoke_sync(serializedConfig);
160-
} catch (e) {
161-
throwError(e as string);
162-
}
150+
return invoke_sync(serializedConfig);
163151
}
164152

165153
public releaseClient(clientId: number): void {
@@ -171,7 +159,24 @@ export class SharedCore {
171159
/**
172160
* Represents the client instance on which a call is made.
173161
*/
174-
export interface InnerClient {
175-
id: number;
176-
core: SharedCore;
162+
export class InnerClient {
163+
public constructor(
164+
public id: number,
165+
public readonly core: SharedCore,
166+
public config: ClientAuthConfig,
167+
) {}
168+
169+
public async invoke(config: InvokeConfig): Promise<string> {
170+
try {
171+
return await this.core.invoke(config);
172+
} catch (err: unknown) {
173+
if (err instanceof DesktopSessionExpiredError) {
174+
const newId = await this.core.initClient(this.config);
175+
this.id = parseInt(newId, 10);
176+
config.invocation.clientId = this.id;
177+
return await this.core.invoke(config);
178+
}
179+
throw err;
180+
}
181+
}
177182
}

client/src/errors.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
// Code generated by op-codegen - DO NOT EDIT MANUALLY
22

3+
export class DesktopSessionExpiredError extends Error {
4+
public message: string;
5+
6+
public constructor(message: string) {
7+
super();
8+
this.message = message;
9+
}
10+
}
11+
312
export class RateLimitExceededError extends Error {
413
public message: string;
514

@@ -23,6 +32,8 @@ export const throwError = (errString: string) => {
2332
}
2433

2534
switch (err.name) {
35+
case "DesktopSessionExpired":
36+
throw new DesktopSessionExpiredError(err.message);
2637
case "RateLimitExceeded":
2738
throw new RateLimitExceededError(err.message);
2839
default:

client/src/groups.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class Groups implements GroupsApi {
3434
},
3535
};
3636
return JSON.parse(
37-
await this.#inner.core.invoke(invocationConfig),
37+
await this.#inner.invoke(invocationConfig),
3838
ReviverFunc,
3939
) as Group;
4040
}

client/src/items.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export class Items implements ItemsApi {
9999
},
100100
};
101101
return JSON.parse(
102-
await this.#inner.core.invoke(invocationConfig),
102+
await this.#inner.invoke(invocationConfig),
103103
ReviverFunc,
104104
) as Item;
105105
}
@@ -124,7 +124,7 @@ export class Items implements ItemsApi {
124124
},
125125
};
126126
return JSON.parse(
127-
await this.#inner.core.invoke(invocationConfig),
127+
await this.#inner.invoke(invocationConfig),
128128
ReviverFunc,
129129
) as ItemsUpdateAllResponse;
130130
}
@@ -146,7 +146,7 @@ export class Items implements ItemsApi {
146146
},
147147
};
148148
return JSON.parse(
149-
await this.#inner.core.invoke(invocationConfig),
149+
await this.#inner.invoke(invocationConfig),
150150
ReviverFunc,
151151
) as Item;
152152
}
@@ -171,7 +171,7 @@ export class Items implements ItemsApi {
171171
},
172172
};
173173
return JSON.parse(
174-
await this.#inner.core.invoke(invocationConfig),
174+
await this.#inner.invoke(invocationConfig),
175175
ReviverFunc,
176176
) as ItemsGetAllResponse;
177177
}
@@ -192,7 +192,7 @@ export class Items implements ItemsApi {
192192
},
193193
};
194194
return JSON.parse(
195-
await this.#inner.core.invoke(invocationConfig),
195+
await this.#inner.invoke(invocationConfig),
196196
ReviverFunc,
197197
) as Item;
198198
}
@@ -213,7 +213,7 @@ export class Items implements ItemsApi {
213213
},
214214
},
215215
};
216-
await this.#inner.core.invoke(invocationConfig);
216+
await this.#inner.invoke(invocationConfig);
217217
}
218218

219219
/**
@@ -236,7 +236,7 @@ export class Items implements ItemsApi {
236236
},
237237
};
238238
return JSON.parse(
239-
await this.#inner.core.invoke(invocationConfig),
239+
await this.#inner.invoke(invocationConfig),
240240
ReviverFunc,
241241
) as ItemsDeleteAllResponse;
242242
}
@@ -257,7 +257,7 @@ export class Items implements ItemsApi {
257257
},
258258
},
259259
};
260-
await this.#inner.core.invoke(invocationConfig);
260+
await this.#inner.invoke(invocationConfig);
261261
}
262262

263263
/**
@@ -280,7 +280,7 @@ export class Items implements ItemsApi {
280280
},
281281
};
282282
return JSON.parse(
283-
await this.#inner.core.invoke(invocationConfig),
283+
await this.#inner.invoke(invocationConfig),
284284
ReviverFunc,
285285
) as ItemOverview[];
286286
}

client/src/items_files.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class ItemsFiles implements ItemsFilesApi {
5959
},
6060
};
6161
return JSON.parse(
62-
await this.#inner.core.invoke(invocationConfig),
62+
await this.#inner.invoke(invocationConfig),
6363
ReviverFunc,
6464
) as Item;
6565
}
@@ -86,7 +86,7 @@ export class ItemsFiles implements ItemsFilesApi {
8686
},
8787
};
8888
return JSON.parse(
89-
await this.#inner.core.invoke(invocationConfig),
89+
await this.#inner.invoke(invocationConfig),
9090
ReviverFunc,
9191
) as Uint8Array;
9292
}
@@ -113,7 +113,7 @@ export class ItemsFiles implements ItemsFilesApi {
113113
},
114114
};
115115
return JSON.parse(
116-
await this.#inner.core.invoke(invocationConfig),
116+
await this.#inner.invoke(invocationConfig),
117117
ReviverFunc,
118118
) as Item;
119119
}
@@ -138,7 +138,7 @@ export class ItemsFiles implements ItemsFilesApi {
138138
},
139139
};
140140
return JSON.parse(
141-
await this.#inner.core.invoke(invocationConfig),
141+
await this.#inner.invoke(invocationConfig),
142142
ReviverFunc,
143143
) as Item;
144144
}

client/src/items_shares.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export class ItemsShares implements ItemsSharesApi {
6363
},
6464
};
6565
return JSON.parse(
66-
await this.#inner.core.invoke(invocationConfig),
66+
await this.#inner.invoke(invocationConfig),
6767
ReviverFunc,
6868
) as ItemShareAccountPolicy;
6969
}
@@ -88,7 +88,7 @@ export class ItemsShares implements ItemsSharesApi {
8888
},
8989
};
9090
return JSON.parse(
91-
await this.#inner.core.invoke(invocationConfig),
91+
await this.#inner.invoke(invocationConfig),
9292
ReviverFunc,
9393
) as ValidRecipient[];
9494
}
@@ -115,7 +115,7 @@ export class ItemsShares implements ItemsSharesApi {
115115
},
116116
};
117117
return JSON.parse(
118-
await this.#inner.core.invoke(invocationConfig),
118+
await this.#inner.invoke(invocationConfig),
119119
ReviverFunc,
120120
) as string;
121121
}

client/src/secrets.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010

1111
/**
1212
* The Secrets API includes all operations the SDK client can perform on secrets.
13-
* Use secret reference URIs to securely load secrets from 1Password: op://<vault-name>/<item-name>[/<section-name>]/<field-name>
13+
* Use secret reference URIs to securely load secrets from 1Password: `op://<vault-name>/<item-name>[/<section-name>]/<field-name>`
1414
*/
1515
export interface SecretsApi {
1616
/**
@@ -47,7 +47,7 @@ export class Secrets implements SecretsApi {
4747
},
4848
};
4949
return JSON.parse(
50-
await this.#inner.core.invoke(invocationConfig),
50+
await this.#inner.invoke(invocationConfig),
5151
ReviverFunc,
5252
) as string;
5353
}
@@ -70,7 +70,7 @@ export class Secrets implements SecretsApi {
7070
},
7171
};
7272
return JSON.parse(
73-
await this.#inner.core.invoke(invocationConfig),
73+
await this.#inner.invoke(invocationConfig),
7474
ReviverFunc,
7575
) as ResolveAllResponse;
7676
}

client/src/shared_lib_core.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as os from "os";
33
import * as path from "path";
44

55
import { Core } from "./core";
6+
import { throwError } from "./errors";
67

78
/**
89
* Find the 1Password shared lib path by asking an the wasm core synchronously.
@@ -32,6 +33,21 @@ const find1PasswordLibPath = (): string => {
3233
];
3334
break;
3435

36+
case "win32": // Windows
37+
searchPaths = [
38+
path.join(
39+
os.homedir(),
40+
"/AppData/Local/1Password/op_sdk_ipc_client.dll",
41+
),
42+
"C:/Program Files/1Password/app/8/op_sdk_ipc_client.dll",
43+
"C:/Program Files (x86)/1Password/app/8/op_sdk_ipc_client.dll",
44+
path.join(
45+
os.homedir(),
46+
"/AppData/Local/1Password/app/8/op_sdk_ipc_client.dll",
47+
),
48+
];
49+
break;
50+
3551
default:
3652
throw new Error(`Unsupported platform: ${platform}`);
3753
}
@@ -127,34 +143,28 @@ export class SharedLibCore implements Core {
127143

128144
const inputBuf = Buffer.from(JSON.stringify(req), "utf8");
129145

130-
try {
131-
const nativeResponse = await this.lib.sendMessage(inputBuf);
146+
const nativeResponse = await this.lib.sendMessage(inputBuf);
132147

133-
if (!(nativeResponse instanceof Uint8Array)) {
134-
throw new Error(
135-
`Native function returned an unexpected type. Expected Uint8Array, got ${typeof nativeResponse}`,
136-
);
137-
}
148+
if (!(nativeResponse instanceof Uint8Array)) {
149+
throw new Error(
150+
`Native function returned an unexpected type. Expected Uint8Array, got ${typeof nativeResponse}`,
151+
);
152+
}
138153

139-
const respString = new TextDecoder().decode(nativeResponse);
140-
const response = JSON.parse(respString) as SharedLibResponse;
154+
const respString = new TextDecoder().decode(nativeResponse);
155+
const response = JSON.parse(respString) as SharedLibResponse;
141156

142-
if (response.success) {
143-
const decodedPayload = Buffer.from(response.payload).toString("utf8");
144-
// On success, the payload is the actual result string
145-
return decodedPayload;
146-
} else {
147-
// On failure, convert the error payload to a readable string and throw
148-
const errorMessage = Array.isArray(response.payload)
149-
? String.fromCharCode(...response.payload)
150-
: JSON.stringify(response.payload);
157+
if (response.success) {
158+
const decodedPayload = Buffer.from(response.payload).toString("utf8");
159+
// On success, the payload is the actual result string
160+
return decodedPayload;
161+
} else {
162+
// On failure, convert the error payload to a readable string and throw
163+
const errorMessage = Array.isArray(response.payload)
164+
? String.fromCharCode(...response.payload)
165+
: JSON.stringify(response.payload);
151166

152-
throw new Error(`Native library returned an error: ${errorMessage}`);
153-
}
154-
} catch (e) {
155-
// Catch errors from the native call or from JSON parsing
156-
console.error("An error occurred during the native library call:", e);
157-
throw e;
167+
throwError(errorMessage);
158168
}
159169
}
160170

0 commit comments

Comments
 (0)