@itwin/core-backend 4.5.0-dev.8 → 4.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 (127) hide show
  1. package/CHANGELOG.md +88 -1
  2. package/LICENSE.md +1 -1
  3. package/lib/cjs/BackendHubAccess.d.ts +1 -1
  4. package/lib/cjs/BackendHubAccess.d.ts.map +1 -1
  5. package/lib/cjs/BackendHubAccess.js.map +1 -1
  6. package/lib/cjs/BackendLoggerCategory.js.map +1 -1
  7. package/lib/cjs/BisCoreSchema.js.map +1 -1
  8. package/lib/cjs/BlobContainerService.js.map +1 -1
  9. package/lib/cjs/BriefcaseManager.js.map +1 -1
  10. package/lib/cjs/Category.js.map +1 -1
  11. package/lib/cjs/ChangeSummaryManager.js +2 -2
  12. package/lib/cjs/ChangeSummaryManager.js.map +1 -1
  13. package/lib/cjs/ChangedElementsDb.js.map +1 -1
  14. package/lib/cjs/ChangedElementsManager.js.map +1 -1
  15. package/lib/cjs/ChangesetECAdaptor.js +237 -237
  16. package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
  17. package/lib/cjs/ChannelControl.js.map +1 -1
  18. package/lib/cjs/CheckpointManager.d.ts +4 -3
  19. package/lib/cjs/CheckpointManager.d.ts.map +1 -1
  20. package/lib/cjs/CheckpointManager.js +37 -28
  21. package/lib/cjs/CheckpointManager.js.map +1 -1
  22. package/lib/cjs/ClassRegistry.js +5 -5
  23. package/lib/cjs/ClassRegistry.js.map +1 -1
  24. package/lib/cjs/CloudSqlite.d.ts +3 -1
  25. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  26. package/lib/cjs/CloudSqlite.js +6 -3
  27. package/lib/cjs/CloudSqlite.js.map +1 -1
  28. package/lib/cjs/CodeService.js.map +1 -1
  29. package/lib/cjs/CodeSpecs.js.map +1 -1
  30. package/lib/cjs/ConcurrentQuery.js.map +1 -1
  31. package/lib/cjs/CustomViewState3dCreator.js.map +1 -1
  32. package/lib/cjs/DevTools.js.map +1 -1
  33. package/lib/cjs/DisplayStyle.js.map +1 -1
  34. package/lib/cjs/ECDb.js.map +1 -1
  35. package/lib/cjs/ECSchemaXmlContext.js.map +1 -1
  36. package/lib/cjs/ECSqlStatement.js.map +1 -1
  37. package/lib/cjs/Element.d.ts +6 -0
  38. package/lib/cjs/Element.d.ts.map +1 -1
  39. package/lib/cjs/Element.js +7 -1
  40. package/lib/cjs/Element.js.map +1 -1
  41. package/lib/cjs/ElementAspect.js.map +1 -1
  42. package/lib/cjs/ElementGraphics.js.map +1 -1
  43. package/lib/cjs/ElementTreeWalker.js.map +1 -1
  44. package/lib/cjs/Entity.js.map +1 -1
  45. package/lib/cjs/EntityReferences.js.map +1 -1
  46. package/lib/cjs/ExportGraphics.js.map +1 -1
  47. package/lib/cjs/ExternalSource.js.map +1 -1
  48. package/lib/cjs/GeoCoordConfig.js.map +1 -1
  49. package/lib/cjs/GeometrySummary.js +47 -47
  50. package/lib/cjs/GeometrySummary.js.map +1 -1
  51. package/lib/cjs/HubMock.js.map +1 -1
  52. package/lib/cjs/IModelCloneContext.js.map +1 -1
  53. package/lib/cjs/IModelDb.d.ts +32 -27
  54. package/lib/cjs/IModelDb.d.ts.map +1 -1
  55. package/lib/cjs/IModelDb.js +173 -41
  56. package/lib/cjs/IModelDb.js.map +1 -1
  57. package/lib/cjs/IModelElementCloneContext.js.map +1 -1
  58. package/lib/cjs/IModelHost.d.ts +0 -2
  59. package/lib/cjs/IModelHost.d.ts.map +1 -1
  60. package/lib/cjs/IModelHost.js +1 -5
  61. package/lib/cjs/IModelHost.js.map +1 -1
  62. package/lib/cjs/IModelJsFs.js.map +1 -1
  63. package/lib/cjs/IpcHost.d.ts.map +1 -1
  64. package/lib/cjs/IpcHost.js +3 -0
  65. package/lib/cjs/IpcHost.js.map +1 -1
  66. package/lib/cjs/LineStyle.js.map +1 -1
  67. package/lib/cjs/LocalHub.js +1 -1
  68. package/lib/cjs/LocalHub.js.map +1 -1
  69. package/lib/cjs/LocalhostIpcHost.js.map +1 -1
  70. package/lib/cjs/Material.js.map +1 -1
  71. package/lib/cjs/Model.js.map +1 -1
  72. package/lib/cjs/NativeAppStorage.js.map +1 -1
  73. package/lib/cjs/NativeHost.js.map +1 -1
  74. package/lib/cjs/NavigationRelationship.js.map +1 -1
  75. package/lib/cjs/PromiseMemoizer.js.map +1 -1
  76. package/lib/cjs/PropertyStore.js.map +1 -1
  77. package/lib/cjs/Relationship.js.map +1 -1
  78. package/lib/cjs/RpcBackend.js.map +1 -1
  79. package/lib/cjs/SQLiteDb.js.map +1 -1
  80. package/lib/cjs/Schema.js.map +1 -1
  81. package/lib/cjs/SchemaSync.js.map +1 -1
  82. package/lib/cjs/SchemaUtils.js.map +1 -1
  83. package/lib/cjs/ServerBasedLocks.js.map +1 -1
  84. package/lib/cjs/SqliteChangesetReader.js.map +1 -1
  85. package/lib/cjs/SqliteStatement.js.map +1 -1
  86. package/lib/cjs/Texture.js.map +1 -1
  87. package/lib/cjs/TileStorage.d.ts.map +1 -1
  88. package/lib/cjs/TileStorage.js +9 -1
  89. package/lib/cjs/TileStorage.js.map +1 -1
  90. package/lib/cjs/TxnManager.js.map +1 -1
  91. package/lib/cjs/ViewDefinition.js.map +1 -1
  92. package/lib/cjs/ViewStateHydrator.js.map +1 -1
  93. package/lib/cjs/ViewStore.js.map +1 -1
  94. package/lib/cjs/assets/IModelChange.02.00.00.ecschema.xml +90 -90
  95. package/lib/cjs/assets/Settings/Schemas/Cloud.Schema.json +44 -44
  96. package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +31 -31
  97. package/lib/cjs/assets/Settings/Schemas/Workspace.Schema.json +52 -52
  98. package/lib/cjs/assets/Settings/backend.setting.json5 +132 -132
  99. package/lib/cjs/core-backend.js.map +1 -1
  100. package/lib/cjs/domains/FunctionalElements.js.map +1 -1
  101. package/lib/cjs/domains/FunctionalSchema.js.map +1 -1
  102. package/lib/cjs/domains/GenericElements.js.map +1 -1
  103. package/lib/cjs/domains/GenericSchema.js.map +1 -1
  104. package/lib/cjs/rpc/multipart.js.map +1 -1
  105. package/lib/cjs/rpc/tracing.js.map +1 -1
  106. package/lib/cjs/rpc/web/logging.d.ts.map +1 -1
  107. package/lib/cjs/rpc/web/logging.js +0 -2
  108. package/lib/cjs/rpc/web/logging.js.map +1 -1
  109. package/lib/cjs/rpc/web/request.js.map +1 -1
  110. package/lib/cjs/rpc/web/response.d.ts.map +1 -1
  111. package/lib/cjs/rpc/web/response.js +16 -0
  112. package/lib/cjs/rpc/web/response.js.map +1 -1
  113. package/lib/cjs/rpc-impl/DevToolsRpcImpl.js.map +1 -1
  114. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  115. package/lib/cjs/rpc-impl/IModelTileRpcImpl.js.map +1 -1
  116. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts.map +1 -1
  117. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js +12 -13
  118. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  119. package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
  120. package/lib/cjs/rpc-impl/WipRpcImpl.js.map +1 -1
  121. package/lib/cjs/workspace/Settings.js.map +1 -1
  122. package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
  123. package/lib/cjs/workspace/Workspace.d.ts +107 -123
  124. package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
  125. package/lib/cjs/workspace/Workspace.js +132 -155
  126. package/lib/cjs/workspace/Workspace.js.map +1 -1
  127. package/package.json +13 -12
