@holochain/hc-spin 0.200.1 → 0.200.3

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.
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  const electron = require("electron");
3
- electron.contextBridge.exposeInMainWorld("electronAPI", {
3
+ electron.contextBridge.exposeInMainWorld("__HC_ZOME_CALL_SIGNER__", {
4
4
  signZomeCall: (zomeCall) => electron.ipcRenderer.invoke("sign-zome-call", zomeCall)
5
5
  });
6
+ electron.contextBridge.exposeInMainWorld("electronAPI", {
7
+ signZomeCall: (zomeCall) => electron.ipcRenderer.invoke("sign-zome-call-legacy", zomeCall)
8
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holochain/hc-spin",
3
- "version": "0.200.1",
3
+ "version": "0.200.3",
4
4
  "description": "CLI to run Holochain aps during development.",
5
5
  "author": "matthme",
6
6
  "homepage": "https://developer.holochain.org",
@@ -17,8 +17,7 @@
17
17
  "typecheck": "npm run typecheck:node && npm run typecheck:web",
18
18
  "start": "electron-vite preview",
19
19
  "dev": "electron-vite dev",
20
- "build": "rimraf dist && npm run typecheck && electron-vite build && mv ./out ./dist && cp ./cli/cli.js ./dist/cli.js",
21
- "setup": "cd rust-utils && yarn && yarn build && cd .."
20
+ "build": "rimraf dist && npm run typecheck && electron-vite build && mv ./out ./dist && cp ./cli/cli.js ./dist/cli.js"
22
21
  },
23
22
  "dependencies": {
24
23
  "@electron-toolkit/preload": "^3.0.0",
@@ -28,7 +27,8 @@
28
27
  "electron": "^28.1.1",
29
28
  "electron-context-menu": "3.6.1",
30
29
  "get-port": "7.0.0",
31
- "hc-spin-rust-utils": "file:./rust-utils/dist",
30
+ "@holochain/hc-spin-rust-utils": "0.200.2",
31
+ "@msgpack/msgpack": "^2.8.0",
32
32
  "nanoid": "5.0.4",
33
33
  "split": "1.0.1"
34
34
  },
package/src/main/index.ts CHANGED
@@ -6,20 +6,28 @@ import { Command, Option } from 'commander';
6
6
  import contextMenu from 'electron-context-menu';
7
7
  import split from 'split';
8
8
  import * as childProcess from 'child_process';
9
- import { ZomeCallSigner, ZomeCallUnsignedNapi } from 'hc-spin-rust-utils';
9
+ import { ZomeCallNapi, ZomeCallSigner, ZomeCallUnsignedNapi } from '@holochain/hc-spin-rust-utils';
10
10
  import { createHappWindow } from './windows';
11
11
  import getPort from 'get-port';
12
- import { AgentPubKey, AppWebsocket } from '@holochain/client';
12
+ import {
13
+ AgentPubKey,
14
+ AppWebsocket,
15
+ CallZomeRequest,
16
+ CallZomeRequestSigned,
17
+ getNonceExpiration,
18
+ randomNonce,
19
+ } from '@holochain/client';
13
20
  import { validateCliArgs } from './validateArgs';
21
+ import { encode } from '@msgpack/msgpack';
14
22
 
15
- const rustUtils = require('hc-spin-rust-utils');
23
+ const rustUtils = require('@holochain/hc-spin-rust-utils');
16
24
 
17
25
  const cli = new Command();
18
26
 
19
27
  cli
20
28
  .name('hc-spin')
21
29
  .description('CLI to run Holochain aps during development.')
22
- .version(`${app.getVersion()} (for holochain 0.2.x)`)
30
+ .version(`0.200.2 (for holochain 0.2.x)`)
23
31
  .argument(
24
32
  '<path>',
25
33
  'Path to .webhapp or .happ file to launch. If a .happ file is passed, either a UI path must be specified via --ui-path or a port pointing to a localhost server via --ui-port',
@@ -91,11 +99,50 @@ contextMenu({
91
99
  showInspectElement: true,
92
100
  });
93
101
 
94
- const handleSignZomeCall = (e: IpcMainInvokeEvent, zomeCall: ZomeCallUnsignedNapi) => {
102
+ const handleSignZomeCall = async (e: IpcMainInvokeEvent, request: CallZomeRequest) => {
95
103
  const windowInfo = WINDOW_INFO_MAP[e.sender.id];
96
- if (zomeCall.provenance.toString() !== Array.from(windowInfo.agentPubKey).toString())
104
+ if (request.provenance.toString() !== Array.from(windowInfo.agentPubKey).toString())
97
105
  return Promise.reject('Agent public key unauthorized.');
98
- return windowInfo.zomeCallSigner.signZomeCall(zomeCall);
106
+
107
+ // console.log("Got zome call request: ", request);
108
+ const zomeCallUnsignedNapi: ZomeCallUnsignedNapi = {
109
+ provenance: Array.from(request.provenance),
110
+ cellId: [Array.from(request.cell_id[0]), Array.from(request.cell_id[1])],
111
+ zomeName: request.zome_name,
112
+ fnName: request.fn_name,
113
+ payload: Array.from(encode(request.payload)),
114
+ nonce: Array.from(await randomNonce()),
115
+ expiresAt: getNonceExpiration(),
116
+ };
117
+
118
+ const zomeCallSignedNapi: ZomeCallNapi =
119
+ await windowInfo.zomeCallSigner.signZomeCall(zomeCallUnsignedNapi);
120
+
121
+ const zomeCallSigned: CallZomeRequestSigned = {
122
+ provenance: Uint8Array.from(zomeCallSignedNapi.provenance),
123
+ cap_secret: null,
124
+ cell_id: [
125
+ Uint8Array.from(zomeCallSignedNapi.cellId[0]),
126
+ Uint8Array.from(zomeCallSignedNapi.cellId[1]),
127
+ ],
128
+ zome_name: zomeCallSignedNapi.zomeName,
129
+ fn_name: zomeCallSignedNapi.fnName,
130
+ payload: Uint8Array.from(zomeCallSignedNapi.payload),
131
+ signature: Uint8Array.from(zomeCallSignedNapi.signature),
132
+ expires_at: zomeCallSignedNapi.expiresAt,
133
+ nonce: Uint8Array.from(zomeCallSignedNapi.nonce),
134
+ };
135
+
136
+ return zomeCallSigned;
137
+ };
138
+
139
+ // https://github.com/holochain/holochain-client-js/issues/221
140
+ const handleSignZomeCallLegacy = async (e: IpcMainInvokeEvent, request: ZomeCallUnsignedNapi) => {
141
+ const windowInfo = WINDOW_INFO_MAP[e.sender.id];
142
+ if (request.provenance.toString() !== Array.from(windowInfo.agentPubKey).toString())
143
+ return Promise.reject('Agent public key unauthorized.');
144
+
145
+ return windowInfo.zomeCallSigner.signZomeCall(request);
99
146
  };
100
147
 
101
148
  async function startLocalServices(): Promise<[string, string]> {
@@ -212,6 +259,7 @@ async function spawnSandboxes(
212
259
  // Some APIs can only be used after this event occurs.
213
260
  app.whenReady().then(async () => {
214
261
  ipcMain.handle('sign-zome-call', handleSignZomeCall);
262
+ ipcMain.handle('sign-zome-call-legacy', handleSignZomeCallLegacy);
215
263
 
216
264
  let happTargetDir: string | undefined;
217
265
  // TODO unpack assets to UI dir if webhapp is passed
@@ -1,8 +1,15 @@
1
1
  // See the Electron documentation for details on how to use preload scripts:
2
2
  // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
3
3
  import { contextBridge, ipcRenderer } from 'electron';
4
- import { ZomeCallUnsignedNapi } from 'hc-spin-rust-utils';
4
+ import { ZomeCallUnsignedNapi } from '@holochain/hc-spin-rust-utils';
5
+ import { CallZomeRequestUnsigned } from '@holochain/client';
6
+
7
+ contextBridge.exposeInMainWorld('__HC_ZOME_CALL_SIGNER__', {
8
+ signZomeCall: (zomeCall: CallZomeRequestUnsigned) =>
9
+ ipcRenderer.invoke('sign-zome-call', zomeCall),
10
+ });
5
11
 
6
12
  contextBridge.exposeInMainWorld('electronAPI', {
7
- signZomeCall: (zomeCall: ZomeCallUnsignedNapi) => ipcRenderer.invoke('sign-zome-call', zomeCall),
13
+ signZomeCall: (zomeCall: ZomeCallUnsignedNapi) =>
14
+ ipcRenderer.invoke('sign-zome-call-legacy', zomeCall),
8
15
  });
@@ -1 +0,0 @@
1
- nodeLinker: node-modules
@@ -1,44 +0,0 @@
1
- [package]
2
- edition = "2021"
3
- name = "hc-spin-rust-utils"
4
- version = "0.0.0"
5
-
6
- [workspace]
7
-
8
- [lib]
9
- crate-type = ["cdylib"]
10
-
11
- [dependencies]
12
- # We keep those holochain dependencies separate from the root project to avoid irrelevant incompatibilities
13
- holochain_client = "0.4.5-rc.0"
14
- holochain_conductor_api = "0.2.4"
15
- holochain_integrity_types = "0.2.4"
16
- holochain_types = "0.2.4"
17
- holochain_zome_types = "0.2.4"
18
- holo_hash = "0.2.4"
19
- kitsune_p2p_timestamp = "0.2.4"
20
- lair_keystore_api = "0.3.0"
21
-
22
- hex = "0.4.3"
23
- futures = "0.3"
24
- nanoid = "0.4.0"
25
- # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
26
- napi = { version = "2.12.2", default-features = false, features = [
27
- "napi4",
28
- "tokio_rt",
29
- "async",
30
- "serde-json",
31
- ] }
32
- napi-derive = "2.12.2"
33
- serde = { version = "1.0", features = ["derive"] }
34
- serde_yaml = "0.8"
35
- sodoken = "0.0.9"
36
- url = "2.2"
37
- url2 = "0.0.6"
38
- zip = "0.5.0"
39
-
40
- [build-dependencies]
41
- napi-build = "2.0.1"
42
-
43
- [profile.release]
44
- lto = true
@@ -1,5 +0,0 @@
1
- extern crate napi_build;
2
-
3
- fn main() {
4
- napi_build::setup();
5
- }
@@ -1,33 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
-
4
- /* auto-generated by NAPI-RS */
5
-
6
- export function saveHappOrWebhapp(happOrWebHappPath: string, appId: string, uisDir: string, happsDir: string): Promise<void>
7
- export interface ZomeCallUnsignedNapi {
8
- cellId: Array<Array<number>>
9
- zomeName: string
10
- fnName: string
11
- payload: Array<number>
12
- capSecret?: Array<number>
13
- provenance: Array<number>
14
- nonce: Array<number>
15
- expiresAt: number
16
- }
17
- export interface ZomeCallNapi {
18
- cellId: Array<Array<number>>
19
- zomeName: string
20
- fnName: string
21
- payload: Array<number>
22
- capSecret?: Array<number>
23
- provenance: Array<number>
24
- nonce: Array<number>
25
- expiresAt: number
26
- signature: Array<number>
27
- }
28
- export type JsZomeCallSigner = ZomeCallSigner
29
- export class ZomeCallSigner {
30
- constructor()
31
- static connect(connectionUrl: string, passphrase: string): Promise<ZomeCallSigner>
32
- signZomeCall(zomeCallUnsignedJs: ZomeCallUnsignedNapi): Promise<ZomeCallNapi>
33
- }
@@ -1,258 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
- /* prettier-ignore */
4
-
5
- /* auto-generated by NAPI-RS */
6
-
7
- const { existsSync, readFileSync } = require('fs')
8
- const { join } = require('path')
9
-
10
- const { platform, arch } = process
11
-
12
- let nativeBinding = null
13
- let localFileExisted = false
14
- let loadError = null
15
-
16
- function isMusl() {
17
- // For Node 10
18
- if (!process.report || typeof process.report.getReport !== 'function') {
19
- try {
20
- const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
- return readFileSync(lddPath, 'utf8').includes('musl')
22
- } catch (e) {
23
- return true
24
- }
25
- } else {
26
- const { glibcVersionRuntime } = process.report.getReport().header
27
- return !glibcVersionRuntime
28
- }
29
- }
30
-
31
- switch (platform) {
32
- case 'android':
33
- switch (arch) {
34
- case 'arm64':
35
- localFileExisted = existsSync(join(__dirname, 'hc-we-rust-utils.android-arm64.node'))
36
- try {
37
- if (localFileExisted) {
38
- nativeBinding = require('./hc-we-rust-utils.android-arm64.node')
39
- } else {
40
- nativeBinding = require('hc-spin-rust-utils-android-arm64')
41
- }
42
- } catch (e) {
43
- loadError = e
44
- }
45
- break
46
- case 'arm':
47
- localFileExisted = existsSync(join(__dirname, 'hc-we-rust-utils.android-arm-eabi.node'))
48
- try {
49
- if (localFileExisted) {
50
- nativeBinding = require('./hc-we-rust-utils.android-arm-eabi.node')
51
- } else {
52
- nativeBinding = require('hc-spin-rust-utils-android-arm-eabi')
53
- }
54
- } catch (e) {
55
- loadError = e
56
- }
57
- break
58
- default:
59
- throw new Error(`Unsupported architecture on Android ${arch}`)
60
- }
61
- break
62
- case 'win32':
63
- switch (arch) {
64
- case 'x64':
65
- localFileExisted = existsSync(
66
- join(__dirname, 'hc-we-rust-utils.win32-x64-msvc.node')
67
- )
68
- try {
69
- if (localFileExisted) {
70
- nativeBinding = require('./hc-we-rust-utils.win32-x64-msvc.node')
71
- } else {
72
- nativeBinding = require('hc-spin-rust-utils-win32-x64-msvc')
73
- }
74
- } catch (e) {
75
- loadError = e
76
- }
77
- break
78
- case 'ia32':
79
- localFileExisted = existsSync(
80
- join(__dirname, 'hc-we-rust-utils.win32-ia32-msvc.node')
81
- )
82
- try {
83
- if (localFileExisted) {
84
- nativeBinding = require('./hc-we-rust-utils.win32-ia32-msvc.node')
85
- } else {
86
- nativeBinding = require('hc-spin-rust-utils-win32-ia32-msvc')
87
- }
88
- } catch (e) {
89
- loadError = e
90
- }
91
- break
92
- case 'arm64':
93
- localFileExisted = existsSync(
94
- join(__dirname, 'hc-we-rust-utils.win32-arm64-msvc.node')
95
- )
96
- try {
97
- if (localFileExisted) {
98
- nativeBinding = require('./hc-we-rust-utils.win32-arm64-msvc.node')
99
- } else {
100
- nativeBinding = require('hc-spin-rust-utils-win32-arm64-msvc')
101
- }
102
- } catch (e) {
103
- loadError = e
104
- }
105
- break
106
- default:
107
- throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
- }
109
- break
110
- case 'darwin':
111
- localFileExisted = existsSync(join(__dirname, 'hc-we-rust-utils.darwin-universal.node'))
112
- try {
113
- if (localFileExisted) {
114
- nativeBinding = require('./hc-we-rust-utils.darwin-universal.node')
115
- } else {
116
- nativeBinding = require('hc-spin-rust-utils-darwin-universal')
117
- }
118
- break
119
- } catch {}
120
- switch (arch) {
121
- case 'x64':
122
- localFileExisted = existsSync(join(__dirname, 'hc-we-rust-utils.darwin-x64.node'))
123
- try {
124
- if (localFileExisted) {
125
- nativeBinding = require('./hc-we-rust-utils.darwin-x64.node')
126
- } else {
127
- nativeBinding = require('hc-spin-rust-utils-darwin-x64')
128
- }
129
- } catch (e) {
130
- loadError = e
131
- }
132
- break
133
- case 'arm64':
134
- localFileExisted = existsSync(
135
- join(__dirname, 'hc-we-rust-utils.darwin-arm64.node')
136
- )
137
- try {
138
- if (localFileExisted) {
139
- nativeBinding = require('./hc-we-rust-utils.darwin-arm64.node')
140
- } else {
141
- nativeBinding = require('hc-spin-rust-utils-darwin-arm64')
142
- }
143
- } catch (e) {
144
- loadError = e
145
- }
146
- break
147
- default:
148
- throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
- }
150
- break
151
- case 'freebsd':
152
- if (arch !== 'x64') {
153
- throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
- }
155
- localFileExisted = existsSync(join(__dirname, 'hc-we-rust-utils.freebsd-x64.node'))
156
- try {
157
- if (localFileExisted) {
158
- nativeBinding = require('./hc-we-rust-utils.freebsd-x64.node')
159
- } else {
160
- nativeBinding = require('hc-spin-rust-utils-freebsd-x64')
161
- }
162
- } catch (e) {
163
- loadError = e
164
- }
165
- break
166
- case 'linux':
167
- switch (arch) {
168
- case 'x64':
169
- if (isMusl()) {
170
- localFileExisted = existsSync(
171
- join(__dirname, 'hc-we-rust-utils.linux-x64-musl.node')
172
- )
173
- try {
174
- if (localFileExisted) {
175
- nativeBinding = require('./hc-we-rust-utils.linux-x64-musl.node')
176
- } else {
177
- nativeBinding = require('hc-spin-rust-utils-linux-x64-musl')
178
- }
179
- } catch (e) {
180
- loadError = e
181
- }
182
- } else {
183
- localFileExisted = existsSync(
184
- join(__dirname, 'hc-we-rust-utils.linux-x64-gnu.node')
185
- )
186
- try {
187
- if (localFileExisted) {
188
- nativeBinding = require('./hc-we-rust-utils.linux-x64-gnu.node')
189
- } else {
190
- nativeBinding = require('hc-spin-rust-utils-linux-x64-gnu')
191
- }
192
- } catch (e) {
193
- loadError = e
194
- }
195
- }
196
- break
197
- case 'arm64':
198
- if (isMusl()) {
199
- localFileExisted = existsSync(
200
- join(__dirname, 'hc-we-rust-utils.linux-arm64-musl.node')
201
- )
202
- try {
203
- if (localFileExisted) {
204
- nativeBinding = require('./hc-we-rust-utils.linux-arm64-musl.node')
205
- } else {
206
- nativeBinding = require('hc-spin-rust-utils-linux-arm64-musl')
207
- }
208
- } catch (e) {
209
- loadError = e
210
- }
211
- } else {
212
- localFileExisted = existsSync(
213
- join(__dirname, 'hc-we-rust-utils.linux-arm64-gnu.node')
214
- )
215
- try {
216
- if (localFileExisted) {
217
- nativeBinding = require('./hc-we-rust-utils.linux-arm64-gnu.node')
218
- } else {
219
- nativeBinding = require('hc-spin-rust-utils-linux-arm64-gnu')
220
- }
221
- } catch (e) {
222
- loadError = e
223
- }
224
- }
225
- break
226
- case 'arm':
227
- localFileExisted = existsSync(
228
- join(__dirname, 'hc-we-rust-utils.linux-arm-gnueabihf.node')
229
- )
230
- try {
231
- if (localFileExisted) {
232
- nativeBinding = require('./hc-we-rust-utils.linux-arm-gnueabihf.node')
233
- } else {
234
- nativeBinding = require('hc-spin-rust-utils-linux-arm-gnueabihf')
235
- }
236
- } catch (e) {
237
- loadError = e
238
- }
239
- break
240
- default:
241
- throw new Error(`Unsupported architecture on Linux: ${arch}`)
242
- }
243
- break
244
- default:
245
- throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
246
- }
247
-
248
- if (!nativeBinding) {
249
- if (loadError) {
250
- throw loadError
251
- }
252
- throw new Error(`Failed to load native binding`)
253
- }
254
-
255
- const { saveHappOrWebhapp, ZomeCallSigner } = nativeBinding
256
-
257
- module.exports.saveHappOrWebhapp = saveHappOrWebhapp
258
- module.exports.ZomeCallSigner = ZomeCallSigner
@@ -1,31 +0,0 @@
1
- {
2
- "name": "hc-spin-rust-utils",
3
- "version": "0.0.1",
4
- "main": "index.js",
5
- "types": "index.d.ts",
6
- "napi": {
7
- "name": "hc-we-rust-utils",
8
- "triples": {}
9
- },
10
- "license": "MIT",
11
- "devDependencies": {
12
- "@napi-rs/cli": "^2.16.5",
13
- "rimraf": "5.0.5",
14
- "ava": "^5.1.1"
15
- },
16
- "ava": {
17
- "timeout": "3m"
18
- },
19
- "engines": {
20
- "node": ">= 10"
21
- },
22
- "scripts": {
23
- "artifacts": "napi artifacts",
24
- "build": "napi build --platform --release && rimraf dist && mkdir dist && cp package.json dist/ && cp index.js dist/ && cp index.d.ts dist/ && cp hc-we-rust-utils* dist/",
25
- "build:debug": "napi build --platform",
26
- "prepublishOnly": "napi prepublish -t npm",
27
- "test": "ava",
28
- "universal": "napi universal",
29
- "version": "napi version"
30
- }
31
- }
@@ -1,112 +0,0 @@
1
- use holochain_types::web_app::WebAppBundle;
2
- use std::fs;
3
- use std::path::PathBuf;
4
-
5
- #[napi]
6
- pub async fn save_happ_or_webhapp(
7
- happ_or_web_happ_path: String,
8
- app_id: String,
9
- uis_dir: String,
10
- happs_dir: String,
11
- ) -> napi::Result<()> {
12
- let happ_or_webhapp_bytes = fs::read(happ_or_web_happ_path)?;
13
-
14
- let app_bundle = match WebAppBundle::decode(&happ_or_webhapp_bytes) {
15
- Ok(web_app_bundle) => {
16
- // extracting ui.zip bytes
17
- let web_ui_zip_bytes = web_app_bundle.web_ui_zip_bytes().await.map_err(|e| {
18
- napi::Error::from_reason(format!("Failed to extract ui zip bytes: {}", e))
19
- })?;
20
-
21
- let ui_target_dir = PathBuf::from(uis_dir);
22
- if !path_exists(&ui_target_dir) {
23
- fs::create_dir_all(&ui_target_dir)?;
24
- }
25
-
26
- let ui_zip_path = PathBuf::from(ui_target_dir.clone()).join("ui.zip");
27
-
28
- // unzip and store UI
29
- fs::write(
30
- ui_zip_path.clone(),
31
- web_ui_zip_bytes.into_owned().into_inner(),
32
- )
33
- .map_err(|e| {
34
- napi::Error::from_reason(format!("Failed to write Web UI Zip file: {}", e))
35
- })?;
36
-
37
- let file = fs::File::open(ui_zip_path.clone()).map_err(|e| {
38
- napi::Error::from_reason(format!("Failed to read Web UI Zip file: {}", e))
39
- })?;
40
-
41
- unzip_file(file, ui_target_dir.into())
42
- .map_err(|e| napi::Error::from_reason(format!("Failed to unzip ui.zip: {}", e)))?;
43
-
44
- fs::remove_file(ui_zip_path).map_err(|e| {
45
- napi::Error::from_reason(format!("Failed to remove ui.zip after unzipping: {}", e))
46
- })?;
47
-
48
- // extracting happ bundle
49
- let app_bundle = web_app_bundle.happ_bundle().await.map_err(|e| {
50
- napi::Error::from_reason(format!(
51
- "Failed to get happ bundle from webapp bundle bytes: {}",
52
- e
53
- ))
54
- })?;
55
-
56
- app_bundle
57
- }
58
- Err(e) => {
59
- return Err(napi::Error::from_reason(format!(
60
- "Failed to decode .webhapp file: {}",
61
- e
62
- )))
63
- }
64
- };
65
-
66
- let happs_dir = PathBuf::from(happs_dir);
67
- if !path_exists(&happs_dir) {
68
- fs::create_dir_all(&happs_dir)?;
69
- }
70
-
71
- let happ_path = happs_dir.join(format!("{}.happ", app_id));
72
-
73
- app_bundle
74
- .write_to_file(&happ_path)
75
- .await
76
- .map_err(|e| napi::Error::from_reason(format!("Failed to write .happ file: {}", e)))?;
77
-
78
- Ok(())
79
- }
80
-
81
- pub fn path_exists(path: &PathBuf) -> bool {
82
- std::path::Path::new(path).exists()
83
- }
84
-
85
- pub fn unzip_file(reader: fs::File, outpath: PathBuf) -> Result<(), String> {
86
- let mut archive = match zip::ZipArchive::new(reader) {
87
- Ok(a) => a,
88
- Err(e) => return Err(format!("Failed to unpack zip archive: {}", e)),
89
- };
90
-
91
- for i in 0..archive.len() {
92
- let mut file = archive.by_index(i).unwrap();
93
- let outpath = match file.enclosed_name() {
94
- Some(path) => outpath.join(path).to_owned(),
95
- None => continue,
96
- };
97
-
98
- if (&*file.name()).ends_with('/') {
99
- fs::create_dir_all(&outpath).unwrap();
100
- } else {
101
- if let Some(p) = outpath.parent() {
102
- if !p.exists() {
103
- fs::create_dir_all(&p).unwrap();
104
- }
105
- }
106
- let mut outfile = fs::File::create(&outpath).unwrap();
107
- std::io::copy(&mut file, &mut outfile).unwrap();
108
- }
109
- }
110
-
111
- Ok(())
112
- }
@@ -1,7 +0,0 @@
1
- #[macro_use]
2
- extern crate napi_derive;
3
-
4
- pub mod decode_webhapp;
5
- pub mod types;
6
- mod utils;
7
- pub mod zome_call_signer;