@itwin/workspace-editor 3.3.0-dev.8 → 3.3.0-dev.82
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/README.md +466 -69
- package/lib/WorkspaceEditor.js +482 -142
- package/package.json +15 -14
- package/.rush/temp/package-deps_build +0 -0
- package/.rush/temp/package-deps_cover.json +0 -13
- package/.rush/temp/package-deps_docs.json +0 -13
- package/.rush/temp/package-deps_lint.json +0 -13
- package/.rush/temp/package-deps_webpack +0 -0
- package/.rush/temp/shrinkwrap-deps.json +0 -178
- package/CHANGELOG.json +0 -65
- package/CHANGELOG.md +0 -51
- package/lib/WorkspaceEditor.d.ts +0 -2
- package/lib/WorkspaceEditor.d.ts.map +0 -1
- package/lib/WorkspaceEditor.js.map +0 -1
- package/lib/tsconfig.tsbuildinfo +0 -1
- package/src/WorkspaceEditor.ts +0 -366
- package/tsconfig.json +0 -7
- package/workspace-editor.build.log +0 -0
package/src/WorkspaceEditor.ts
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
/*---------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
-
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as glob from "glob";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import * as readline from "readline";
|
|
10
|
-
import * as Yargs from "yargs";
|
|
11
|
-
import {
|
|
12
|
-
CloudSqlite,
|
|
13
|
-
EditableWorkspaceDb, IModelHost, IModelHostConfiguration, IModelJsFs, ITwinWorkspaceDb, WorkspaceContainerId, WorkspaceDbName,
|
|
14
|
-
WorkspaceResourceName,
|
|
15
|
-
} from "@itwin/core-backend";
|
|
16
|
-
import { DbResult, StopWatch } from "@itwin/core-bentley";
|
|
17
|
-
import { LocalDirName, LocalFileName } from "@itwin/core-common";
|
|
18
|
-
|
|
19
|
-
// cspell:ignore nodir
|
|
20
|
-
/* eslint-disable id-blacklist,no-console */
|
|
21
|
-
|
|
22
|
-
/** Properties for accessing a blob storage account. */
|
|
23
|
-
interface BlobAccountProps {
|
|
24
|
-
/** Token that provides required access (read/write/create/etc.) for blob store operation. */
|
|
25
|
-
sasToken: string;
|
|
26
|
-
/** Name for blob store user account */
|
|
27
|
-
accountName: string;
|
|
28
|
-
/** The string that identifies the storage type. Default = "azure?sas=1" */
|
|
29
|
-
storageType: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Allows overriding the location of WorkspaceDbs. If not present, defaults to `${homedir}/iTwin/Workspace` */
|
|
33
|
-
interface EditorOpts extends BlobAccountProps {
|
|
34
|
-
/** Directory for WorkspaceDbs */
|
|
35
|
-
directory?: LocalDirName;
|
|
36
|
-
containerId: WorkspaceContainerId;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Id of WorkspaceDb for operation */
|
|
40
|
-
interface WorkspaceDbOpt extends EditorOpts {
|
|
41
|
-
dbName: WorkspaceDbName;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Resource type names */
|
|
45
|
-
type RscType = "blob" | "string" | "file";
|
|
46
|
-
|
|
47
|
-
/** Options for adding, updating, extracting, or deleting resources from a WorkspaceDb */
|
|
48
|
-
interface ResourceOption extends WorkspaceDbOpt {
|
|
49
|
-
rscName?: WorkspaceResourceName;
|
|
50
|
-
update: boolean;
|
|
51
|
-
type: RscType;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Options for deleting resources from a WorkspaceDb */
|
|
55
|
-
interface RemoveResourceOpts extends ResourceOption {
|
|
56
|
-
rscName: WorkspaceResourceName;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Options for extracting resources from a WorkspaceDb */
|
|
60
|
-
interface ExtractResourceOpts extends ResourceOption {
|
|
61
|
-
rscName: WorkspaceResourceName;
|
|
62
|
-
fileName: LocalFileName;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Options for adding or updating local files as resources into a WorkspaceDb */
|
|
66
|
-
interface AddFileOptions extends ResourceOption {
|
|
67
|
-
files: LocalFileName;
|
|
68
|
-
root?: LocalDirName;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Options for listing the resources in a WorkspaceDb */
|
|
72
|
-
interface ListOptions extends WorkspaceDbOpt {
|
|
73
|
-
strings?: boolean;
|
|
74
|
-
files?: boolean;
|
|
75
|
-
blobs?: boolean;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
interface TransferOptions extends BlobAccountProps, WorkspaceDbOpt {
|
|
79
|
-
/** If present, name of local file for download. */
|
|
80
|
-
localFile?: string;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Options for uploading a WorkspaceDb to blob storage */
|
|
84
|
-
interface UploadOptions extends TransferOptions {
|
|
85
|
-
initialize: boolean;
|
|
86
|
-
replace: boolean;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Create a new empty WorkspaceDb */
|
|
90
|
-
async function createWorkspaceDb(args: WorkspaceDbOpt) {
|
|
91
|
-
const wsFile = new EditableWorkspaceDb(args.dbName, IModelHost.appWorkspace.getContainer(args));
|
|
92
|
-
wsFile.create();
|
|
93
|
-
console.log(`created WorkspaceDb ${wsFile.sqliteDb.nativeDb.getFilePath()}`);
|
|
94
|
-
wsFile.close();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** open, call a function to process, then close a WorkspaceDb */
|
|
98
|
-
function processWorkspace<W extends ITwinWorkspaceDb, T extends WorkspaceDbOpt>(args: T, ws: W, fn: (ws: W, args: T) => void) {
|
|
99
|
-
ws.open();
|
|
100
|
-
console.log(`WorkspaceDb [${ws.sqliteDb.nativeDb.getFilePath()}]`);
|
|
101
|
-
try {
|
|
102
|
-
fn(ws, args);
|
|
103
|
-
} finally {
|
|
104
|
-
ws.close();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Open for write, call a function to process, then close a WorkspaceDb */
|
|
109
|
-
function editWorkspace<T extends WorkspaceDbOpt>(args: T, fn: (ws: EditableWorkspaceDb, args: T) => void) {
|
|
110
|
-
processWorkspace(args, new EditableWorkspaceDb(args.dbName, IModelHost.appWorkspace.getContainer(args)), fn);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Open for read, call a function to process, then close a WorkspaceDb */
|
|
114
|
-
function readWorkspace<T extends WorkspaceDbOpt>(args: T, fn: (ws: ITwinWorkspaceDb, args: T) => void) {
|
|
115
|
-
processWorkspace(args, new ITwinWorkspaceDb(args.dbName, IModelHost.appWorkspace.getContainer(args)), fn);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** List the contents of a WorkspaceDb */
|
|
119
|
-
async function listWorkspaceDb(args: ListOptions) {
|
|
120
|
-
readWorkspace(args, (file, args) => {
|
|
121
|
-
if (!args.strings && !args.blobs && !args.files)
|
|
122
|
-
args.blobs = args.files = args.strings = true;
|
|
123
|
-
|
|
124
|
-
if (args.strings) {
|
|
125
|
-
console.log(" strings:");
|
|
126
|
-
file.sqliteDb.withSqliteStatement("SELECT id,value FROM strings", (stmt) => {
|
|
127
|
-
while (DbResult.BE_SQLITE_ROW === stmt.step())
|
|
128
|
-
console.log(` name=[${stmt.getValueString(0)}], size=${stmt.getValueString(1).length}`);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
if (args.blobs) {
|
|
132
|
-
console.log(" blobs:");
|
|
133
|
-
file.sqliteDb.withSqliteStatement("SELECT id,value FROM blobs", (stmt) => {
|
|
134
|
-
while (DbResult.BE_SQLITE_ROW === stmt.step())
|
|
135
|
-
console.log(` name=[${stmt.getValueString(0)}], size=${stmt.getValueBlob(1).length}`);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
if (args.files) {
|
|
139
|
-
console.log(" files:");
|
|
140
|
-
file.sqliteDb.withSqliteStatement("SELECT name FROM be_EmbedFile", (stmt) => {
|
|
141
|
-
while (DbResult.BE_SQLITE_ROW === stmt.step()) {
|
|
142
|
-
const embed = file.queryFileResource(stmt.getValueString(0));
|
|
143
|
-
if (embed) {
|
|
144
|
-
const info = embed.info;
|
|
145
|
-
const date = new Date(info.date);
|
|
146
|
-
console.log(` name=[${stmt.getValueString(0)}], size=${info.size}, ext="${info.fileExt}", date=${date.toString()}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/** Add or Update files into a WorkspaceDb. */
|
|
155
|
-
async function addResource(args: AddFileOptions) {
|
|
156
|
-
editWorkspace(args, (wsFile, args) => {
|
|
157
|
-
glob.sync(args.files, { cwd: args.root ?? process.cwd(), nodir: true }).forEach((filePath) => {
|
|
158
|
-
const file = args.root ? join(args.root, filePath) : filePath;
|
|
159
|
-
if (!IModelJsFs.existsSync(file))
|
|
160
|
-
throw new Error(`file [${file}] does not exist`);
|
|
161
|
-
const name = args.rscName ?? filePath;
|
|
162
|
-
try {
|
|
163
|
-
if (args.type === "string") {
|
|
164
|
-
const val = fs.readFileSync(file, "utf-8");
|
|
165
|
-
wsFile[args.update ? "updateString" : "addString"](name, val);
|
|
166
|
-
} else if (args.type === "blob") {
|
|
167
|
-
const val = fs.readFileSync(file);
|
|
168
|
-
wsFile[args.update ? "updateBlob" : "addBlob"](name, val);
|
|
169
|
-
} else {
|
|
170
|
-
wsFile[args.update ? "updateFile" : "addFile"](name, file);
|
|
171
|
-
}
|
|
172
|
-
console.log(` ${args.update ? "updated" : "added"} "${file}" as ${args.type} resource [${name}]`);
|
|
173
|
-
} catch (e: any) {
|
|
174
|
-
console.error(e.message);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/** Extract a single resource from a WorkspaceDb into a local file */
|
|
181
|
-
async function extractResource(args: ExtractResourceOpts) {
|
|
182
|
-
readWorkspace(args, (file, args) => {
|
|
183
|
-
const verify = <T>(val: T | undefined): T => {
|
|
184
|
-
if (val === undefined)
|
|
185
|
-
throw new Error(` ${args.type} resource "${args.rscName}" does not exist`);
|
|
186
|
-
return val;
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
if (args.type === "string") {
|
|
190
|
-
fs.writeFileSync(args.fileName, verify(file.getString(args.rscName)));
|
|
191
|
-
} else if (args.type === "blob") {
|
|
192
|
-
fs.writeFileSync(args.fileName, verify(file.getBlob(args.rscName)));
|
|
193
|
-
} else {
|
|
194
|
-
verify(file.getFile(args.rscName, args.fileName));
|
|
195
|
-
}
|
|
196
|
-
console.log(` ${args.type} resource [${args.rscName}] extracted to "${args.fileName}"`);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/** Remove a single resource from a WorkspaceDb */
|
|
201
|
-
async function removeResource(args: RemoveResourceOpts) {
|
|
202
|
-
editWorkspace(args, (wsFile, args) => {
|
|
203
|
-
if (args.type === "string")
|
|
204
|
-
wsFile.removeString(args.rscName);
|
|
205
|
-
else if (args.type === "blob")
|
|
206
|
-
wsFile.removeBlob(args.rscName);
|
|
207
|
-
else
|
|
208
|
-
wsFile.removeFile(args.rscName);
|
|
209
|
-
console.log(` removed ${args.type} resource [${args.rscName}]`);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function getDbFileName(args: WorkspaceDbOpt): LocalFileName {
|
|
214
|
-
return new ITwinWorkspaceDb(args.dbName, IModelHost.appWorkspace.getContainer(args)).localFile;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/** Vacuum a local WorkspaceDb file, usually immediately prior to uploading. */
|
|
218
|
-
async function vacuumWorkspaceDb(args: WorkspaceDbOpt) {
|
|
219
|
-
const localFile = getDbFileName(args);
|
|
220
|
-
IModelHost.platform.DgnDb.vacuum(localFile);
|
|
221
|
-
console.log(`${localFile} vacuumed`);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** Either upload or download a WorkspaceDb to/from a WorkspaceContainer. Shows progress % during transfer */
|
|
225
|
-
async function performTransfer(direction: CloudSqlite.TransferDirection, args: TransferOptions) {
|
|
226
|
-
const localFile = args.localFile ?? getDbFileName(args);
|
|
227
|
-
const info = `${direction} ${localFile}, containerId=${args.containerId}, WorkspaceDbName=${args.dbName} : `;
|
|
228
|
-
|
|
229
|
-
let last = 0;
|
|
230
|
-
const onProgress = (loaded: number, total: number) => {
|
|
231
|
-
if (loaded > last) {
|
|
232
|
-
last = loaded;
|
|
233
|
-
const message = ` ${(loaded * 100 / total).toFixed(2)}%`;
|
|
234
|
-
readline.cursorTo(process.stdout, info.length);
|
|
235
|
-
process.stdout.write(message);
|
|
236
|
-
}
|
|
237
|
-
return 0;
|
|
238
|
-
};
|
|
239
|
-
process.stdout.write(info);
|
|
240
|
-
const timer = new StopWatch(direction, true);
|
|
241
|
-
await CloudSqlite.transferDb(direction, { ...args, localFile, onProgress });
|
|
242
|
-
readline.cursorTo(process.stdout, info.length);
|
|
243
|
-
process.stdout.write(`complete, ${timer.elapsedSeconds.toString()} seconds`);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/** Upload a WorkspaceDb to a WorkspaceContainer. */
|
|
247
|
-
async function uploadWorkspaceDb(args: UploadOptions) {
|
|
248
|
-
if (args.initialize)
|
|
249
|
-
await CloudSqlite.initializeContainer(args);
|
|
250
|
-
return performTransfer("upload", args);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/** Download a WorkspaceDb from a WorkspaceContainer. */
|
|
254
|
-
async function downloadWorkspaceDb(args: TransferOptions) {
|
|
255
|
-
return performTransfer("download", args);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/** Delete a WorkspaceDb from a WorkspaceContainer. */
|
|
259
|
-
async function deleteWorkspaceDb(args: BlobAccountProps & WorkspaceDbOpt) {
|
|
260
|
-
await CloudSqlite.deleteDb(args);
|
|
261
|
-
console.log(`deleted WorkspaceDb [${args.dbName}] from containerId: ${args.containerId}`);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/** Start `IModelHost`, then run a WorkspaceEditor command. Errors are logged to console. */
|
|
265
|
-
function runCommand<T extends EditorOpts>(cmd: (args: T) => Promise<void>) {
|
|
266
|
-
return async (args: T) => {
|
|
267
|
-
try {
|
|
268
|
-
const config = new IModelHostConfiguration();
|
|
269
|
-
if (args.directory)
|
|
270
|
-
config.workspace = { containerDir: args.directory };
|
|
271
|
-
await IModelHost.startup(config);
|
|
272
|
-
await cmd(args);
|
|
273
|
-
} catch (e: any) {
|
|
274
|
-
console.error(e.message);
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/** Parse and execute WorkspaceEditor commands */
|
|
280
|
-
async function main() {
|
|
281
|
-
const type = { alias: "t", describe: "the type of resource", choices: ["blob", "string", "file"], required: true };
|
|
282
|
-
const update = { alias: "u", describe: "update (i.e. replace) rather than add the files", boolean: true, default: false };
|
|
283
|
-
Yargs.usage("Edits or lists contents of a WorkspaceDb");
|
|
284
|
-
Yargs.wrap(Math.min(130, Yargs.terminalWidth()));
|
|
285
|
-
Yargs.strict();
|
|
286
|
-
Yargs.config();
|
|
287
|
-
Yargs.default("config", "workspaceEditor.json");
|
|
288
|
-
Yargs.help();
|
|
289
|
-
Yargs.version("V2.0");
|
|
290
|
-
Yargs.options({
|
|
291
|
-
directory: { alias: "d", describe: "directory to use for WorkspaceContainers", string: true },
|
|
292
|
-
containerId: { alias: "c", describe: "WorkspaceContainerId for WorkspaceDb", string: true, required: true },
|
|
293
|
-
sasToken: { alias: "s", describe: "shared access signature token", string: true, default: "" },
|
|
294
|
-
accountName: { alias: "a", describe: "cloud storage account name for container", string: true, default: "" },
|
|
295
|
-
storageType: { describe: "storage module type", string: true, default: "azure?sas=1" },
|
|
296
|
-
});
|
|
297
|
-
Yargs.command({
|
|
298
|
-
command: "create <dbName>",
|
|
299
|
-
describe: "create a new WorkspaceDb",
|
|
300
|
-
handler: runCommand(createWorkspaceDb),
|
|
301
|
-
});
|
|
302
|
-
Yargs.command({
|
|
303
|
-
command: "list <dbName>",
|
|
304
|
-
describe: "list the contents of a WorkspaceDb",
|
|
305
|
-
builder: {
|
|
306
|
-
strings: { alias: "s", describe: "list string resources", boolean: true, default: false },
|
|
307
|
-
blobs: { alias: "b", describe: "list blob resources", boolean: true, default: false },
|
|
308
|
-
files: { alias: "f", describe: "list file resources", boolean: true, default: false },
|
|
309
|
-
},
|
|
310
|
-
handler: runCommand(listWorkspaceDb),
|
|
311
|
-
});
|
|
312
|
-
Yargs.command({
|
|
313
|
-
command: "add <dbName> <files>",
|
|
314
|
-
describe: "add or update files into a WorkspaceDb",
|
|
315
|
-
builder: {
|
|
316
|
-
name: { alias: "n", describe: "resource name for file", string: true },
|
|
317
|
-
root: { alias: "r", describe: "root directory. Path parts after this will be saved in resource name", string: true },
|
|
318
|
-
update,
|
|
319
|
-
type,
|
|
320
|
-
},
|
|
321
|
-
handler: runCommand(addResource),
|
|
322
|
-
});
|
|
323
|
-
Yargs.command({
|
|
324
|
-
command: "extract <dbName> <rscName> <fileName>",
|
|
325
|
-
describe: "extract a resource from a WorkspaceDb into a local file",
|
|
326
|
-
builder: { type },
|
|
327
|
-
handler: runCommand(extractResource),
|
|
328
|
-
});
|
|
329
|
-
Yargs.command({
|
|
330
|
-
command: "remove <dbName> <rscName>",
|
|
331
|
-
describe: "remove a resource from a WorkspaceDb",
|
|
332
|
-
builder: { type },
|
|
333
|
-
handler: runCommand(removeResource),
|
|
334
|
-
});
|
|
335
|
-
Yargs.command({
|
|
336
|
-
command: "upload <dbName>",
|
|
337
|
-
describe: "upload a WorkspaceDb to cloud storage",
|
|
338
|
-
builder: {
|
|
339
|
-
initialize: { alias: "i", describe: "initialize container", boolean: true, default: false },
|
|
340
|
-
localFile: { alias: "l", describe: "name of source local file", string: true, required: false },
|
|
341
|
-
},
|
|
342
|
-
handler: runCommand(uploadWorkspaceDb),
|
|
343
|
-
});
|
|
344
|
-
Yargs.command({
|
|
345
|
-
command: "download <dbName>",
|
|
346
|
-
describe: "download a WorkspaceDb from cloud storage to local file",
|
|
347
|
-
builder: {
|
|
348
|
-
localFile: { alias: "l", describe: "name of target local file", string: true, required: false },
|
|
349
|
-
},
|
|
350
|
-
handler: runCommand(downloadWorkspaceDb),
|
|
351
|
-
});
|
|
352
|
-
Yargs.command({
|
|
353
|
-
command: "delete <dbName>",
|
|
354
|
-
describe: "delete a WorkspaceDb from cloud storage",
|
|
355
|
-
handler: runCommand(deleteWorkspaceDb),
|
|
356
|
-
});
|
|
357
|
-
Yargs.command({
|
|
358
|
-
command: "vacuum <dbName>",
|
|
359
|
-
describe: "vacuum a WorkspaceDb",
|
|
360
|
-
handler: runCommand(vacuumWorkspaceDb),
|
|
361
|
-
});
|
|
362
|
-
Yargs.demandCommand();
|
|
363
|
-
Yargs.argv;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
void main();
|
package/tsconfig.json
DELETED
|
File without changes
|