@welshare/react 0.4.0 → 0.5.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 (45) hide show
  1. package/README.md +3 -55
  2. package/dist/esm/index.d.ts +1 -3
  3. package/dist/esm/index.d.ts.map +1 -1
  4. package/dist/esm/index.js +3 -4
  5. package/dist/esm/lib/uploads.d.ts +1 -1
  6. package/dist/esm/lib/uploads.d.ts.map +1 -1
  7. package/dist/esm/lib/uploads.js +1 -1
  8. package/dist/esm/types.d.ts +1 -1
  9. package/dist/esm/types.d.ts.map +1 -1
  10. package/dist/node_modules/@welshare/react/.turbo/turbo-lint.log +1 -1
  11. package/dist/node_modules/@welshare/react/README.md +3 -55
  12. package/dist/node_modules/@welshare/react/dist/esm/index.d.ts +1 -3
  13. package/dist/node_modules/@welshare/react/dist/esm/index.d.ts.map +1 -1
  14. package/dist/node_modules/@welshare/react/dist/esm/index.js +3 -4
  15. package/dist/node_modules/@welshare/react/dist/esm/lib/uploads.d.ts +1 -1
  16. package/dist/node_modules/@welshare/react/dist/esm/lib/uploads.d.ts.map +1 -1
  17. package/dist/node_modules/@welshare/react/dist/esm/lib/uploads.js +1 -1
  18. package/dist/node_modules/@welshare/react/dist/esm/types.d.ts +1 -1
  19. package/dist/node_modules/@welshare/react/dist/esm/types.d.ts.map +1 -1
  20. package/dist/node_modules/@welshare/react/package.json +1 -8
  21. package/dist/node_modules/@welshare/react/src/index.ts +7 -8
  22. package/dist/node_modules/@welshare/react/src/lib/uploads.ts +2 -2
  23. package/dist/node_modules/@welshare/react/src/types.ts +1 -1
  24. package/package.json +2 -9
  25. package/dist/esm/hooks/use-binary-uploads.d.ts +0 -59
  26. package/dist/esm/hooks/use-binary-uploads.d.ts.map +0 -1
  27. package/dist/esm/hooks/use-binary-uploads.js +0 -93
  28. package/dist/esm/lib/encryption.d.ts +0 -9
  29. package/dist/esm/lib/encryption.d.ts.map +0 -1
  30. package/dist/esm/lib/encryption.js +0 -44
  31. package/dist/esm/utils.d.ts +0 -12
  32. package/dist/esm/utils.d.ts.map +0 -1
  33. package/dist/esm/utils.js +0 -8
  34. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-binary-uploads.d.ts +0 -59
  35. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-binary-uploads.d.ts.map +0 -1
  36. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-binary-uploads.js +0 -93
  37. package/dist/node_modules/@welshare/react/dist/esm/lib/encryption.d.ts +0 -9
  38. package/dist/node_modules/@welshare/react/dist/esm/lib/encryption.d.ts.map +0 -1
  39. package/dist/node_modules/@welshare/react/dist/esm/lib/encryption.js +0 -44
  40. package/dist/node_modules/@welshare/react/dist/esm/utils.d.ts +0 -12
  41. package/dist/node_modules/@welshare/react/dist/esm/utils.d.ts.map +0 -1
  42. package/dist/node_modules/@welshare/react/dist/esm/utils.js +0 -8
  43. package/dist/node_modules/@welshare/react/src/hooks/use-binary-uploads.ts +0 -181
  44. package/dist/node_modules/@welshare/react/src/lib/encryption.ts +0 -79
  45. package/dist/node_modules/@welshare/react/src/utils.ts +0 -18