@@ -7,7 +7,7 @@
7
7
  * @module Workspace
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.EditableWorkspaceDb = exports.ITwinWorkspaceDb = exports.ITwinWorkspaceContainer = exports.ITwinWorkspace = exports.WorkspaceSetting = void 0;
10
+ exports.EditableWorkspaceDb = exports.Workspace = exports.WorkspaceDb = exports.WorkspaceContainer = exports.WorkspaceSetting = void 0;
11
11
  const crypto_1 = require("crypto");
12
12
  const fs = require("fs-extra");
13
13
  const path_1 = require("path");
@@ -22,16 +22,116 @@ const Settings_1 = require("./Settings");
22
22
  const SettingsSchemas_1 = require("./SettingsSchemas");
23
23
  /* eslint-disable @typescript-eslint/naming-convention */
24
24
  // cspell:ignore rowid primarykey julianday
25
+ function noLeadingOrTrailingSpaces(name, msg) {
26
+ if (name.trim() !== name)
27
+ throw new Error(`${msg} [${name}] may not have leading or tailing spaces`);
28
+ }
25
29
  /** The Settings used by Workspace api
26
30
  * @beta
27
31
  */
28
32
  exports.WorkspaceSetting = {
29
- Accounts: "cloud/accounts",
30
33
  Containers: "cloud/containers",
31
34
  Databases: "workspace/databases",
32
35
  };
