@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.
Files changed (85) hide show
  1. package/lib/cjs/core-backend.d.ts +2 -0
  2. package/lib/cjs/core-backend.d.ts.map +1 -1
  3. package/lib/cjs/core-backend.js +2 -0
  4. package/lib/cjs/core-backend.js.map +1 -1
  5. package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts +38 -0
  6. package/lib/cjs/internal/workspace/SettingsDbImpl.d.ts.map +1 -0
  7. package/lib/cjs/internal/workspace/SettingsDbImpl.js +106 -0
  8. package/lib/cjs/internal/workspace/SettingsDbImpl.js.map +1 -0
  9. package/lib/cjs/internal/workspace/SettingsImpl.d.ts +3 -0
  10. package/lib/cjs/internal/workspace/SettingsImpl.d.ts.map +1 -1
  11. package/lib/cjs/internal/workspace/SettingsImpl.js +251 -1
  12. package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
  13. package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts +14 -0
  14. package/lib/cjs/internal/workspace/SettingsSqliteDb.d.ts.map +1 -0
  15. package/lib/cjs/internal/workspace/SettingsSqliteDb.js +40 -0
  16. package/lib/cjs/internal/workspace/SettingsSqliteDb.js.map +1 -0
  17. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts +1 -0
  18. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  19. package/lib/cjs/internal/workspace/WorkspaceImpl.js +44 -3
  20. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  21. package/lib/cjs/workspace/Settings.d.ts +8 -0
  22. package/lib/cjs/workspace/Settings.d.ts.map +1 -1
  23. package/lib/cjs/workspace/Settings.js.map +1 -1
  24. package/lib/cjs/workspace/SettingsDb.d.ts +109 -0
  25. package/lib/cjs/workspace/SettingsDb.d.ts.map +1 -0
  26. package/lib/cjs/workspace/SettingsDb.js +19 -0
  27. package/lib/cjs/workspace/SettingsDb.js.map +1 -0
  28. package/lib/cjs/workspace/SettingsEditor.d.ts +246 -0
  29. package/lib/cjs/workspace/SettingsEditor.d.ts.map +1 -0
  30. package/lib/cjs/workspace/SettingsEditor.js +51 -0
  31. package/lib/cjs/workspace/SettingsEditor.js.map +1 -0
  32. package/lib/cjs/workspace/Workspace.d.ts +39 -18
  33. package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
  34. package/lib/cjs/workspace/Workspace.js.map +1 -1
  35. package/lib/cjs/workspace/WorkspaceEditor.d.ts +28 -0
  36. package/lib/cjs/workspace/WorkspaceEditor.d.ts.map +1 -1
  37. package/lib/cjs/workspace/WorkspaceEditor.js +17 -0
  38. package/lib/cjs/workspace/WorkspaceEditor.js.map +1 -1
  39. package/lib/esm/core-backend.d.ts +2 -0
  40. package/lib/esm/core-backend.d.ts.map +1 -1
  41. package/lib/esm/core-backend.js +2 -0
  42. package/lib/esm/core-backend.js.map +1 -1
  43. package/lib/esm/internal/workspace/SettingsDbImpl.d.ts +38 -0
  44. package/lib/esm/internal/workspace/SettingsDbImpl.d.ts.map +1 -0
  45. package/lib/esm/internal/workspace/SettingsDbImpl.js +102 -0
  46. package/lib/esm/internal/workspace/SettingsDbImpl.js.map +1 -0
  47. package/lib/esm/internal/workspace/SettingsImpl.d.ts +3 -0
  48. package/lib/esm/internal/workspace/SettingsImpl.d.ts.map +1 -1
  49. package/lib/esm/internal/workspace/SettingsImpl.js +253 -4
  50. package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
  51. package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts +14 -0
  52. package/lib/esm/internal/workspace/SettingsSqliteDb.d.ts.map +1 -0
  53. package/lib/esm/internal/workspace/SettingsSqliteDb.js +36 -0
  54. package/lib/esm/internal/workspace/SettingsSqliteDb.js.map +1 -0
  55. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts +1 -0
  56. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  57. package/lib/esm/internal/workspace/WorkspaceImpl.js +44 -4
  58. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  59. package/lib/esm/test/standalone/Settings.test.js +18 -0
  60. package/lib/esm/test/standalone/Settings.test.js.map +1 -1
  61. package/lib/esm/test/standalone/Workspace.test.js +60 -0
  62. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  63. package/lib/esm/test/workspace/SettingsDb.test.d.ts +2 -0
  64. package/lib/esm/test/workspace/SettingsDb.test.d.ts.map +1 -0
  65. package/lib/esm/test/workspace/SettingsDb.test.js +372 -0
  66. package/lib/esm/test/workspace/SettingsDb.test.js.map +1 -0
  67. package/lib/esm/workspace/Settings.d.ts +8 -0
  68. package/lib/esm/workspace/Settings.d.ts.map +1 -1
  69. package/lib/esm/workspace/Settings.js.map +1 -1
  70. package/lib/esm/workspace/SettingsDb.d.ts +109 -0
  71. package/lib/esm/workspace/SettingsDb.d.ts.map +1 -0
  72. package/lib/esm/workspace/SettingsDb.js +16 -0
  73. package/lib/esm/workspace/SettingsDb.js.map +1 -0
  74. package/lib/esm/workspace/SettingsEditor.d.ts +246 -0
  75. package/lib/esm/workspace/SettingsEditor.d.ts.map +1 -0
  76. package/lib/esm/workspace/SettingsEditor.js +48 -0
  77. package/lib/esm/workspace/SettingsEditor.js.map +1 -0
  78. package/lib/esm/workspace/Workspace.d.ts +39 -18
  79. package/lib/esm/workspace/Workspace.d.ts.map +1 -1
  80. package/lib/esm/workspace/Workspace.js.map +1 -1
  81. package/lib/esm/workspace/WorkspaceEditor.d.ts +28 -0
  82. package/lib/esm/workspace/WorkspaceEditor.d.ts.map +1 -1
  83. package/lib/esm/workspace/WorkspaceEditor.js +17 -0
  84. package/lib/esm/workspace/WorkspaceEditor.js.map +1 -1
  85. package/package.json +13 -13