package/README.md CHANGED
@@ -84,16 +84,9 @@ export function QuestionnaireForm() {
84
84
 
85
85
  ### Binary file uploads (e.g. images)
86
86
 
87
- The package provides two ways to upload binary files:
88
-
89
- 1. **`useWelshare` hook** - Upload via the wallet dialog (external wallet flow)
90
- 2. **`useBinaryUploads` hook** - Upload directly with your own session keypair
91
-
92
87
  Before data hits any server, the SDK encrypts all files with a new random symmetric AES (GCM / 256 bits) key. Users request a presigned upload url and post the encrypted file to an S3 compatible API that's currently operated by Welshare. Ultimately, they encrypt the encryption key for a Nillion _owned_ BinaryData collection and store it across Nillion nodes (no single node can recover the key). At the time of insertion, they currently also grant ACL read rights for the application (Technically, this is the welshare builder keypair at the moment).
93
88
 
94
- #### Option 1: Upload via Wallet Dialog (`useWelshare`)
95
-
96
- This works best for applications that **don't** manage their own keypairs. It delegates the heavy lifting to the welshare wallet dialog frame.
89
+ #### Upload via Wallet Dialog
97
90
 
98
91
  ```ts
99
92
  const { isConnected, openWallet, uploadFile, submitData } = useWelshare({
@@ -122,55 +115,10 @@ const responseItem = {
122
115
  };
123
116
  ```
124
117
 
125
- #### Option 2: Direct Upload (`useBinaryUploads`)
126
-
127
- For applications that manage storage keypairs directly:
128
-
129
- ```ts
130
- import {
131
- useBinaryUploads,
132
- encryptAndUploadFile,
133
- Schemas,
134
- } from "@welshare/react";
135
- import { WelshareApi } from "@welshare/sdk";
136
-
137
- const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } =
138
- useBinaryUploads({
139
- keypair: storageKeyPair, // storage keypairs are derived by users
140
- environment: "production",
141
- });
142
-
143
- // Get presigned URL
144
- const { presignedUrl, uploadKey } = await createUploadCredentials({
145
- applicationId: "your-app-id",
146
- reference: `questionnaire/${questionnaireId}/photo`,
147
- fileName: file.name,
148
- fileType: file.type,
149
- });
150
-
151
- // Encrypt & upload to S3, then submit metadata to Nillion
152
- const { encryptionKey } = await encryptAndUploadFile(file, presignedUrl);
153
- await WelshareApi.submitBinaryData(
154
- storageKeyPair,
155
- {
156
- encryption_key: JSON.stringify(encryptionKey),
157
- reference: `questionnaire/${questionnaireId}/photo`,
158
- file_name: file.name,
159
- file_size: file.size,
160
- file_type: file.type,
161
- controller_did: storageKeyPair.toDidString(),
162
- url: `welshare://${uploadKey}`,
163
- },
164
- "production",
165
- applicationId
166
- );
167
-
168
- // Download and decrypt owned files
169
- const decryptedFile = await downloadAndDecryptFile(documentId);
170
- ```
171
-
172
118
  Binary files are addressed as `valueAttachment` items in FHIR. See https://www.hl7.org/fhir/questionnaireresponse.html
173
119
 
120
+ For applications that manage storage keypairs directly and need more control over the upload process, see the [Binary File Uploads section in the SDK documentation](../welshare/README.md#binary-file-uploads).
121
+
174
122
  ## API
175
123
 
176
124
  ### supported callbacks
@@ -1,10 +1,8 @@
1
1
  export { ConnectWelshareButton } from "./components/connect-button.js";
2
2
  export { WelshareLogo } from "./components/welshare-logo.js";
3
3
  export { useWelshare } from "./hooks/use-welshare.js";
4
- export { useBinaryUploads, type UseBinaryUploadsOptions, type UseBinaryUploadsResult, } from "./hooks/use-binary-uploads.js";
5
4
  export { WELSHARE_API_ENVIRONMENT, resolveEnvironment, getBaseUrl, type WelshareApiEnvironment, type WelshareEnvironmentName, type NillionClusterConfig, } from "@welshare/sdk/environment";
6
- export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./lib/encryption.js";
7
- export { decodeEncryptionKey, type EncryptionKey } from "./utils.js";
5
+ export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, decodeEncryptionKey, ALGORITHM, type EncryptionKey, type Algorithm, } from "@welshare/sdk";
8
6
  export { browserDownload, encryptAndUploadFile } from "./lib/uploads.js";
9
7
  export declare const Schemas: {
10
8
  QuestionnaireResponse: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,UAAU,EACV,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGzE,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,UAAU,EACV,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGzE,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
package/dist/esm/index.js CHANGED
@@ -3,12 +3,11 @@ export { ConnectWelshareButton } from "./components/connect-button.js";
3
3
  export { WelshareLogo } from "./components/welshare-logo.js";
4
4
  // ---- Hooks ----
5
5
  export { useWelshare } from "./hooks/use-welshare.js";
6
- export { useBinaryUploads, } from "./hooks/use-binary-uploads.js";
7
6
  // ---- Environment (re-exported from @welshare/sdk) ----
8
7
  export { WELSHARE_API_ENVIRONMENT, resolveEnvironment, getBaseUrl, } from "@welshare/sdk/environment";
9
- // ---- Utils ----
10
- export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./lib/encryption.js";
11
- export { decodeEncryptionKey } from "./utils.js";
8
+ // ---- Encryption utilities (re-exported from @welshare/sdk) ----
9
+ export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, decodeEncryptionKey, ALGORITHM, } from "@welshare/sdk";
10
+ // ---- Upload utilities (local, for frame-based upload flow) ----
12
11
  export { browserDownload, encryptAndUploadFile } from "./lib/uploads.js";
13
12
  //todo: import them from the SDK
14
13
  export const Schemas = {
@@ -1,4 +1,4 @@
1
- import { EncryptionKey } from "@/utils.js";
1
+ import { type EncryptionKey } from "@welshare/sdk";
2
2
  export declare const encryptAndUploadFile: (file: File, presignedUrl: string) => Promise<EncryptionKey>;
3
3
  export declare const browserDownload: (decryptedFile: File) => void;
4
4
  //# sourceMappingURL=uploads.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../../src/lib/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAO3C,eAAO,MAAM,oBAAoB,SACzB,IAAI,gBACI,MAAM,KACnB,OAAO,CAAC,aAAa,CAgBvB,CAAC;AAEF,eAAO,MAAM,eAAe,kBAAmB,IAAI,SASlD,CAAC"}
1
+ {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../../src/lib/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,oBAAoB,SACzB,IAAI,gBACI,MAAM,KACnB,OAAO,CAAC,aAAa,CAgBvB,CAAC;AAEF,eAAO,MAAM,eAAe,kBAAmB,IAAI,SASlD,CAAC"}
@@ -1,4 +1,4 @@
1
- import { encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./encryption.js";
1
+ import { encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "@welshare/sdk";
2
2
  export const encryptAndUploadFile = async (file, presignedUrl) => {
3
3
  const encryptionKey = await generateRandomAESKey();
4
4
  const { encryptedData, iv } = await encryptFile(file, encryptionKey);
@@ -1,4 +1,4 @@
1
- import { EncryptionKey } from "./utils.js";
1
+ import type { EncryptionKey } from "@welshare/sdk";
2
2
  import type { WelshareApiEnvironment, WelshareEnvironmentName } from "@welshare/sdk/environment";
3
3
  export interface DialogMessage {
4
4
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,2BACf,SAAQ,+BAA+B;IACvC,aAAa,EAAE,aAAa,CAAC;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAkB,SAAQ,+BAA+B;IACxE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QACb,OAAO,EAAE,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,CAAC;QAClE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IAChE,OAAO,EACH,iBAAiB,CAAC,OAAO,CAAC,GAC1B,2BAA2B,GAC3B,+BAA+B,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5D,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;QACjD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,2BACf,SAAQ,+BAA+B;IACvC,aAAa,EAAE,aAAa,CAAC;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAkB,SAAQ,+BAA+B;IACxE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QACb,OAAO,EAAE,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,CAAC;QAClE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IAChE,OAAO,EACH,iBAAiB,CAAC,OAAO,CAAC,GAC1B,2BAA2B,GAC3B,+BAA+B,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5D,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;QACjD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC;CACH"}
@@ -1,5 +1,5 @@
1
1
 
2
- > @welshare/react@0.3.0 lint /Users/stadolf/work/welshare/workspace/surveys-monorepo/packages/welshare-react
2
+ > @welshare/react@0.4.0 lint /Users/stadolf/work/welshare/workspace/surveys-monorepo/packages/welshare-react
3
3
  > eslint . --max-warnings 25
4
4
 
5
5
 
@@ -84,16 +84,9 @@ export function QuestionnaireForm() {
84
84
 
85
85
  ### Binary file uploads (e.g. images)
86
86
 
87
- The package provides two ways to upload binary files:
88
-
89
- 1. **`useWelshare` hook** - Upload via the wallet dialog (external wallet flow)
90
- 2. **`useBinaryUploads` hook** - Upload directly with your own session keypair
91
-
92
87
  Before data hits any server, the SDK encrypts all files with a new random symmetric AES (GCM / 256 bits) key. Users request a presigned upload url and post the encrypted file to an S3 compatible API that's currently operated by Welshare. Ultimately, they encrypt the encryption key for a Nillion _owned_ BinaryData collection and store it across Nillion nodes (no single node can recover the key). At the time of insertion, they currently also grant ACL read rights for the application (Technically, this is the welshare builder keypair at the moment).
93
88
 
94
- #### Option 1: Upload via Wallet Dialog (`useWelshare`)
95
-
96
- This works best for applications that **don't** manage their own keypairs. It delegates the heavy lifting to the welshare wallet dialog frame.
89
+ #### Upload via Wallet Dialog
97
90
 
98
91
  ```ts