33
- /** @internal */
34
- class ITwinWorkspace {
36
+ /** @beta */
37
+ var WorkspaceContainer;
38
+ (function (WorkspaceContainer) {
39
+ function validateDbName(dbName) {
40
+ if (dbName === "" || dbName.length > 255 || /[#\.<>:"/\\"`'|?*\u0000-\u001F]/g.test(dbName) || /^(con|prn|aux|nul|com\d|lpt\d)$/i.test(dbName))
41
+ throw new Error(`invalid dbName: [${dbName}]`);
42
+ noLeadingOrTrailingSpaces(dbName, "dbName");
43
+ }
44
+ WorkspaceContainer.validateDbName = validateDbName;
45
+ /**
46
+ * Validate that a WorkspaceContainer.Id is valid.
47
+ * The rules for ContainerIds (from Azure, see https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata):
48
+ * - may only contain lower case letters, numbers or dashes
49
+ * - may not start or end with with a dash nor have more than one dash in a row
50
+ * - may not be shorter than 3 or longer than 63 characters
51
+ */
52
+ function validateContainerId(id) {
53
+ if (!/^(?=.{3,63}$)[a-z0-9]+(-[a-z0-9]+)*$/g.test(id))
54
+ throw new Error(`invalid containerId: [${id}]`);
55
+ }
56
+ WorkspaceContainer.validateContainerId = validateContainerId;
57
+ /** @internal */
58
+ function validateVersion(version) {
59
+ version = version ?? "1.0.0";
60
+ if (version) {
61
+ const opts = { loose: true, includePrerelease: true };
62
+ // clean allows prerelease, so try it first. If that fails attempt to coerce it (coerce strips prerelease even if you say not to.)
63
+ const semVersion = semver.clean(version, opts) ?? semver.coerce(version, opts)?.version;
64
+ if (!semVersion)
65
+ throw new Error("invalid version specification");
66
+ version = semVersion;
67
+ }
68
+ return version;
69
+ }
70
+ WorkspaceContainer.validateVersion = validateVersion;
71
+ /**
72
+ * Parse the name stored in a WorkspaceContainer into the dbName and version number. A single WorkspaceContainer may hold
73
+ * many versions of the same WorkspaceDb. The name of the Db in the WorkspaceContainer is in the format "name:version". This
74
+ * function splits them into separate strings.
75
+ */
76
+ function parseDbFileName(dbFileName) {
77
+ const parts = dbFileName.split(":");
78
+ return { dbName: parts[0], version: parts[1] };
79
+ }
80
+ WorkspaceContainer.parseDbFileName = parseDbFileName;
81
+ /** Create a dbName for a WorkspaceDb from its base name and version. This will be in the format "name:version" */
82
+ function makeDbFileName(dbName, version) {
83
+ return `${dbName}:${WorkspaceContainer.validateVersion(version)}`;
84
+ }
85
+ WorkspaceContainer.makeDbFileName = makeDbFileName;
86
+ })(WorkspaceContainer = exports.WorkspaceContainer || (exports.WorkspaceContainer = {}));
87
+ /** @beta */
88
+ var WorkspaceDb;
89
+ (function (WorkspaceDb) {
90
+ /** file extension for local WorkspaceDbs
91
+ * @internal
92
+ */
93
+ WorkspaceDb.fileExt = "itwin-workspace";
94
+ /** construct a new instance of a WorkspaceDb */
95
+ function construct(props, container) {
96
+ return new WorkspaceDbImpl(props, container);
97
+ }
98
+ WorkspaceDb.construct = construct;
99
+ })(WorkspaceDb = exports.WorkspaceDb || (exports.WorkspaceDb = {}));
100
+ /** @beta */
101
+ var Workspace;
102
+ (function (Workspace) {
103
+ /** @internal */
104
+ function construct(settings, opts) {
105
+ return new WorkspaceImpl(settings, opts);
106
+ }
107
+ Workspace.construct = construct;
108
+ })(Workspace = exports.Workspace || (exports.Workspace = {}));
109
+ /** @beta */
110
+ var EditableWorkspaceDb;
111
+ (function (EditableWorkspaceDb) {
112
+ /** construct a new instance of an EditableWorkspaceDb */
113
+ function construct(props, container) {
114
+ return new EditableWorkspaceDbImpl(props, container);
115
+ }
116
+ EditableWorkspaceDb.construct = construct;
117
+ /** Create a new, empty, EditableWorkspaceDb file on the local filesystem for importing Workspace resources. */
118
+ function createEmpty(fileName) {
119
+ const db = new SQLiteDb_1.SQLiteDb();
120
+ IModelJsFs_1.IModelJsFs.recursiveMkDirSync((0, path_1.dirname)(fileName));
121
+ db.createDb(fileName);
122
+ const timeStampCol = "lastMod TIMESTAMP NOT NULL DEFAULT(julianday('now'))";
123
+ db.executeSQL(`CREATE TABLE strings(id TEXT PRIMARY KEY NOT NULL,value TEXT,${timeStampCol})`);
124
+ db.executeSQL(`CREATE TABLE blobs(id TEXT PRIMARY KEY NOT NULL,value BLOB,${timeStampCol})`);
125
+ const createTrigger = (tableName) => {
126
+ db.executeSQL(`CREATE TRIGGER ${tableName}_timeStamp AFTER UPDATE ON ${tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${tableName} SET lastMod=julianday('now') WHERE id=new.id; END`);
127
+ };
128
+ createTrigger("strings");
129
+ createTrigger("blobs");
130
+ db.closeDb(true);
131
+ }
132
+ EditableWorkspaceDb.createEmpty = createEmpty;
133
+ })(EditableWorkspaceDb = exports.EditableWorkspaceDb || (exports.EditableWorkspaceDb = {}));
134
+ class WorkspaceImpl {
35
135
  getCloudCache() {
36
136
  return this._cloudCache ??= CloudSqlite_1.CloudSqlite.CloudCaches.getCache({ cacheName: "Workspace", cacheSize: "20G" });
37
137
  }
@@ -56,7 +156,7 @@ class ITwinWorkspace {
56
156
  return this._containers.get(containerId);
57
157
  }
58
158
  getContainer(props) {
59
- return this.findContainer(props.containerId) ?? new ITwinWorkspaceContainer(this, props);
159
+ return this.findContainer(props.containerId) ?? new WorkspaceContainerImpl(this, props);
60
160
  }
61
161
  getWorkspaceDbFromProps(dbProps, containerProps) {
62
162
  return this.getContainer(containerProps).getWorkspaceDb(dbProps);
@@ -112,31 +212,11 @@ class ITwinWorkspace {
112
212
  return resolved;
113
213
  }
114
214
  }
115
- exports.ITwinWorkspace = ITwinWorkspace;
116
- /** @internal */
117
- class ITwinWorkspaceContainer {
215
+ class WorkspaceContainerImpl {
118
216
  get dirName() { return (0, path_1.join)(this.workspace.containerDir, this.id); }
119
- static noLeadingOrTrailingSpaces(name, msg) {
120
- if (name.trim() !== name)
121
- throw new Error(`${msg} [${name}] may not have leading or tailing spaces`);
122
- }
123
- /** rules for ContainerIds (from Azure, see https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata)
124
- * - may only contain lower case letters, numbers or dashes
125
- * - may not start or end with with a dash nor have more than one dash in a row
126
- * - may not be shorter than 3 or longer than 63 characters
127
- */
128
- static validateContainerId(id) {
129
- if (!/^(?=.{3,63}$)[a-z0-9]+(-[a-z0-9]+)*$/g.test(id))
130
- throw new Error(`invalid containerId: [${id}]`);
131
- }
132
- static validateDbName(dbName) {
133
- if (dbName === "" || dbName.length > 255 || /[#\.<>:"/\\"`'|?*\u0000-\u001F]/g.test(dbName) || /^(con|prn|aux|nul|com\d|lpt\d)$/i.test(dbName))
134
- throw new Error(`invalid dbName: [${dbName}]`);
135
- this.noLeadingOrTrailingSpaces(dbName, "dbName");
136
- }
137
217
  constructor(workspace, props) {
138
218
  this._wsDbs = new Map();
139
- ITwinWorkspaceContainer.validateContainerId(props.containerId);
219
+ WorkspaceContainer.validateContainerId(props.containerId);
140
220
  this.workspace = workspace;
141
221
  this.id = props.containerId;
142
222
  if (props.baseUri !== "")
@@ -156,31 +236,15 @@ class ITwinWorkspaceContainer {
156
236
  }
157
237
  }
158
238
  }
159
- static validateVersion(version) {
160
- version = version ?? "1.0.0";
161
- if (version) {
162
- const opts = { loose: true, includePrerelease: true };
163
- // clean allows prerelease, so try it first. If that fails attempt to coerce it (coerce strips prerelease even if you say not to.)
164
- const semVersion = semver.clean(version, opts) ?? semver.coerce(version, opts)?.version;
165
- if (!semVersion)
166
- throw new Error("invalid version specification");
167
- version = semVersion;
168
- }
169
- return version;
170
- }
171
- static parseDbFileName(dbFileName) {
172
- const parts = dbFileName.split(":");
173
- return { dbName: parts[0], version: parts[1] };
174
- }
175
- static makeDbFileName(dbName, version) {
176
- return `${dbName}:${this.validateVersion(version)}`;
177
- }
178
- static resolveCloudFileName(cloudContainer, props) {
239
+ resolveDbFileName(props) {
240
+ const cloudContainer = this.cloudContainer;
241
+ if (undefined === cloudContainer)
242
+ return (0, path_1.join)(this.dirName, `${props.dbName}.${WorkspaceDb.fileExt}`); // local file, versions not allowed
179
243
  const dbName = props.dbName;
180
244
  const dbs = cloudContainer.queryDatabases(`${dbName}*`); // get all databases that start with dbName
181
245
  const versions = [];
182
246
  for (const db of dbs) {
183
- const thisDb = ITwinWorkspaceContainer.parseDbFileName(db);
247
+ const thisDb = WorkspaceContainer.parseDbFileName(db);
184
248
  if (thisDb.dbName === dbName && "string" === typeof thisDb.version && thisDb.version.length > 0)
185
249
  versions.push(thisDb.version);
186
250
  }
@@ -196,46 +260,31 @@ class ITwinWorkspaceContainer {
196
260
  }
197
261
  throw new Error(`No version of [${dbName}] available for "${range}"`);
198
262
  }
199
- /**
200
- * Create a copy of an existing [[WorkspaceDb]] in a cloud container with a new version number.
201
- * @param cloudContainer The attached cloud container holding the existing WorkspaceDb
202
- * @param fromProps Properties that describe the source WorkspaceDb for the new version
203
- * @param versionType The type of version increment to apply to the existing version.
204
- * @note This requires that the cloudContainer is attached and the write lock on the container be held. The copy should be modified with
205
- * new content before the write lock is released, and thereafter should never be modified again.
206
- */
207
- static async makeNewVersion(cloudContainer, fromProps, versionType) {
208
- const oldName = this.resolveCloudFileName(cloudContainer, fromProps);
209
- const oldDb = this.parseDbFileName(oldName);
263
+ async makeNewVersion(fromProps, versionType) {
264
+ const cloudContainer = this.cloudContainer;
265
+ if (undefined === cloudContainer)
266
+ throw new Error("versions require cloud containers");
267
+ const oldName = this.resolveDbFileName(fromProps);
268
+ const oldDb = WorkspaceContainer.parseDbFileName(oldName);
210
269
  const newVersion = semver.inc(oldDb.version, versionType);
211
270
  if (!newVersion)
212
271
  throw new Error("invalid version");
213
- const newName = this.makeDbFileName(oldDb.dbName, newVersion);
272
+ const newName = WorkspaceContainer.makeDbFileName(oldDb.dbName, newVersion);
214
273
  await cloudContainer.copyDatabase(oldName, newName);
215
274
  return { oldName, newName };
216
275
  }
217
- /**
218
- * Convert a WorkspaceDb.Props specification into a DbFileName. For cloud-based containers, this resolves to the dbName, incorporating the appropriate
219
- * version. For file-based containers, this returns a local filename of a WorkspaceDb file with the extension ".itwin-workspace"
220
- */
221
- resolveDbFileName(props) {
222
- const cloudContainer = this.cloudContainer;
223
- if (undefined === cloudContainer)
224
- return (0, path_1.join)(this.dirName, `${props.dbName}.${ITwinWorkspaceDb.fileExt}`); // local file, versions not allowed
225
- return ITwinWorkspaceContainer.resolveCloudFileName(cloudContainer, props);
226
- }
227
276
  addWorkspaceDb(toAdd) {
228
277
  if (undefined !== this._wsDbs.get(toAdd.dbName))
229
278
  throw new Error(`workspaceDb ${toAdd.dbName} already exists in workspace`);
230
279
  this._wsDbs.set(toAdd.dbName, toAdd);
231
280
  }
232
281
  getWorkspaceDb(props) {
233
- const db = this._wsDbs.get(props.dbName) ?? new ITwinWorkspaceDb(props, this);
282
+ const db = this._wsDbs.get(props.dbName) ?? new WorkspaceDbImpl(props, this);
234
283
  if (!db.isOpen)
235
284
  db.open();
236
285
  return db;
237
286
  }
238
- dropWorkspaceDb(toDrop) {
287
+ closeWorkspaceDb(toDrop) {
239
288
  const name = toDrop.dbName;
240
289
  const wsDb = this._wsDbs.get(name);
241
290
  if (wsDb === toDrop) {
@@ -249,17 +298,9 @@ class ITwinWorkspaceContainer {
249
298
  this._wsDbs.clear();
250
299
  this.cloudContainer?.disconnect();
251
300
  }
252
- /** Delete all local files extracted by [[WorkspaceDb.getFile]] for this container. */
253
- purgeContainerFiles() {
254
- IModelJsFs_1.IModelJsFs.purgeDirSync(this.filesDir);
255
- }
256
301
  }
257
- exports.ITwinWorkspaceContainer = ITwinWorkspaceContainer;
258
- /**
259
- * Implementation of WorkspaceDb
260
- * @internal
261
- */
262
- class ITwinWorkspaceDb {
302
+ /** Implementation of WorkspaceDb */
303
+ class WorkspaceDbImpl {
263
304
  /** true if this WorkspaceDb is currently open */
264
305
  get isOpen() { return this.sqliteDb.isOpen; }
265
306
  queryFileResource(rscName) {
@@ -273,11 +314,9 @@ class ITwinWorkspaceDb {
273
314
  return { localFileName, info };
274
315
  }
275
316
  constructor(props, container) {
276
- /** the SQLiteDb for this WorkspaceDb*/
277
317
  this.sqliteDb = new SQLiteDb_1.SQLiteDb();
278
- /** called before db is closed */
279
318
  this.onClose = new core_bentley_1.BeEvent();
280
- ITwinWorkspaceContainer.validateDbName(props.dbName);
319
+ WorkspaceContainer.validateDbName(props.dbName);
281
320
  this.dbName = props.dbName;
282
321
  this.container = container;
283
322
  this.dbFileName = container.resolveDbFileName(props);
@@ -290,7 +329,7 @@ class ITwinWorkspaceDb {
290
329
  if (this.isOpen) {
291
330
  this.onClose.raiseEvent();
292
331
  this.sqliteDb.closeDb();
293
- this.container.dropWorkspaceDb(this);
332
+ this.container.closeWorkspaceDb(this);
294
333
  }
295
334
  }
296
335
  getString(rscName) {
@@ -299,9 +338,6 @@ class ITwinWorkspaceDb {
299
338
  return core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getValueString(0) : undefined;
300
339
  });
301
340
  }
302
- /** Get a BlobIO reader for a blob WorkspaceResource.
303
- * @note when finished, caller *must* call `close` on the BlobIO.
304
- */
305
341
  getBlobReader(rscName) {
306
342
  return this.sqliteDb.withSqliteStatement("SELECT rowid from blobs WHERE id=?", (stmt) => {
307
343
  stmt.bindString(1, rscName);
@@ -344,18 +380,9 @@ class ITwinWorkspaceDb {
344
380
  return CloudSqlite_1.CloudSqlite.startCloudPrefetch(cloudContainer, this.dbFileName, opts);
345
381
  }
346
382
  }
347
- /** file extension for local WorkspaceDbs */
348
- ITwinWorkspaceDb.fileExt = "itwin-workspace";
349
- exports.ITwinWorkspaceDb = ITwinWorkspaceDb;
350
- /**
351
- * An editable [[WorkspaceDb]]. This is used by administrators for creating and modifying `WorkspaceDb`s.
352
- * For cloud-backed containers, the write token must be obtained before this class may be used. Only one user at at time
353
- * may be editing.
354
- * @internal
355
- */
356
- class EditableWorkspaceDb extends ITwinWorkspaceDb {
383
+ class EditableWorkspaceDbImpl extends WorkspaceDbImpl {
357
384
  static validateResourceName(name) {
358
- ITwinWorkspaceContainer.noLeadingOrTrailingSpaces(name, "resource name");
385
+ noLeadingOrTrailingSpaces(name, "resource name");
359
386
  if (name.length > 1024)
360
387
  throw new Error("resource name too long");
361
388
  }
@@ -389,72 +416,37 @@ class EditableWorkspaceDb extends ITwinWorkspaceDb {
389
416
  }
390
417
  else {
391
418
  // currently the only way to create a workspaceDb in a cloud container is to create a temporary workspaceDb and upload it.
392
- const tempDbFile = (0, path_1.join)(IModelHost_1.KnownLocations.tmpdir, `empty.${ITwinWorkspaceDb.fileExt}`);
419
+ const tempDbFile = (0, path_1.join)(IModelHost_1.KnownLocations.tmpdir, `empty.${WorkspaceDb.fileExt}`);
393
420
  if (fs.existsSync(tempDbFile))
394
421
  IModelJsFs_1.IModelJsFs.removeSync(tempDbFile);
395
422
  EditableWorkspaceDb.createEmpty(tempDbFile);
396
- this.dbFileName = ITwinWorkspaceContainer.makeDbFileName(this.dbName, version);
423
+ this.dbFileName = WorkspaceContainer.makeDbFileName(this.dbName, version);
397
424
  await CloudSqlite_1.CloudSqlite.uploadDb(this.container.cloudContainer, { localFileName: tempDbFile, dbName: this.dbFileName });
398
425
  IModelJsFs_1.IModelJsFs.removeSync(tempDbFile);
399
426
  }
400
427
  this.open();
401
428
  }
402
- /** Create a new, empty, EditableWorkspaceDb for importing Workspace resources. */
403
- static createEmpty(fileName) {
404
- const db = new SQLiteDb_1.SQLiteDb();
405
- IModelJsFs_1.IModelJsFs.recursiveMkDirSync((0, path_1.dirname)(fileName));
406
- db.createDb(fileName);
407
- const timeStampCol = "lastMod TIMESTAMP NOT NULL DEFAULT(julianday('now'))";
408
- db.executeSQL(`CREATE TABLE strings(id TEXT PRIMARY KEY NOT NULL,value TEXT,${timeStampCol})`);
409
- db.executeSQL(`CREATE TABLE blobs(id TEXT PRIMARY KEY NOT NULL,value BLOB,${timeStampCol})`);
410
- const createTrigger = (tableName) => {
411
- db.executeSQL(`CREATE TRIGGER ${tableName}_timeStamp AFTER UPDATE ON ${tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${tableName} SET lastMod=julianday('now') WHERE id=new.id; END`);
412
- };
413
- createTrigger("strings");
414
- createTrigger("blobs");
415
- db.closeDb(true);
416
- }
417
- /** Add a new string resource to this WorkspaceDb.
418
- * @param rscName The name of the string resource.
419
- * @param val The string to save.
420
- */
421
429
  addString(rscName, val) {
422
- EditableWorkspaceDb.validateResourceName(rscName);
430
+ EditableWorkspaceDbImpl.validateResourceName(rscName);
423
431
  this.validateResourceSize(val);
424
432
  this.performWriteSql(rscName, "INSERT INTO strings(id,value) VALUES(?,?)", (stmt) => stmt.bindString(2, val));
425
433
  }
426
- /** Update an existing string resource with a new value, or add it if it does not exist.
427
- * @param rscName The name of the string resource.
428
- * @param val The new value.
429
- */
430
434
  updateString(rscName, val) {
431
435
  this.validateResourceSize(val);
432
436
  this.performWriteSql(rscName, "INSERT INTO strings(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", (stmt) => stmt.bindString(2, val));
433
437
  }
434
- /** Remove a string resource. */
435
438
  removeString(rscName) {
436
439
  this.performWriteSql(rscName, "DELETE FROM strings WHERE id=?");
437
440
  }
438
- /** Add a new blob resource to this WorkspaceDb.
439
- * @param rscName The name of the blob resource.
440
- * @param val The blob to save.
441
- */
442
441
  addBlob(rscName, val) {
443
- EditableWorkspaceDb.validateResourceName(rscName);
442
+ EditableWorkspaceDbImpl.validateResourceName(rscName);
444
443
  this.validateResourceSize(val);
445
444
  this.performWriteSql(rscName, "INSERT INTO blobs(id,value) VALUES(?,?)", (stmt) => stmt.bindBlob(2, val));
446
445
  }
447
- /** Update an existing blob resource with a new value, or add it if it does not exist.
448
- * @param rscName The name of the blob resource.
449
- * @param val The new value.
450
- */
451
446
  updateBlob(rscName, val) {
452
447
  this.validateResourceSize(val);
453
448
  this.performWriteSql(rscName, "INSERT INTO blobs(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", (stmt) => stmt.bindBlob(2, val));
454
449
  }
455
- /** Get a BlobIO writer for a previously-added blob WorkspaceResource.
456
- * @note after writing is complete, caller must call `close` on the BlobIO and must call `saveChanges` on the `db`.
457
- */
458
450
  getBlobWriter(rscName) {
459
451
  return this.sqliteDb.withSqliteStatement("SELECT rowid from blobs WHERE id=?", (stmt) => {
460
452
  stmt.bindString(1, rscName);
@@ -463,34 +455,20 @@ class EditableWorkspaceDb extends ITwinWorkspaceDb {
463
455
  return blobWriter;
464
456
  });
465
457
  }
466
- /** Remove a blob resource. */
467
458
  removeBlob(rscName) {
468
459
  this.performWriteSql(rscName, "DELETE FROM blobs WHERE id=?");
469
460
  }
470
- /** Copy the contents of an existing local file into this WorkspaceDb as a file resource.
471
- * @param rscName The name of the file resource.
472
- * @param localFileName The name of a local file to be read.
473
- * @param fileExt The extension (do not include the leading ".") to be appended to the generated fileName
474
- * when this WorkspaceDb is extracted from the WorkspaceDb. By default the characters after the last "." in `localFileName`
475
- * are used. Pass this argument to override that.
476
- */
477
461
  addFile(rscName, localFileName, fileExt) {
478
- EditableWorkspaceDb.validateResourceName(rscName);
462
+ EditableWorkspaceDbImpl.validateResourceName(rscName);
479
463
  fileExt = fileExt ?? (0, path_1.extname)(localFileName);
480
464
  if (fileExt?.[0] === ".")
481
465
  fileExt = fileExt.slice(1);
482
466
  this.sqliteDb.nativeDb.embedFile({ name: rscName, localFileName, date: this.getFileModifiedTime(localFileName), fileExt });
483
467
  }
484
- /** Replace an existing file resource with the contents of another local file.
485
- * @param rscName The name of the file resource.
486
- * @param localFileName The name of a local file to be read.
487
- * @throws if rscName does not exist
488
- */
489
468
  updateFile(rscName, localFileName) {
490
469
  this.queryFileResource(rscName); // throws if not present
491
470
  this.sqliteDb.nativeDb.replaceEmbeddedFile({ name: rscName, localFileName, date: this.getFileModifiedTime(localFileName) });
492
471
  }
493
- /** Remove a file resource. */
494
472
  removeFile(rscName) {
495
473
  const file = this.queryFileResource(rscName);
496
474
  if (undefined === file)
@@ -500,5 +478,4 @@ class EditableWorkspaceDb extends ITwinWorkspaceDb {
500
478
  this.sqliteDb.nativeDb.removeEmbeddedFile(rscName);
501
479
  }
502
480
  }
503
- exports.EditableWorkspaceDb = EditableWorkspaceDb;
504
481
  //# sourceMappingURL=Workspace.js.map