@bentley/imodeljs-native 3.3.1 → 3.3.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.
package/CloudSqlite.d.ts CHANGED
@@ -3,135 +3,143 @@
3
3
  */
4
4
  /// <reference types="node" />
5
5
  import * as child_process from "child_process";
6
+ import { IModelJsNative } from "./NativeLibrary";
6
7
  /**
7
8
  * @note This package may only have **dev** dependencies on @itwin packages, so they are *not* available at runtime. Therefore we can only import **types** from them.
8
9
  */
9
- import type { DbResult } from "@itwin/core-bentley";
10
10
  import type { LocalFileName } from "@itwin/core-common";
11
11
  export declare namespace CloudSqlite {
12
- /** Error values for negative numbers returned by the Daemon `attach` command. */
13
- const enum DaemonAttachError {
14
- INVALID_DAEMON_DIRECTORY = -1,
15
- DAEMON_NOT_ACTIVE = -2,
16
- SOCKET_ERROR = -3
12
+ const enum LogMask {
13
+ LOG_HTTP = 1,
14
+ LOG_UPLOAD = 2,
15
+ LOG_CLEANUP = 4,
16
+ LOG_EVENT = 8
17
17
  }
18
- /** Possible values for `command` argument of `Daemon.command` method. */
19
- type DaemonCommand = "attach" | "detach" | "create" | "destroy" | "upload" | "download" | "delete" | "copy" | "queryManifestETag";
20
- interface AccountProps {
18
+ /** Properties that specify how to access the account for a cloud blob-store container. */
19
+ interface AccountAccessProps {
21
20
  /** blob storage module: e.g. "azure", "google", "aws". May also include URI style parameters. */
22
21
  storageType: string;
23
- /** blob store account name. */
24
- accountName: string;
22
+ /** blob store account name, or a URI for custom domains. */
23
+ accessName: string;
25
24
  }
25
+ /** Properties of a CloudContainer. */
26
26
  interface ContainerProps {
27
27
  /** the name of the container. */
28
28
  containerId: string;
29
- /** SAS token that grants access to the container. */
30
- sasToken: string;
31
- /** if true, container is attached with write permissions. */
29
+ /** an alias for the container. Defaults to `containerId` */
30
+ alias?: string;
31
+ /** token that grants access to the container. For sas=1 `storageType`s, this is the sasToken. For sas=0, this is the account key */
32
+ accessToken: string;
33
+ /** if true, container is attached with write permissions, and accessToken must provide write access to the cloud container. */
32
34
  writeable?: boolean;
33
- /** if true, container is attached in "secure" mode (blocks are encrypted). */
35
+ /** if true, container is attached in "secure" mode (blocks are encrypted). Only supported in daemon mode. */
34
36
  secure?: boolean;
35
37
  }
36
- type ContainerAccessProps = AccountProps & ContainerProps;
38
+ /** Returned from `CloudContainer.queryDatabase` describing one database in the container */
39
+ interface CachedDbProps {
40
+ /** The total of (4Mb) blocks in the database. */
41
+ readonly totalBlocks: number;
42
+ /** the number of blocks of the database that have been downloaded into the CloudCache */
43
+ readonly localBlocks: number;
44
+ /** the number of blocks from this database that have been modified in the CloudCache and need to be uploaded. */
45
+ readonly dirtyBlocks: number;
46
+ /** If true, the database currently has transactions in the WAL file and may not be uploaded until they have been checkPointed. */
47
+ readonly transactions: boolean;
48
+ /** the state of this database. Indicates whether the database is new or deleted since last upload */
49
+ readonly state: "" | "copied" | "deleted";
50
+ }
51
+ /** Properties for accessing a CloudContainer */
52
+ type ContainerAccessProps = AccountAccessProps & ContainerProps & {
53
+ /** Duration for holding write lock, in seconds. After this time the write lock expires if not refreshed. Default is one hour. */
54
+ durationSeconds?: number;
55
+ };
56
+ /** The name of a CloudSqlite database within a CloudContainer. */
37
57
  interface DbNameProp {
58
+ /** the name of the database within the CloudContainer.
59
+ * @note names of databases within a CloudContainer are always **case sensitive** on all platforms.*/
38
60
  dbName: string;
39
61
  }
62
+ /** Properties for accessing a database within a CloudContainer */
40
63
  interface DbProps extends DbNameProp {
41
- localFile: LocalFileName;
64
+ /** the name of the local file to access the database. */
65
+ localFileName: LocalFileName;
42
66
  }
43
67
  type TransferDirection = "upload" | "download";
44
68
  interface TransferProgress {
69
+ /** a user-supplied progress function called during the transfer operation. Return a non-0 value to abort the transfer. */
45
70
  onProgress?: (loaded: number, total: number) => number;
46
71
  }
47
- type TransferProps = ContainerAccessProps & TransferProgress;
48
- type TransferDbProps = TransferProps & DbProps;
49
- interface CacheProps {
50
- /** full path of directory for daemon to store its files. Must be on fast local drive. */
51
- daemonDir?: string;
52
- /** block size, in megabytes used by CREATE command. Default is 4MB. */
53
- blockSizeMb?: number;
72
+ interface CloudHttpProps {
73
+ /** The number of simultaneous HTTP requests. Default is 10. */
74
+ nRequests?: number;
75
+ }
76
+ interface PrefetchProps extends CloudHttpProps {
77
+ /** timeout between requests, in milliseconds. Default is 100. */
78
+ timeout?: number;
79
+ }
80
+ type TransferDbProps = DbProps & TransferProgress & CloudHttpProps;
81
+ /** Properties for creating a CloudCache. */
82
+ interface CacheProps extends CloudHttpProps {
83
+ /** full path of directory for cache to store its files. Must be on a (preferably fast) local drive, and must be empty when the cache is first created. */
84
+ rootDir: string;
85
+ /** name of this cache. It is possible to have more than one CloudCache in the same session. */
86
+ name: string;
87
+ /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */
88
+ cacheSize?: string;
89
+ /** turn on diagnostics for `curl` (outputs to stderr) */
90
+ curlDiagnostics?: boolean;
54
91
  }
55
- /** Properties for creating a new instance of the daemon process. */
92
+ /** Properties for creating a new instance of a daemon process. */
56
93
  interface DaemonProps {
57
- /** full path name of daemon.exe file. Default is to find "BeBlobDaemon.exe" in the same directory as this library. */
94
+ /** full path name of daemon.exe file. Default is to find "iTwinDaemon.exe" in the same directory as this library. */
58
95
  exePath?: string;
59
96
  /** daemon connection address. Default is "127.0.0.1" */
60
97
  addr?: string;
61
98
  /** port number. Default 22002 */
62
99
  portNumber?: number;
63
100
  /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */
64
- maxCacheSize?: string;
65
- /** How often cloud storage is polled for database changes made by other daemon processes, in seconds. Default is 60. */
66
- pollTime?: number;
67
- /** How long an overwritten block is allowed to persist before it is permanently deleted, in seconds. Default is 3600. */
68
- deleteTime?: number;
69
- /** How often each daemon process scans for and deletes such garbage files, in seconds. Default is 3600. */
70
- gcTime?: number;
71
- /** How long after a failed checkpoint-to-upload operation the daemon process waits before retrying, in seconds. Default=10. */
72
- retryTime?: number;
73
- /** The maximum number of concurrent uploads (PUT requests) the daemon will make when uploading a new version of a database to cloud storage. Default=10. */
74
- nWrites?: number;
75
- /** The maximum number of concurrent deletes (DELETE requests) the daemon will make when uploading a new version of a database. Default=10. */
76
- nDeletes?: number;
77
- /** If true, unmodified cache entries are retained across runs of the daemon. Default=false. */
78
- persistAcrossSessions?: boolean;
101
+ cacheSize?: string;
79
102
  /** logging options */
80
103
  log?: string;
81
104
  /** if true, don't include timestamps in log messages */
82
105
  noTimeStamps?: boolean;
83
- /** if true, create local files only when first accessed. Default=false. */
84
- lazy?: boolean;
85
- /** if true, extra space for nonces is not reserved and no nonce values are used for encrypted pages. Default=false. */
86
- noNonce?: boolean;
87
- /** If specified, containers are automatically detached from the daemon process if there have been no connected clients for at least autodetach seconds.
88
- * If set to 0, then containers are never automatically detached. Default=0.
89
- */
90
- autodetach?: number;
91
106
  /** The amount of time, in seconds before an http request made to cloud storage by the daemon times out. Default 600 seconds. */
92
107
  httptimeout?: number;
93
- /** If true, two virtual tables become available to database clients for querying the internal state of the connected daemon process. */
94
- vtab?: boolean;
95
108
  /** options for spawn */
96
109
  spawnOptions?: child_process.SpawnOptions;
97
110
  }
98
- /** Optional arguments for Db upload and download commands. */
99
- interface UploadDownloadArgs {
100
- /** The number of simultaneous HTTP requests. */
101
- nRequests?: number;
102
- }
103
- interface CopyDbArgs {
104
- /** A new alias, for the `copy` command */
105
- toAlias?: string;
106
- }
107
- type DaemonCommandArg = DbNameProp & AccountProps & CacheProps & CopyDbArgs & ContainerProps & UploadDownloadArgs & {
108
- localFile?: LocalFileName;
109
- };
111
+ type DaemonCommandArg = DbNameProp & AccountAccessProps & CacheProps & ContainerProps;
110
112
  class Daemon {
111
113
  private static exeName;
112
114
  static daemonDir(props: CacheProps): string;
113
115
  /** Start the Daemon process using the supplied properties. The process will be detached from the current process. */
114
- static start(props: DaemonProps & AccountProps & CacheProps): child_process.ChildProcess;
115
- /** Get the full path to the local file that can be used to open a BlobDb. For the file to exist, you must first issue the "attach" command. */
116
- static getDbFileName(props: CacheProps & ContainerProps & DbNameProp): string;
117
- /** Perform one of the Daemon commands.
118
- * @param command The Daemon command to run.
119
- * @param args arguments to the command.
120
- * @return `Promise<{ result, errMsg }>` the meaning of result varies by command, but 0 always means success. For `attach`, negative values are
121
- * `DaemonAttachError`, positive numbers below 400 are `SQLITE_xxx` errors, and values 400 and above are HTTP errors.
122
- * `errMsg` is blank on success, but an english message useful for diagnostics otherwise.
123
- */
124
- static command(command: DaemonCommand, args: DaemonCommandArg): Promise<{
125
- result: DaemonAttachError | DbResult | number;
126
- errMsg: string;
127
- eTag?: string;
128
- }>;
116
+ static start(props: DaemonProps & CacheProps): child_process.ChildProcess;
129
117
  }
130
- function transferDb(direction: TransferDirection, props: TransferDbProps): Promise<void>;
131
- function initializeContainer(props: ContainerAccessProps): Promise<void>;
132
- function uploadDb(props: TransferDbProps): Promise<void>;
133
- function downloadDb(props: TransferDbProps): Promise<void>;
134
- function copyDb(oldVersion: string, newVersion: string, props: ContainerAccessProps): Promise<void>;
135
- function deleteDb(props: ContainerAccessProps & DbNameProp): Promise<void>;
118
+ /** @internal */
119
+ function transferDb(direction: TransferDirection, container: IModelJsNative.CloudContainer, props: TransferDbProps): Promise<void>;
120
+ /** Upload a database into a CloudContainer
121
+ * @param container the CloudContainer holding the database. Must be connected.
122
+ * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.
123
+ * @note this function requires that the write lock be held on the container
124
+ */
125
+ function uploadDb(container: IModelJsNative.CloudContainer, props: TransferDbProps): Promise<void>;
126
+ /** Download a database from a CloudContainer
127
+ * @param container the CloudContainer holding the database. Must be connected.
128
+ * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.
129
+ * @returns a Promise that is resolved when the download completes.
130
+ * @note the download is "restartable." If the transfer is aborted and then re-requested, it will continue from where
131
+ * it left off rather than re-downloading the entire file.
132
+ */
133
+ function downloadDb(container: IModelJsNative.CloudContainer, props: TransferDbProps): Promise<void>;
134
+ /**
135
+ * Perform an asynchronous write operation on a CloudContainer with the write lock held.
136
+ * 1. acquire the write lock if not already held
137
+ * 2. perform the operation
138
+ * 3. if the write lock was not held before step 1., release the write lock.
139
+ * @param user the name to be displayed in the event of lock collisions
140
+ * @param container the CloudContainer on which the operation will be performed
141
+ * @param operation an asynchronous operation performed with the write lock held.
142
+ */
143
+ function withWriteLock(user: string, container: IModelJsNative.CloudContainer, operation: () => Promise<void>): Promise<void>;
136
144
  }
137
145
  //# sourceMappingURL=CloudSqlite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CloudSqlite.d.ts","sourceRoot":"","sources":["../src/CloudSqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CloudSqlite.d.ts","sourceRoot":"","sources":["../src/CloudSqlite.ts"],"names":[],"mappings":"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"}
package/CloudSqlite.js CHANGED
@@ -13,84 +13,49 @@ const fs = require("fs");
13
13
  const os = require("os");
14
14
  const path = require("path");
15
15
  const NativeLibrary_1 = require("./NativeLibrary");
16
- // cspell:ignore polltime blocksize cachesize notimestamps deletetime gctime retrytime nwrite ndelete
16
+ // cspell:ignore polltime blocksize cachesize notimestamps deletetime gctime retrytime nwrite ndelete prefetch httptimeout
17
17
  /* eslint-disable no-restricted-syntax */
18
18
  var CloudSqlite;
19
19
  (function (CloudSqlite) {
20
+ ;
20
21
  class Daemon {
21
22
  static exeName(props) {
22
23
  var _a;
23
- return (_a = props.exePath) !== null && _a !== void 0 ? _a : path.join(path.dirname(require.resolve(NativeLibrary_1.NativeLibrary.libraryName)), os.platform() === "win32" ? "BeBlobDaemon.exe" : "BeBlobDaemon");
24
+ return (_a = props.exePath) !== null && _a !== void 0 ? _a : path.join(path.dirname(require.resolve(NativeLibrary_1.NativeLibrary.libraryName)), os.platform() === "win32" ? "iTwinDaemon.exe" : "iTwinDaemon");
24
25
  }
25
26
  static daemonDir(props) {
26
27
  var _a;
27
- return (_a = props.daemonDir) !== null && _a !== void 0 ? _a : path.join(NativeLibrary_1.NativeLibrary.defaultCacheDir, "blob-daemon");
28
+ return (_a = props.rootDir) !== null && _a !== void 0 ? _a : path.join(NativeLibrary_1.NativeLibrary.defaultCacheDir, "itwin-daemon");
28
29
  }
29
30
  /** Start the Daemon process using the supplied properties. The process will be detached from the current process. */
30
31
  static start(props) {
31
- var _a;
32
32
  const dir = this.daemonDir(props);
33
33
  fs.mkdirSync(dir, { recursive: true }); // make sure the directory exists before starting the daemon
34
- const args = [`daemon`, `-module`, `${props.storageType}`, `-user`, `${props.accountName}`, `-directory`, `${dir}`, `-polltime`, `${(_a = props.pollTime) !== null && _a !== void 0 ? _a : 60}`];
34
+ const args = [`daemon`];
35
35
  if (props.addr !== undefined)
36
36
  args.push(`-addr`, `${props.addr}`);
37
37
  if (props.portNumber !== undefined)
38
38
  args.push(`-port`, `${props.portNumber}`);
39
- if (props.maxCacheSize)
40
- args.push(`-cachesize`, `${props.maxCacheSize}`);
39
+ if (props.cacheSize)
40
+ args.push(`-cachesize`, `${props.cacheSize}`);
41
41
  if (props.log)
42
42
  args.push(`-log`, `${props.log}`);
43
- if (props.deleteTime !== undefined)
44
- args.push(`-deletetime`, `${props.deleteTime}`);
45
- if (props.gcTime !== undefined)
46
- args.push(`-gctime`, `${props.gcTime}`);
47
- if (props.retryTime !== undefined)
48
- args.push(`-retrytime`, `${props.retryTime}`);
49
- if (props.nWrites !== undefined)
50
- args.push(`-nwrite`, `${props.nWrites}`);
51
- if (props.nDeletes !== undefined)
52
- args.push(`-ndelete`, `${props.nDeletes}`);
53
43
  if (props.noTimeStamps)
54
44
  args.push(`-notimestamps`);
55
- if (props.persistAcrossSessions)
56
- args.push(`-persistent`);
57
- if (props.lazy)
58
- args.push(`-lazy`);
59
- if (props.noNonce)
60
- args.push(`-nononce`);
61
- if (props.autodetach !== undefined)
62
- args.push(`-autodetach`, `${props.autodetach}`);
63
45
  if (props.httptimeout !== undefined)
64
46
  args.push(`-httptimeout`, `${props.httptimeout}`);
65
- if (props.vtab)
66
- args.push(`-vtab`);
47
+ args.push(`${dir}`); // This MUST be the last arg when starting the daemon.
67
48
  return child_process.spawn(this.exeName(props), args, Object.assign(Object.assign({}, props.spawnOptions), { windowsVerbatimArguments: true }));
68
49
  }
69
- /** Get the full path to the local file that can be used to open a BlobDb. For the file to exist, you must first issue the "attach" command. */
70
- static getDbFileName(props) {
71
- return path.join(this.daemonDir(props), props.containerId, props.dbName);
72
- }
73
- /** Perform one of the Daemon commands.
74
- * @param command The Daemon command to run.
75
- * @param args arguments to the command.
76
- * @return `Promise<{ result, errMsg }>` the meaning of result varies by command, but 0 always means success. For `attach`, negative values are
77
- * `DaemonAttachError`, positive numbers below 400 are `SQLITE_xxx` errors, and values 400 and above are HTTP errors.
78
- * `errMsg` is blank on success, but an english message useful for diagnostics otherwise.
79
- */
80
- static async command(command, args) {
81
- var _a;
82
- const fullArgs = Object.assign({}, args);
83
- fullArgs.daemonDir = (_a = fullArgs.daemonDir) !== null && _a !== void 0 ? _a : this.daemonDir(args);
84
- return NativeLibrary_1.NativeLibrary.nativeLib.runDaemonCommand(command, fullArgs);
85
- }
86
50
  }
87
51
  CloudSqlite.Daemon = Daemon;
88
- async function transferDb(direction, props) {
52
+ /** @internal */
53
+ async function transferDb(direction, container, props) {
89
54
  if (direction === "download")
90
- fs.mkdirSync(path.dirname(props.localFile), { recursive: true }); // make sure the directory exists before starting download
91
- const transfer = new NativeLibrary_1.NativeLibrary.nativeLib.CloudDbTransfer(direction, props);
55
+ fs.mkdirSync(path.dirname(props.localFileName), { recursive: true }); // make sure the directory exists before starting download
92
56
  let timer;
93
57
  try {
58
+ const transfer = new NativeLibrary_1.NativeLibrary.nativeLib.CloudDbTransfer(direction, container, props);
94
59
  let total = 0;
95
60
  const onProgress = props.onProgress;
96
61
  if (onProgress) {
@@ -115,31 +80,48 @@ var CloudSqlite;
115
80
  }
116
81
  }
117
82
  CloudSqlite.transferDb = transferDb;
118
- async function initializeContainer(props) {
119
- const stat = await Daemon.command("create", Object.assign(Object.assign({}, props), { dbName: "" }));
120
- if (stat.result !== 0) // DbResult.BE_SQLITE_OK
121
- throw new Error(`Cannot initialize container: ${stat.errMsg}`);
122
- }
123
- CloudSqlite.initializeContainer = initializeContainer;
124
- async function uploadDb(props) {
125
- return transferDb("upload", props);
83
+ /** Upload a database into a CloudContainer
84
+ * @param container the CloudContainer holding the database. Must be connected.
85
+ * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.
86
+ * @note this function requires that the write lock be held on the container
87
+ */
88
+ async function uploadDb(container, props) {
89
+ await transferDb("upload", container, props);
90
+ await container.checkForChanges(); // re-read the manifest so the database is available locally.
126
91
  }
127
92
  CloudSqlite.uploadDb = uploadDb;
128
- async function downloadDb(props) {
129
- return transferDb("download", props);
93
+ /** Download a database from a CloudContainer
94
+ * @param container the CloudContainer holding the database. Must be connected.
95
+ * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.
96
+ * @returns a Promise that is resolved when the download completes.
97
+ * @note the download is "restartable." If the transfer is aborted and then re-requested, it will continue from where
98
+ * it left off rather than re-downloading the entire file.
99
+ */
100
+ async function downloadDb(container, props) {
101
+ await transferDb("download", container, props);
130
102
  }
131
103
  CloudSqlite.downloadDb = downloadDb;
132
- async function copyDb(oldVersion, newVersion, props) {
133
- const stat = await Daemon.command("copy", Object.assign({ dbName: oldVersion, toAlias: newVersion }, props));
134
- if (stat.result !== 0) // DbResult.BE_SQLITE_OK
135
- throw new Error(`Cannot copy db: ${stat.errMsg}`);
136
- }
137
- CloudSqlite.copyDb = copyDb;
138
- async function deleteDb(props) {
139
- const stat = await Daemon.command("delete", props);
140
- if (stat.result !== 0) // DbResult.BE_SQLITE_OK
141
- throw new Error(`Cannot delete db: ${stat.errMsg}`);
104
+ /**
105
+ * Perform an asynchronous write operation on a CloudContainer with the write lock held.
106
+ * 1. acquire the write lock if not already held
107
+ * 2. perform the operation
108
+ * 3. if the write lock was not held before step 1., release the write lock.
109
+ * @param user the name to be displayed in the event of lock collisions
110
+ * @param container the CloudContainer on which the operation will be performed
111
+ * @param operation an asynchronous operation performed with the write lock held.
112
+ */
113
+ async function withWriteLock(user, container, operation) {
114
+ const hadLock = container.hasWriteLock;
115
+ try {
116
+ if (!hadLock)
117
+ container.acquireWriteLock(user);
118
+ await operation(); // wait for work to finish or fail
119
+ }
120
+ finally {
121
+ if (!hadLock && container.hasWriteLock)
122
+ container.releaseWriteLock();
123
+ }
142
124
  }
143
- CloudSqlite.deleteDb = deleteDb;
125
+ CloudSqlite.withWriteLock = withWriteLock;
144
126
  })(CloudSqlite = exports.CloudSqlite || (exports.CloudSqlite = {}));
145
127
  //# sourceMappingURL=CloudSqlite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CloudSqlite.js","sourceRoot":"","sources":["../src/CloudSqlite.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,+CAA+C;AAC/C,yBAAyB;AACzB,yBAAyB;AACzB,6BAA6B;AAC7B,mDAAgD;AAShD,qGAAqG;AACrG,yCAAyC;AAEzC,IAAiB,WAAW,CA8N3B;AA9ND,WAAiB,WAAW;IAkG1B,MAAa,MAAM;QACT,MAAM,CAAC,OAAO,CAAC,KAAkB;;YACvC,OAAO,MAAA,KAAK,CAAC,OAAO,mCAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,6BAAa,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QAC/J,CAAC;QACM,MAAM,CAAC,SAAS,CAAC,KAAiB;;YACvC,OAAO,MAAA,KAAK,CAAC,SAAS,mCAAI,IAAI,CAAC,IAAI,CAAC,6BAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QACpF,CAAC;QAED,qHAAqH;QAC9G,MAAM,CAAC,KAAK,CAAC,KAA8C;;YAChE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAClC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,4DAA4D;YAEpG,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,EAAE,YAAY,EAAE,GAAG,GAAG,EAAE,EAAE,WAAW,EAAE,GAAG,MAAA,KAAK,CAAC,QAAQ,mCAAI,EAAE,EAAE,CAAC,CAAC;YAC5J,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;gBAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAChC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5C,IAAI,KAAK,CAAC,YAAY;gBACpB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;YACnD,IAAI,KAAK,CAAC,GAAG;gBACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAChC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;YAClD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAC5B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1C,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;gBAC/B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;gBAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3C,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;gBAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,YAAY;gBACpB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,qBAAqB;gBAC7B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC3B,IAAI,KAAK,CAAC,IAAI;gBACZ,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,OAAO;gBACf,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAChC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAA;YACjD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;gBACjC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;YACnD,IAAI,KAAK,CAAC,IAAI;gBACZ,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,kCAAO,KAAK,CAAC,YAAY,KAAE,wBAAwB,EAAE,IAAI,IAAG,CAAC;QACnH,CAAC;QAED,+IAA+I;QACxI,MAAM,CAAC,aAAa,CAAC,KAA+C;YACzE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3E,CAAC;QAED;;;;;;WAMG;QACI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAsB,EAAE,IAAsB;;YACxE,MAAM,QAAQ,qBAAQ,IAAI,CAAE,CAAC;YAC7B,QAAQ,CAAC,SAAS,GAAG,MAAA,QAAQ,CAAC,SAAS,mCAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChE,OAAO,6BAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrE,CAAC;KACF;IAlEY,kBAAM,SAkElB,CAAA;IAEM,KAAK,UAAU,UAAU,CAAC,SAA4B,EAAE,KAAsB;QACnF,IAAI,SAAS,KAAK,UAAU;YAC1B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,0DAA0D;QAE9H,MAAM,QAAQ,GAAG,IAAI,6BAAa,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAE/E,IAAI,KAAiC,CAAC;QACtC,IAAI;YACF,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YACpC,IAAI,UAAU,EAAE;gBACd,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;oBAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;oBACxC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;oBACvB,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC;wBAC7C,QAAQ,CAAC,cAAc,EAAE,CAAC;gBAC9B,CAAC,EAAE,GAAG,CAAC,CAAC;aACT;YACD,MAAM,QAAQ,CAAC,OAAO,CAAC;YACvB,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,wEAAwE;SACrG;QAAC,OAAO,GAAQ,EAAE;YACjB,IAAI,GAAG,CAAC,OAAO,KAAK,WAAW;gBAC7B,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC,CAAC,oCAAoC;YAEhE,MAAM,GAAG,CAAC;SACX;gBAAS;YACR,IAAI,KAAK;gBACP,aAAa,CAAC,KAAK,CAAC,CAAC;SACxB;IACH,CAAC;IA7BqB,sBAAU,aA6B/B,CAAA;IAEM,KAAK,UAAU,mBAAmB,CAAC,KAA2B;QACnE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,kCAAO,KAAK,KAAE,MAAM,EAAE,EAAE,IAAG,CAAC;QACtE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,wBAAwB;YAC7C,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IAJqB,+BAAmB,sBAIxC,CAAA;IAEM,KAAK,UAAU,QAAQ,CAAC,KAAsB;QACnD,OAAO,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAFqB,oBAAQ,WAE7B,CAAA;IAEM,KAAK,UAAU,UAAU,CAAC,KAAsB;QACrD,OAAO,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAFqB,sBAAU,aAE/B,CAAA;IAEM,KAAK,UAAU,MAAM,CAAC,UAAkB,EAAE,UAAkB,EAAE,KAA2B;QAC9F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,kBAAI,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,IAAK,KAAK,EAAG,CAAC;QACjG,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,wBAAwB;YAC7C,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;IAJqB,kBAAM,SAI3B,CAAA;IAEM,KAAK,UAAU,QAAQ,CAAC,KAAwC;QACrE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,wBAAwB;YAC7C,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IAJqB,oBAAQ,WAI7B,CAAA;AACH,CAAC,EA9NgB,WAAW,GAAX,mBAAW,KAAX,mBAAW,QA8N3B","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module iModels\r\n */\r\n\r\nimport * as child_process from \"child_process\";\r\nimport * as fs from \"fs\";\r\nimport * as os from \"os\";\r\nimport * as path from \"path\";\r\nimport { NativeLibrary } from \"./NativeLibrary\";\r\n\r\n/**\r\n * @note This package may only have **dev** dependencies on @itwin packages, so they are *not* available at runtime. Therefore we can only import **types** from them.\r\n */\r\n\r\nimport type { DbResult } from \"@itwin/core-bentley\";\r\nimport type { LocalFileName } from \"@itwin/core-common\";\r\n\r\n// cspell:ignore polltime blocksize cachesize notimestamps deletetime gctime retrytime nwrite ndelete\r\n/* eslint-disable no-restricted-syntax */\r\n\r\nexport namespace CloudSqlite {\r\n /** Error values for negative numbers returned by the Daemon `attach` command. */\r\n export const enum DaemonAttachError {\r\n INVALID_DAEMON_DIRECTORY = -1, DAEMON_NOT_ACTIVE = -2, SOCKET_ERROR = -3,\r\n }\r\n /** Possible values for `command` argument of `Daemon.command` method. */\r\n export type DaemonCommand = \"attach\" | \"detach\" | \"create\" | \"destroy\" | \"upload\" | \"download\" | \"delete\" | \"copy\" | \"queryManifestETag\";\r\n\r\n export interface AccountProps {\r\n /** blob storage module: e.g. \"azure\", \"google\", \"aws\". May also include URI style parameters. */\r\n storageType: string;\r\n /** blob store account name. */\r\n accountName: string;\r\n }\r\n\r\n export interface ContainerProps {\r\n /** the name of the container. */\r\n containerId: string;\r\n /** SAS token that grants access to the container. */\r\n sasToken: string;\r\n /** if true, container is attached with write permissions. */\r\n writeable?: boolean;\r\n /** if true, container is attached in \"secure\" mode (blocks are encrypted). */\r\n secure?: boolean;\r\n }\r\n\r\n export type ContainerAccessProps = AccountProps & ContainerProps;\r\n export interface DbNameProp { dbName: string }\r\n export interface DbProps extends DbNameProp { localFile: LocalFileName }\r\n export type TransferDirection = \"upload\" | \"download\";\r\n export interface TransferProgress { onProgress?: (loaded: number, total: number) => number }\r\n export type TransferProps = ContainerAccessProps & TransferProgress;\r\n export type TransferDbProps = TransferProps & DbProps;\r\n\r\n export interface CacheProps {\r\n /** full path of directory for daemon to store its files. Must be on fast local drive. */\r\n daemonDir?: string;\r\n /** block size, in megabytes used by CREATE command. Default is 4MB. */\r\n blockSizeMb?: number;\r\n }\r\n\r\n /** Properties for creating a new instance of the daemon process. */\r\n export interface DaemonProps {\r\n /** full path name of daemon.exe file. Default is to find \"BeBlobDaemon.exe\" in the same directory as this library. */\r\n exePath?: string;\r\n /** daemon connection address. Default is \"127.0.0.1\" */\r\n addr?: string;\r\n /** port number. Default 22002 */\r\n portNumber?: number;\r\n /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */\r\n maxCacheSize?: string;\r\n /** How often cloud storage is polled for database changes made by other daemon processes, in seconds. Default is 60. */\r\n pollTime?: number;\r\n /** How long an overwritten block is allowed to persist before it is permanently deleted, in seconds. Default is 3600. */\r\n deleteTime?: number;\r\n /** How often each daemon process scans for and deletes such garbage files, in seconds. Default is 3600. */\r\n gcTime?: number;\r\n /** How long after a failed checkpoint-to-upload operation the daemon process waits before retrying, in seconds. Default=10. */\r\n retryTime?: number;\r\n /** The maximum number of concurrent uploads (PUT requests) the daemon will make when uploading a new version of a database to cloud storage. Default=10. */\r\n nWrites?: number;\r\n /** The maximum number of concurrent deletes (DELETE requests) the daemon will make when uploading a new version of a database. Default=10. */\r\n nDeletes?: number;\r\n /** If true, unmodified cache entries are retained across runs of the daemon. Default=false. */\r\n persistAcrossSessions?: boolean;\r\n /** logging options */\r\n log?: string;\r\n /** if true, don't include timestamps in log messages */\r\n noTimeStamps?: boolean;\r\n /** if true, create local files only when first accessed. Default=false. */\r\n lazy?: boolean;\r\n /** if true, extra space for nonces is not reserved and no nonce values are used for encrypted pages. Default=false. */\r\n noNonce?: boolean;\r\n /** If specified, containers are automatically detached from the daemon process if there have been no connected clients for at least autodetach seconds.\r\n * If set to 0, then containers are never automatically detached. Default=0.\r\n */\r\n autodetach?: number;\r\n /** The amount of time, in seconds before an http request made to cloud storage by the daemon times out. Default 600 seconds. */\r\n httptimeout?: number;\r\n /** If true, two virtual tables become available to database clients for querying the internal state of the connected daemon process. */\r\n vtab?: boolean;\r\n /** options for spawn */\r\n spawnOptions?: child_process.SpawnOptions;\r\n }\r\n\r\n /** Optional arguments for Db upload and download commands. */\r\n export interface UploadDownloadArgs {\r\n /** The number of simultaneous HTTP requests. */\r\n nRequests?: number;\r\n }\r\n\r\n export interface CopyDbArgs {\r\n /** A new alias, for the `copy` command */\r\n toAlias?: string;\r\n }\r\n\r\n export type DaemonCommandArg = DbNameProp & AccountProps & CacheProps & CopyDbArgs & ContainerProps & UploadDownloadArgs & { localFile?: LocalFileName };\r\n\r\n export class Daemon {\r\n private static exeName(props: DaemonProps) {\r\n return props.exePath ?? path.join(path.dirname(require.resolve(NativeLibrary.libraryName)), os.platform() === \"win32\" ? \"BeBlobDaemon.exe\" : \"BeBlobDaemon\");\r\n }\r\n public static daemonDir(props: CacheProps) {\r\n return props.daemonDir ?? path.join(NativeLibrary.defaultCacheDir, \"blob-daemon\");\r\n }\r\n\r\n /** Start the Daemon process using the supplied properties. The process will be detached from the current process. */\r\n public static start(props: DaemonProps & AccountProps & CacheProps): child_process.ChildProcess {\r\n const dir = this.daemonDir(props);\r\n fs.mkdirSync(dir, { recursive: true }); // make sure the directory exists before starting the daemon\r\n\r\n const args = [`daemon`, `-module`, `${props.storageType}`, `-user`, `${props.accountName}`, `-directory`, `${dir}`, `-polltime`, `${props.pollTime ?? 60}`];\r\n if (props.addr !== undefined)\r\n args.push(`-addr`, `${props.addr}`);\r\n if (props.portNumber !== undefined)\r\n args.push(`-port`, `${props.portNumber}`);\r\n if (props.maxCacheSize)\r\n args.push(`-cachesize`, `${props.maxCacheSize}`);\r\n if (props.log)\r\n args.push(`-log`, `${props.log}`);\r\n if (props.deleteTime !== undefined)\r\n args.push(`-deletetime`, `${props.deleteTime}`);\r\n if (props.gcTime !== undefined)\r\n args.push(`-gctime`, `${props.gcTime}`);\r\n if (props.retryTime !== undefined)\r\n args.push(`-retrytime`, `${props.retryTime}`);\r\n if (props.nWrites !== undefined)\r\n args.push(`-nwrite`, `${props.nWrites}`);\r\n if (props.nDeletes !== undefined)\r\n args.push(`-ndelete`, `${props.nDeletes}`);\r\n if (props.noTimeStamps)\r\n args.push(`-notimestamps`);\r\n if (props.persistAcrossSessions)\r\n args.push(`-persistent`);\r\n if (props.lazy)\r\n args.push(`-lazy`);\r\n if (props.noNonce)\r\n args.push(`-nononce`);\r\n if (props.autodetach !== undefined)\r\n args.push(`-autodetach`, `${props.autodetach}`)\r\n if (props.httptimeout !== undefined)\r\n args.push(`-httptimeout`, `${props.httptimeout}`)\r\n if (props.vtab)\r\n args.push(`-vtab`);\r\n return child_process.spawn(this.exeName(props), args, { ...props.spawnOptions, windowsVerbatimArguments: true });\r\n }\r\n\r\n /** Get the full path to the local file that can be used to open a BlobDb. For the file to exist, you must first issue the \"attach\" command. */\r\n public static getDbFileName(props: CacheProps & ContainerProps & DbNameProp) {\r\n return path.join(this.daemonDir(props), props.containerId, props.dbName);\r\n }\r\n\r\n /** Perform one of the Daemon commands.\r\n * @param command The Daemon command to run.\r\n * @param args arguments to the command.\r\n * @return `Promise<{ result, errMsg }>` the meaning of result varies by command, but 0 always means success. For `attach`, negative values are\r\n * `DaemonAttachError`, positive numbers below 400 are `SQLITE_xxx` errors, and values 400 and above are HTTP errors.\r\n * `errMsg` is blank on success, but an english message useful for diagnostics otherwise.\r\n */\r\n public static async command(command: DaemonCommand, args: DaemonCommandArg): Promise<{ result: DaemonAttachError | DbResult | number, errMsg: string, eTag?: string }> {\r\n const fullArgs = { ...args };\r\n fullArgs.daemonDir = fullArgs.daemonDir ?? this.daemonDir(args);\r\n return NativeLibrary.nativeLib.runDaemonCommand(command, fullArgs);\r\n }\r\n }\r\n\r\n export async function transferDb(direction: TransferDirection, props: TransferDbProps) {\r\n if (direction === \"download\")\r\n fs.mkdirSync(path.dirname(props.localFile), { recursive: true }); // make sure the directory exists before starting download\r\n\r\n const transfer = new NativeLibrary.nativeLib.CloudDbTransfer(direction, props);\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n try {\r\n let total = 0;\r\n const onProgress = props.onProgress;\r\n if (onProgress) {\r\n timer = setInterval(async () => { // set an interval timer to show progress every 250ms\r\n const progress = transfer.getProgress();\r\n total = progress.total;\r\n if (onProgress(progress.loaded, progress.total))\r\n transfer.cancelTransfer();\r\n }, 250);\r\n }\r\n await transfer.promise;\r\n onProgress?.(total, total); // make sure we call progress func one last time when download completes\r\n } catch (err: any) {\r\n if (err.message === \"cancelled\")\r\n err.errorNumber = 131079; // BriefcaseStatus.DownloadCancelled\r\n\r\n throw err;\r\n } finally {\r\n if (timer)\r\n clearInterval(timer);\r\n }\r\n }\r\n\r\n export async function initializeContainer(props: ContainerAccessProps) {\r\n const stat = await Daemon.command(\"create\", { ...props, dbName: \"\" });\r\n if (stat.result !== 0) // DbResult.BE_SQLITE_OK\r\n throw new Error(`Cannot initialize container: ${stat.errMsg}`);\r\n }\r\n\r\n export async function uploadDb(props: TransferDbProps) {\r\n return transferDb(\"upload\", props);\r\n }\r\n\r\n export async function downloadDb(props: TransferDbProps) {\r\n return transferDb(\"download\", props);\r\n }\r\n\r\n export async function copyDb(oldVersion: string, newVersion: string, props: ContainerAccessProps) {\r\n const stat = await Daemon.command(\"copy\", { dbName: oldVersion, toAlias: newVersion, ...props });\r\n if (stat.result !== 0) // DbResult.BE_SQLITE_OK\r\n throw new Error(`Cannot copy db: ${stat.errMsg}`);\r\n }\r\n\r\n export async function deleteDb(props: ContainerAccessProps & DbNameProp) {\r\n const stat = await Daemon.command(\"delete\", props);\r\n if (stat.result !== 0) // DbResult.BE_SQLITE_OK\r\n throw new Error(`Cannot delete db: ${stat.errMsg}`);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"CloudSqlite.js","sourceRoot":"","sources":["../src/CloudSqlite.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module iModels\r\n */\r\n\r\nimport * as child_process from \"child_process\";\r\nimport * as fs from \"fs\";\r\nimport * as os from \"os\";\r\nimport * as path from \"path\";\r\nimport { IModelJsNative, NativeLibrary } from \"./NativeLibrary\";\r\n\r\n/**\r\n * @note This package may only have **dev** dependencies on @itwin packages, so they are *not* available at runtime. Therefore we can only import **types** from them.\r\n */\r\nimport type { LocalFileName } from \"@itwin/core-common\";\r\n\r\n// cspell:ignore polltime blocksize cachesize notimestamps deletetime gctime retrytime nwrite ndelete prefetch httptimeout\r\n/* eslint-disable no-restricted-syntax */\r\n\r\nexport namespace CloudSqlite {\r\n\r\n export const enum LogMask {\r\n LOG_HTTP = 0x0001, LOG_UPLOAD = 0x0002, LOG_CLEANUP = 0x0004, LOG_EVENT = 0x0008\r\n };\r\n\r\n /** Properties that specify how to access the account for a cloud blob-store container. */\r\n export interface AccountAccessProps {\r\n /** blob storage module: e.g. \"azure\", \"google\", \"aws\". May also include URI style parameters. */\r\n storageType: string;\r\n /** blob store account name, or a URI for custom domains. */\r\n accessName: string;\r\n }\r\n\r\n /** Properties of a CloudContainer. */\r\n export interface ContainerProps {\r\n /** the name of the container. */\r\n containerId: string;\r\n /** an alias for the container. Defaults to `containerId` */\r\n alias?: string;\r\n /** token that grants access to the container. For sas=1 `storageType`s, this is the sasToken. For sas=0, this is the account key */\r\n accessToken: string;\r\n /** if true, container is attached with write permissions, and accessToken must provide write access to the cloud container. */\r\n writeable?: boolean;\r\n /** if true, container is attached in \"secure\" mode (blocks are encrypted). Only supported in daemon mode. */\r\n secure?: boolean;\r\n }\r\n\r\n /** Returned from `CloudContainer.queryDatabase` describing one database in the container */\r\n export interface CachedDbProps {\r\n /** The total of (4Mb) blocks in the database. */\r\n readonly totalBlocks: number,\r\n /** the number of blocks of the database that have been downloaded into the CloudCache */\r\n readonly localBlocks: number,\r\n /** the number of blocks from this database that have been modified in the CloudCache and need to be uploaded. */\r\n readonly dirtyBlocks: number,\r\n /** If true, the database currently has transactions in the WAL file and may not be uploaded until they have been checkPointed. */\r\n readonly transactions: boolean;\r\n\r\n /** the state of this database. Indicates whether the database is new or deleted since last upload */\r\n readonly state: \"\" | \"copied\" | \"deleted\";\r\n }\r\n\r\n /** Properties for accessing a CloudContainer */\r\n export type ContainerAccessProps = AccountAccessProps & ContainerProps & {\r\n\r\n /** Duration for holding write lock, in seconds. After this time the write lock expires if not refreshed. Default is one hour. */\r\n durationSeconds?: number\r\n };\r\n\r\n /** The name of a CloudSqlite database within a CloudContainer. */\r\n export interface DbNameProp {\r\n /** the name of the database within the CloudContainer.\r\n * @note names of databases within a CloudContainer are always **case sensitive** on all platforms.*/\r\n dbName: string\r\n }\r\n\r\n /** Properties for accessing a database within a CloudContainer */\r\n export interface DbProps extends DbNameProp {\r\n /** the name of the local file to access the database. */\r\n localFileName: LocalFileName\r\n }\r\n\r\n export type TransferDirection = \"upload\" | \"download\";\r\n export interface TransferProgress {\r\n /** a user-supplied progress function called during the transfer operation. Return a non-0 value to abort the transfer. */\r\n onProgress?: (loaded: number, total: number) => number\r\n }\r\n\r\n export interface CloudHttpProps {\r\n /** The number of simultaneous HTTP requests. Default is 10. */\r\n nRequests?: number;\r\n }\r\n\r\n export interface PrefetchProps extends CloudHttpProps {\r\n /** timeout between requests, in milliseconds. Default is 100. */\r\n timeout?: number;\r\n }\r\n\r\n export type TransferDbProps = DbProps & TransferProgress & CloudHttpProps;\r\n\r\n /** Properties for creating a CloudCache. */\r\n export interface CacheProps extends CloudHttpProps {\r\n /** full path of directory for cache to store its files. Must be on a (preferably fast) local drive, and must be empty when the cache is first created. */\r\n rootDir: string;\r\n /** name of this cache. It is possible to have more than one CloudCache in the same session. */\r\n name: string;\r\n /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */\r\n cacheSize?: string;\r\n /** turn on diagnostics for `curl` (outputs to stderr) */\r\n curlDiagnostics?: boolean;\r\n }\r\n\r\n /** Properties for creating a new instance of a daemon process. */\r\n export interface DaemonProps {\r\n /** full path name of daemon.exe file. Default is to find \"iTwinDaemon.exe\" in the same directory as this library. */\r\n exePath?: string;\r\n /** daemon connection address. Default is \"127.0.0.1\" */\r\n addr?: string;\r\n /** port number. Default 22002 */\r\n portNumber?: number;\r\n /** maximum cache Size. Must be a number followed by either M (for megabytes) or G (for gigabytes.) Default is 1G */\r\n cacheSize?: string;\r\n /** logging options */\r\n log?: string;\r\n /** if true, don't include timestamps in log messages */\r\n noTimeStamps?: boolean;\r\n /** The amount of time, in seconds before an http request made to cloud storage by the daemon times out. Default 600 seconds. */\r\n httptimeout?: number;\r\n /** options for spawn */\r\n spawnOptions?: child_process.SpawnOptions;\r\n }\r\n export type DaemonCommandArg = DbNameProp & AccountAccessProps & CacheProps & ContainerProps;\r\n\r\n export class Daemon {\r\n private static exeName(props: DaemonProps) {\r\n return props.exePath ?? path.join(path.dirname(require.resolve(NativeLibrary.libraryName)), os.platform() === \"win32\" ? \"iTwinDaemon.exe\" : \"iTwinDaemon\");\r\n }\r\n public static daemonDir(props: CacheProps) {\r\n return props.rootDir ?? path.join(NativeLibrary.defaultCacheDir, \"itwin-daemon\");\r\n }\r\n\r\n /** Start the Daemon process using the supplied properties. The process will be detached from the current process. */\r\n public static start(props: DaemonProps & CacheProps): child_process.ChildProcess {\r\n const dir = this.daemonDir(props);\r\n fs.mkdirSync(dir, { recursive: true }); // make sure the directory exists before starting the daemon\r\n\r\n const args = [`daemon`];\r\n if (props.addr !== undefined)\r\n args.push(`-addr`, `${props.addr}`);\r\n if (props.portNumber !== undefined)\r\n args.push(`-port`, `${props.portNumber}`);\r\n if (props.cacheSize)\r\n args.push(`-cachesize`, `${props.cacheSize}`);\r\n if (props.log)\r\n args.push(`-log`, `${props.log}`);\r\n if (props.noTimeStamps)\r\n args.push(`-notimestamps`);\r\n if (props.httptimeout !== undefined)\r\n args.push(`-httptimeout`, `${props.httptimeout}`)\r\n args.push(`${dir}`); // This MUST be the last arg when starting the daemon.\r\n return child_process.spawn(this.exeName(props), args, { ...props.spawnOptions, windowsVerbatimArguments: true });\r\n }\r\n }\r\n\r\n /** @internal */\r\n export async function transferDb(direction: TransferDirection, container: IModelJsNative.CloudContainer, props: TransferDbProps) {\r\n if (direction === \"download\")\r\n fs.mkdirSync(path.dirname(props.localFileName), { recursive: true }); // make sure the directory exists before starting download\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n try {\r\n const transfer = new NativeLibrary.nativeLib.CloudDbTransfer(direction, container, props);\r\n let total = 0;\r\n const onProgress = props.onProgress;\r\n if (onProgress) {\r\n timer = setInterval(async () => { // set an interval timer to show progress every 250ms\r\n const progress = transfer.getProgress();\r\n total = progress.total;\r\n if (onProgress(progress.loaded, progress.total))\r\n transfer.cancelTransfer();\r\n }, 250);\r\n }\r\n await transfer.promise;\r\n onProgress?.(total, total); // make sure we call progress func one last time when download completes\r\n } catch (err: any) {\r\n if (err.message === \"cancelled\")\r\n err.errorNumber = 131079; // BriefcaseStatus.DownloadCancelled\r\n\r\n throw err;\r\n } finally {\r\n if (timer)\r\n clearInterval(timer);\r\n }\r\n }\r\n\r\n /** Upload a database into a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @note this function requires that the write lock be held on the container\r\n */\r\n export async function uploadDb(container: IModelJsNative.CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"upload\", container, props);\r\n await container.checkForChanges(); // re-read the manifest so the database is available locally.\r\n }\r\n\r\n /** Download a database from a CloudContainer\r\n * @param container the CloudContainer holding the database. Must be connected.\r\n * @param props the properties that describe the database to be downloaded, plus optionally an `onProgress` function.\r\n * @returns a Promise that is resolved when the download completes.\r\n * @note the download is \"restartable.\" If the transfer is aborted and then re-requested, it will continue from where\r\n * it left off rather than re-downloading the entire file.\r\n */\r\n export async function downloadDb(container: IModelJsNative.CloudContainer, props: TransferDbProps): Promise<void> {\r\n await transferDb(\"download\", container, props);\r\n }\r\n\r\n /**\r\n * Perform an asynchronous write operation on a CloudContainer with the write lock held.\r\n * 1. acquire the write lock if not already held\r\n * 2. perform the operation\r\n * 3. if the write lock was not held before step 1., release the write lock.\r\n * @param user the name to be displayed in the event of lock collisions\r\n * @param container the CloudContainer on which the operation will be performed\r\n * @param operation an asynchronous operation performed with the write lock held.\r\n */\r\n export async function withWriteLock(user: string, container: IModelJsNative.CloudContainer, operation: () => Promise<void>) {\r\n const hadLock = container.hasWriteLock;\r\n try {\r\n if (!hadLock)\r\n container.acquireWriteLock(user);\r\n await operation(); // wait for work to finish or fail\r\n } finally {\r\n if (!hadLock && container.hasWriteLock)\r\n container.releaseWriteLock();\r\n }\r\n }\r\n\r\n}\r\n"]}