99
92
  const { isConnected, openWallet, uploadFile, submitData } = useWelshare({
@@ -122,55 +115,10 @@ const responseItem = {
122
115
  };
123
116
  ```
124
117
 
125
- #### Option 2: Direct Upload (`useBinaryUploads`)
126
-
127
- For applications that manage storage keypairs directly:
128
-
129
- ```ts
130
- import {
131
- useBinaryUploads,
132
- encryptAndUploadFile,
133
- Schemas,
134
- } from "@welshare/react";
135
- import { WelshareApi } from "@welshare/sdk";
136
-
137
- const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } =
138
- useBinaryUploads({
139
- keypair: storageKeyPair, // storage keypairs are derived by users
140
- environment: "production",
141
- });
142
-
143
- // Get presigned URL
144
- const { presignedUrl, uploadKey } = await createUploadCredentials({
145
- applicationId: "your-app-id",
146
- reference: `questionnaire/${questionnaireId}/photo`,
147
- fileName: file.name,
148
- fileType: file.type,
149
- });
150
-
151
- // Encrypt & upload to S3, then submit metadata to Nillion
152
- const { encryptionKey } = await encryptAndUploadFile(file, presignedUrl);
153
- await WelshareApi.submitBinaryData(
154
- storageKeyPair,
155
- {
156
- encryption_key: JSON.stringify(encryptionKey),
157
- reference: `questionnaire/${questionnaireId}/photo`,
158
- file_name: file.name,
159
- file_size: file.size,
160
- file_type: file.type,
161
- controller_did: storageKeyPair.toDidString(),
162
- url: `welshare://${uploadKey}`,
163
- },
164
- "production",
165
- applicationId
166
- );
167
-
168
- // Download and decrypt owned files
169
- const decryptedFile = await downloadAndDecryptFile(documentId);
170
- ```
171
-
172
118
  Binary files are addressed as `valueAttachment` items in FHIR. See https://www.hl7.org/fhir/questionnaireresponse.html
173
119
 
120
+ For applications that manage storage keypairs directly and need more control over the upload process, see the [Binary File Uploads section in the SDK documentation](../welshare/README.md#binary-file-uploads).
121
+
174
122
  ## API
175
123
 
176
124
  ### supported callbacks
@@ -1,10 +1,8 @@
1
1
  export { ConnectWelshareButton } from "./components/connect-button.js";
2
2
  export { WelshareLogo } from "./components/welshare-logo.js";
3
3
  export { useWelshare } from "./hooks/use-welshare.js";
4
- export { useBinaryUploads, type UseBinaryUploadsOptions, type UseBinaryUploadsResult, } from "./hooks/use-binary-uploads.js";
5
4
  export { WELSHARE_API_ENVIRONMENT, resolveEnvironment, getBaseUrl, type WelshareApiEnvironment, type WelshareEnvironmentName, type NillionClusterConfig, } from "@welshare/sdk/environment";
6
- export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./lib/encryption.js";
7
- export { decodeEncryptionKey, type EncryptionKey } from "./utils.js";
5
+ export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, decodeEncryptionKey, ALGORITHM, type EncryptionKey, type Algorithm, } from "@welshare/sdk";
8
6
  export { browserDownload, encryptAndUploadFile } from "./lib/uploads.js";
9
7
  export declare const Schemas: {
10
8
  QuestionnaireResponse: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,UAAU,EACV,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGzE,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,UAAU,EACV,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGzE,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
@@ -3,12 +3,11 @@ export { ConnectWelshareButton } from "./components/connect-button.js";
3
3
  export { WelshareLogo } from "./components/welshare-logo.js";
4
4
  // ---- Hooks ----
5
5
  export { useWelshare } from "./hooks/use-welshare.js";
6
- export { useBinaryUploads, } from "./hooks/use-binary-uploads.js";
7
6
  // ---- Environment (re-exported from @welshare/sdk) ----
8
7
  export { WELSHARE_API_ENVIRONMENT, resolveEnvironment, getBaseUrl, } from "@welshare/sdk/environment";
9
- // ---- Utils ----
10
- export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./lib/encryption.js";
11
- export { decodeEncryptionKey } from "./utils.js";
8
+ // ---- Encryption utilities (re-exported from @welshare/sdk) ----
9
+ export { decrypt, encodeEncryptionKey, encryptFile, generateRandomAESKey, decodeEncryptionKey, ALGORITHM, } from "@welshare/sdk";
10
+ // ---- Upload utilities (local, for frame-based upload flow) ----
12
11
  export { browserDownload, encryptAndUploadFile } from "./lib/uploads.js";
13
12
  //todo: import them from the SDK
14
13
  export const Schemas = {
@@ -1,4 +1,4 @@
1
- import { EncryptionKey } from "@/utils.js";
1
+ import { type EncryptionKey } from "@welshare/sdk";
2
2
  export declare const encryptAndUploadFile: (file: File, presignedUrl: string) => Promise<EncryptionKey>;
3
3
  export declare const browserDownload: (decryptedFile: File) => void;
4
4
  //# sourceMappingURL=uploads.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../../src/lib/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAO3C,eAAO,MAAM,oBAAoB,SACzB,IAAI,gBACI,MAAM,KACnB,OAAO,CAAC,aAAa,CAgBvB,CAAC;AAEF,eAAO,MAAM,eAAe,kBAAmB,IAAI,SASlD,CAAC"}
1
+ {"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../../src/lib/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,oBAAoB,SACzB,IAAI,gBACI,MAAM,KACnB,OAAO,CAAC,aAAa,CAgBvB,CAAC;AAEF,eAAO,MAAM,eAAe,kBAAmB,IAAI,SASlD,CAAC"}
@@ -1,4 +1,4 @@
1
- import { encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "./encryption.js";
1
+ import { encodeEncryptionKey, encryptFile, generateRandomAESKey, } from "@welshare/sdk";
2
2
  export const encryptAndUploadFile = async (file, presignedUrl) => {
3
3
  const encryptionKey = await generateRandomAESKey();
4
4
  const { encryptedData, iv } = await encryptFile(file, encryptionKey);
@@ -1,4 +1,4 @@
1
- import { EncryptionKey } from "./utils.js";
1
+ import type { EncryptionKey } from "@welshare/sdk";
2
2
  import type { WelshareApiEnvironment, WelshareEnvironmentName } from "@welshare/sdk/environment";
3
3
  export interface DialogMessage {
4
4
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,2BACf,SAAQ,+BAA+B;IACvC,aAAa,EAAE,aAAa,CAAC;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAkB,SAAQ,+BAA+B;IACxE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QACb,OAAO,EAAE,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,CAAC;QAClE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IAChE,OAAO,EACH,iBAAiB,CAAC,OAAO,CAAC,GAC1B,2BAA2B,GAC3B,+BAA+B,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5D,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;QACjD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,2BACf,SAAQ,+BAA+B;IACvC,aAAa,EAAE,aAAa,CAAC;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAkB,SAAQ,+BAA+B;IACxE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QACb,OAAO,EAAE,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,CAAC;QAClE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IAChE,OAAO,EACH,iBAAiB,CAAC,OAAO,CAAC,GAC1B,2BAA2B,GAC3B,+BAA+B,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5D,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;QACjD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC;CACH"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@welshare/react",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "React library for integrating with Welshare's sovereign data sharing platform",
5
5
  "keywords": [
6
6
  "react",
@@ -61,7 +61,6 @@
61
61
  "exports": {
62
62
  "./package.json": "./package.json",
63
63
  "./types": "./src/types.ts",
64
- "./utils": "./src/utils.ts",
65
64
  ".": "./src/index.ts"
66
65
  }
67
66
  },
@@ -73,12 +72,6 @@
73
72
  "default": "./dist/esm/types.js"
74
73
  }
75
74
  },
76
- "./utils": {
77
- "import": {
78
- "types": "./dist/esm/utils.d.ts",
79
- "default": "./dist/esm/utils.js"
80
- }
81
- },
82
75
  ".": {
83
76
  "import": {
84
77
  "types": "./dist/esm/index.d.ts",
@@ -4,11 +4,6 @@ export { WelshareLogo } from "./components/welshare-logo.js";
4
4
 
5
5
  // ---- Hooks ----
6
6
  export { useWelshare } from "./hooks/use-welshare.js";
7
- export {
8
- useBinaryUploads,
9
- type UseBinaryUploadsOptions,
10
- type UseBinaryUploadsResult,
11
- } from "./hooks/use-binary-uploads.js";
12
7
 
13
8
  // ---- Environment (re-exported from @welshare/sdk) ----
14
9
  export {
@@ -20,15 +15,19 @@ export {
20
15
  type NillionClusterConfig,
21
16
  } from "@welshare/sdk/environment";
22
17
 
23
- // ---- Utils ----
18
+ // ---- Encryption utilities (re-exported from @welshare/sdk) ----
24
19
  export {
25
20
  decrypt,
26
21
  encodeEncryptionKey,
27
22
  encryptFile,
28
23
  generateRandomAESKey,
29
- } from "./lib/encryption.js";
30
- export { decodeEncryptionKey, type EncryptionKey } from "./utils.js";
24
+ decodeEncryptionKey,
25
+ ALGORITHM,
26
+ type EncryptionKey,
27
+ type Algorithm,
28
+ } from "@welshare/sdk";
31
29
 
30
+ // ---- Upload utilities (local, for frame-based upload flow) ----
32
31
  export { browserDownload, encryptAndUploadFile } from "./lib/uploads.js";
33
32
 
34
33
  //todo: import them from the SDK
@@ -1,9 +1,9 @@
1
- import { EncryptionKey } from "@/utils.js";
2
1
  import {
2
+ type EncryptionKey,
3
3
  encodeEncryptionKey,
4
4
  encryptFile,
5
5
  generateRandomAESKey,
6
- } from "./encryption.js";
6
+ } from "@welshare/sdk";
7
7
 
8
8
  export const encryptAndUploadFile = async (
9
9
  file: File,
@@ -1,4 +1,4 @@
1
- import { EncryptionKey } from "./utils.js";
1
+ import type { EncryptionKey } from "@welshare/sdk";
2
2
  import type {
3
3
  WelshareApiEnvironment,
4
4
  WelshareEnvironmentName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@welshare/react",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "React library for integrating with Welshare's sovereign data sharing platform",
5
5
  "keywords": [
6
6
  "react",
@@ -23,7 +23,7 @@
23
23
  "homepage": "https://welshare.health",
24
24
  "type": "module",
25
25
  "dependencies": {
26
- "@welshare/sdk": "0.2.0"
26
+ "@welshare/sdk": "0.3.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "react": "^19",
@@ -52,7 +52,6 @@
52
52
  "exports": {
53
53
  "./package.json": "./package.json",
54
54
  "./types": "./src/types.ts",
55
- "./utils": "./src/utils.ts",
56
55
  ".": "./src/index.ts"
57
56
  }
58
57
  },
@@ -64,12 +63,6 @@
64
63
  "default": "./dist/esm/types.js"
65
64
  }
66
65
  },
67
- "./utils": {
68
- "import": {
69
- "types": "./dist/esm/utils.d.ts",
70
- "default": "./dist/esm/utils.js"
71
- }
72
- },
73
66
  ".": {
74
67
  "import": {
75
68
  "types": "./dist/esm/index.d.ts",
@@ -1,59 +0,0 @@
1
- import type { RequestUploadCredentialsPayload, UploadCredentials } from "../types.js";
2
- import { Nillion, type WelshareApiEnvironment, type WelshareEnvironmentName } from "@welshare/sdk";
3
- export interface UseBinaryUploadsOptions {
4
- /**
5
- * The user's session keypair for authentication.
6
- */
7
- keypair: Nillion.Keypair | null | undefined;
8
- /**
9
- * The Welshare environment to use for API calls.
10
- */
11
- environment: WelshareApiEnvironment | WelshareEnvironmentName;
12
- }
13
- export interface UseBinaryUploadsResult {
14
- /**
15
- * Request upload credentials (presigned URL) for uploading an encrypted file.
16
- */
17
- createUploadCredentials: (payload: RequestUploadCredentialsPayload) => Promise<UploadCredentials>;
18
- /**
19
- * Download and decrypt a file by its document ID.
20
- * Only works for files owned by the current user.
21
- */
22
- downloadAndDecryptFile: (documentId: string) => Promise<File | undefined>;
23
- /**
24
- * Whether an operation is currently running.
25
- */
26
- isRunning: boolean;
27
- /**
28
- * Error message if the last operation failed.
29
- */
30
- error: string | null;
31
- }
32
- /**
33
- * Hook for managing binary file uploads and downloads with Welshare.
34
- *
35
- * This hook provides functionality to:
36
- * - Request presigned URLs for uploading encrypted files to S3
37
- * - Download and decrypt files from Nillion storage
38
- *
39
- * @example
40
- * ```tsx
41
- * const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } = useBinaryUploads({
42
- * keypair: sessionKeyPair,
43
- * environment: 'production',
44
- * });
45
- *
46
- * // Upload flow: get credentials, encrypt, upload to S3, then submit metadata via submitBinaryData
47
- * const credentials = await createUploadCredentials({
48
- * applicationId: 'my-app',
49
- * reference: 'user-photo',
50
- * fileName: 'photo.jpg',
51
- * fileType: 'image/jpeg',
52
- * });
53
- *
54
- * // Download and decrypt
55
- * const file = await downloadAndDecryptFile(documentId);
56
- * ```
57
- */
58
- export declare const useBinaryUploads: (options: UseBinaryUploadsOptions) => UseBinaryUploadsResult;
59
- //# sourceMappingURL=use-binary-uploads.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-binary-uploads.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-binary-uploads.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,+BAA+B,EAC/B,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,OAAO,EAGP,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC7B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C;;OAEG;IACH,WAAW,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;CAC/D;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,uBAAuB,EAAE,CACvB,OAAO,EAAE,+BAA+B,KACrC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEhC;;;OAGG;IACH,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC1E;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,gBAAgB,YAClB,uBAAuB,KAC/B,sBAuGF,CAAC"}
@@ -1,93 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { decrypt } from "../lib/encryption.js";
3
- import { WelshareApi, resolveEnvironment, } from "@welshare/sdk";
4
- /**
5
- * Hook for managing binary file uploads and downloads with Welshare.
6
- *
7
- * This hook provides functionality to:
8
- * - Request presigned URLs for uploading encrypted files to S3
9
- * - Download and decrypt files from Nillion storage
10
- *
11
- * @example
12
- * ```tsx
13
- * const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } = useBinaryUploads({
14
- * keypair: sessionKeyPair,
15
- * environment: 'production',
16
- * });
17
- *
18
- * // Upload flow: get credentials, encrypt, upload to S3, then submit metadata via submitBinaryData
19
- * const credentials = await createUploadCredentials({
20
- * applicationId: 'my-app',
21
- * reference: 'user-photo',
22
- * fileName: 'photo.jpg',
23
- * fileType: 'image/jpeg',
24
- * });
25
- *
26
- * // Download and decrypt
27
- * const file = await downloadAndDecryptFile(documentId);
28
- * ```
29
- */
30
- export const useBinaryUploads = (options) => {
31
- const [isRunning, setIsRunning] = useState(false);
32
- const [error, setError] = useState(null);
33
- const mountedRef = useRef(true);
34
- useEffect(() => {
35
- mountedRef.current = true;
36
- return () => {
37
- mountedRef.current = false;
38
- };
39
- }, []);
40
- const resolvedEnvironment = useMemo(() => resolveEnvironment(options.environment), [options.environment]);
41
- const { keypair } = options;
42
- const createUploadCredentials = useCallback(async (payload) => {
43
- if (!keypair) {
44
- throw new Error("No keypair available");
45
- }
46
- const { reference, fileName, fileType } = payload;
47
- const { presignedUrl, uploadKey } = await WelshareApi.fetchS3WriteDelegation(keypair, { reference, fileName, fileType }, resolvedEnvironment);
48
- return { presignedUrl, uploadKey };
49
- }, [keypair, resolvedEnvironment]);
50
- /**
51
- * Downloads and decrypts a file by its document ID from Nillion.
52
- */
53
- const downloadAndDecryptFile = useCallback(async (documentId) => {
54
- if (!keypair) {
55
- throw new Error("No keypair available");
56
- }
57
- try {
58
- setIsRunning(true);
59
- setError(null);
60
- const { binaryFile, data: downloadResponse } = await WelshareApi.fetchBinaryData(keypair, resolvedEnvironment, documentId);
61
- const encodedEncryptionKey = JSON.parse(binaryFile.encryption_key);
62
- const decryptedData = await decrypt(await downloadResponse, encodedEncryptionKey);
63
- if (!decryptedData) {
64
- throw new Error("Failed to decrypt file (received null)");
65
- }
66
- const decryptedFile = new File([decryptedData], binaryFile.file_name, {
67
- type: binaryFile.file_type,
68
- });
69
- return decryptedFile;
70
- }
71
- catch (err) {
72
- console.error("Error during file download/decryption:", err);
73
- const errorMessage = err instanceof Error
74
- ? err.message
75
- : "Failed to download/decrypt file";
76
- if (mountedRef.current) {
77
- setError(errorMessage);
78
- }
79
- return undefined;
80
- }
81
- finally {
82
- if (mountedRef.current) {
83
- setIsRunning(false);
84
- }
85
- }
86
- }, [keypair, resolvedEnvironment]);
87
- return {
88
- createUploadCredentials,
89
- downloadAndDecryptFile,
90
- isRunning,
91
- error,
92
- };
93
- };
@@ -1,9 +0,0 @@
1
- import { EncryptionKey } from "../utils.js";
2
- export declare const generateRandomAESKey: () => Promise<CryptoKey>;
3
- export declare const encryptFile: (file: File, key: CryptoKey) => Promise<{
4
- encryptedData: ArrayBuffer;
5
- iv: Uint8Array;
6
- }>;
7
- export declare const encodeEncryptionKey: (key: CryptoKey, iv: Uint8Array) => Promise<EncryptionKey>;
8
- export declare const decrypt: (encryptedData: ArrayBuffer, encryptionKey: EncryptionKey) => Promise<ArrayBuffer | null>;
9
- //# sourceMappingURL=encryption.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../src/lib/encryption.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAuB,MAAM,aAAa,CAAC;AAE5E,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,SAAS,CAU9D,CAAC;AAIF,eAAO,MAAM,WAAW,SAChB,IAAI,OACL,SAAS,KACb,OAAO,CAAC;IAAE,aAAa,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,CAaxD,CAAC;AAEF,eAAO,MAAM,mBAAmB,QACzB,SAAS,MACV,UAAU,KACb,OAAO,CAAC,aAAa,CAYvB,CAAC;AAGF,eAAO,MAAM,OAAO,kBACH,WAAW,iBACX,aAAa,KAC3B,OAAO,CAAC,WAAW,GAAG,IAAI,CAuB5B,CAAC"}
@@ -1,44 +0,0 @@
1
- import { ALGORITHM, decodeEncryptionKey } from "../utils.js";
2
- export const generateRandomAESKey = async () => {
3
- // Generate a 256-bit AES-GCM key for file encryption
4
- return window.crypto.subtle.generateKey({
5
- name: ALGORITHM,
6
- length: 256, // 256-bit key
7
- }, true, // Key is extractable (needed for storage/transmission)
8
- ["encrypt", "decrypt"] // Key usage
9
- );
10
- };
11
- /// also Generates random IV (12 bytes for AES-GCM)
12
- /// @return {arraybuffer ciphertext, uint8array iv}
13
- export const encryptFile = async (file, key) => {
14
- // Read file as ArrayBuffer
15
- const fileData = await file.arrayBuffer();
16
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
17
- // Encrypt the file data
18
- const encryptedData = await window.crypto.subtle.encrypt({ name: ALGORITHM, iv: iv }, key, fileData);
19
- return { encryptedData, iv };
20
- };
21
- export const encodeEncryptionKey = async (key, iv) => {
22
- // Export the key as raw bytes
23
- const exportedKey = await window.crypto.subtle.exportKey("raw", key);
24
- const keyHex = Array.from(new Uint8Array(exportedKey))
25
- .map((b) => b.toString(16).padStart(2, "0"))
26
- .join("");
27
- const ivHex = Array.from(iv)
28
- .map((b) => b.toString(16).padStart(2, "0"))
29
- .join("");
30
- return { algorithm: ALGORITHM, key: keyHex, iv: ivHex };
31
- };
32
- // Helper function to decrypt a file using encoded encryption key
33
- export const decrypt = async (encryptedData, encryptionKey) => {
34
- try {
35
- const { key: keyBytes, iv } = decodeEncryptionKey(encryptionKey);
36
- const key = await window.crypto.subtle.importKey("raw", keyBytes, { name: ALGORITHM }, false, ["decrypt"]);
37
- const decryptedData = await window.crypto.subtle.decrypt({ name: ALGORITHM, iv: iv }, key, encryptedData);
38
- return decryptedData;
39
- }
40
- catch (error) {
41
- console.error("Failed to decrypt file:", error);
42
- return null;
43
- }
44
- };
@@ -1,12 +0,0 @@
1
- export declare const ALGORITHM = "AES-GCM";
2
- export type Algorithm = "AES-GCM";
3
- export type EncryptionKey = {
4
- algorithm: Algorithm;
5
- key: string;
6
- iv: string;
7
- };
8
- export declare const decodeEncryptionKey: (encryptionKey: EncryptionKey) => {
9
- key: BufferSource;
10
- iv: BufferSource;
11
- };
12
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,eAAO,MAAM,mBAAmB,kBACf,aAAa,KAC3B;IAAE,GAAG,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAUvC,CAAC"}
package/dist/esm/utils.js DELETED
@@ -1,8 +0,0 @@
1
- export const ALGORITHM = "AES-GCM";
2
- export const decodeEncryptionKey = (encryptionKey) => {
3
- const keyBytes = new Uint8Array(encryptionKey.key
4
- .match(/.{1,2}/g)
5
- .map((byte) => parseInt(byte, 16)));
6
- const ivBytes = new Uint8Array(encryptionKey.iv.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
7
- return { key: keyBytes, iv: ivBytes };
8
- };
@@ -1,59 +0,0 @@
1
- import type { RequestUploadCredentialsPayload, UploadCredentials } from "../types.js";
2
- import { Nillion, type WelshareApiEnvironment, type WelshareEnvironmentName } from "@welshare/sdk";
3
- export interface UseBinaryUploadsOptions {
4
- /**
5
- * The user's session keypair for authentication.
6
- */
7
- keypair: Nillion.Keypair | null | undefined;
8
- /**
9
- * The Welshare environment to use for API calls.
10
- */
11
- environment: WelshareApiEnvironment | WelshareEnvironmentName;
12
- }
13
- export interface UseBinaryUploadsResult {
14
- /**
15
- * Request upload credentials (presigned URL) for uploading an encrypted file.
16
- */
17
- createUploadCredentials: (payload: RequestUploadCredentialsPayload) => Promise<UploadCredentials>;
18
- /**
19
- * Download and decrypt a file by its document ID.
20
- * Only works for files owned by the current user.
21
- */
22
- downloadAndDecryptFile: (documentId: string) => Promise<File | undefined>;
23
- /**
24
- * Whether an operation is currently running.
25
- */
26
- isRunning: boolean;
27
- /**
28
- * Error message if the last operation failed.
29
- */
30
- error: string | null;
31
- }
32
- /**
33
- * Hook for managing binary file uploads and downloads with Welshare.
34
- *
35
- * This hook provides functionality to:
36
- * - Request presigned URLs for uploading encrypted files to S3
37
- * - Download and decrypt files from Nillion storage
38
- *
39
- * @example
40
- * ```tsx
41
- * const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } = useBinaryUploads({
42
- * keypair: sessionKeyPair,
43
- * environment: 'production',
44
- * });
45
- *
46
- * // Upload flow: get credentials, encrypt, upload to S3, then submit metadata via submitBinaryData
47
- * const credentials = await createUploadCredentials({
48
- * applicationId: 'my-app',
49
- * reference: 'user-photo',
50
- * fileName: 'photo.jpg',
51
- * fileType: 'image/jpeg',
52
- * });
53
- *
54
- * // Download and decrypt
55
- * const file = await downloadAndDecryptFile(documentId);
56
- * ```
57
- */
58
- export declare const useBinaryUploads: (options: UseBinaryUploadsOptions) => UseBinaryUploadsResult;
59
- //# sourceMappingURL=use-binary-uploads.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-binary-uploads.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-binary-uploads.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,+BAA+B,EAC/B,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,OAAO,EAGP,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC7B,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C;;OAEG;IACH,WAAW,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;CAC/D;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,uBAAuB,EAAE,CACvB,OAAO,EAAE,+BAA+B,KACrC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEhC;;;OAGG;IACH,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC1E;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,gBAAgB,YAClB,uBAAuB,KAC/B,sBAuGF,CAAC"}
@@ -1,93 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { decrypt } from "../lib/encryption.js";
3
- import { WelshareApi, resolveEnvironment, } from "@welshare/sdk";
4
- /**
5
- * Hook for managing binary file uploads and downloads with Welshare.
6
- *
7
- * This hook provides functionality to:
8
- * - Request presigned URLs for uploading encrypted files to S3
9
- * - Download and decrypt files from Nillion storage
10
- *
11
- * @example
12
- * ```tsx
13
- * const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } = useBinaryUploads({
14
- * keypair: sessionKeyPair,
15
- * environment: 'production',
16
- * });
17
- *
18
- * // Upload flow: get credentials, encrypt, upload to S3, then submit metadata via submitBinaryData
19
- * const credentials = await createUploadCredentials({
20
- * applicationId: 'my-app',
21
- * reference: 'user-photo',
22
- * fileName: 'photo.jpg',
23
- * fileType: 'image/jpeg',
24
- * });
25
- *
26
- * // Download and decrypt
27
- * const file = await downloadAndDecryptFile(documentId);
28
- * ```
29
- */
30
- export const useBinaryUploads = (options) => {
31
- const [isRunning, setIsRunning] = useState(false);
32
- const [error, setError] = useState(null);
33
- const mountedRef = useRef(true);
34
- useEffect(() => {
35
- mountedRef.current = true;
36
- return () => {
37
- mountedRef.current = false;
38
- };
39
- }, []);
40
- const resolvedEnvironment = useMemo(() => resolveEnvironment(options.environment), [options.environment]);
41
- const { keypair } = options;
42
- const createUploadCredentials = useCallback(async (payload) => {
43
- if (!keypair) {
44
- throw new Error("No keypair available");
45
- }
46
- const { reference, fileName, fileType } = payload;
47
- const { presignedUrl, uploadKey } = await WelshareApi.fetchS3WriteDelegation(keypair, { reference, fileName, fileType }, resolvedEnvironment);
48
- return { presignedUrl, uploadKey };
49
- }, [keypair, resolvedEnvironment]);
50
- /**
51
- * Downloads and decrypts a file by its document ID from Nillion.
52
- */
53
- const downloadAndDecryptFile = useCallback(async (documentId) => {
54
- if (!keypair) {
55
- throw new Error("No keypair available");
56
- }
57
- try {
58
- setIsRunning(true);
59
- setError(null);
60
- const { binaryFile, data: downloadResponse } = await WelshareApi.fetchBinaryData(keypair, resolvedEnvironment, documentId);
61
- const encodedEncryptionKey = JSON.parse(binaryFile.encryption_key);
62
- const decryptedData = await decrypt(await downloadResponse, encodedEncryptionKey);
63
- if (!decryptedData) {
64
- throw new Error("Failed to decrypt file (received null)");
65
- }
66
- const decryptedFile = new File([decryptedData], binaryFile.file_name, {
67
- type: binaryFile.file_type,
68
- });
69
- return decryptedFile;
70
- }
71
- catch (err) {
72
- console.error("Error during file download/decryption:", err);
73
- const errorMessage = err instanceof Error
74
- ? err.message
75
- : "Failed to download/decrypt file";
76
- if (mountedRef.current) {
77
- setError(errorMessage);
78
- }
79
- return undefined;
80
- }
81
- finally {
82
- if (mountedRef.current) {
83
- setIsRunning(false);
84
- }
85
- }
86
- }, [keypair, resolvedEnvironment]);
87
- return {
88
- createUploadCredentials,
89
- downloadAndDecryptFile,
90
- isRunning,
91
- error,
92
- };
93
- };
@@ -1,9 +0,0 @@
1
- import { EncryptionKey } from "../utils.js";
2
- export declare const generateRandomAESKey: () => Promise<CryptoKey>;
3
- export declare const encryptFile: (file: File, key: CryptoKey) => Promise<{
4
- encryptedData: ArrayBuffer;
5
- iv: Uint8Array;
6
- }>;
7
- export declare const encodeEncryptionKey: (key: CryptoKey, iv: Uint8Array) => Promise<EncryptionKey>;
8
- export declare const decrypt: (encryptedData: ArrayBuffer, encryptionKey: EncryptionKey) => Promise<ArrayBuffer | null>;
9
- //# sourceMappingURL=encryption.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../src/lib/encryption.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAuB,MAAM,aAAa,CAAC;AAE5E,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,SAAS,CAU9D,CAAC;AAIF,eAAO,MAAM,WAAW,SAChB,IAAI,OACL,SAAS,KACb,OAAO,CAAC;IAAE,aAAa,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,CAaxD,CAAC;AAEF,eAAO,MAAM,mBAAmB,QACzB,SAAS,MACV,UAAU,KACb,OAAO,CAAC,aAAa,CAYvB,CAAC;AAGF,eAAO,MAAM,OAAO,kBACH,WAAW,iBACX,aAAa,KAC3B,OAAO,CAAC,WAAW,GAAG,IAAI,CAuB5B,CAAC"}
@@ -1,44 +0,0 @@
1
- import { ALGORITHM, decodeEncryptionKey } from "../utils.js";
2
- export const generateRandomAESKey = async () => {
3
- // Generate a 256-bit AES-GCM key for file encryption
4
- return window.crypto.subtle.generateKey({
5
- name: ALGORITHM,
6
- length: 256, // 256-bit key
7
- }, true, // Key is extractable (needed for storage/transmission)
8
- ["encrypt", "decrypt"] // Key usage
9
- );
10
- };
11
- /// also Generates random IV (12 bytes for AES-GCM)
12
- /// @return {arraybuffer ciphertext, uint8array iv}
13
- export const encryptFile = async (file, key) => {
14
- // Read file as ArrayBuffer
15
- const fileData = await file.arrayBuffer();
16
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
17
- // Encrypt the file data
18
- const encryptedData = await window.crypto.subtle.encrypt({ name: ALGORITHM, iv: iv }, key, fileData);
19
- return { encryptedData, iv };
20
- };
21
- export const encodeEncryptionKey = async (key, iv) => {
22
- // Export the key as raw bytes
23
- const exportedKey = await window.crypto.subtle.exportKey("raw", key);
24
- const keyHex = Array.from(new Uint8Array(exportedKey))
25
- .map((b) => b.toString(16).padStart(2, "0"))
26
- .join("");
27
- const ivHex = Array.from(iv)
28
- .map((b) => b.toString(16).padStart(2, "0"))
29
- .join("");
30
- return { algorithm: ALGORITHM, key: keyHex, iv: ivHex };
31
- };
32
- // Helper function to decrypt a file using encoded encryption key
33
- export const decrypt = async (encryptedData, encryptionKey) => {
34
- try {
35
- const { key: keyBytes, iv } = decodeEncryptionKey(encryptionKey);
36
- const key = await window.crypto.subtle.importKey("raw", keyBytes, { name: ALGORITHM }, false, ["decrypt"]);
37
- const decryptedData = await window.crypto.subtle.decrypt({ name: ALGORITHM, iv: iv }, key, encryptedData);
38
- return decryptedData;
39
- }
40
- catch (error) {
41
- console.error("Failed to decrypt file:", error);
42
- return null;
43
- }
44
- };
@@ -1,12 +0,0 @@
1
- export declare const ALGORITHM = "AES-GCM";
2
- export type Algorithm = "AES-GCM";
3
- export type EncryptionKey = {
4
- algorithm: Algorithm;
5
- key: string;
6
- iv: string;
7
- };
8
- export declare const decodeEncryptionKey: (encryptionKey: EncryptionKey) => {
9
- key: BufferSource;
10
- iv: BufferSource;
11
- };
12
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,eAAO,MAAM,mBAAmB,kBACf,aAAa,KAC3B;IAAE,GAAG,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAUvC,CAAC"}
@@ -1,8 +0,0 @@
1
- export const ALGORITHM = "AES-GCM";
2
- export const decodeEncryptionKey = (encryptionKey) => {
3
- const keyBytes = new Uint8Array(encryptionKey.key
4
- .match(/.{1,2}/g)
5
- .map((byte) => parseInt(byte, 16)));
6
- const ivBytes = new Uint8Array(encryptionKey.iv.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
7
- return { key: keyBytes, iv: ivBytes };
8
- };
@@ -1,181 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { decrypt } from "../lib/encryption.js";
3
- import { type EncryptionKey } from "../utils.js";
4
- import type {
5
- RequestUploadCredentialsPayload,
6
- UploadCredentials,
7
- } from "../types.js";
8
- import {
9
- Nillion,
10
- WelshareApi,
11
- resolveEnvironment,
12
- type WelshareApiEnvironment,
13
- type WelshareEnvironmentName,
14
- } from "@welshare/sdk";
15
-
16
- export interface UseBinaryUploadsOptions {
17
- /**
18
- * The user's session keypair for authentication.
19
- */
20
- keypair: Nillion.Keypair | null | undefined;
21
- /**
22
- * The Welshare environment to use for API calls.
23
- */
24
- environment: WelshareApiEnvironment | WelshareEnvironmentName;
25
- }
26
-
27
- export interface UseBinaryUploadsResult {
28
- /**
29
- * Request upload credentials (presigned URL) for uploading an encrypted file.
30
- */
31
- createUploadCredentials: (
32
- payload: RequestUploadCredentialsPayload
33
- ) => Promise<UploadCredentials>;
34
-
35
- /**
36
- * Download and decrypt a file by its document ID.
37
- * Only works for files owned by the current user.
38
- */
39
- downloadAndDecryptFile: (documentId: string) => Promise<File | undefined>;
40
- /**
41
- * Whether an operation is currently running.
42
- */
43
- isRunning: boolean;
44
- /**
45
- * Error message if the last operation failed.
46
- */
47
- error: string | null;
48
- }
49
-
50
- /**
51
- * Hook for managing binary file uploads and downloads with Welshare.
52
- *
53
- * This hook provides functionality to:
54
- * - Request presigned URLs for uploading encrypted files to S3
55
- * - Download and decrypt files from Nillion storage
56
- *
57
- * @example
58
- * ```tsx
59
- * const { createUploadCredentials, downloadAndDecryptFile, isRunning, error } = useBinaryUploads({
60
- * keypair: sessionKeyPair,
61
- * environment: 'production',
62
- * });
63
- *
64
- * // Upload flow: get credentials, encrypt, upload to S3, then submit metadata via submitBinaryData
65
- * const credentials = await createUploadCredentials({
66
- * applicationId: 'my-app',
67
- * reference: 'user-photo',
68
- * fileName: 'photo.jpg',
69
- * fileType: 'image/jpeg',
70
- * });
71
- *
72
- * // Download and decrypt
73
- * const file = await downloadAndDecryptFile(documentId);
74
- * ```
75
- */
76
- export const useBinaryUploads = (
77
- options: UseBinaryUploadsOptions
78
- ): UseBinaryUploadsResult => {
79
- const [isRunning, setIsRunning] = useState(false);
80
- const [error, setError] = useState<string | null>(null);
81
- const mountedRef = useRef(true);
82
-
83
- useEffect(() => {
84
- mountedRef.current = true;
85
- return () => {
86
- mountedRef.current = false;
87
- };
88
- }, []);
89
-
90
- const resolvedEnvironment = useMemo(
91
- () => resolveEnvironment(options.environment),
92
- [options.environment]
93
- );
94
- const { keypair } = options;
95
-
96
- const createUploadCredentials = useCallback(
97
- async (
98
- payload: RequestUploadCredentialsPayload
99
- ): Promise<UploadCredentials> => {
100
- if (!keypair) {
101
- throw new Error("No keypair available");
102
- }
103
-
104
- const { reference, fileName, fileType } = payload;
105
-
106
- const { presignedUrl, uploadKey } =
107
- await WelshareApi.fetchS3WriteDelegation(
108
- keypair,
109
- { reference, fileName, fileType },
110
- resolvedEnvironment
111
- );
112
-
113
- return { presignedUrl, uploadKey };
114
- },
115
- [keypair, resolvedEnvironment]
116
- );
117
-
118
- /**
119
- * Downloads and decrypts a file by its document ID from Nillion.
120
- */
121
- const downloadAndDecryptFile = useCallback(
122
- async (documentId: string): Promise<File | undefined> => {
123
- if (!keypair) {
124
- throw new Error("No keypair available");
125
- }
126
-
127
- try {
128
- setIsRunning(true);
129
- setError(null);
130
-
131
- const { binaryFile, data: downloadResponse } =
132
- await WelshareApi.fetchBinaryData(
133
- keypair,
134
- resolvedEnvironment,
135
- documentId
136
- );
137
-
138
- const encodedEncryptionKey: EncryptionKey = JSON.parse(
139
- binaryFile.encryption_key
140
- );
141
-
142
- const decryptedData = await decrypt(
143
- await downloadResponse,
144
- encodedEncryptionKey
145
- );
146
-
147
- if (!decryptedData) {
148
- throw new Error("Failed to decrypt file (received null)");
149
- }
150
-
151
- const decryptedFile = new File([decryptedData], binaryFile.file_name, {
152
- type: binaryFile.file_type,
153
- });
154
-
155
- return decryptedFile;
156
- } catch (err) {
157
- console.error("Error during file download/decryption:", err);
158
- const errorMessage =
159
- err instanceof Error
160
- ? err.message
161
- : "Failed to download/decrypt file";
162
- if (mountedRef.current) {
163
- setError(errorMessage);
164
- }
165
- return undefined;
166
- } finally {
167
- if (mountedRef.current) {
168
- setIsRunning(false);
169
- }
170
- }
171
- },
172
- [keypair, resolvedEnvironment]
173
- );
174
-
175
- return {
176
- createUploadCredentials,
177
- downloadAndDecryptFile,
178
- isRunning,
179
- error,
180
- };
181
- };
@@ -1,79 +0,0 @@
1
- import { ALGORITHM, EncryptionKey, decodeEncryptionKey } from "../utils.js";
2
-
3
- export const generateRandomAESKey = async (): Promise<CryptoKey> => {
4
- // Generate a 256-bit AES-GCM key for file encryption
5
- return window.crypto.subtle.generateKey(
6
- {
7
- name: ALGORITHM,
8
- length: 256, // 256-bit key
9
- },
10
- true, // Key is extractable (needed for storage/transmission)
11
- ["encrypt", "decrypt"] // Key usage
12
- );
13
- };
14
-
15
- /// also Generates random IV (12 bytes for AES-GCM)
16
- /// @return {arraybuffer ciphertext, uint8array iv}
17
- export const encryptFile = async (
18
- file: File,
19
- key: CryptoKey
20
- ): Promise<{ encryptedData: ArrayBuffer; iv: Uint8Array }> => {
21
- // Read file as ArrayBuffer
22
- const fileData = await file.arrayBuffer();
23
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
24
-
25
- // Encrypt the file data
26
- const encryptedData = await window.crypto.subtle.encrypt(
27
- { name: ALGORITHM, iv: iv },
28
- key,
29
- fileData
30
- );
31
-
32
- return { encryptedData, iv };
33
- };
34
-
35
- export const encodeEncryptionKey = async (
36
- key: CryptoKey,
37
- iv: Uint8Array
38
- ): Promise<EncryptionKey> => {
39
- // Export the key as raw bytes
40
- const exportedKey = await window.crypto.subtle.exportKey("raw", key);
41
- const keyHex = Array.from(new Uint8Array(exportedKey))
42
- .map((b) => b.toString(16).padStart(2, "0"))
43
- .join("");
44
-
45
- const ivHex = Array.from(iv)
46
- .map((b) => b.toString(16).padStart(2, "0"))
47
- .join("");
48
-
49
- return { algorithm: ALGORITHM, key: keyHex, iv: ivHex };
50
- };
51
-
52
- // Helper function to decrypt a file using encoded encryption key
53
- export const decrypt = async (
54
- encryptedData: ArrayBuffer,
55
- encryptionKey: EncryptionKey
56
- ): Promise<ArrayBuffer | null> => {
57
- try {
58
- const { key: keyBytes, iv } = decodeEncryptionKey(encryptionKey);
59
-
60
- const key = await window.crypto.subtle.importKey(
61
- "raw",
62
- keyBytes as BufferSource,
63
- { name: ALGORITHM },
64
- false,
65
- ["decrypt"]
66
- );
67
-
68
- const decryptedData = await window.crypto.subtle.decrypt(
69
- { name: ALGORITHM, iv: iv as BufferSource },
70
- key,
71
- encryptedData
72
- );
73
-
74
- return decryptedData;
75
- } catch (error) {
76
- console.error("Failed to decrypt file:", error);
77
- return null;
78
- }
79
- };
@@ -1,18 +0,0 @@
1
- export const ALGORITHM = "AES-GCM";
2
- export type Algorithm = "AES-GCM";
3
-
4
- export type EncryptionKey = { algorithm: Algorithm; key: string; iv: string };
5
-
6
- export const decodeEncryptionKey = (
7
- encryptionKey: EncryptionKey
8
- ): { key: BufferSource; iv: BufferSource } => {
9
- const keyBytes = new Uint8Array(
10
- encryptionKey.key
11
- .match(/.{1,2}/g)!
12
- .map((byte: string) => parseInt(byte, 16))
13
- );
14
- const ivBytes = new Uint8Array(
15
- encryptionKey.iv.match(/.{1,2}/g)!.map((byte: string) => parseInt(byte, 16))
16
- );
17
- return { key: keyBytes, iv: ivBytes };
18
- };