@itwin/core-backend 5.8.0-dev.10 → 5.8.0-dev.11
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/lib/cjs/core-backend.d.ts +2 -0
- package/lib/cjs/core-backend.d.ts.map +1 -1
- package/lib/cjs/core-backend.js +2 -0
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts +38 -0
- package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts.map +1 -0
- package/lib/cjs/internal/workspace/SettingsDbImpl.js +106 -0
- package/lib/cjs/internal/workspace/SettingsDbImpl.js.map +1 -0
- package/lib/cjs/internal/workspace/SettingsImpl.d.ts +3 -0
- package/lib/cjs/internal/workspace/SettingsImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/SettingsImpl.js +251 -1
- package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
- package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts +14 -0
- package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts.map +1 -0
- package/lib/cjs/internal/workspace/SettingsSqliteDb.js +40 -0
- package/lib/cjs/internal/workspace/SettingsSqliteDb.js.map +1 -0
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts +1 -0
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.js +44 -3
- package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/cjs/workspace/Settings.d.ts +8 -0
- package/lib/cjs/workspace/Settings.d.ts.map +1 -1
- package/lib/cjs/workspace/Settings.js.map +1 -1
- package/lib/cjs/workspace/SettingsDb.d.ts +109 -0
- package/lib/cjs/workspace/SettingsDb.d.ts.map +1 -0
- package/lib/cjs/workspace/SettingsDb.js +19 -0
- package/lib/cjs/workspace/SettingsDb.js.map +1 -0
- package/lib/cjs/workspace/SettingsEditor.d.ts +246 -0
- package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -0
- package/lib/cjs/workspace/SettingsEditor.js +51 -0
- package/lib/cjs/workspace/SettingsEditor.js.map +1 -0
- package/lib/cjs/workspace/Workspace.d.ts +39 -18
- package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
- package/lib/cjs/workspace/Workspace.js.map +1 -1
- package/lib/cjs/workspace/WorkspaceEditor.d.ts +28 -0
- package/lib/cjs/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/lib/cjs/workspace/WorkspaceEditor.js +17 -0
- package/lib/cjs/workspace/WorkspaceEditor.js.map +1 -1
- package/lib/esm/core-backend.d.ts +2 -0
- package/lib/esm/core-backend.d.ts.map +1 -1
- package/lib/esm/core-backend.js +2 -0
- package/lib/esm/core-backend.js.map +1 -1
- package/lib/esm/internal/workspace/SettingsDbImpl.d.ts +38 -0
- package/lib/esm/internal/workspace/SettingsDbImpl.d.ts.map +1 -0
- package/lib/esm/internal/workspace/SettingsDbImpl.js +102 -0
- package/lib/esm/internal/workspace/SettingsDbImpl.js.map +1 -0
- package/lib/esm/internal/workspace/SettingsImpl.d.ts +3 -0
- package/lib/esm/internal/workspace/SettingsImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/SettingsImpl.js +253 -4
- package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
- package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts +14 -0
- package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts.map +1 -0
- package/lib/esm/internal/workspace/SettingsSqliteDb.js +36 -0
- package/lib/esm/internal/workspace/SettingsSqliteDb.js.map +1 -0
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts +1 -0
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.js +44 -4
- package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/esm/test/standalone/Settings.test.js +18 -0
- package/lib/esm/test/standalone/Settings.test.js.map +1 -1
- package/lib/esm/test/standalone/Workspace.test.js +60 -0
- package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
- package/lib/esm/test/workspace/SettingsDb.test.d.ts +2 -0
- package/lib/esm/test/workspace/SettingsDb.test.d.ts.map +1 -0
- package/lib/esm/test/workspace/SettingsDb.test.js +372 -0
- package/lib/esm/test/workspace/SettingsDb.test.js.map +1 -0
- package/lib/esm/workspace/Settings.d.ts +8 -0
- package/lib/esm/workspace/Settings.d.ts.map +1 -1
- package/lib/esm/workspace/Settings.js.map +1 -1
- package/lib/esm/workspace/SettingsDb.d.ts +109 -0
- package/lib/esm/workspace/SettingsDb.d.ts.map +1 -0
- package/lib/esm/workspace/SettingsDb.js +16 -0
- package/lib/esm/workspace/SettingsDb.js.map +1 -0
- package/lib/esm/workspace/SettingsEditor.d.ts +246 -0
- package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -0
- package/lib/esm/workspace/SettingsEditor.js +48 -0
- package/lib/esm/workspace/SettingsEditor.js.map +1 -0
- package/lib/esm/workspace/Workspace.d.ts +39 -18
- package/lib/esm/workspace/Workspace.d.ts.map +1 -1
- package/lib/esm/workspace/Workspace.js.map +1 -1
- package/lib/esm/workspace/WorkspaceEditor.d.ts +28 -0
- package/lib/esm/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/lib/esm/workspace/WorkspaceEditor.js +17 -0
- package/lib/esm/workspace/WorkspaceEditor.js.map +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsDbImpl.js","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsDbImpl.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 Workspace\r\n */\r\n\r\nimport { DbResult, OpenMode } from \"@itwin/core-bentley\";\r\nimport { FilePropertyProps } from \"@itwin/core-common\";\r\nimport { CloudSqlite } from \"../../CloudSqlite\";\r\nimport { Setting, SettingName, SettingsContainer, SettingsPriority } from \"../../workspace/Settings\";\r\nimport { CloudSqliteContainer, WorkspaceDbName } from \"../../workspace/Workspace\";\r\nimport { SettingsDb, SettingsDbManifest, SettingsDbProps, settingsResourceName } from \"../../workspace/SettingsDb\";\r\nimport { WorkspaceSqliteDb } from \"./WorkspaceSqliteDb\";\r\nimport { _implementationProhibited, _nativeDb } from \"../Symbols\";\r\n\r\nexport const settingsDbDefaultName: WorkspaceDbName = \"settings-db\";\r\n\r\nexport const settingsManifestProperty: FilePropertyProps = { namespace: \"settings\", name: \"manifest\" };\r\n\r\n/** Internal implementation of [[SettingsDb]]. Wraps a [[WorkspaceSqliteDb]] to provide a\r\n * settings-only read interface over the `strings` table.\r\n */\r\nexport class SettingsDbImpl implements SettingsDb {\r\n public readonly [_implementationProhibited] = undefined;\r\n public readonly sqliteDb = new WorkspaceSqliteDb();\r\n public readonly dbName: string;\r\n public readonly dbFileName: string;\r\n protected readonly _container: CloudSqliteContainer;\r\n public readonly priority: SettingsPriority;\r\n protected _manifest?: SettingsDbManifest;\r\n\r\n public constructor(props: SettingsDbProps, container: CloudSqliteContainer, priority: SettingsPriority) {\r\n this.dbName = props.dbName ?? settingsDbDefaultName;\r\n CloudSqlite.validateDbName(this.dbName);\r\n this._container = container;\r\n this.dbFileName = container.resolveDbFileName(props);\r\n this.priority = priority;\r\n }\r\n\r\n public get container(): CloudSqliteContainer { return this._container; }\r\n public get isOpen() { return this.sqliteDb.isOpen; }\r\n\r\n public get version(): string {\r\n const cloudContainer = this.container.cloudContainer;\r\n if (undefined === cloudContainer)\r\n return \"0.0.0\";\r\n return CloudSqlite.parseDbFileName(this.dbFileName).version;\r\n }\r\n\r\n public get manifest(): SettingsDbManifest {\r\n return this._manifest ??= this.withOpenDb((db) => {\r\n const manifestJson = db[_nativeDb].queryFileProperty(settingsManifestProperty, true) as string | undefined;\r\n if (!manifestJson)\r\n return { settingsName: this.dbName };\r\n try {\r\n return JSON.parse(manifestJson);\r\n } catch (e) {\r\n throw new Error(`Failed to parse manifest in SettingsDb \"${this.dbName}\": ${e instanceof Error ? e.message : String(e)}`);\r\n }\r\n });\r\n }\r\n\r\n /** Check whether the underlying database has a settings manifest property.\r\n * Used to validate that a container actually holds a SettingsDb rather than a WorkspaceDb.\r\n */\r\n public get hasSettingsManifestProperty(): boolean {\r\n return this.withOpenDb((db) => {\r\n const manifestJson = db[_nativeDb].queryFileProperty(settingsManifestProperty, true) as string | undefined;\r\n return manifestJson !== undefined;\r\n });\r\n }\r\n\r\n protected withOpenDb<T>(operation: (db: WorkspaceSqliteDb) => T): T {\r\n const done = this.isOpen ? () => { } : (this.open(), () => this.close());\r\n try {\r\n return operation(this.sqliteDb);\r\n } finally {\r\n done();\r\n }\r\n }\r\n\r\n public open(): void {\r\n this.sqliteDb.openDb(this.dbFileName, OpenMode.Readonly, this._container.cloudContainer);\r\n }\r\n\r\n public close(): void {\r\n if (this.isOpen)\r\n this.sqliteDb.closeDb();\r\n }\r\n\r\n public getSettings(): SettingsContainer {\r\n return this.withOpenDb((db) => {\r\n return db.withSqliteStatement(\"SELECT value FROM strings WHERE id=?\", (stmt) => {\r\n stmt.bindString(1, settingsResourceName);\r\n if (DbResult.BE_SQLITE_ROW !== stmt.step())\r\n return {};\r\n try {\r\n // JSON.parse already returns a fresh object tree — no explicit clone needed.\r\n return JSON.parse(stmt.getValueString(0));\r\n } catch (e) {\r\n throw new Error(`Failed to parse settings in SettingsDb \"${this.dbName}\": ${e instanceof Error ? e.message : String(e)}`);\r\n }\r\n });\r\n });\r\n }\r\n\r\n public getSetting<T extends Setting>(settingName: SettingName): T | undefined {\r\n const settings = this.getSettings();\r\n const value = settings[settingName] as T | undefined;\r\n return value !== undefined ? Setting.clone(value) : undefined;\r\n }\r\n}\r\n"]}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { BeEvent } from "@itwin/core-bentley";
|
|
5
5
|
import { LocalDirName, LocalFileName } from "@itwin/core-common";
|
|
6
6
|
import { Setting, SettingName, Settings, SettingsContainer, SettingsDictionary, SettingsDictionaryProps, SettingsDictionarySource, SettingsPriority } from "../../workspace/Settings";
|
|
7
|
+
import { type SettingsEditor } from "../../workspace/SettingsEditor";
|
|
7
8
|
import { _implementationProhibited } from "../Symbols";
|
|
8
9
|
/**
|
|
9
10
|
* Internal implementation of Settings interface.
|
|
@@ -40,4 +41,6 @@ export declare class SettingsImpl implements Settings {
|
|
|
40
41
|
getArray<T extends Setting>(name: SettingName): T[] | undefined;
|
|
41
42
|
private getCombinedArray;
|
|
42
43
|
}
|
|
44
|
+
/** Construct a new [[SettingsEditor]]. Called by the [[SettingsEditor]] namespace. */
|
|
45
|
+
export declare function constructSettingsEditor(): SettingsEditor;
|
|
43
46
|
//# sourceMappingURL=SettingsImpl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsImpl.d.ts","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsImpl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAKH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"SettingsImpl.d.ts","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsImpl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAKH,OAAO,EAAE,OAAO,EAA4B,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAoB,YAAY,EAAE,aAAa,EAAkB,MAAM,oBAAoB,CAAC;AAInG,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAItL,OAAO,EAEyB,KAAK,cAAc,EAElD,MAAM,gCAAgC,CAAC;AAKxC,OAAO,EAAE,yBAAyB,EAAa,MAAM,YAAY,CAAC;AA0BlE;;;GAGG;AACH,qBAAa,YAAa,YAAW,QAAQ;IAC3C,SAAgB,CAAC,yBAAyB,CAAC,YAAa;IACjD,YAAY,EAAE,kBAAkB,EAAE,CAAM;IAC/C,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,gBAAgB;IAC7C,KAAK;IACZ,SAAgB,iBAAiB,gBAAqB,IAAI,EAAI;IAEvD,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB;IAI3D,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB;IAQ9D,OAAO,CAAC,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM;IAI5D,aAAa,CAAC,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,iBAAiB;IAiBzE,aAAa,CAAC,MAAM,EAAE,wBAAwB,GAAG,kBAAkB,GAAG,SAAS;IAQ/E,cAAc,CAAC,MAAM,EAAE,wBAAwB,EAAE,UAAU,UAAO;IAYhE,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,WAAW,EAAE,WAAW,GAAG,QAAQ,CAAC;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,UAAU,EAAE,kBAAkB,CAAA;KAAC,CAAC;IASrH,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAAE,WAAW,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC;IAM5E,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAS/F,OAAO,CAAC,SAAS;IAMV,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAC1D,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAIhD,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO;IAC7D,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS;IAIlD,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAC1D,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAIhD,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC;IAClE,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC,GAAG,SAAS;IAK7D,QAAQ,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE;IACtE,QAAQ,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC,EAAE,GAAG,SAAS;IActE,OAAO,CAAC,gBAAgB;CAgBzB;AAMD,sFAAsF;AACtF,wBAAgB,uBAAuB,IAAI,cAAc,CAExD"}
|
|
@@ -8,11 +8,19 @@
|
|
|
8
8
|
import * as fs from "fs-extra";
|
|
9
9
|
import { parse } from "json5";
|
|
10
10
|
import { extname, join } from "path";
|
|
11
|
-
import { BeEvent } from "@itwin/core-bentley";
|
|
11
|
+
import { BeEvent, DbResult, Guid, OpenMode } from "@itwin/core-bentley";
|
|
12
|
+
import { CloudSqliteError, WorkspaceError } from "@itwin/core-common";
|
|
13
|
+
import { CloudSqlite } from "../../CloudSqlite";
|
|
12
14
|
import { IModelJsFs } from "../../IModelJsFs";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
15
|
+
import { IModelHost, KnownLocations } from "../../IModelHost";
|
|
16
|
+
import { Setting, SettingsPriority } from "../../workspace/Settings";
|
|
17
|
+
import { settingsResourceName } from "../../workspace/SettingsDb";
|
|
18
|
+
import { SettingsEditor as SettingsEditorNs, } from "../../workspace/SettingsEditor";
|
|
19
|
+
import { BlobContainer } from "../../BlobContainerService";
|
|
20
|
+
import { settingsDbDefaultName, SettingsDbImpl, settingsManifestProperty } from "./SettingsDbImpl";
|
|
21
|
+
import { SettingsSqliteDb } from "./SettingsSqliteDb";
|
|
22
|
+
import { constructSettingsEditorWorkspace } from "./WorkspaceImpl";
|
|
23
|
+
import { _implementationProhibited, _nativeDb } from "../Symbols";
|
|
16
24
|
const dictionaryMatches = (d1, d2) => {
|
|
17
25
|
return (d1.workspaceDb === d2.workspaceDb) && (d1.name === d2.name);
|
|
18
26
|
};
|
|
@@ -28,6 +36,9 @@ class SettingsDictionaryImpl {
|
|
|
28
36
|
const value = this.settings[settingName];
|
|
29
37
|
return undefined !== value ? Setting.clone(value) : undefined;
|
|
30
38
|
}
|
|
39
|
+
toJSON() {
|
|
40
|
+
return Setting.clone(this.settings);
|
|
41
|
+
}
|
|
31
42
|
}
|
|
32
43
|
/**
|
|
33
44
|
* Internal implementation of Settings interface.
|
|
@@ -151,4 +162,242 @@ export class SettingsImpl {
|
|
|
151
162
|
return foundSetting ? out : defaultValue;
|
|
152
163
|
}
|
|
153
164
|
}
|
|
165
|
+
// ==================== SettingsEditor implementation ====================
|
|
166
|
+
const settingsEditorName = "SettingsEditor";
|
|
167
|
+
/** Construct a new [[SettingsEditor]]. Called by the [[SettingsEditor]] namespace. */
|
|
168
|
+
export function constructSettingsEditor() {
|
|
169
|
+
return new SettingsEditorImpl();
|
|
170
|
+
}
|
|
171
|
+
class SettingsEditorImpl {
|
|
172
|
+
[_implementationProhibited] = undefined;
|
|
173
|
+
_workspace;
|
|
174
|
+
_containers = new Map();
|
|
175
|
+
constructor() {
|
|
176
|
+
this._workspace = constructSettingsEditorWorkspace(new SettingsImpl(), { containerDir: join(IModelHost.cacheDir, settingsEditorName) });
|
|
177
|
+
}
|
|
178
|
+
get workspace() { return this._workspace; }
|
|
179
|
+
async initializeContainer(args) {
|
|
180
|
+
class CloudAccess extends CloudSqlite.DbAccess {
|
|
181
|
+
static _cacheName = settingsEditorName;
|
|
182
|
+
static async initializeSettings(initArgs) {
|
|
183
|
+
const props = await this.createBlobContainer({ scope: initArgs.scope, metadata: { ...initArgs.metadata, containerType: "settings" } });
|
|
184
|
+
const dbFullName = CloudSqlite.makeSemverName(initArgs.dbName ?? settingsDbDefaultName, "0.0.0");
|
|
185
|
+
await super._initializeDb({ ...initArgs, props, dbName: dbFullName, dbType: SettingsSqliteDb, blockSize: "4M" });
|
|
186
|
+
return props;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return CloudAccess.initializeSettings(args);
|
|
190
|
+
}
|
|
191
|
+
async createNewCloudContainer(args) {
|
|
192
|
+
const cloudContainer = await this.initializeContainer(args);
|
|
193
|
+
const userToken = await IModelHost.authorizationClient?.getAccessToken();
|
|
194
|
+
const accessToken = await CloudSqlite.requestToken({ ...cloudContainer, accessLevel: "write", userToken });
|
|
195
|
+
return this.getContainer({ accessToken, ...cloudContainer, writeable: true, description: args.metadata.description });
|
|
196
|
+
}
|
|
197
|
+
getContainer(args) {
|
|
198
|
+
const existing = this._containers.get(args.containerId);
|
|
199
|
+
if (existing)
|
|
200
|
+
return existing;
|
|
201
|
+
const baseContainer = this._workspace.getContainer(args);
|
|
202
|
+
const editable = new EditableSettingsContainerImpl(baseContainer);
|
|
203
|
+
this._containers.set(args.containerId, editable);
|
|
204
|
+
return editable;
|
|
205
|
+
}
|
|
206
|
+
async getContainerAsync(props) {
|
|
207
|
+
let accessToken = props.accessToken;
|
|
208
|
+
if (undefined === accessToken && props.baseUri !== "")
|
|
209
|
+
accessToken = await CloudSqlite.requestToken({ ...props, accessLevel: "write" });
|
|
210
|
+
return this.getContainer({ ...props, accessToken: accessToken ?? "" });
|
|
211
|
+
}
|
|
212
|
+
async findContainers(args) {
|
|
213
|
+
const containers = await SettingsEditorNs.queryContainers(args);
|
|
214
|
+
const userToken = await IModelHost.getAccessToken();
|
|
215
|
+
const results = [];
|
|
216
|
+
for (const containerMeta of containers) {
|
|
217
|
+
// queryContainers already validates that BlobContainer.service is defined, so the non-null assertion is safe here.
|
|
218
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
219
|
+
const tokenProps = await BlobContainer.service.requestToken({ containerId: containerMeta.containerId, userToken, accessLevel: "write" });
|
|
220
|
+
results.push(this.getContainer({
|
|
221
|
+
containerId: containerMeta.containerId,
|
|
222
|
+
baseUri: tokenProps.baseUri,
|
|
223
|
+
storageType: tokenProps.provider,
|
|
224
|
+
accessToken: tokenProps.token,
|
|
225
|
+
writeable: true,
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
return results;
|
|
229
|
+
}
|
|
230
|
+
close() {
|
|
231
|
+
const errors = [];
|
|
232
|
+
for (const [_, container] of this._containers) {
|
|
233
|
+
try {
|
|
234
|
+
container.cleanup();
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
errors.push(e);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
this._containers.clear();
|
|
241
|
+
try {
|
|
242
|
+
this._workspace.close();
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
errors.push(e);
|
|
246
|
+
}
|
|
247
|
+
if (errors.length === 1)
|
|
248
|
+
throw errors[0];
|
|
249
|
+
if (errors.length > 1)
|
|
250
|
+
throw new Error(`SettingsEditor.close() encountered ${errors.length} errors: ${errors.map((e) => e instanceof Error ? e.message : String(e)).join("; ")}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
class EditableSettingsContainerImpl {
|
|
254
|
+
[_implementationProhibited] = undefined;
|
|
255
|
+
_inner;
|
|
256
|
+
_settingsDbs = new Map();
|
|
257
|
+
writeLockHeldBy;
|
|
258
|
+
constructor(inner) {
|
|
259
|
+
this._inner = inner;
|
|
260
|
+
}
|
|
261
|
+
// CloudSqliteContainer delegation
|
|
262
|
+
get workspace() { return this._inner.workspace; }
|
|
263
|
+
get filesDir() { return this._inner.filesDir; }
|
|
264
|
+
get cloudContainer() { return this._inner.cloudContainer; }
|
|
265
|
+
get fromProps() { return this._inner.fromProps; }
|
|
266
|
+
resolveDbFileName(props) { return this._inner.resolveDbFileName(props); }
|
|
267
|
+
get cloudProps() {
|
|
268
|
+
const cc = this.cloudContainer;
|
|
269
|
+
if (undefined === cc)
|
|
270
|
+
return undefined;
|
|
271
|
+
return {
|
|
272
|
+
baseUri: cc.baseUri,
|
|
273
|
+
containerId: cc.containerId,
|
|
274
|
+
storageType: cc.storageType,
|
|
275
|
+
isPublic: cc.isPublic,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
getEditableDb(props) {
|
|
279
|
+
const dbName = props?.dbName ?? settingsDbDefaultName;
|
|
280
|
+
let db = this._settingsDbs.get(dbName);
|
|
281
|
+
if (undefined === db) {
|
|
282
|
+
db = new EditableSettingsDbImpl(props ?? { dbName }, this);
|
|
283
|
+
this._settingsDbs.set(dbName, db);
|
|
284
|
+
}
|
|
285
|
+
if (this.cloudContainer && !CloudSqlite.isSemverEditable(db.dbFileName, this.cloudContainer)) {
|
|
286
|
+
this._settingsDbs.delete(dbName);
|
|
287
|
+
CloudSqliteError.throwError("already-published", { message: `${db.dbFileName} has been published and is not editable. Make a new version first.` });
|
|
288
|
+
}
|
|
289
|
+
return db;
|
|
290
|
+
}
|
|
291
|
+
async createNewSettingsDbVersion(args) {
|
|
292
|
+
const container = this.cloudContainer;
|
|
293
|
+
if (undefined === container)
|
|
294
|
+
WorkspaceError.throwError("no-cloud-container", { message: "versions require cloud containers" });
|
|
295
|
+
const fromDb = { ...args.fromProps, dbName: args.fromProps?.dbName ?? settingsDbDefaultName };
|
|
296
|
+
return CloudSqlite.createNewDbVersion(container, { ...args, fromDb });
|
|
297
|
+
}
|
|
298
|
+
async createDb(args) {
|
|
299
|
+
const dbName = args.dbName ?? settingsDbDefaultName;
|
|
300
|
+
if (!this.cloudContainer) {
|
|
301
|
+
SettingsSqliteDb.createNewDb(this.resolveDbFileName({ dbName }), { manifest: args.manifest });
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
const tempDbFile = join(KnownLocations.tmpdir, `empty-${Guid.createValue()}.itwin-settings`);
|
|
305
|
+
try {
|
|
306
|
+
SettingsSqliteDb.createNewDb(tempDbFile, { manifest: args.manifest });
|
|
307
|
+
await CloudSqlite.uploadDb(this.cloudContainer, { localFileName: tempDbFile, dbName: CloudSqlite.makeSemverName(dbName, args.version) });
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
if (fs.existsSync(tempDbFile))
|
|
311
|
+
IModelJsFs.removeSync(tempDbFile);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return this.getEditableDb({ dbName });
|
|
315
|
+
}
|
|
316
|
+
acquireWriteLock(user) {
|
|
317
|
+
if (this.cloudContainer) {
|
|
318
|
+
this.cloudContainer.acquireWriteLock(user);
|
|
319
|
+
this.writeLockHeldBy = user;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
releaseWriteLock() {
|
|
323
|
+
if (this.cloudContainer) {
|
|
324
|
+
this.cloudContainer.releaseWriteLock();
|
|
325
|
+
this.writeLockHeldBy = undefined;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
abandonChanges() {
|
|
329
|
+
if (this.cloudContainer) {
|
|
330
|
+
this.cloudContainer.abandonChanges();
|
|
331
|
+
this.writeLockHeldBy = undefined;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/** Close all editable settings dbs tracked by this container. */
|
|
335
|
+
cleanup() {
|
|
336
|
+
for (const [_, db] of this._settingsDbs)
|
|
337
|
+
db.close();
|
|
338
|
+
this._settingsDbs.clear();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
class EditableSettingsDbImpl extends SettingsDbImpl {
|
|
342
|
+
get container() {
|
|
343
|
+
return this._container;
|
|
344
|
+
}
|
|
345
|
+
constructor(props, container) {
|
|
346
|
+
super(props, container, SettingsPriority.application);
|
|
347
|
+
}
|
|
348
|
+
open() {
|
|
349
|
+
this.sqliteDb.openDb(this.dbFileName, OpenMode.ReadWrite, this._container.cloudContainer);
|
|
350
|
+
}
|
|
351
|
+
close() {
|
|
352
|
+
let error;
|
|
353
|
+
try {
|
|
354
|
+
if (this.isOpen) {
|
|
355
|
+
const lastEditedBy = this._container.writeLockHeldBy;
|
|
356
|
+
if (lastEditedBy !== undefined)
|
|
357
|
+
this.updateManifest({ ...this.manifest, lastEditedBy });
|
|
358
|
+
this.sqliteDb.saveChanges();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch (e) {
|
|
362
|
+
error = e;
|
|
363
|
+
}
|
|
364
|
+
finally {
|
|
365
|
+
super.close();
|
|
366
|
+
}
|
|
367
|
+
if (error) {
|
|
368
|
+
if (error instanceof Error)
|
|
369
|
+
throw error;
|
|
370
|
+
throw new Error(`EditableSettingsDb.close() failed`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
updateManifest(manifest) {
|
|
374
|
+
this.sqliteDb[_nativeDb].saveFileProperty(settingsManifestProperty, JSON.stringify(manifest));
|
|
375
|
+
this._manifest = undefined;
|
|
376
|
+
}
|
|
377
|
+
updateSettings(settings) {
|
|
378
|
+
const val = JSON.stringify(settings);
|
|
379
|
+
this.sqliteDb.withSqliteStatement("INSERT INTO strings(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", (stmt) => {
|
|
380
|
+
stmt.bindString(1, settingsResourceName);
|
|
381
|
+
stmt.bindString(2, val);
|
|
382
|
+
const rc = stmt.step();
|
|
383
|
+
if (DbResult.BE_SQLITE_DONE !== rc)
|
|
384
|
+
WorkspaceError.throwError("write-error", { message: `settings [updateSettings], rc=${rc}` });
|
|
385
|
+
});
|
|
386
|
+
this.sqliteDb.saveChanges();
|
|
387
|
+
}
|
|
388
|
+
updateSetting(args) {
|
|
389
|
+
this.withOpenDb(() => {
|
|
390
|
+
const container = this.getSettings();
|
|
391
|
+
container[args.settingName] = args.value;
|
|
392
|
+
this.updateSettings(container);
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
removeSetting(settingName) {
|
|
396
|
+
this.withOpenDb(() => {
|
|
397
|
+
const container = this.getSettings();
|
|
398
|
+
delete container[settingName];
|
|
399
|
+
this.updateSettings(container);
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
154
403
|
//# sourceMappingURL=SettingsImpl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsImpl.js","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsImpl.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 Workspace\r\n */\r\n\r\nimport * as fs from \"fs-extra\";\r\nimport { parse } from \"json5\";\r\nimport { extname, join } from \"path\";\r\nimport { BeEvent } from \"@itwin/core-bentley\";\r\nimport { LocalDirName, LocalFileName } from \"@itwin/core-common\";\r\nimport { IModelJsFs } from \"../../IModelJsFs\";\r\nimport { Setting, SettingName, Settings, SettingsContainer, SettingsDictionary, SettingsDictionaryProps, SettingsDictionarySource, SettingsPriority } from \"../../workspace/Settings\";\r\nimport { IModelHost } from \"../../IModelHost\";\r\nimport { _implementationProhibited } from \"../Symbols\";\r\n\r\nconst dictionaryMatches = (d1: SettingsDictionarySource, d2: SettingsDictionarySource): boolean => {\r\n return (d1.workspaceDb === d2.workspaceDb) && (d1.name === d2.name);\r\n};\r\n\r\nclass SettingsDictionaryImpl implements SettingsDictionary {\r\n public readonly [_implementationProhibited] = undefined;\r\n public readonly props: SettingsDictionaryProps;\r\n public readonly settings: SettingsContainer;\r\n\r\n public constructor(props: SettingsDictionaryProps, settings: SettingsContainer) {\r\n this.props = { ...props }; // make a copy so it can't be changed by caller\r\n this.settings = settings;\r\n }\r\n\r\n public getSetting<T extends Setting>(settingName: string): T | undefined {\r\n const value = this.settings[settingName] as T | undefined;\r\n return undefined !== value ? Setting.clone(value) : undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Internal implementation of Settings interface.\r\n * @internal\r\n */\r\nexport class SettingsImpl implements Settings {\r\n public readonly [_implementationProhibited] = undefined;\r\n public dictionaries: SettingsDictionary[] = [];\r\n protected verifyPriority(_priority: SettingsPriority) { }\r\n public close() { }\r\n public readonly onSettingsChanged = new BeEvent<() => void>();\r\n\r\n public addFile(fileName: LocalFileName, priority: SettingsPriority) {\r\n this.addJson({ name: fileName, priority }, fs.readFileSync(fileName, \"utf-8\"));\r\n }\r\n\r\n public addDirectory(dirName: LocalDirName, priority: SettingsPriority) {\r\n for (const fileName of IModelJsFs.readdirSync(dirName)) {\r\n const ext = extname(fileName);\r\n if (ext === \".json5\" || ext === \".json\")\r\n this.addFile(join(dirName, fileName), priority);\r\n }\r\n }\r\n\r\n public addJson(props: SettingsDictionaryProps, settingsJson: string) {\r\n this.addDictionary(props, parse(settingsJson));\r\n }\r\n\r\n public addDictionary(props: SettingsDictionaryProps, settings: SettingsContainer) {\r\n this.verifyPriority(props.priority);\r\n this.dropDictionary(props, false); // make sure we don't have the same dictionary twice\r\n const dict = new SettingsDictionaryImpl(props, settings);\r\n const doAdd = () => {\r\n for (let i = 0; i < this.dictionaries.length; ++i) {\r\n if (this.dictionaries[i].props.priority <= dict.props.priority) {\r\n this.dictionaries.splice(i, 0, dict);\r\n return;\r\n }\r\n }\r\n this.dictionaries.push(dict);\r\n };\r\n doAdd();\r\n this.onSettingsChanged.raiseEvent();\r\n }\r\n\r\n public getDictionary(source: SettingsDictionarySource): SettingsDictionary | undefined {\r\n for (const dictionary of this.dictionaries) {\r\n if (dictionaryMatches(dictionary.props, source))\r\n return dictionary;\r\n }\r\n return undefined;\r\n }\r\n\r\n public dropDictionary(source: SettingsDictionarySource, raiseEvent = true) {\r\n for (let i = 0; i < this.dictionaries.length; ++i) {\r\n if (dictionaryMatches(this.dictionaries[i].props, source)) {\r\n this.dictionaries.splice(i, 1);\r\n if (raiseEvent)\r\n this.onSettingsChanged.raiseEvent();\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public * getSettingEntries<T extends Setting>(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary}> {\r\n for (const dictionary of this.dictionaries) {\r\n const value = dictionary.getSetting<T>(settingName);\r\n if (undefined !== value) {\r\n yield { value, dictionary };\r\n }\r\n }\r\n }\r\n\r\n public * getSettingValues<T extends Setting>(settingName: SettingName): Iterable<T> {\r\n for (const entry of this.getSettingEntries<T>(settingName)) {\r\n yield entry.value;\r\n }\r\n }\r\n\r\n public getSetting<T extends Setting>(settingName: SettingName, defaultValue?: T): T | undefined {\r\n for (const value of this.getSettingValues<T>(settingName)) {\r\n return value;\r\n }\r\n\r\n return defaultValue;\r\n }\r\n\r\n // get the setting and verify the result is either undefined or the correct type. If so, return it. Otherwise throw an exception.\r\n private getResult<T extends Setting>(name: SettingName, expectedType: string) {\r\n const out = this.getSetting<T>(name);\r\n if (out === undefined || typeof out === expectedType)\r\n return out;\r\n throw new Error(`setting \"${name}\" is not a ${expectedType}: ${typeof out}`);\r\n }\r\n public getString(name: SettingName, defaultValue: string): string;\r\n public getString(name: SettingName): string | undefined;\r\n public getString(name: SettingName, defaultValue?: string): string | undefined {\r\n return this.getResult<string>(name, \"string\") ?? defaultValue;\r\n }\r\n public getBoolean(name: SettingName, defaultValue: boolean): boolean;\r\n public getBoolean(name: SettingName): boolean | undefined;\r\n public getBoolean(name: SettingName, defaultValue?: boolean): boolean | undefined {\r\n return this.getResult<boolean>(name, \"boolean\") ?? defaultValue;\r\n }\r\n public getNumber(name: SettingName, defaultValue: number): number;\r\n public getNumber(name: SettingName): number | undefined;\r\n public getNumber(name: SettingName, defaultValue?: number): number | undefined {\r\n return this.getResult<number>(name, \"number\") ?? defaultValue;\r\n }\r\n public getObject<T extends object>(name: SettingName, defaultValue: T): T;\r\n public getObject<T extends object>(name: SettingName): T | undefined;\r\n public getObject<T extends object>(name: SettingName, defaultValue?: T): T | undefined {\r\n const out = this.getResult<T>(name, \"object\");\r\n return out ? IModelHost.settingsSchemas.validateSetting(out, name) : defaultValue;\r\n }\r\n public getArray<T extends Setting>(name: SettingName, defaultValue: T[]): T[];\r\n public getArray<T extends Setting>(name: SettingName): T[] | undefined;\r\n public getArray<T extends Setting>(name: SettingName, defaultValue?: T[]): T[] | undefined {\r\n if (IModelHost.settingsSchemas.settingDefs.get(name)?.combineArray) {\r\n return this.getCombinedArray<T>(name, defaultValue);\r\n }\r\n\r\n const out = this.getSetting<T[]>(name);\r\n if (out === undefined)\r\n return defaultValue;\r\n if (!Array.isArray(out))\r\n throw new Error(`setting ${name} is not an array: ${String(out)}`);\r\n return IModelHost.settingsSchemas.validateSetting(out, name);\r\n }\r\n\r\n private getCombinedArray<T extends Setting>(name: SettingName, defaultValue?: T[]): T[] | undefined {\r\n let foundSetting = false;\r\n const out: T[] = [];\r\n for (const array of this.getSettingValues<T[]>(name)) {\r\n foundSetting = true;\r\n\r\n IModelHost.settingsSchemas.validateSetting(array, name);\r\n for (const value of array) {\r\n if (undefined === out.find((x) => Setting.areEqual(x, value))) {\r\n out.push(value);\r\n }\r\n }\r\n }\r\n\r\n return foundSetting ? out : defaultValue;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"SettingsImpl.js","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsImpl.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 Workspace\r\n */\r\n\r\nimport * as fs from \"fs-extra\";\r\nimport { parse } from \"json5\";\r\nimport { extname, join } from \"path\";\r\nimport { BeEvent, DbResult, Guid, OpenMode } from \"@itwin/core-bentley\";\r\nimport { CloudSqliteError, LocalDirName, LocalFileName, WorkspaceError } from \"@itwin/core-common\";\r\nimport { CloudSqlite } from \"../../CloudSqlite\";\r\nimport { IModelJsFs } from \"../../IModelJsFs\";\r\nimport { IModelHost, KnownLocations } from \"../../IModelHost\";\r\nimport { Setting, SettingName, Settings, SettingsContainer, SettingsDictionary, SettingsDictionaryProps, SettingsDictionarySource, SettingsPriority } from \"../../workspace/Settings\";\r\nimport { CloudSqliteContainer, GetWorkspaceContainerArgs, Workspace, WorkspaceContainerProps, WorkspaceDbProps,\r\n} from \"../../workspace/Workspace\";\r\nimport { SettingsDbManifest, SettingsDbProps, settingsResourceName } from \"../../workspace/SettingsDb\";\r\nimport {\r\n type CreateNewSettingsContainerArgs, type CreateNewSettingsDbVersionArgs, type CreateSettingsDbArgs, type EditableSettingsCloudContainer, type EditableSettingsDb,\r\n type SettingsDbVersionResult, type SettingsEditor, SettingsEditor as SettingsEditorNs,\r\n type UpdateSettingArgs,\r\n} from \"../../workspace/SettingsEditor\";\r\nimport { BlobContainer } from \"../../BlobContainerService\";\r\nimport { settingsDbDefaultName, SettingsDbImpl, settingsManifestProperty } from \"./SettingsDbImpl\";\r\nimport { SettingsSqliteDb } from \"./SettingsSqliteDb\";\r\nimport { constructSettingsEditorWorkspace, OwnedWorkspace } from \"./WorkspaceImpl\";\r\nimport { _implementationProhibited, _nativeDb } from \"../Symbols\";\r\n\r\nconst dictionaryMatches = (d1: SettingsDictionarySource, d2: SettingsDictionarySource): boolean => {\r\n return (d1.workspaceDb === d2.workspaceDb) && (d1.name === d2.name);\r\n};\r\n\r\nclass SettingsDictionaryImpl implements SettingsDictionary {\r\n public readonly [_implementationProhibited] = undefined;\r\n public readonly props: SettingsDictionaryProps;\r\n public readonly settings: SettingsContainer;\r\n\r\n public constructor(props: SettingsDictionaryProps, settings: SettingsContainer) {\r\n this.props = { ...props }; // make a copy so it can't be changed by caller\r\n this.settings = settings;\r\n }\r\n\r\n public getSetting<T extends Setting>(settingName: string): T | undefined {\r\n const value = this.settings[settingName] as T | undefined;\r\n return undefined !== value ? Setting.clone(value) : undefined;\r\n }\r\n\r\n public toJSON(): SettingsContainer {\r\n return Setting.clone(this.settings);\r\n }\r\n}\r\n\r\n/**\r\n * Internal implementation of Settings interface.\r\n * @internal\r\n */\r\nexport class SettingsImpl implements Settings {\r\n public readonly [_implementationProhibited] = undefined;\r\n public dictionaries: SettingsDictionary[] = [];\r\n protected verifyPriority(_priority: SettingsPriority) { }\r\n public close() { }\r\n public readonly onSettingsChanged = new BeEvent<() => void>();\r\n\r\n public addFile(fileName: LocalFileName, priority: SettingsPriority) {\r\n this.addJson({ name: fileName, priority }, fs.readFileSync(fileName, \"utf-8\"));\r\n }\r\n\r\n public addDirectory(dirName: LocalDirName, priority: SettingsPriority) {\r\n for (const fileName of IModelJsFs.readdirSync(dirName)) {\r\n const ext = extname(fileName);\r\n if (ext === \".json5\" || ext === \".json\")\r\n this.addFile(join(dirName, fileName), priority);\r\n }\r\n }\r\n\r\n public addJson(props: SettingsDictionaryProps, settingsJson: string) {\r\n this.addDictionary(props, parse(settingsJson));\r\n }\r\n\r\n public addDictionary(props: SettingsDictionaryProps, settings: SettingsContainer) {\r\n this.verifyPriority(props.priority);\r\n this.dropDictionary(props, false); // make sure we don't have the same dictionary twice\r\n const dict = new SettingsDictionaryImpl(props, settings);\r\n const doAdd = () => {\r\n for (let i = 0; i < this.dictionaries.length; ++i) {\r\n if (this.dictionaries[i].props.priority <= dict.props.priority) {\r\n this.dictionaries.splice(i, 0, dict);\r\n return;\r\n }\r\n }\r\n this.dictionaries.push(dict);\r\n };\r\n doAdd();\r\n this.onSettingsChanged.raiseEvent();\r\n }\r\n\r\n public getDictionary(source: SettingsDictionarySource): SettingsDictionary | undefined {\r\n for (const dictionary of this.dictionaries) {\r\n if (dictionaryMatches(dictionary.props, source))\r\n return dictionary;\r\n }\r\n return undefined;\r\n }\r\n\r\n public dropDictionary(source: SettingsDictionarySource, raiseEvent = true) {\r\n for (let i = 0; i < this.dictionaries.length; ++i) {\r\n if (dictionaryMatches(this.dictionaries[i].props, source)) {\r\n this.dictionaries.splice(i, 1);\r\n if (raiseEvent)\r\n this.onSettingsChanged.raiseEvent();\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public * getSettingEntries<T extends Setting>(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary}> {\r\n for (const dictionary of this.dictionaries) {\r\n const value = dictionary.getSetting<T>(settingName);\r\n if (undefined !== value) {\r\n yield { value, dictionary };\r\n }\r\n }\r\n }\r\n\r\n public * getSettingValues<T extends Setting>(settingName: SettingName): Iterable<T> {\r\n for (const entry of this.getSettingEntries<T>(settingName)) {\r\n yield entry.value;\r\n }\r\n }\r\n\r\n public getSetting<T extends Setting>(settingName: SettingName, defaultValue?: T): T | undefined {\r\n for (const value of this.getSettingValues<T>(settingName)) {\r\n return value;\r\n }\r\n\r\n return defaultValue;\r\n }\r\n\r\n // get the setting and verify the result is either undefined or the correct type. If so, return it. Otherwise throw an exception.\r\n private getResult<T extends Setting>(name: SettingName, expectedType: string) {\r\n const out = this.getSetting<T>(name);\r\n if (out === undefined || typeof out === expectedType)\r\n return out;\r\n throw new Error(`setting \"${name}\" is not a ${expectedType}: ${typeof out}`);\r\n }\r\n public getString(name: SettingName, defaultValue: string): string;\r\n public getString(name: SettingName): string | undefined;\r\n public getString(name: SettingName, defaultValue?: string): string | undefined {\r\n return this.getResult<string>(name, \"string\") ?? defaultValue;\r\n }\r\n public getBoolean(name: SettingName, defaultValue: boolean): boolean;\r\n public getBoolean(name: SettingName): boolean | undefined;\r\n public getBoolean(name: SettingName, defaultValue?: boolean): boolean | undefined {\r\n return this.getResult<boolean>(name, \"boolean\") ?? defaultValue;\r\n }\r\n public getNumber(name: SettingName, defaultValue: number): number;\r\n public getNumber(name: SettingName): number | undefined;\r\n public getNumber(name: SettingName, defaultValue?: number): number | undefined {\r\n return this.getResult<number>(name, \"number\") ?? defaultValue;\r\n }\r\n public getObject<T extends object>(name: SettingName, defaultValue: T): T;\r\n public getObject<T extends object>(name: SettingName): T | undefined;\r\n public getObject<T extends object>(name: SettingName, defaultValue?: T): T | undefined {\r\n const out = this.getResult<T>(name, \"object\");\r\n return out ? IModelHost.settingsSchemas.validateSetting(out, name) : defaultValue;\r\n }\r\n public getArray<T extends Setting>(name: SettingName, defaultValue: T[]): T[];\r\n public getArray<T extends Setting>(name: SettingName): T[] | undefined;\r\n public getArray<T extends Setting>(name: SettingName, defaultValue?: T[]): T[] | undefined {\r\n if (IModelHost.settingsSchemas.settingDefs.get(name)?.combineArray) {\r\n return this.getCombinedArray<T>(name, defaultValue);\r\n }\r\n\r\n const out = this.getSetting<T[]>(name);\r\n if (out === undefined)\r\n return defaultValue;\r\n if (!Array.isArray(out))\r\n throw new Error(`setting ${name} is not an array: ${String(out)}`);\r\n return IModelHost.settingsSchemas.validateSetting(out, name);\r\n }\r\n\r\n private getCombinedArray<T extends Setting>(name: SettingName, defaultValue?: T[]): T[] | undefined {\r\n let foundSetting = false;\r\n const out: T[] = [];\r\n for (const array of this.getSettingValues<T[]>(name)) {\r\n foundSetting = true;\r\n\r\n IModelHost.settingsSchemas.validateSetting(array, name);\r\n for (const value of array) {\r\n if (undefined === out.find((x) => Setting.areEqual(x, value))) {\r\n out.push(value);\r\n }\r\n }\r\n }\r\n\r\n return foundSetting ? out : defaultValue;\r\n }\r\n}\r\n\r\n// ==================== SettingsEditor implementation ====================\r\n\r\nconst settingsEditorName = \"SettingsEditor\";\r\n\r\n/** Construct a new [[SettingsEditor]]. Called by the [[SettingsEditor]] namespace. */\r\nexport function constructSettingsEditor(): SettingsEditor {\r\n return new SettingsEditorImpl();\r\n}\r\n\r\nclass SettingsEditorImpl implements SettingsEditor {\r\n public readonly [_implementationProhibited] = undefined;\r\n private readonly _workspace: OwnedWorkspace;\r\n private _containers = new Map<string, EditableSettingsContainerImpl>();\r\n\r\n public constructor() {\r\n this._workspace = constructSettingsEditorWorkspace(new SettingsImpl(), { containerDir: join(IModelHost.cacheDir, settingsEditorName) });\r\n }\r\n\r\n public get workspace(): Workspace { return this._workspace; }\r\n\r\n private async initializeContainer(args: CreateNewSettingsContainerArgs) {\r\n class CloudAccess extends CloudSqlite.DbAccess<SettingsSqliteDb> {\r\n protected static override _cacheName = settingsEditorName;\r\n public static async initializeSettings(initArgs: CreateNewSettingsContainerArgs) {\r\n const props = await this.createBlobContainer({ scope: initArgs.scope, metadata: { ...initArgs.metadata, containerType: \"settings\" } });\r\n const dbFullName = CloudSqlite.makeSemverName(initArgs.dbName ?? settingsDbDefaultName, \"0.0.0\");\r\n await super._initializeDb({ ...initArgs, props, dbName: dbFullName, dbType: SettingsSqliteDb, blockSize: \"4M\" });\r\n return props;\r\n }\r\n }\r\n return CloudAccess.initializeSettings(args);\r\n }\r\n\r\n public async createNewCloudContainer(args: CreateNewSettingsContainerArgs): Promise<EditableSettingsCloudContainer> {\r\n const cloudContainer = await this.initializeContainer(args);\r\n const userToken = await IModelHost.authorizationClient?.getAccessToken();\r\n const accessToken = await CloudSqlite.requestToken({ ...cloudContainer, accessLevel: \"write\", userToken });\r\n return this.getContainer({ accessToken, ...cloudContainer, writeable: true, description: args.metadata.description });\r\n }\r\n\r\n public getContainer(args: GetWorkspaceContainerArgs): EditableSettingsCloudContainer {\r\n const existing = this._containers.get(args.containerId);\r\n if (existing)\r\n return existing;\r\n const baseContainer = this._workspace.getContainer(args);\r\n const editable = new EditableSettingsContainerImpl(baseContainer);\r\n this._containers.set(args.containerId, editable);\r\n return editable;\r\n }\r\n\r\n public async getContainerAsync(props: WorkspaceContainerProps): Promise<EditableSettingsCloudContainer> {\r\n let accessToken = props.accessToken;\r\n if (undefined === accessToken && props.baseUri !== \"\")\r\n accessToken = await CloudSqlite.requestToken({ ...props, accessLevel: \"write\" });\r\n\r\n return this.getContainer({ ...props, accessToken: accessToken ?? \"\" });\r\n }\r\n\r\n public async findContainers(args: SettingsEditorNs.QuerySettingsContainersArgs): Promise<EditableSettingsCloudContainer[]> {\r\n const containers = await SettingsEditorNs.queryContainers(args);\r\n const userToken = await IModelHost.getAccessToken();\r\n const results: EditableSettingsCloudContainer[] = [];\r\n for (const containerMeta of containers) {\r\n // queryContainers already validates that BlobContainer.service is defined, so the non-null assertion is safe here.\r\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\r\n const tokenProps = await BlobContainer.service!.requestToken({ containerId: containerMeta.containerId, userToken, accessLevel: \"write\" });\r\n results.push(this.getContainer({\r\n containerId: containerMeta.containerId,\r\n baseUri: tokenProps.baseUri,\r\n storageType: tokenProps.provider,\r\n accessToken: tokenProps.token,\r\n writeable: true,\r\n }));\r\n }\r\n return results;\r\n }\r\n\r\n public close() {\r\n const errors: unknown[] = [];\r\n for (const [_, container] of this._containers) {\r\n try {\r\n container.cleanup();\r\n } catch (e) {\r\n errors.push(e);\r\n }\r\n }\r\n this._containers.clear();\r\n try {\r\n this._workspace.close();\r\n } catch (e) {\r\n errors.push(e);\r\n }\r\n if (errors.length === 1)\r\n throw errors[0];\r\n if (errors.length > 1)\r\n throw new Error(`SettingsEditor.close() encountered ${errors.length} errors: ${errors.map((e) => e instanceof Error ? e.message : String(e)).join(\"; \")}`);\r\n }\r\n}\r\n\r\nclass EditableSettingsContainerImpl implements EditableSettingsCloudContainer {\r\n public readonly [_implementationProhibited] = undefined;\r\n private readonly _inner: CloudSqliteContainer;\r\n private _settingsDbs = new Map<string, EditableSettingsDbImpl>();\r\n public writeLockHeldBy?: string;\r\n\r\n public constructor(inner: CloudSqliteContainer) {\r\n this._inner = inner;\r\n }\r\n\r\n // CloudSqliteContainer delegation\r\n public get workspace() { return this._inner.workspace; }\r\n public get filesDir() { return this._inner.filesDir; }\r\n public get cloudContainer() { return this._inner.cloudContainer; }\r\n public get fromProps() { return this._inner.fromProps; }\r\n public resolveDbFileName(props: WorkspaceDbProps) { return this._inner.resolveDbFileName(props); }\r\n\r\n public get cloudProps(): WorkspaceContainerProps | undefined {\r\n const cc = this.cloudContainer;\r\n if (undefined === cc)\r\n return undefined;\r\n return {\r\n baseUri: cc.baseUri,\r\n containerId: cc.containerId,\r\n storageType: cc.storageType as \"azure\" | \"google\",\r\n isPublic: cc.isPublic,\r\n };\r\n }\r\n\r\n public getEditableDb(props?: SettingsDbProps): EditableSettingsDb {\r\n const dbName = props?.dbName ?? settingsDbDefaultName;\r\n let db = this._settingsDbs.get(dbName);\r\n if (undefined === db) {\r\n db = new EditableSettingsDbImpl(props ?? { dbName }, this);\r\n this._settingsDbs.set(dbName, db);\r\n }\r\n\r\n if (this.cloudContainer && !CloudSqlite.isSemverEditable(db.dbFileName, this.cloudContainer)) {\r\n this._settingsDbs.delete(dbName);\r\n CloudSqliteError.throwError(\"already-published\", { message: `${db.dbFileName} has been published and is not editable. Make a new version first.` });\r\n }\r\n\r\n return db;\r\n }\r\n\r\n public async createNewSettingsDbVersion(args: CreateNewSettingsDbVersionArgs): Promise<SettingsDbVersionResult> {\r\n const container = this.cloudContainer;\r\n if (undefined === container)\r\n WorkspaceError.throwError(\"no-cloud-container\", { message: \"versions require cloud containers\" });\r\n\r\n const fromDb = { ...args.fromProps, dbName: args.fromProps?.dbName ?? settingsDbDefaultName };\r\n return CloudSqlite.createNewDbVersion(container, { ...args, fromDb });\r\n }\r\n\r\n public async createDb(args: CreateSettingsDbArgs): Promise<EditableSettingsDb> {\r\n const dbName = args.dbName ?? settingsDbDefaultName;\r\n if (!this.cloudContainer) {\r\n SettingsSqliteDb.createNewDb(this.resolveDbFileName({ dbName }), { manifest: args.manifest });\r\n } else {\r\n const tempDbFile = join(KnownLocations.tmpdir, `empty-${Guid.createValue()}.itwin-settings`);\r\n try {\r\n SettingsSqliteDb.createNewDb(tempDbFile, { manifest: args.manifest });\r\n await CloudSqlite.uploadDb(this.cloudContainer, { localFileName: tempDbFile, dbName: CloudSqlite.makeSemverName(dbName, args.version) });\r\n } finally {\r\n if (fs.existsSync(tempDbFile))\r\n IModelJsFs.removeSync(tempDbFile);\r\n }\r\n }\r\n\r\n return this.getEditableDb({ dbName });\r\n }\r\n\r\n public acquireWriteLock(user: string): void {\r\n if (this.cloudContainer) {\r\n this.cloudContainer.acquireWriteLock(user);\r\n this.writeLockHeldBy = user;\r\n }\r\n }\r\n\r\n public releaseWriteLock(): void {\r\n if (this.cloudContainer) {\r\n this.cloudContainer.releaseWriteLock();\r\n this.writeLockHeldBy = undefined;\r\n }\r\n }\r\n\r\n public abandonChanges(): void {\r\n if (this.cloudContainer) {\r\n this.cloudContainer.abandonChanges();\r\n this.writeLockHeldBy = undefined;\r\n }\r\n }\r\n\r\n /** Close all editable settings dbs tracked by this container. */\r\n public cleanup(): void {\r\n for (const [_, db] of this._settingsDbs)\r\n db.close();\r\n this._settingsDbs.clear();\r\n }\r\n}\r\n\r\nclass EditableSettingsDbImpl extends SettingsDbImpl implements EditableSettingsDb {\r\n public override get container(): EditableSettingsCloudContainer {\r\n return this._container as EditableSettingsCloudContainer;\r\n }\r\n\r\n public constructor(props: SettingsDbProps, container: EditableSettingsContainerImpl) {\r\n super(props, container, SettingsPriority.application);\r\n }\r\n\r\n public override open(): void {\r\n this.sqliteDb.openDb(this.dbFileName, OpenMode.ReadWrite, this._container.cloudContainer);\r\n }\r\n\r\n public override close(): void {\r\n let error: unknown;\r\n try {\r\n if (this.isOpen) {\r\n const lastEditedBy = (this._container as EditableSettingsContainerImpl).writeLockHeldBy;\r\n if (lastEditedBy !== undefined)\r\n this.updateManifest({ ...this.manifest, lastEditedBy });\r\n this.sqliteDb.saveChanges();\r\n }\r\n } catch (e) {\r\n error = e;\r\n } finally {\r\n super.close();\r\n }\r\n if (error) {\r\n if (error instanceof Error)\r\n throw error;\r\n throw new Error(`EditableSettingsDb.close() failed`);\r\n }\r\n }\r\n\r\n public updateManifest(manifest: SettingsDbManifest): void {\r\n this.sqliteDb[_nativeDb].saveFileProperty(settingsManifestProperty, JSON.stringify(manifest));\r\n this._manifest = undefined;\r\n }\r\n\r\n public updateSettings(settings: SettingsContainer): void {\r\n const val = JSON.stringify(settings);\r\n this.sqliteDb.withSqliteStatement(\r\n \"INSERT INTO strings(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value\",\r\n (stmt) => {\r\n stmt.bindString(1, settingsResourceName);\r\n stmt.bindString(2, val);\r\n const rc = stmt.step();\r\n if (DbResult.BE_SQLITE_DONE !== rc)\r\n WorkspaceError.throwError(\"write-error\", { message: `settings [updateSettings], rc=${rc}` });\r\n },\r\n );\r\n this.sqliteDb.saveChanges();\r\n }\r\n\r\n public updateSetting(args: UpdateSettingArgs): void {\r\n this.withOpenDb(() => {\r\n const container = this.getSettings();\r\n container[args.settingName] = args.value;\r\n this.updateSettings(container);\r\n });\r\n }\r\n\r\n public removeSetting(settingName: SettingName): void {\r\n this.withOpenDb(() => {\r\n const container = this.getSettings();\r\n delete container[settingName];\r\n this.updateSettings(container);\r\n });\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @packageDocumentation
|
|
2
|
+
* @module Workspace
|
|
3
|
+
*/
|
|
4
|
+
import { SQLiteDb, VersionedSqliteDb } from "../../SQLiteDb";
|
|
5
|
+
/** A [[VersionedSqliteDb]] that stores settings dictionaries. Unlike [[WorkspaceSqliteDb]], the
|
|
6
|
+
* manifest is stored using [[settingsManifestProperty]] so that settings and workspace databases
|
|
7
|
+
* can coexist in the same container without ambiguity.
|
|
8
|
+
*/
|
|
9
|
+
export declare class SettingsSqliteDb extends VersionedSqliteDb {
|
|
10
|
+
myVersion: string;
|
|
11
|
+
getRequiredVersions(): SQLiteDb.RequiredVersionRanges;
|
|
12
|
+
protected createDDL(args: any): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=SettingsSqliteDb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsSqliteDb.d.ts","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsSqliteDb.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAK7D;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB;IACrC,SAAS,SAAW;IACpB,mBAAmB,IAAI,QAAQ,CAAC,qBAAqB;cAUlD,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;CAO9C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
/** @packageDocumentation
|
|
6
|
+
* @module Workspace
|
|
7
|
+
*/
|
|
8
|
+
import { VersionedSqliteDb } from "../../SQLiteDb";
|
|
9
|
+
import { SqliteError } from "@itwin/core-common";
|
|
10
|
+
import { _nativeDb } from "../Symbols";
|
|
11
|
+
import { settingsManifestProperty } from "./SettingsDbImpl";
|
|
12
|
+
/** A [[VersionedSqliteDb]] that stores settings dictionaries. Unlike [[WorkspaceSqliteDb]], the
|
|
13
|
+
* manifest is stored using [[settingsManifestProperty]] so that settings and workspace databases
|
|
14
|
+
* can coexist in the same container without ambiguity.
|
|
15
|
+
*/
|
|
16
|
+
export class SettingsSqliteDb extends VersionedSqliteDb {
|
|
17
|
+
myVersion = "1.0.0";
|
|
18
|
+
getRequiredVersions() {
|
|
19
|
+
try {
|
|
20
|
+
return super.getRequiredVersions();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
if (SqliteError.isError(e, "invalid-versions-property"))
|
|
24
|
+
return { readVersion: "^1", writeVersion: "^1" };
|
|
25
|
+
throw e;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
createDDL(args) {
|
|
29
|
+
const timeStampCol = "lastMod TIMESTAMP NOT NULL DEFAULT(julianday('now'))";
|
|
30
|
+
this.executeSQL(`CREATE TABLE strings(id TEXT PRIMARY KEY NOT NULL,value TEXT,${timeStampCol})`);
|
|
31
|
+
this.executeSQL(`CREATE TRIGGER strings_timeStamp AFTER UPDATE ON strings WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE strings SET lastMod=julianday('now') WHERE id=new.id; END`);
|
|
32
|
+
if (args?.manifest)
|
|
33
|
+
this[_nativeDb].saveFileProperty(settingsManifestProperty, JSON.stringify(args.manifest));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=SettingsSqliteDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsSqliteDb.js","sourceRoot":"","sources":["../../../../src/internal/workspace/SettingsSqliteDb.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,iBAAiB;IACrC,SAAS,GAAG,OAAO,CAAC;IACpB,mBAAmB;QACjC,IAAI,CAAC;YACH,OAAO,KAAK,CAAC,mBAAmB,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,2BAA2B,CAAC;gBACrD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;YACnD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAEkB,SAAS,CAAC,IAAS;QACpC,MAAM,YAAY,GAAG,sDAAsD,CAAC;QAC5E,IAAI,CAAC,UAAU,CAAC,gEAAgE,YAAY,GAAG,CAAC,CAAC;QACjG,IAAI,CAAC,UAAU,CAAC,kMAAkM,CAAC,CAAC;QACpN,IAAI,IAAI,EAAE,QAAQ;YAChB,IAAI,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9F,CAAC;CACF","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 Workspace\r\n */\r\n\r\nimport { SQLiteDb, VersionedSqliteDb } from \"../../SQLiteDb\";\r\nimport { SqliteError } from \"@itwin/core-common\";\r\nimport { _nativeDb } from \"../Symbols\";\r\nimport { settingsManifestProperty } from \"./SettingsDbImpl\";\r\n\r\n/** A [[VersionedSqliteDb]] that stores settings dictionaries. Unlike [[WorkspaceSqliteDb]], the\r\n * manifest is stored using [[settingsManifestProperty]] so that settings and workspace databases\r\n * can coexist in the same container without ambiguity.\r\n */\r\nexport class SettingsSqliteDb extends VersionedSqliteDb {\r\n public override myVersion = \"1.0.0\";\r\n public override getRequiredVersions(): SQLiteDb.RequiredVersionRanges {\r\n try {\r\n return super.getRequiredVersions();\r\n } catch (e) {\r\n if (SqliteError.isError(e, \"invalid-versions-property\"))\r\n return { readVersion: \"^1\", writeVersion: \"^1\" };\r\n throw e;\r\n }\r\n }\r\n\r\n protected override createDDL(args: any): void {\r\n const timeStampCol = \"lastMod TIMESTAMP NOT NULL DEFAULT(julianday('now'))\";\r\n this.executeSQL(`CREATE TABLE strings(id TEXT PRIMARY KEY NOT NULL,value TEXT,${timeStampCol})`);\r\n this.executeSQL(`CREATE TRIGGER strings_timeStamp AFTER UPDATE ON strings WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE strings SET lastMod=julianday('now') WHERE id=new.id; END`);\r\n if (args?.manifest)\r\n this[_nativeDb].saveFileProperty(settingsManifestProperty, JSON.stringify(args.manifest));\r\n }\r\n}\r\n"]}
|
|
@@ -10,6 +10,7 @@ export declare const workspaceDbFileExt = "itwin-workspace";
|
|
|
10
10
|
export declare function constructWorkspaceDb(props: WorkspaceDbProps, container: WorkspaceContainer): WorkspaceDb;
|
|
11
11
|
export declare function constructWorkspace(settings: Settings, opts?: WorkspaceOpts): OwnedWorkspace;
|
|
12
12
|
export declare function constructWorkspaceEditor(): WorkspaceEditor;
|
|
13
|
+
export declare function constructSettingsEditorWorkspace(settings: Settings, opts?: WorkspaceOpts): OwnedWorkspace;
|
|
13
14
|
/**
|
|
14
15
|
* Validate that a WorkspaceContainer.Id is valid.
|
|
15
16
|
* The rules for ContainerIds (from Azure, see https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceImpl.d.ts","sourceRoot":"","sources":["../../../../src/internal/workspace/WorkspaceImpl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAMH,OAAO,EAAoB,iBAAiB,EAA+C,MAAM,oBAAoB,CAAC;AAMtH,OAAO,EAAe,QAAQ,EAAgE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkspaceImpl.d.ts","sourceRoot":"","sources":["../../../../src/internal/workspace/WorkspaceImpl.ts"],"names":[],"mappings":"AAIA;;GAEG;AAMH,OAAO,EAAoB,iBAAiB,EAA+C,MAAM,oBAAoB,CAAC;AAMtH,OAAO,EAAe,QAAQ,EAAgE,MAAM,0BAA0B,CAAC;AAG/H,OAAO,EACsB,SAAS,EAAE,kBAAkB,EAAE,oBAAoB,EAA2B,WAAW,EAC/F,oBAAoB,EAA0F,gBAAgB,EAC1F,aAAa,EACvE,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAqH,eAAe,EAAwC,MAAM,iCAAiC,CAAC;AAY3N,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AA6tBpD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,kBAAkB,GAAG,WAAW,CAExG;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAE3F;AAED,wBAAgB,wBAAwB,IAAI,eAAe,CAE1D;AAED,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAEzG;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,oBAAoB,QAGpE;AAED,eAAO,MAAM,yBAAyB,EAAE,iBAAgE,CAAC;AAOzG,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,oBAAoB,EAAE,GAAG,KAAK,CAEvG;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,kDAAkD;IAClD,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -15,12 +15,15 @@ import { IModelHost, KnownLocations } from "../../IModelHost";
|
|
|
15
15
|
import { IModelJsFs } from "../../IModelJsFs";
|
|
16
16
|
import { SQLiteDb } from "../../SQLiteDb";
|
|
17
17
|
import { SettingsPriority } from "../../workspace/Settings";
|
|
18
|
+
import { settingsResourceName } from "../../workspace/SettingsDb";
|
|
18
19
|
import { Workspace, WorkspaceSettingNames, } from "../../workspace/Workspace";
|
|
19
|
-
import { WorkspaceEditor } from "../../workspace/WorkspaceEditor";
|
|
20
|
+
import { WorkspaceEditor, WorkspaceEditor as WorkspaceEditorNs } from "../../workspace/WorkspaceEditor";
|
|
20
21
|
import { WorkspaceSqliteDb } from "./WorkspaceSqliteDb";
|
|
22
|
+
import { SettingsDbImpl } from "./SettingsDbImpl";
|
|
21
23
|
import { SettingsImpl } from "./SettingsImpl";
|
|
22
24
|
import { _implementationProhibited, _nativeDb } from "../Symbols";
|
|
23
25
|
import { getOnlineStatus } from "../OnlineStatus";
|
|
26
|
+
import { BlobContainer } from "../../BlobContainerService";
|
|
24
27
|
function workspaceDbNameWithDefault(dbName) {
|
|
25
28
|
return dbName ?? "workspace-db";
|
|
26
29
|
}
|
|
@@ -313,6 +316,15 @@ class WorkspaceImpl {
|
|
|
313
316
|
}
|
|
314
317
|
return container.getWorkspaceDb(props);
|
|
315
318
|
}
|
|
319
|
+
getSettingsDb(args) {
|
|
320
|
+
const container = this.findContainer(args.containerId);
|
|
321
|
+
if (undefined === container)
|
|
322
|
+
WorkspaceError.throwError("does-not-exist", { message: `No settings container found for containerId "${args.containerId}"` });
|
|
323
|
+
const settingsDb = new SettingsDbImpl({ dbName: args.dbName ?? "settings-db", version: args.version }, container, args.priority);
|
|
324
|
+
if (!settingsDb.hasSettingsManifestProperty)
|
|
325
|
+
WorkspaceError.throwError("does-not-exist", { message: `Container "${args.containerId}" does not contain a SettingsDb — missing settings manifest` });
|
|
326
|
+
return settingsDb;
|
|
327
|
+
}
|
|
316
328
|
async loadSettingsDictionary(props, problems) {
|
|
317
329
|
if (!Array.isArray(props))
|
|
318
330
|
props = [props];
|
|
@@ -321,12 +333,13 @@ class WorkspaceImpl {
|
|
|
321
333
|
db.open();
|
|
322
334
|
try {
|
|
323
335
|
const manifest = db.manifest;
|
|
324
|
-
const
|
|
336
|
+
const resourceName = prop.resourceName ?? settingsResourceName;
|
|
337
|
+
const dictProps = { name: resourceName, workspaceDb: db, priority: prop.priority };
|
|
325
338
|
// don't load if we already have this dictionary. Happens if the same WorkspaceDb is in more than one list
|
|
326
339
|
if (undefined === this.settings.getDictionary(dictProps)) {
|
|
327
|
-
const settingsJson = db.getString(
|
|
340
|
+
const settingsJson = db.getString(resourceName);
|
|
328
341
|
if (undefined === settingsJson)
|
|
329
|
-
throwWorkspaceDbLoadError(`could not load setting dictionary resource '${
|
|
342
|
+
throwWorkspaceDbLoadError(`could not load setting dictionary resource '${resourceName}' from: '${manifest.workspaceName}'`, prop, db);
|
|
330
343
|
db.close(); // don't leave this db open in case we're going to find another dictionary in it recursively.
|
|
331
344
|
this.settings.addJson(dictProps, settingsJson);
|
|
332
345
|
const dict = this.settings.getDictionary(dictProps);
|
|
@@ -401,6 +414,12 @@ class EditorWorkspaceImpl extends WorkspaceImpl {
|
|
|
401
414
|
return this._cloudCache ??= makeWorkspaceCloudCache({ cacheName: workspaceEditorName, cacheSize: "20G" });
|
|
402
415
|
}
|
|
403
416
|
}
|
|
417
|
+
const settingsEditorCacheName = "SettingsEditor";
|
|
418
|
+
class SettingsEditorWorkspaceImpl extends WorkspaceImpl {
|
|
419
|
+
getCloudCache() {
|
|
420
|
+
return this._cloudCache ??= makeWorkspaceCloudCache({ cacheName: settingsEditorCacheName, cacheSize: "2G" });
|
|
421
|
+
}
|
|
422
|
+
}
|
|
404
423
|
class EditorImpl {
|
|
405
424
|
[_implementationProhibited] = undefined;
|
|
406
425
|
workspace = new EditorWorkspaceImpl(new SettingsImpl(), { containerDir: join(IModelHost.cacheDir, workspaceEditorName) });
|
|
@@ -433,6 +452,24 @@ class EditorImpl {
|
|
|
433
452
|
: await CloudSqlite.requestToken({ ...props, accessLevel: "write" });
|
|
434
453
|
return this.getContainer({ ...props, accessToken });
|
|
435
454
|
}
|
|
455
|
+
async findContainers(args) {
|
|
456
|
+
const containers = await WorkspaceEditorNs.queryContainers(args);
|
|
457
|
+
const userToken = await IModelHost.getAccessToken();
|
|
458
|
+
const results = [];
|
|
459
|
+
for (const containerMeta of containers) {
|
|
460
|
+
// queryContainers already validates that BlobContainer.service is defined, so the non-null assertion is safe here.
|
|
461
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
462
|
+
const tokenProps = await BlobContainer.service.requestToken({ containerId: containerMeta.containerId, userToken, accessLevel: "write" });
|
|
463
|
+
results.push(this.getContainer({
|
|
464
|
+
containerId: containerMeta.containerId,
|
|
465
|
+
baseUri: tokenProps.baseUri,
|
|
466
|
+
storageType: tokenProps.provider,
|
|
467
|
+
accessToken: tokenProps.token,
|
|
468
|
+
writeable: true,
|
|
469
|
+
}));
|
|
470
|
+
}
|
|
471
|
+
return results;
|
|
472
|
+
}
|
|
436
473
|
close() {
|
|
437
474
|
this.workspace.close();
|
|
438
475
|
}
|
|
@@ -626,6 +663,9 @@ export function constructWorkspace(settings, opts) {
|
|
|
626
663
|
export function constructWorkspaceEditor() {
|
|
627
664
|
return new EditorImpl();
|
|
628
665
|
}
|
|
666
|
+
export function constructSettingsEditorWorkspace(settings, opts) {
|
|
667
|
+
return new SettingsEditorWorkspaceImpl(settings, opts);
|
|
668
|
+
}
|
|
629
669
|
/**
|
|
630
670
|
* Validate that a WorkspaceContainer.Id is valid.
|
|
631
671
|
* The rules for ContainerIds (from Azure, see https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata):
|