@@ -1 +1 @@
1
- {"version":3,"file":"Workspace.test.js","sourceRoot":"","sources":["../../../../src/test/standalone/Workspace.test.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\r\nimport { expect } from \"chai\";\r\nimport * as fs from \"fs-extra\";\r\nimport { extname } from \"path\";\r\nimport * as sinon from \"sinon\";\r\nimport { Guid } from \"@itwin/core-bentley\";\r\nimport { Range3d } from \"@itwin/core-geometry\";\r\nimport { SettingsPriority } from \"../../workspace/Settings\";\r\nimport { Workspace, WorkspaceContainerProps, WorkspaceDbManifest, WorkspaceDbProps } from \"../../workspace/Workspace\";\r\nimport { EditableWorkspaceDb, WorkspaceEditor } from \"../../workspace/WorkspaceEditor\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\nimport { validateWorkspaceContainerId } from \"../../internal/workspace/WorkspaceImpl\";\r\nimport { _nativeDb } from \"../../internal/Symbols\";\r\nimport { CloudSqlite } from \"../../CloudSqlite\";\r\n\r\ndescribe(\"WorkspaceFile\", () => {\r\n\r\n let editor: WorkspaceEditor;\r\n let workspace: Workspace;\r\n\r\n before(() => {\r\n editor = WorkspaceEditor.construct();\r\n workspace = editor.workspace;\r\n });\r\n after(() => {\r\n editor.close();\r\n });\r\n\r\n async function makeEditableDb(props: WorkspaceDbProps & WorkspaceContainerProps, manifest: WorkspaceDbManifest): Promise<EditableWorkspaceDb> {\r\n const container = editor.getContainer({ ...props, accessToken: \"\" });\r\n const wsFile = await container.createDb({ ...props, manifest });\r\n wsFile.open();\r\n return wsFile;\r\n }\r\n\r\n function compareFiles(file1: string, file2: string) {\r\n expect(fs.lstatSync(file1).size).equal(fs.lstatSync(file2).size);\r\n expect(fs.readFileSync(file1)).to.deep.equal(fs.readFileSync(file2));\r\n }\r\n\r\n it(\"WorkspaceContainer names\", () => {\r\n const expectBadName = (names: string[]) => {\r\n names.forEach((containerId) => {\r\n expect(() => validateWorkspaceContainerId(containerId), containerId).to.throw(\"containerId\");\r\n });\r\n };\r\n\r\n expectBadName([\r\n \"\",\r\n \" \",\r\n \"12\", // too short\r\n \"a\\\\b\",\r\n `a\"b`,\r\n \"a:b\",\r\n \"a.b\",\r\n \"a?b\",\r\n \"a*b\",\r\n \"a|b\",\r\n \"123--4\",\r\n \"Abc\",\r\n \"return\\r\",\r\n \"newline\\n\",\r\n \"a\".repeat(64), // too long\r\n \"-leading-dash\",\r\n \"trailing-dash-\"]);\r\n\r\n validateWorkspaceContainerId(Guid.createValue()); // guids should be valid\r\n });\r\n\r\n it(\"WorkspaceDbNames\", () => {\r\n const expectBadName = (names: string[]) => {\r\n names.forEach((dbName) => {\r\n expect(() => CloudSqlite.validateDbName(dbName)).to.throw(\"dbName\");\r\n });\r\n };\r\n\r\n expectBadName([\r\n \"\",\r\n \" \",\r\n \"1/2\",\r\n \"a\\\\b\",\r\n `a\"b`,\r\n \"base:1.2.3\",\r\n \"a:b\",\r\n \"a.b\",\r\n \"a?b\",\r\n \"a*b\",\r\n \"a|b\",\r\n \"con\",\r\n \"prn\",\r\n \"return\\r\",\r\n \"newline\\n\",\r\n \"a\".repeat(256), // too long\r\n \" leading space\",\r\n \"trailing space \",\r\n \"per.iod\",\r\n \"hash#tag\",\r\n \"back`tick\",\r\n \"single'quote\",\r\n ]);\r\n\r\n CloudSqlite.validateDbName(Guid.createValue()); // guids should be valid\r\n });\r\n\r\n it(\"WorkspaceDb version fallback\", () => {\r\n expect(CloudSqlite.validateDbVersion(\"\" as CloudSqlite.DbVersion)).equals(\"0.0.0\");\r\n expect(CloudSqlite.makeSemverName(\"db1\", \"\" as CloudSqlite.DbVersion)).equals(\"db1:0.0.0\");\r\n expect(() => CloudSqlite.validateDbVersion(\" \" as CloudSqlite.DbVersion)).to.throw(\"invalid version specification\");\r\n });\r\n\r\n it(\"create new WorkspaceDb\", async () => {\r\n const manifest: WorkspaceDbManifest = { workspaceName: \"resources for acme users\", contactName: \"contact me\" };\r\n const wsFile = await makeEditableDb({ containerId: \"acme-engineering-inc-2\", dbName: \"db1\", baseUri: \"\", storageType: \"azure\" }, manifest);\r\n const inFile = IModelTestUtils.resolveAssetFile(\"test.setting.json5\");\r\n const testRange = new Range3d(1.2, 2.3, 3.4, 4.5, 5.6, 6.7);\r\n let blobVal = new Uint8Array(testRange.toFloat64Array().buffer);\r\n let strVal = \"this is test1\";\r\n const strRscName = \"string-resource/1\";\r\n const blobRscName = \"blob.resource:1\";\r\n const fileRscName = \"settings files/my settings/a.json5\";\r\n\r\n let testManifest = wsFile.manifest;\r\n expect(testManifest.workspaceName).equals(manifest.workspaceName);\r\n expect(testManifest.contactName).equals(manifest.contactName);\r\n\r\n wsFile.updateManifest({ ...testManifest, contactName: \"new contact\" });\r\n testManifest = wsFile.manifest;\r\n expect(testManifest.workspaceName).equals(manifest.workspaceName);\r\n expect(testManifest.contactName).equals(\"new contact\");\r\n\r\n expect(() => wsFile.addFile(fileRscName, \"bad file name\")).to.throw(\"no such file\");\r\n expect(() => wsFile.updateFile(fileRscName, inFile)).to.throw(\"error replacing\");\r\n expect(() => wsFile.removeFile(fileRscName)).to.throw(\"does not exist\");\r\n\r\n wsFile.addBlob(blobRscName, blobVal);\r\n wsFile.addString(strRscName, strVal);\r\n expect(wsFile.getString(strRscName)).equals(strVal);\r\n expect(wsFile.getBlob(blobRscName)).to.deep.equal(blobVal);\r\n strVal = \"updated string\";\r\n blobVal = Uint8Array.from([0, 1, 2, 3]);\r\n wsFile.updateString(strRscName, strVal);\r\n wsFile.updateBlob(blobRscName, blobVal);\r\n expect(wsFile.getString(strRscName)).equals(strVal);\r\n expect(wsFile.getBlob(blobRscName)).to.deep.equal(blobVal);\r\n\r\n wsFile.removeBlob(blobRscName);\r\n wsFile.removeString(strRscName);\r\n expect(wsFile.getString(strRscName)).to.be.undefined;\r\n expect(wsFile.getBlob(blobRscName)).to.be.undefined;\r\n\r\n wsFile.addFile(fileRscName, inFile);\r\n const writeFile = sinon.spy(wsFile.sqliteDb[_nativeDb], \"extractEmbeddedFile\");\r\n expect(writeFile.callCount).eq(0);\r\n const outFile = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(1);\r\n expect(extname(outFile)).equals(\".json5\");\r\n compareFiles(inFile, outFile);\r\n\r\n let outFile2 = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(1);\r\n expect(outFile).eq(outFile2);\r\n\r\n const inFile2 = IModelTestUtils.resolveAssetFile(\"TestSettings.schema.json\");\r\n wsFile.updateFile(fileRscName, inFile2);\r\n outFile2 = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(2);\r\n expect(outFile).eq(outFile2);\r\n compareFiles(inFile2, outFile);\r\n });\r\n\r\n it(\"load workspace settings\", async () => {\r\n const settingsFile = IModelTestUtils.resolveAssetFile(\"test.setting.json5\");\r\n const defaultDb = await makeEditableDb({ containerId: \"default\", dbName: \"db1\", baseUri: \"\", storageType: \"azure\" }, { workspaceName: \"default resources\", contactName: \"contact 123\" });\r\n defaultDb.addString(\"default-settings\", fs.readFileSync(settingsFile, \"utf-8\"));\r\n defaultDb.close();\r\n\r\n const settings = workspace.settings;\r\n await workspace.loadSettingsDictionary(\r\n { dbName: \"db1\", containerId: \"default\", baseUri: \"\", storageType: \"azure\", resourceName: \"default-settings\", priority: SettingsPriority.defaults });\r\n expect(settings.getSetting(\"editor/renderWhitespace\")).equals(\"selection\");\r\n\r\n const workspaceName = \"all fonts workspace\";\r\n const schemaFile = IModelTestUtils.resolveAssetFile(\"TestSettings.schema.json\");\r\n const fontsDb = await makeEditableDb({ containerId: \"fonts\", dbName: \"fonts\", baseUri: \"\", storageType: \"azure\" }, { workspaceName, contactName: \"font guy\" });\r\n\r\n fontsDb.addFile(\"Helvetica.ttf\", schemaFile, \"ttf\");\r\n fontsDb.close();\r\n });\r\n\r\n describe(\"getContainerAsync token resolution\", () => {\r\n afterEach(() => sinon.restore());\r\n\r\n it(\"preserves an explicitly-provided accessToken\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").rejects(new Error(\"should not be called\"));\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"explicit-token-test\",\r\n baseUri: \"https://some-cloud-uri\",\r\n storageType: \"azure\",\r\n accessToken: \"my-explicit-token\",\r\n };\r\n\r\n try {\r\n await workspace.getContainerAsync(props);\r\n } catch {\r\n // expected — no real cloud endpoint\r\n }\r\n expect(requestTokenStub.called).to.be.false;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"my-explicit-token\");\r\n });\r\n\r\n it(\"uses empty token for local containers with empty baseUri\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").rejects(new Error(\"should not be called\"));\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"local-token-test\",\r\n baseUri: \"\",\r\n storageType: \"azure\",\r\n };\r\n\r\n await workspace.getContainerAsync(props);\r\n expect(requestTokenStub.called).to.be.false;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"\");\r\n });\r\n\r\n it(\"calls requestToken when no accessToken is provided for a cloud container\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").resolves(\"resolved-token\");\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"cloud-no-token-test\",\r\n baseUri: \"https://some-cloud-uri\",\r\n storageType: \"azure\",\r\n };\r\n\r\n try {\r\n await workspace.getContainerAsync(props);\r\n } catch {\r\n // expected — no real cloud endpoint\r\n }\r\n expect(requestTokenStub.calledOnce).to.be.true;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"resolved-token\");\r\n });\r\n });\r\n\r\n});\r\n"]}
1
+ {"version":3,"file":"Workspace.test.js","sourceRoot":"","sources":["../../../../src/test/standalone/Workspace.test.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\r\nimport { expect } from \"chai\";\r\nimport * as fs from \"fs-extra\";\r\nimport { extname } from \"path\";\r\nimport * as sinon from \"sinon\";\r\nimport { Guid } from \"@itwin/core-bentley\";\r\nimport { Range3d } from \"@itwin/core-geometry\";\r\nimport { SettingsPriority } from \"../../workspace/Settings\";\r\nimport { Workspace, WorkspaceContainerProps, WorkspaceDbManifest, WorkspaceDbProps } from \"../../workspace/Workspace\";\r\nimport { EditableWorkspaceDb, WorkspaceEditor } from \"../../workspace/WorkspaceEditor\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\nimport { validateWorkspaceContainerId } from \"../../internal/workspace/WorkspaceImpl\";\r\nimport { _nativeDb } from \"../../internal/Symbols\";\r\nimport { CloudSqlite } from \"../../CloudSqlite\";\r\nimport { BlobContainer } from \"../../BlobContainerService\";\r\n\r\ndescribe(\"WorkspaceFile\", () => {\r\n\r\n let editor: WorkspaceEditor;\r\n let workspace: Workspace;\r\n\r\n before(() => {\r\n editor = WorkspaceEditor.construct();\r\n workspace = editor.workspace;\r\n });\r\n after(() => {\r\n editor.close();\r\n });\r\n\r\n async function makeEditableDb(props: WorkspaceDbProps & WorkspaceContainerProps, manifest: WorkspaceDbManifest): Promise<EditableWorkspaceDb> {\r\n const container = editor.getContainer({ ...props, accessToken: \"\" });\r\n const wsFile = await container.createDb({ ...props, manifest });\r\n wsFile.open();\r\n return wsFile;\r\n }\r\n\r\n function compareFiles(file1: string, file2: string) {\r\n expect(fs.lstatSync(file1).size).equal(fs.lstatSync(file2).size);\r\n expect(fs.readFileSync(file1)).to.deep.equal(fs.readFileSync(file2));\r\n }\r\n\r\n it(\"WorkspaceContainer names\", () => {\r\n const expectBadName = (names: string[]) => {\r\n names.forEach((containerId) => {\r\n expect(() => validateWorkspaceContainerId(containerId), containerId).to.throw(\"containerId\");\r\n });\r\n };\r\n\r\n expectBadName([\r\n \"\",\r\n \" \",\r\n \"12\", // too short\r\n \"a\\\\b\",\r\n `a\"b`,\r\n \"a:b\",\r\n \"a.b\",\r\n \"a?b\",\r\n \"a*b\",\r\n \"a|b\",\r\n \"123--4\",\r\n \"Abc\",\r\n \"return\\r\",\r\n \"newline\\n\",\r\n \"a\".repeat(64), // too long\r\n \"-leading-dash\",\r\n \"trailing-dash-\"]);\r\n\r\n validateWorkspaceContainerId(Guid.createValue()); // guids should be valid\r\n });\r\n\r\n it(\"WorkspaceDbNames\", () => {\r\n const expectBadName = (names: string[]) => {\r\n names.forEach((dbName) => {\r\n expect(() => CloudSqlite.validateDbName(dbName)).to.throw(\"dbName\");\r\n });\r\n };\r\n\r\n expectBadName([\r\n \"\",\r\n \" \",\r\n \"1/2\",\r\n \"a\\\\b\",\r\n `a\"b`,\r\n \"base:1.2.3\",\r\n \"a:b\",\r\n \"a.b\",\r\n \"a?b\",\r\n \"a*b\",\r\n \"a|b\",\r\n \"con\",\r\n \"prn\",\r\n \"return\\r\",\r\n \"newline\\n\",\r\n \"a\".repeat(256), // too long\r\n \" leading space\",\r\n \"trailing space \",\r\n \"per.iod\",\r\n \"hash#tag\",\r\n \"back`tick\",\r\n \"single'quote\",\r\n ]);\r\n\r\n CloudSqlite.validateDbName(Guid.createValue()); // guids should be valid\r\n });\r\n\r\n it(\"WorkspaceDb version fallback\", () => {\r\n expect(CloudSqlite.validateDbVersion(\"\" as CloudSqlite.DbVersion)).equals(\"0.0.0\");\r\n expect(CloudSqlite.makeSemverName(\"db1\", \"\" as CloudSqlite.DbVersion)).equals(\"db1:0.0.0\");\r\n expect(() => CloudSqlite.validateDbVersion(\" \" as CloudSqlite.DbVersion)).to.throw(\"invalid version specification\");\r\n });\r\n\r\n it(\"create new WorkspaceDb\", async () => {\r\n const manifest: WorkspaceDbManifest = { workspaceName: \"resources for acme users\", contactName: \"contact me\" };\r\n const wsFile = await makeEditableDb({ containerId: \"acme-engineering-inc-2\", dbName: \"db1\", baseUri: \"\", storageType: \"azure\" }, manifest);\r\n const inFile = IModelTestUtils.resolveAssetFile(\"test.setting.json5\");\r\n const testRange = new Range3d(1.2, 2.3, 3.4, 4.5, 5.6, 6.7);\r\n let blobVal = new Uint8Array(testRange.toFloat64Array().buffer);\r\n let strVal = \"this is test1\";\r\n const strRscName = \"string-resource/1\";\r\n const blobRscName = \"blob.resource:1\";\r\n const fileRscName = \"settings files/my settings/a.json5\";\r\n\r\n let testManifest = wsFile.manifest;\r\n expect(testManifest.workspaceName).equals(manifest.workspaceName);\r\n expect(testManifest.contactName).equals(manifest.contactName);\r\n\r\n wsFile.updateManifest({ ...testManifest, contactName: \"new contact\" });\r\n testManifest = wsFile.manifest;\r\n expect(testManifest.workspaceName).equals(manifest.workspaceName);\r\n expect(testManifest.contactName).equals(\"new contact\");\r\n\r\n expect(() => wsFile.addFile(fileRscName, \"bad file name\")).to.throw(\"no such file\");\r\n expect(() => wsFile.updateFile(fileRscName, inFile)).to.throw(\"error replacing\");\r\n expect(() => wsFile.removeFile(fileRscName)).to.throw(\"does not exist\");\r\n\r\n wsFile.addBlob(blobRscName, blobVal);\r\n wsFile.addString(strRscName, strVal);\r\n expect(wsFile.getString(strRscName)).equals(strVal);\r\n expect(wsFile.getBlob(blobRscName)).to.deep.equal(blobVal);\r\n strVal = \"updated string\";\r\n blobVal = Uint8Array.from([0, 1, 2, 3]);\r\n wsFile.updateString(strRscName, strVal);\r\n wsFile.updateBlob(blobRscName, blobVal);\r\n expect(wsFile.getString(strRscName)).equals(strVal);\r\n expect(wsFile.getBlob(blobRscName)).to.deep.equal(blobVal);\r\n\r\n wsFile.removeBlob(blobRscName);\r\n wsFile.removeString(strRscName);\r\n expect(wsFile.getString(strRscName)).to.be.undefined;\r\n expect(wsFile.getBlob(blobRscName)).to.be.undefined;\r\n\r\n wsFile.addFile(fileRscName, inFile);\r\n const writeFile = sinon.spy(wsFile.sqliteDb[_nativeDb], \"extractEmbeddedFile\");\r\n expect(writeFile.callCount).eq(0);\r\n const outFile = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(1);\r\n expect(extname(outFile)).equals(\".json5\");\r\n compareFiles(inFile, outFile);\r\n\r\n let outFile2 = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(1);\r\n expect(outFile).eq(outFile2);\r\n\r\n const inFile2 = IModelTestUtils.resolveAssetFile(\"TestSettings.schema.json\");\r\n wsFile.updateFile(fileRscName, inFile2);\r\n outFile2 = wsFile.getFile(fileRscName)!;\r\n expect(writeFile.callCount).eq(2);\r\n expect(outFile).eq(outFile2);\r\n compareFiles(inFile2, outFile);\r\n });\r\n\r\n it(\"load workspace settings\", async () => {\r\n const settingsFile = IModelTestUtils.resolveAssetFile(\"test.setting.json5\");\r\n const defaultDb = await makeEditableDb({ containerId: \"default\", dbName: \"db1\", baseUri: \"\", storageType: \"azure\" }, { workspaceName: \"default resources\", contactName: \"contact 123\" });\r\n defaultDb.addString(\"default-settings\", fs.readFileSync(settingsFile, \"utf-8\"));\r\n defaultDb.close();\r\n\r\n const settings = workspace.settings;\r\n await workspace.loadSettingsDictionary(\r\n { dbName: \"db1\", containerId: \"default\", baseUri: \"\", storageType: \"azure\", resourceName: \"default-settings\", priority: SettingsPriority.defaults });\r\n expect(settings.getSetting(\"editor/renderWhitespace\")).equals(\"selection\");\r\n\r\n const workspaceName = \"all fonts workspace\";\r\n const schemaFile = IModelTestUtils.resolveAssetFile(\"TestSettings.schema.json\");\r\n const fontsDb = await makeEditableDb({ containerId: \"fonts\", dbName: \"fonts\", baseUri: \"\", storageType: \"azure\" }, { workspaceName, contactName: \"font guy\" });\r\n\r\n fontsDb.addFile(\"Helvetica.ttf\", schemaFile, \"ttf\");\r\n fontsDb.close();\r\n });\r\n\r\n describe(\"getContainerAsync token resolution\", () => {\r\n afterEach(() => sinon.restore());\r\n\r\n it(\"preserves an explicitly-provided accessToken\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").rejects(new Error(\"should not be called\"));\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"explicit-token-test\",\r\n baseUri: \"https://some-cloud-uri\",\r\n storageType: \"azure\",\r\n accessToken: \"my-explicit-token\",\r\n };\r\n\r\n try {\r\n await workspace.getContainerAsync(props);\r\n } catch {\r\n // expected — no real cloud endpoint\r\n }\r\n expect(requestTokenStub.called).to.be.false;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"my-explicit-token\");\r\n });\r\n\r\n it(\"uses empty token for local containers with empty baseUri\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").rejects(new Error(\"should not be called\"));\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"local-token-test\",\r\n baseUri: \"\",\r\n storageType: \"azure\",\r\n };\r\n\r\n await workspace.getContainerAsync(props);\r\n expect(requestTokenStub.called).to.be.false;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"\");\r\n });\r\n\r\n it(\"calls requestToken when no accessToken is provided for a cloud container\", async () => {\r\n const requestTokenStub = sinon.stub(CloudSqlite, \"requestToken\").resolves(\"resolved-token\");\r\n const getContainerSpy = sinon.spy(workspace, \"getContainer\");\r\n const props: WorkspaceContainerProps = {\r\n containerId: \"cloud-no-token-test\",\r\n baseUri: \"https://some-cloud-uri\",\r\n storageType: \"azure\",\r\n };\r\n\r\n try {\r\n await workspace.getContainerAsync(props);\r\n } catch {\r\n // expected — no real cloud endpoint\r\n }\r\n expect(requestTokenStub.calledOnce).to.be.true;\r\n expect(getContainerSpy.calledOnce).to.be.true;\r\n expect(getContainerSpy.firstCall.args[0].accessToken).to.equal(\"resolved-token\");\r\n });\r\n });\r\n\r\n describe(\"findContainers\", () => {\r\n const testContainerId = \"mock-workspace-container-id\";\r\n const testITwinId = \"mock-itwin-id\";\r\n const testIModelId = \"mock-imodel-id\";\r\n let savedService: BlobContainer.ContainerService | undefined;\r\n\r\n function createMockService(containers: BlobContainer.MetadataResponse[]): BlobContainer.ContainerService {\r\n return {\r\n create: async () => ({ containerId: testContainerId, baseUri: \"https://mock.blob.core/\", provider: \"azure\" as const }),\r\n delete: async () => {},\r\n queryScope: async () => ({ iTwinId: testITwinId }),\r\n queryMetadata: async () => ({ containerType: \"workspace\", label: \"mock\" }),\r\n queryContainersMetadata: async (_userToken, args) => {\r\n return containers.filter((c) =>\r\n (args.containerType === undefined || c.containerType === args.containerType) &&\r\n (args.iTwinId === testITwinId || args.iTwinId === undefined),\r\n );\r\n },\r\n updateJson: async () => {},\r\n requestToken: async (_props) => ({\r\n token: \"\",\r\n scope: { iTwinId: testITwinId },\r\n provider: \"azure\" as const,\r\n expiration: new Date(Date.now() + 3600000),\r\n metadata: { containerType: \"workspace\", label: \"mock\" },\r\n baseUri: \"\",\r\n }),\r\n };\r\n }\r\n\r\n before(() => {\r\n savedService = BlobContainer.service;\r\n });\r\n\r\n afterEach(() => {\r\n BlobContainer.service = savedService;\r\n });\r\n\r\n it(\"finds containers by iTwinId\", async () => {\r\n BlobContainer.service = createMockService([\r\n { containerId: testContainerId, containerType: \"workspace\", label: \"Test Workspace\" },\r\n ]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: testITwinId });\r\n expect(containers).to.have.length(1);\r\n expect(containers[0].fromProps.containerId).to.equal(testContainerId);\r\n });\r\n\r\n it(\"finds a container by iTwinId and iModelId\", async () => {\r\n BlobContainer.service = createMockService([\r\n { containerId: \"imodel-scoped-container\", containerType: \"workspace\", label: \"iModel Workspace\" },\r\n ]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: testITwinId, iModelId: testIModelId });\r\n expect(containers).to.have.length(1);\r\n expect(containers[0].fromProps.containerId).to.equal(\"imodel-scoped-container\");\r\n });\r\n\r\n it(\"returns empty array when no workspace containers are found\", async () => {\r\n BlobContainer.service = createMockService([]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: \"nonexistent-itwin\" });\r\n expect(containers).to.have.length(0);\r\n });\r\n\r\n it(\"throws when BlobContainer.service is not available\", async () => {\r\n BlobContainer.service = undefined;\r\n\r\n await expect(editor.findContainers({ iTwinId: testITwinId }))\r\n .to.be.rejectedWith(/BlobContainer.service is not available/);\r\n });\r\n });\r\n\r\n});\r\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SettingsDb.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SettingsDb.test.d.ts","sourceRoot":"","sources":["../../../../src/test/workspace/SettingsDb.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,372 @@
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
+ import { expect } from "chai";
6
+ import { WorkspaceError } from "@itwin/core-common";
7
+ import { IModelHost } from "../../IModelHost";
8
+ import { SettingsPriority } from "../../workspace/Settings";
9
+ import { SettingsEditor } from "../../workspace/SettingsEditor";
10
+ import { SettingsDbImpl } from "../../internal/workspace/SettingsDbImpl";
11
+ import { BlobContainer } from "../../BlobContainerService";
12
+ describe("SettingsDb", () => {
13
+ let editor;
14
+ before(async () => {
15
+ await IModelHost.startup();
16
+ editor = SettingsEditor.construct();
17
+ });
18
+ after(() => {
19
+ editor.close();
20
+ });
21
+ function getContainer(containerId) {
22
+ return editor.getContainer({ containerId, baseUri: "", storageType: "azure", accessToken: "" });
23
+ }
24
+ it("SettingsDbImpl construction", async () => {
25
+ const container = getContainer("construct-test");
26
+ await container.createDb({ dbName: "test-db", manifest: { settingsName: "construct-test" } });
27
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
28
+ expect(settingsDb.dbName).to.equal("test-db");
29
+ expect(settingsDb.priority).to.equal(SettingsPriority.application);
30
+ expect(settingsDb.isOpen).to.be.false;
31
+ expect(settingsDb.container).to.equal(container);
32
+ expect(settingsDb.version).to.equal("0.0.0");
33
+ });
34
+ it("open and close", async () => {
35
+ const container = getContainer("open-close-test");
36
+ await container.createDb({ dbName: "test-db", manifest: { settingsName: "open-close-test" } });
37
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
38
+ expect(settingsDb.isOpen).to.be.false;
39
+ settingsDb.open();
40
+ expect(settingsDb.isOpen).to.be.true;
41
+ settingsDb.close();
42
+ expect(settingsDb.isOpen).to.be.false;
43
+ // closing an already-closed db is safe
44
+ settingsDb.close();
45
+ expect(settingsDb.isOpen).to.be.false;
46
+ });
47
+ it("getSetting reads a written setting", async () => {
48
+ const container = getContainer("get-setting-test");
49
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "get-setting-test" } });
50
+ editableDb.open();
51
+ editableDb.updateSettings({
52
+ "setting1": "value1",
53
+ "setting2": 42,
54
+ "setting3": true,
55
+ });
56
+ editableDb.close();
57
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.iTwin);
58
+ settingsDb.open();
59
+ expect(settingsDb.getSetting("setting1")).to.equal("value1");
60
+ expect(settingsDb.getSetting("setting2")).to.equal(42);
61
+ expect(settingsDb.getSetting("setting3")).to.equal(true);
62
+ settingsDb.close();
63
+ });
64
+ it("getSettings reads all settings", async () => {
65
+ const container = getContainer("get-settings-test");
66
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "get-settings-test" } });
67
+ editableDb.open();
68
+ editableDb.updateSettings({
69
+ "keyA": "valA",
70
+ "keyB": 100,
71
+ "keyC": [1, 2, 3],
72
+ });
73
+ editableDb.close();
74
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.organization);
75
+ settingsDb.open();
76
+ const all = settingsDb.getSettings();
77
+ expect(all.keyA).to.equal("valA");
78
+ expect(all.keyB).to.equal(100);
79
+ expect(all.keyC).to.deep.equal([1, 2, 3]);
80
+ settingsDb.close();
81
+ });
82
+ it("getSetting returns undefined for non-existent setting", async () => {
83
+ const container = getContainer("no-setting-test");
84
+ await container.createDb({ dbName: "test-db", manifest: { settingsName: "no-setting-test" } });
85
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.defaults);
86
+ settingsDb.open();
87
+ expect(settingsDb.getSetting("nonExistentSetting")).to.be.undefined;
88
+ settingsDb.close();
89
+ });
90
+ it("manifest reads stored manifest", async () => {
91
+ const container = getContainer("manifest-test");
92
+ await container.createDb({
93
+ dbName: "test-db",
94
+ manifest: { settingsName: "My Settings DB", description: "A test settings database" },
95
+ });
96
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
97
+ // manifest auto-opens the db via withOpenDb when not explicitly opened
98
+ const manifest = settingsDb.manifest;
99
+ expect(manifest.settingsName).to.equal("My Settings DB");
100
+ expect(manifest.description).to.equal("A test settings database");
101
+ expect(settingsDb.isOpen).to.be.false;
102
+ });
103
+ it("getSetting auto-opens and auto-closes when db is not open", async () => {
104
+ const container = getContainer("auto-open-test");
105
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "auto-open-test" } });
106
+ editableDb.open();
107
+ editableDb.updateSettings({ "key": "auto-value" });
108
+ editableDb.close();
109
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
110
+ expect(settingsDb.isOpen).to.be.false;
111
+ // getSetting should auto-open, read, and auto-close
112
+ expect(settingsDb.getSetting("key")).to.equal("auto-value");
113
+ expect(settingsDb.isOpen).to.be.false;
114
+ });
115
+ it("removeSetting removes a setting", async () => {
116
+ const container = getContainer("remove-setting-test");
117
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "remove-setting-test" } });
118
+ editableDb.open();
119
+ editableDb.updateSettings({ "toKeep": 1, "toRemove": 2 });
120
+ editableDb.close();
121
+ // Verify both exist
122
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
123
+ settingsDb.open();
124
+ expect(settingsDb.getSetting("toKeep")).to.equal(1);
125
+ expect(settingsDb.getSetting("toRemove")).to.equal(2);
126
+ settingsDb.close();
127
+ // Remove one
128
+ editableDb.open();
129
+ editableDb.removeSetting("toRemove");
130
+ editableDb.close();
131
+ // Verify only one remains
132
+ settingsDb.open();
133
+ const all = settingsDb.getSettings();
134
+ expect(all.toKeep).to.equal(1);
135
+ expect(all.toRemove).to.be.undefined;
136
+ expect(settingsDb.getSetting("toRemove")).to.be.undefined;
137
+ settingsDb.close();
138
+ });
139
+ it("close updates lastEditedBy in manifest when write lock is held", async () => {
140
+ const container = getContainer("manifest-update-test");
141
+ const editableDb = await container.createDb({
142
+ dbName: "test-db",
143
+ manifest: { settingsName: "manifest-update-test", contactName: "Original Author" },
144
+ });
145
+ // For local (non-cloud) containers, acquireWriteLock is a no-op,
146
+ // so lastEditedBy should remain unchanged after close.
147
+ container.acquireWriteLock("Jane Admin");
148
+ editableDb.open();
149
+ editableDb.updateSettings({ "key": "value" });
150
+ editableDb.close();
151
+ container.releaseWriteLock();
152
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
153
+ const manifest = settingsDb.manifest;
154
+ expect(manifest.settingsName).to.equal("manifest-update-test");
155
+ expect(manifest.contactName).to.equal("Original Author");
156
+ // lastEditedBy is only auto-set for cloud containers (where acquireWriteLock actually tracks the user)
157
+ expect(manifest.lastEditedBy).to.be.undefined;
158
+ });
159
+ it("getSettingsDb returns a SettingsDb from a loaded container", async () => {
160
+ const container = getContainer("getsettingsdb-test");
161
+ await container.createDb({ dbName: "settings-db", manifest: { settingsName: "getsettingsdb-test" } });
162
+ const settingsDb = editor.workspace.getSettingsDb({ containerId: "getsettingsdb-test", priority: SettingsPriority.iTwin });
163
+ expect(settingsDb).to.not.be.undefined;
164
+ expect(settingsDb.dbName).to.equal("settings-db");
165
+ expect(settingsDb.manifest.settingsName).to.equal("getsettingsdb-test");
166
+ });
167
+ it("getSettingsDb throws for unloaded container", () => {
168
+ expect(() => editor.workspace.getSettingsDb({ containerId: "nonexistent-container-id", priority: SettingsPriority.iTwin }))
169
+ .to.throw()
170
+ .and.satisfy((e) => WorkspaceError.isError(e, "does-not-exist"));
171
+ });
172
+ it("getSettingsDb uses caller-supplied priority", async () => {
173
+ const container = getContainer("imodel-scope-test");
174
+ await container.createDb({ dbName: "settings-db", manifest: { settingsName: "imodel-scope-test" } });
175
+ const settingsDb = editor.workspace.getSettingsDb({ containerId: "imodel-scope-test", priority: SettingsPriority.iModel });
176
+ expect(settingsDb).to.not.be.undefined;
177
+ expect(settingsDb.priority).to.equal(SettingsPriority.iModel);
178
+ });
179
+ it("getSettingsDb respects iTwin priority", async () => {
180
+ const container = getContainer("itwin-priority-test");
181
+ await container.createDb({ dbName: "settings-db", manifest: { settingsName: "itwin-priority-test" } });
182
+ const settingsDb = editor.workspace.getSettingsDb({ containerId: "itwin-priority-test", priority: SettingsPriority.iTwin });
183
+ expect(settingsDb.priority).to.equal(SettingsPriority.iTwin);
184
+ });
185
+ it("hasSettingsManifestProperty returns true for SettingsDb containers", async () => {
186
+ const container = getContainer("has-manifest-test");
187
+ await container.createDb({ dbName: "settings-db", manifest: { settingsName: "has-manifest-test" } });
188
+ const settingsDb = new SettingsDbImpl({ dbName: "settings-db" }, container, SettingsPriority.application);
189
+ expect(settingsDb.hasSettingsManifestProperty).to.be.true;
190
+ });
191
+ it("getSetting returns undefined on empty db", async () => {
192
+ const container = getContainer("missing-setting-test");
193
+ await container.createDb({ dbName: "test-db", manifest: { settingsName: "missing-setting-test" } });
194
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
195
+ settingsDb.open();
196
+ expect(settingsDb.getSetting("does-not-exist")).to.be.undefined;
197
+ settingsDb.close();
198
+ });
199
+ it("editor close is resilient to container cleanup failures", () => {
200
+ // Verify that closing an editor with no containers doesn't throw
201
+ const freshEditor = SettingsEditor.construct();
202
+ expect(() => freshEditor.close()).to.not.throw();
203
+ });
204
+ it("getSettingsDb with custom dbName", async () => {
205
+ const container = getContainer("custom-dbname-test");
206
+ await container.createDb({ dbName: "my-custom-db", manifest: { settingsName: "custom-dbname" } });
207
+ const settingsDb = editor.workspace.getSettingsDb({ containerId: "custom-dbname-test", priority: SettingsPriority.application, dbName: "my-custom-db" });
208
+ expect(settingsDb.dbName).to.equal("my-custom-db");
209
+ });
210
+ it("iTwin and iModel settings containers coexist with correct priorities", async () => {
211
+ // Simulate the real scenario: an iTwin has its own settings container, and one of its
212
+ // iModels also has a settings container. Both are loaded into the workspace with separate
213
+ // containerId GUIDs (assigned by the storage container service) and different priorities.
214
+ const itwinContainer = getContainer("itwin-container-guid");
215
+ const imodelContainer = getContainer("imodel-container-guid");
216
+ const itwinDb = await itwinContainer.createDb({ dbName: "settings-db", manifest: { settingsName: "iTwin Settings" } });
217
+ const imodelDb = await imodelContainer.createDb({ dbName: "settings-db", manifest: { settingsName: "iModel Settings" } });
218
+ // Write the same setting name to both, with different values
219
+ itwinDb.open();
220
+ itwinDb.updateSettings({ "theme": "light", "itwinOnly": true });
221
+ itwinDb.close();
222
+ imodelDb.open();
223
+ imodelDb.updateSettings({ "theme": "dark", "imodelOnly": true });
224
+ imodelDb.close();
225
+ // Retrieve both via getSettingsDb with the priorities a real caller would assign
226
+ const itwinSettingsDb = editor.workspace.getSettingsDb({ containerId: "itwin-container-guid", priority: SettingsPriority.iTwin });
227
+ const imodelSettingsDb = editor.workspace.getSettingsDb({ containerId: "imodel-container-guid", priority: SettingsPriority.iModel });
228
+ // Verify they are independent dbs with correct priorities
229
+ expect(itwinSettingsDb.priority).to.equal(SettingsPriority.iTwin);
230
+ expect(imodelSettingsDb.priority).to.equal(SettingsPriority.iModel);
231
+ expect(imodelSettingsDb.priority).to.be.greaterThan(itwinSettingsDb.priority);
232
+ // Verify each db returns its own setting values
233
+ expect(itwinSettingsDb.getSetting("theme")).to.equal("light");
234
+ expect(itwinSettingsDb.getSetting("itwinOnly")).to.equal(true);
235
+ expect(imodelSettingsDb.getSetting("theme")).to.equal("dark");
236
+ expect(imodelSettingsDb.getSetting("imodelOnly")).to.equal(true);
237
+ });
238
+ it("SettingsEditor uses a separate cloud cache from the read-only Workspace", () => {
239
+ const editorCache = editor.workspace.getCloudCache();
240
+ const workspaceCache = IModelHost.appWorkspace.getCloudCache();
241
+ expect(editorCache.name).to.equal("SettingsEditor");
242
+ expect(workspaceCache.name).to.equal("Workspace");
243
+ expect(editorCache).to.not.equal(workspaceCache);
244
+ });
245
+ describe("findContainers", () => {
246
+ const testContainerId = "mock-settings-container-id";
247
+ const testITwinId = "mock-itwin-id";
248
+ const testIModelId = "mock-imodel-id";
249
+ let savedService;
250
+ function createMockService(containers) {
251
+ return {
252
+ create: async () => ({ containerId: testContainerId, baseUri: "https://mock.blob.core/", provider: "azure" }),
253
+ delete: async () => { },
254
+ queryScope: async () => ({ iTwinId: testITwinId }),
255
+ queryMetadata: async () => ({ containerType: "settings", label: "mock" }),
256
+ queryContainersMetadata: async (_userToken, args) => {
257
+ // Filter by containerType and iTwinId like the real service would
258
+ return containers.filter((c) => (args.containerType === undefined || c.containerType === args.containerType) &&
259
+ (args.iTwinId === testITwinId || args.iTwinId === undefined));
260
+ },
261
+ updateJson: async () => { },
262
+ requestToken: async (_props) => ({
263
+ token: "",
264
+ scope: { iTwinId: testITwinId },
265
+ provider: "azure",
266
+ expiration: new Date(Date.now() + 3600000),
267
+ metadata: { containerType: "settings", label: "mock" },
268
+ baseUri: "",
269
+ }),
270
+ };
271
+ }
272
+ before(() => {
273
+ savedService = BlobContainer.service;
274
+ });
275
+ afterEach(() => {
276
+ BlobContainer.service = savedService;
277
+ });
278
+ it("finds containers by iTwinId", async () => {
279
+ BlobContainer.service = createMockService([
280
+ { containerId: testContainerId, containerType: "settings", label: "Test Settings" },
281
+ ]);
282
+ const containers = await editor.findContainers({ iTwinId: testITwinId });
283
+ expect(containers).to.have.length(1);
284
+ expect(containers[0].fromProps.containerId).to.equal(testContainerId);
285
+ });
286
+ it("finds a container by iTwinId and iModelId", async () => {
287
+ BlobContainer.service = createMockService([
288
+ { containerId: "imodel-scoped-container", containerType: "settings", label: "iModel Settings" },
289
+ ]);
290
+ const containers = await editor.findContainers({ iTwinId: testITwinId, iModelId: testIModelId });
291
+ expect(containers).to.have.length(1);
292
+ expect(containers[0].fromProps.containerId).to.equal("imodel-scoped-container");
293
+ });
294
+ it("returns empty array when no settings containers are found", async () => {
295
+ BlobContainer.service = createMockService([]);
296
+ const containers = await editor.findContainers({ iTwinId: "nonexistent-itwin" });
297
+ expect(containers).to.have.length(0);
298
+ });
299
+ it("throws when BlobContainer.service is not available", async () => {
300
+ BlobContainer.service = undefined;
301
+ await expect(editor.findContainers({ iTwinId: testITwinId }))
302
+ .to.be.rejectedWith(/BlobContainer.service is not available/);
303
+ });
304
+ });
305
+ describe("getSettings", () => {
306
+ it("returns a deep copy of all settings", async () => {
307
+ const container = getContainer("getsettings-deep-copy-test");
308
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "getsettings-deep-copy-test" } });
309
+ editableDb.open();
310
+ editableDb.updateSettings({
311
+ "theme": "dark",
312
+ "fontSize": 14,
313
+ "nested": { "a": 1, "b": [2, 3] },
314
+ });
315
+ editableDb.close();
316
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
317
+ const all = settingsDb.getSettings();
318
+ expect(all).to.deep.equal({ "theme": "dark", "fontSize": 14, "nested": { "a": 1, "b": [2, 3] } });
319
+ // Mutating the copy should not affect the stored settings
320
+ all.theme = "light";
321
+ all.nested.a = 999;
322
+ expect(settingsDb.getSetting("theme")).to.equal("dark");
323
+ expect(settingsDb.getSetting("nested")).to.deep.equal({ "a": 1, "b": [2, 3] });
324
+ });
325
+ it("returns empty object for empty db", async () => {
326
+ const container = getContainer("getsettings-empty-test");
327
+ await container.createDb({ dbName: "test-db", manifest: { settingsName: "getsettings-empty-test" } });
328
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
329
+ expect(settingsDb.getSettings()).to.deep.equal({});
330
+ });
331
+ });
332
+ describe("updateSetting", () => {
333
+ it("adds a setting to an empty db", async () => {
334
+ const container = getContainer("updatesetting-new-test");
335
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "updatesetting-new-test" } });
336
+ editableDb.open();
337
+ editableDb.updateSetting({ settingName: "myKey", value: "myValue" });
338
+ editableDb.close();
339
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
340
+ expect(settingsDb.getSetting("myKey")).to.equal("myValue");
341
+ });
342
+ it("patches existing settings without losing other keys", async () => {
343
+ const container = getContainer("updatesetting-patch-test");
344
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "updatesetting-patch-test" } });
345
+ editableDb.open();
346
+ editableDb.updateSettings({
347
+ "theme": "light",
348
+ "fontSize": 12,
349
+ "showGrid": true,
350
+ });
351
+ // Patch just one key
352
+ editableDb.updateSetting({ settingName: "theme", value: "dark" });
353
+ editableDb.close();
354
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
355
+ expect(settingsDb.getSetting("theme")).to.equal("dark");
356
+ expect(settingsDb.getSetting("fontSize")).to.equal(12);
357
+ expect(settingsDb.getSetting("showGrid")).to.equal(true);
358
+ });
359
+ it("adds a new key to existing settings", async () => {
360
+ const container = getContainer("updatesetting-addkey-test");
361
+ const editableDb = await container.createDb({ dbName: "test-db", manifest: { settingsName: "updatesetting-addkey-test" } });
362
+ editableDb.open();
363
+ editableDb.updateSettings({ "existing": "value" });
364
+ editableDb.updateSetting({ settingName: "newKey", value: 42 });
365
+ editableDb.close();
366
+ const settingsDb = new SettingsDbImpl({ dbName: "test-db" }, container, SettingsPriority.application);
367
+ expect(settingsDb.getSetting("existing")).to.equal("value");
368
+ expect(settingsDb.getSetting("newKey")).to.equal(42);
369
+ });
370
+ });
371
+ });
372
+ //# sourceMappingURL=SettingsDb.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SettingsDb.test.js","sourceRoot":"","sources":["../../../../src/test/workspace/SettingsDb.test.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAE/F,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAkC,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,MAAsB,CAAC;IAE3B,MAAM,CAAC,KAAK,IAAI,EAAE;QAChB,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;QAC3B,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,WAAmB;QACvC,OAAO,MAAM,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,SAAS,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAE9F,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QACtC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE/F,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAEtC,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAErC,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAEtC,uCAAuC;QACvC,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,SAAS,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEnH,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,cAAc,CAAC;YACxB,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,EAAE;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAChG,UAAU,CAAC,IAAI,EAAE,CAAC;QAElB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,UAAU,CAAC,UAAU,CAAU,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElE,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,SAAS,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAEpH,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,cAAc,CAAC;YACxB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG;YACX,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAClB,CAAC,CAAC;QACH,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;QACvG,UAAU,CAAC,IAAI,EAAE,CAAC;QAElB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1C,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE/F,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACnG,UAAU,CAAC,IAAI,EAAE,CAAC;QAElB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;QAEpE,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,SAAS,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QAChD,MAAM,SAAS,CAAC,QAAQ,CAAC;YACvB,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,0BAA0B,EAAE;SACtF,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAEtG,uEAAuE;QACvE,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACrC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAClE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,SAAS,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAEjH,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QACnD,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAEtC,oDAAoD;QACpD,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACpE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,SAAS,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;QAEtH,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1D,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,oBAAoB;QACpB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtD,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,aAAa;QACb,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACrC,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,0BAA0B;QAC1B,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;QAC1D,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,SAAS,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;YAC1C,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,EAAE,YAAY,EAAE,sBAAsB,EAAE,WAAW,EAAE,iBAAiB,EAAE;SACnF,CAAC,CAAC;QAEH,iEAAiE;QACjE,uDAAuD;QACvD,SAAS,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QACzC,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9C,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAE7B,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACrC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC/D,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACzD,uGAAuG;QACvG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,SAAS,GAAG,YAAY,CAAC,oBAAoB,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAC;QAEtG,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3H,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC;QACvC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,0BAA0B,EAAE,QAAQ,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;aACxH,EAAE,CAAC,KAAK,EAAE;aACV,GAAG,CAAC,OAAO,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,SAAS,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAErG,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3H,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC;QACvC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,SAAS,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QACtD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;QAEvG,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5H,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,SAAS,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAErG,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC1G,MAAM,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,SAAS,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;QACvD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAEpG,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtG,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;QAChE,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,iEAAiE;QACjE,MAAM,WAAW,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,SAAS,GAAG,YAAY,CAAC,oBAAoB,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;QAElG,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;QACzJ,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,sFAAsF;QACtF,0FAA0F;QAC1F,0FAA0F;QAC1F,MAAM,cAAc,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;QAC5D,MAAM,eAAe,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAC;QAE9D,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;QACvH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAE1H,6DAA6D;QAC7D,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,EAAE,CAAC;QAEhB,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEjB,iFAAiF;QACjF,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,sBAAsB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;QAClI,MAAM,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,uBAAuB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;QAErI,0DAA0D;QAC1D,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAE9E,gDAAgD;QAChD,MAAM,CAAC,eAAe,CAAC,UAAU,CAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtE,MAAM,CAAC,eAAe,CAAC,UAAU,CAAU,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExE,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtE,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAU,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC;QACrD,MAAM,cAAc,GAAG,UAAU,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC;QAC/D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,MAAM,eAAe,GAAG,4BAA4B,CAAC;QACrD,MAAM,WAAW,GAAG,eAAe,CAAC;QACpC,MAAM,YAAY,GAAG,gBAAgB,CAAC;QACtC,IAAI,YAAwD,CAAC;QAE7D,SAAS,iBAAiB,CAAC,UAA4C;YACrE,OAAO;gBACL,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,yBAAyB,EAAE,QAAQ,EAAE,OAAgB,EAAE,CAAC;gBACtH,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;gBACtB,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;gBAClD,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;gBACzE,uBAAuB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;oBAClD,kEAAkE;oBAClE,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7B,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,aAAa,CAAC;wBAC5E,CAAC,IAAI,CAAC,OAAO,KAAK,WAAW,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAC7D,CAAC;gBACJ,CAAC;gBACD,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;gBAC1B,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;oBAC/B,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;oBAC/B,QAAQ,EAAE,OAAgB;oBAC1B,UAAU,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;oBAC1C,QAAQ,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;oBACtD,OAAO,EAAE,EAAE;iBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,GAAG,EAAE;YACV,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,aAAa,CAAC,OAAO,GAAG,YAAY,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;YAC3C,aAAa,CAAC,OAAO,GAAG,iBAAiB,CAAC;gBACxC,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE;aACpF,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,aAAa,CAAC,OAAO,GAAG,iBAAiB,CAAC;gBACxC,EAAE,WAAW,EAAE,yBAAyB,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,iBAAiB,EAAE;aAChG,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;YACjG,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,aAAa,CAAC,OAAO,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;YAE9C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACjF,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC;YAElC,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;iBAC1D,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,wCAAwC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,SAAS,GAAG,YAAY,CAAC,4BAA4B,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC;YAE7H,UAAU,CAAC,IAAI,EAAE,CAAC;YAClB,UAAU,CAAC,cAAc,CAAC;gBACxB,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;gBACd,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;aAClC,CAAC,CAAC;YACH,UAAU,CAAC,KAAK,EAAE,CAAC;YAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACtG,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAElG,0DAA0D;YACzD,GAAW,CAAC,KAAK,GAAG,OAAO,CAAC;YAC5B,GAAW,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC;YAC5B,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAgB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,SAAS,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;YACzD,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC;YAEtG,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACtG,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC;YAEzH,UAAU,CAAC,IAAI,EAAE,CAAC;YAClB,UAAU,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACrE,UAAU,CAAC,KAAK,EAAE,CAAC;YAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACtG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,SAAS,GAAG,YAAY,CAAC,0BAA0B,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,0BAA0B,EAAE,EAAE,CAAC,CAAC;YAE3H,UAAU,CAAC,IAAI,EAAE,CAAC;YAClB,UAAU,CAAC,cAAc,CAAC;gBACxB,OAAO,EAAE,OAAO;gBAChB,UAAU,EAAE,EAAE;gBACd,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;YAEH,qBAAqB;YACrB,UAAU,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAClE,UAAU,CAAC,KAAK,EAAE,CAAC;YAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACtG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/D,MAAM,CAAC,UAAU,CAAC,UAAU,CAAU,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,SAAS,GAAG,YAAY,CAAC,2BAA2B,CAAC,CAAC;YAC5D,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,2BAA2B,EAAE,EAAE,CAAC,CAAC;YAE5H,UAAU,CAAC,IAAI,EAAE,CAAC;YAClB,UAAU,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;YAEnD,UAAU,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAC/D,UAAU,CAAC,KAAK,EAAE,CAAC;YAEnB,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACtG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","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\r\nimport { expect } from \"chai\";\r\nimport { WorkspaceError } from \"@itwin/core-common\";\r\nimport { IModelHost } from \"../../IModelHost\";\r\nimport { SettingsPriority } from \"../../workspace/Settings\";\r\nimport { EditableSettingsCloudContainer, SettingsEditor } from \"../../workspace/SettingsEditor\";\r\nimport { SettingsDbImpl } from \"../../internal/workspace/SettingsDbImpl\";\r\nimport { BlobContainer } from \"../../BlobContainerService\";\r\n\r\ndescribe(\"SettingsDb\", () => {\r\n let editor: SettingsEditor;\r\n\r\n before(async () => {\r\n await IModelHost.startup();\r\n editor = SettingsEditor.construct();\r\n });\r\n\r\n after(() => {\r\n editor.close();\r\n });\r\n\r\n function getContainer(containerId: string): EditableSettingsCloudContainer {\r\n return editor.getContainer({ containerId, baseUri: \"\", storageType: \"azure\", accessToken: \"\" });\r\n }\r\n\r\n it(\"SettingsDbImpl construction\", async () => {\r\n const container = getContainer(\"construct-test\");\r\n await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"construct-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.dbName).to.equal(\"test-db\");\r\n expect(settingsDb.priority).to.equal(SettingsPriority.application);\r\n expect(settingsDb.isOpen).to.be.false;\r\n expect(settingsDb.container).to.equal(container);\r\n expect(settingsDb.version).to.equal(\"0.0.0\");\r\n });\r\n\r\n it(\"open and close\", async () => {\r\n const container = getContainer(\"open-close-test\");\r\n await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"open-close-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.isOpen).to.be.false;\r\n\r\n settingsDb.open();\r\n expect(settingsDb.isOpen).to.be.true;\r\n\r\n settingsDb.close();\r\n expect(settingsDb.isOpen).to.be.false;\r\n\r\n // closing an already-closed db is safe\r\n settingsDb.close();\r\n expect(settingsDb.isOpen).to.be.false;\r\n });\r\n\r\n it(\"getSetting reads a written setting\", async () => {\r\n const container = getContainer(\"get-setting-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"get-setting-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({\r\n \"setting1\": \"value1\",\r\n \"setting2\": 42,\r\n \"setting3\": true,\r\n });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.iTwin);\r\n settingsDb.open();\r\n\r\n expect(settingsDb.getSetting<string>(\"setting1\")).to.equal(\"value1\");\r\n expect(settingsDb.getSetting<number>(\"setting2\")).to.equal(42);\r\n expect(settingsDb.getSetting<boolean>(\"setting3\")).to.equal(true);\r\n\r\n settingsDb.close();\r\n });\r\n\r\n it(\"getSettings reads all settings\", async () => {\r\n const container = getContainer(\"get-settings-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"get-settings-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({\r\n \"keyA\": \"valA\",\r\n \"keyB\": 100,\r\n \"keyC\": [1, 2, 3],\r\n });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.organization);\r\n settingsDb.open();\r\n\r\n const all = settingsDb.getSettings();\r\n expect(all.keyA).to.equal(\"valA\");\r\n expect(all.keyB).to.equal(100);\r\n expect(all.keyC).to.deep.equal([1, 2, 3]);\r\n\r\n settingsDb.close();\r\n });\r\n\r\n it(\"getSetting returns undefined for non-existent setting\", async () => {\r\n const container = getContainer(\"no-setting-test\");\r\n await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"no-setting-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.defaults);\r\n settingsDb.open();\r\n\r\n expect(settingsDb.getSetting(\"nonExistentSetting\")).to.be.undefined;\r\n\r\n settingsDb.close();\r\n });\r\n\r\n it(\"manifest reads stored manifest\", async () => {\r\n const container = getContainer(\"manifest-test\");\r\n await container.createDb({\r\n dbName: \"test-db\",\r\n manifest: { settingsName: \"My Settings DB\", description: \"A test settings database\" },\r\n });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n\r\n // manifest auto-opens the db via withOpenDb when not explicitly opened\r\n const manifest = settingsDb.manifest;\r\n expect(manifest.settingsName).to.equal(\"My Settings DB\");\r\n expect(manifest.description).to.equal(\"A test settings database\");\r\n expect(settingsDb.isOpen).to.be.false;\r\n });\r\n\r\n it(\"getSetting auto-opens and auto-closes when db is not open\", async () => {\r\n const container = getContainer(\"auto-open-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"auto-open-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({ \"key\": \"auto-value\" });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.isOpen).to.be.false;\r\n\r\n // getSetting should auto-open, read, and auto-close\r\n expect(settingsDb.getSetting<string>(\"key\")).to.equal(\"auto-value\");\r\n expect(settingsDb.isOpen).to.be.false;\r\n });\r\n\r\n it(\"removeSetting removes a setting\", async () => {\r\n const container = getContainer(\"remove-setting-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"remove-setting-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({ \"toKeep\": 1, \"toRemove\": 2 });\r\n editableDb.close();\r\n\r\n // Verify both exist\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n settingsDb.open();\r\n expect(settingsDb.getSetting(\"toKeep\")).to.equal(1);\r\n expect(settingsDb.getSetting(\"toRemove\")).to.equal(2);\r\n settingsDb.close();\r\n\r\n // Remove one\r\n editableDb.open();\r\n editableDb.removeSetting(\"toRemove\");\r\n editableDb.close();\r\n\r\n // Verify only one remains\r\n settingsDb.open();\r\n const all = settingsDb.getSettings();\r\n expect(all.toKeep).to.equal(1);\r\n expect(all.toRemove).to.be.undefined;\r\n expect(settingsDb.getSetting(\"toRemove\")).to.be.undefined;\r\n settingsDb.close();\r\n });\r\n\r\n it(\"close updates lastEditedBy in manifest when write lock is held\", async () => {\r\n const container = getContainer(\"manifest-update-test\");\r\n const editableDb = await container.createDb({\r\n dbName: \"test-db\",\r\n manifest: { settingsName: \"manifest-update-test\", contactName: \"Original Author\" },\r\n });\r\n\r\n // For local (non-cloud) containers, acquireWriteLock is a no-op,\r\n // so lastEditedBy should remain unchanged after close.\r\n container.acquireWriteLock(\"Jane Admin\");\r\n editableDb.open();\r\n editableDb.updateSettings({ \"key\": \"value\" });\r\n editableDb.close();\r\n container.releaseWriteLock();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n const manifest = settingsDb.manifest;\r\n expect(manifest.settingsName).to.equal(\"manifest-update-test\");\r\n expect(manifest.contactName).to.equal(\"Original Author\");\r\n // lastEditedBy is only auto-set for cloud containers (where acquireWriteLock actually tracks the user)\r\n expect(manifest.lastEditedBy).to.be.undefined;\r\n });\r\n\r\n it(\"getSettingsDb returns a SettingsDb from a loaded container\", async () => {\r\n const container = getContainer(\"getsettingsdb-test\");\r\n await container.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"getsettingsdb-test\" } });\r\n\r\n const settingsDb = editor.workspace.getSettingsDb({ containerId: \"getsettingsdb-test\", priority: SettingsPriority.iTwin });\r\n expect(settingsDb).to.not.be.undefined;\r\n expect(settingsDb.dbName).to.equal(\"settings-db\");\r\n expect(settingsDb.manifest.settingsName).to.equal(\"getsettingsdb-test\");\r\n });\r\n\r\n it(\"getSettingsDb throws for unloaded container\", () => {\r\n expect(() => editor.workspace.getSettingsDb({ containerId: \"nonexistent-container-id\", priority: SettingsPriority.iTwin }))\r\n .to.throw()\r\n .and.satisfy((e: unknown) => WorkspaceError.isError(e, \"does-not-exist\"));\r\n });\r\n\r\n it(\"getSettingsDb uses caller-supplied priority\", async () => {\r\n const container = getContainer(\"imodel-scope-test\");\r\n await container.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"imodel-scope-test\" } });\r\n\r\n const settingsDb = editor.workspace.getSettingsDb({ containerId: \"imodel-scope-test\", priority: SettingsPriority.iModel });\r\n expect(settingsDb).to.not.be.undefined;\r\n expect(settingsDb.priority).to.equal(SettingsPriority.iModel);\r\n });\r\n\r\n it(\"getSettingsDb respects iTwin priority\", async () => {\r\n const container = getContainer(\"itwin-priority-test\");\r\n await container.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"itwin-priority-test\" } });\r\n\r\n const settingsDb = editor.workspace.getSettingsDb({ containerId: \"itwin-priority-test\", priority: SettingsPriority.iTwin });\r\n expect(settingsDb.priority).to.equal(SettingsPriority.iTwin);\r\n });\r\n\r\n it(\"hasSettingsManifestProperty returns true for SettingsDb containers\", async () => {\r\n const container = getContainer(\"has-manifest-test\");\r\n await container.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"has-manifest-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"settings-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.hasSettingsManifestProperty).to.be.true;\r\n });\r\n\r\n it(\"getSetting returns undefined on empty db\", async () => {\r\n const container = getContainer(\"missing-setting-test\");\r\n await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"missing-setting-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n settingsDb.open();\r\n expect(settingsDb.getSetting(\"does-not-exist\")).to.be.undefined;\r\n settingsDb.close();\r\n });\r\n\r\n it(\"editor close is resilient to container cleanup failures\", () => {\r\n // Verify that closing an editor with no containers doesn't throw\r\n const freshEditor = SettingsEditor.construct();\r\n expect(() => freshEditor.close()).to.not.throw();\r\n });\r\n\r\n it(\"getSettingsDb with custom dbName\", async () => {\r\n const container = getContainer(\"custom-dbname-test\");\r\n await container.createDb({ dbName: \"my-custom-db\", manifest: { settingsName: \"custom-dbname\" } });\r\n\r\n const settingsDb = editor.workspace.getSettingsDb({ containerId: \"custom-dbname-test\", priority: SettingsPriority.application, dbName: \"my-custom-db\" });\r\n expect(settingsDb.dbName).to.equal(\"my-custom-db\");\r\n });\r\n\r\n it(\"iTwin and iModel settings containers coexist with correct priorities\", async () => {\r\n // Simulate the real scenario: an iTwin has its own settings container, and one of its\r\n // iModels also has a settings container. Both are loaded into the workspace with separate\r\n // containerId GUIDs (assigned by the storage container service) and different priorities.\r\n const itwinContainer = getContainer(\"itwin-container-guid\");\r\n const imodelContainer = getContainer(\"imodel-container-guid\");\r\n\r\n const itwinDb = await itwinContainer.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"iTwin Settings\" } });\r\n const imodelDb = await imodelContainer.createDb({ dbName: \"settings-db\", manifest: { settingsName: \"iModel Settings\" } });\r\n\r\n // Write the same setting name to both, with different values\r\n itwinDb.open();\r\n itwinDb.updateSettings({ \"theme\": \"light\", \"itwinOnly\": true });\r\n itwinDb.close();\r\n\r\n imodelDb.open();\r\n imodelDb.updateSettings({ \"theme\": \"dark\", \"imodelOnly\": true });\r\n imodelDb.close();\r\n\r\n // Retrieve both via getSettingsDb with the priorities a real caller would assign\r\n const itwinSettingsDb = editor.workspace.getSettingsDb({ containerId: \"itwin-container-guid\", priority: SettingsPriority.iTwin });\r\n const imodelSettingsDb = editor.workspace.getSettingsDb({ containerId: \"imodel-container-guid\", priority: SettingsPriority.iModel });\r\n\r\n // Verify they are independent dbs with correct priorities\r\n expect(itwinSettingsDb.priority).to.equal(SettingsPriority.iTwin);\r\n expect(imodelSettingsDb.priority).to.equal(SettingsPriority.iModel);\r\n expect(imodelSettingsDb.priority).to.be.greaterThan(itwinSettingsDb.priority);\r\n\r\n // Verify each db returns its own setting values\r\n expect(itwinSettingsDb.getSetting<string>(\"theme\")).to.equal(\"light\");\r\n expect(itwinSettingsDb.getSetting<boolean>(\"itwinOnly\")).to.equal(true);\r\n\r\n expect(imodelSettingsDb.getSetting<string>(\"theme\")).to.equal(\"dark\");\r\n expect(imodelSettingsDb.getSetting<boolean>(\"imodelOnly\")).to.equal(true);\r\n });\r\n\r\n it(\"SettingsEditor uses a separate cloud cache from the read-only Workspace\", () => {\r\n const editorCache = editor.workspace.getCloudCache();\r\n const workspaceCache = IModelHost.appWorkspace.getCloudCache();\r\n expect(editorCache.name).to.equal(\"SettingsEditor\");\r\n expect(workspaceCache.name).to.equal(\"Workspace\");\r\n expect(editorCache).to.not.equal(workspaceCache);\r\n });\r\n\r\n describe(\"findContainers\", () => {\r\n const testContainerId = \"mock-settings-container-id\";\r\n const testITwinId = \"mock-itwin-id\";\r\n const testIModelId = \"mock-imodel-id\";\r\n let savedService: BlobContainer.ContainerService | undefined;\r\n\r\n function createMockService(containers: BlobContainer.MetadataResponse[]): BlobContainer.ContainerService {\r\n return {\r\n create: async () => ({ containerId: testContainerId, baseUri: \"https://mock.blob.core/\", provider: \"azure\" as const }),\r\n delete: async () => {},\r\n queryScope: async () => ({ iTwinId: testITwinId }),\r\n queryMetadata: async () => ({ containerType: \"settings\", label: \"mock\" }),\r\n queryContainersMetadata: async (_userToken, args) => {\r\n // Filter by containerType and iTwinId like the real service would\r\n return containers.filter((c) =>\r\n (args.containerType === undefined || c.containerType === args.containerType) &&\r\n (args.iTwinId === testITwinId || args.iTwinId === undefined),\r\n );\r\n },\r\n updateJson: async () => {},\r\n requestToken: async (_props) => ({\r\n token: \"\",\r\n scope: { iTwinId: testITwinId },\r\n provider: \"azure\" as const,\r\n expiration: new Date(Date.now() + 3600000),\r\n metadata: { containerType: \"settings\", label: \"mock\" },\r\n baseUri: \"\",\r\n }),\r\n };\r\n }\r\n\r\n before(() => {\r\n savedService = BlobContainer.service;\r\n });\r\n\r\n afterEach(() => {\r\n BlobContainer.service = savedService;\r\n });\r\n\r\n it(\"finds containers by iTwinId\", async () => {\r\n BlobContainer.service = createMockService([\r\n { containerId: testContainerId, containerType: \"settings\", label: \"Test Settings\" },\r\n ]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: testITwinId });\r\n expect(containers).to.have.length(1);\r\n expect(containers[0].fromProps.containerId).to.equal(testContainerId);\r\n });\r\n\r\n it(\"finds a container by iTwinId and iModelId\", async () => {\r\n BlobContainer.service = createMockService([\r\n { containerId: \"imodel-scoped-container\", containerType: \"settings\", label: \"iModel Settings\" },\r\n ]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: testITwinId, iModelId: testIModelId });\r\n expect(containers).to.have.length(1);\r\n expect(containers[0].fromProps.containerId).to.equal(\"imodel-scoped-container\");\r\n });\r\n\r\n it(\"returns empty array when no settings containers are found\", async () => {\r\n BlobContainer.service = createMockService([]);\r\n\r\n const containers = await editor.findContainers({ iTwinId: \"nonexistent-itwin\" });\r\n expect(containers).to.have.length(0);\r\n });\r\n\r\n it(\"throws when BlobContainer.service is not available\", async () => {\r\n BlobContainer.service = undefined;\r\n\r\n await expect(editor.findContainers({ iTwinId: testITwinId }))\r\n .to.be.rejectedWith(/BlobContainer.service is not available/);\r\n });\r\n });\r\n\r\n describe(\"getSettings\", () => {\r\n it(\"returns a deep copy of all settings\", async () => {\r\n const container = getContainer(\"getsettings-deep-copy-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"getsettings-deep-copy-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({\r\n \"theme\": \"dark\",\r\n \"fontSize\": 14,\r\n \"nested\": { \"a\": 1, \"b\": [2, 3] },\r\n });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n const all = settingsDb.getSettings();\r\n expect(all).to.deep.equal({ \"theme\": \"dark\", \"fontSize\": 14, \"nested\": { \"a\": 1, \"b\": [2, 3] } });\r\n\r\n // Mutating the copy should not affect the stored settings\r\n (all as any).theme = \"light\";\r\n (all as any).nested.a = 999;\r\n expect(settingsDb.getSetting<string>(\"theme\")).to.equal(\"dark\");\r\n expect(settingsDb.getSetting<{ a: number }>(\"nested\")).to.deep.equal({ \"a\": 1, \"b\": [2, 3] });\r\n });\r\n\r\n it(\"returns empty object for empty db\", async () => {\r\n const container = getContainer(\"getsettings-empty-test\");\r\n await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"getsettings-empty-test\" } });\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.getSettings()).to.deep.equal({});\r\n });\r\n });\r\n\r\n describe(\"updateSetting\", () => {\r\n it(\"adds a setting to an empty db\", async () => {\r\n const container = getContainer(\"updatesetting-new-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"updatesetting-new-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSetting({ settingName: \"myKey\", value: \"myValue\" });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.getSetting<string>(\"myKey\")).to.equal(\"myValue\");\r\n });\r\n\r\n it(\"patches existing settings without losing other keys\", async () => {\r\n const container = getContainer(\"updatesetting-patch-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"updatesetting-patch-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({\r\n \"theme\": \"light\",\r\n \"fontSize\": 12,\r\n \"showGrid\": true,\r\n });\r\n\r\n // Patch just one key\r\n editableDb.updateSetting({ settingName: \"theme\", value: \"dark\" });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.getSetting<string>(\"theme\")).to.equal(\"dark\");\r\n expect(settingsDb.getSetting<number>(\"fontSize\")).to.equal(12);\r\n expect(settingsDb.getSetting<boolean>(\"showGrid\")).to.equal(true);\r\n });\r\n\r\n it(\"adds a new key to existing settings\", async () => {\r\n const container = getContainer(\"updatesetting-addkey-test\");\r\n const editableDb = await container.createDb({ dbName: \"test-db\", manifest: { settingsName: \"updatesetting-addkey-test\" } });\r\n\r\n editableDb.open();\r\n editableDb.updateSettings({ \"existing\": \"value\" });\r\n\r\n editableDb.updateSetting({ settingName: \"newKey\", value: 42 });\r\n editableDb.close();\r\n\r\n const settingsDb = new SettingsDbImpl({ dbName: \"test-db\" }, container, SettingsPriority.application);\r\n expect(settingsDb.getSetting<string>(\"existing\")).to.equal(\"value\");\r\n expect(settingsDb.getSetting<number>(\"newKey\")).to.equal(42);\r\n });\r\n });\r\n});\r\n"]}
@@ -90,6 +90,14 @@ export interface SettingsDictionary {
90
90
  * dictionaries. Those methods - unlike this one - also validate that `settingName` is of type `T` as defined by its [[SettingSchema]].
91
91
  */
92
92
  getSetting<T extends Setting>(settingName: SettingName): T | undefined;
93
+ /** Return a deep copy of all settings in this dictionary as a [[SettingsContainer]].
94
+ * This is useful for inspecting the full contents of the dictionary or for building a modified copy
95
+ * to pass to [[EditableSettingsDb.updateSettingsDictionary]].
96
+ * The returned container is cloned using [[Setting.clone]], so callers may freely mutate it without
97
+ * affecting this dictionary's internal state.
98
+ * @beta
99
+ */
100
+ toJSON(): SettingsContainer;
93
101
  }
94
102
  /** Uniquely identifies a [[SettingsDictionary]].
95
103
  * @beta