diff --git a/bun.lockb b/bun.lockb index 48d5c37..87174c7 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/manifest.json b/manifest.json index ebfba02..30c4268 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "vault-explorer", "name": "Vault Explorer", - "version": "1.17.1", + "version": "1.17.2", "minAppVersion": "1.4.13", "description": "Explore your vault in visual format", "author": "DecafDev", diff --git a/package.json b/package.json index 699b8ae..012def3 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "obsidian-vault-explorer", - "version": "1.17.1", + "version": "1.17.2", "description": "Explore your vault in visual format", "main": "main.js", "scripts": { "dev": "node esbuild.config.mjs", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", + "guardgen": "ts-auto-guard", "test": "jest --config jest.config.js" }, "keywords": [], @@ -25,6 +26,7 @@ "jest": "^29.7.0", "obsidian": "latest", "svelte-preprocess": "^5.1.4", + "ts-auto-guard": "^5.0.0", "ts-jest": "^29.1.4", "tslib": "2.4.0", "typescript": "4.7.4" diff --git a/src/main.ts b/src/main.ts index 080ab7e..ece27d7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,30 +3,16 @@ import { Plugin, TAbstractFile, TFile, TFolder } from 'obsidian'; import VaultExplorerView from './obsidian/vault-explorer-view'; import VaultExplorerSettingsTab from './obsidian/vault-explorer-settings-tab'; -import { FilterRuleType, TExplorerView, VaultExplorerPluginSettings } from './types'; +import { VaultExplorerPluginSettings } from './types'; import { DEFAULT_SETTINGS, HOVER_LINK_SOURCE_ID, VAULT_EXPLORER_VIEW } from './constants'; import _ from 'lodash'; import EventManager from './event/event-manager'; -import { isVersionLessThan } from './utils'; -import { VaultExplorerPluginSettings_0_3_3 } from './types/types-0.3.0'; -import { VaultExplorerPluginSettings_0_5_5 } from './types/types-0.5.5'; +import { preformMigrations } from './migrations'; import Logger from 'js-logger'; import { formatMessageForLogger, stringToLogLevel } from './logger'; -import { LOG_LEVEL_WARN } from './logger/constants'; -import { VaultExplorerPluginSettings_1_0_1 } from './types/types-1.0.1'; import { moveFocus } from './focus-utils'; -import { VaultExplorerPluginSettings_1_2_0, ViewType_1_2_0 } from './types/types-1.2.0'; -import { VaultExplorerPluginSettings_1_2_1 } from './types/types-1.2.1'; -import { PropertyFilterGroup_1_5_0, PropertyFilter_1_5_0, VaultExplorerPluginSettings_1_5_0 } from './types/types-1.5.0'; -import { VaultExplorerPluginSettings_1_6_0 } from './types/types-1.6.0'; import { loadDeviceId } from './svelte/shared/services/device-id-utils'; import License from './svelte/shared/services/license'; -import { VaultExplorerPluginSettings_1_8_1 } from './types/types-1.8.1'; -import { VaultExplorerPluginSettings_1_9_1 } from './types/types-1.9.1'; -import { VaultExplorerPluginSettings_1_12_1 } from './types/types-1.12.1'; -import { VaultExplorerPluginSettings_1_13_1 } from './types/types-1.13.1'; -import { VaultExplorerPluginSettings_1_14_2 } from './types/types-1.14.2'; -import { VaultExplorerPluginSettings_1_16_0, ViewType_1_16_0 } from './types/types-1.16.0'; export default class VaultExplorerPlugin extends Plugin { settings: VaultExplorerPluginSettings = DEFAULT_SETTINGS; @@ -36,9 +22,6 @@ export default class VaultExplorerPlugin extends Plugin { await this.loadSettings(); this.setupLogger(); - await loadDeviceId(); - await License.getInstance().verifyLicense(); - this.registerView( VAULT_EXPLORER_VIEW, (leaf) => new VaultExplorerView(leaf, this) @@ -64,6 +47,9 @@ export default class VaultExplorerPlugin extends Plugin { this.layoutReady = true; }); + await loadDeviceId(); + await License.getInstance().verifyLicense(); + } private registerEvents() { @@ -133,320 +119,21 @@ export default class VaultExplorerPlugin extends Plugin { } async loadSettings() { - let data: Record | null = await this.loadData(); - - if (data !== null) { - //This will be null if the settings are from a version before 0.3.0 - const settingsVersion = (data["pluginVersion"] as string) ?? null; - if (settingsVersion !== null) { - if (isVersionLessThan(settingsVersion, "0.4.0")) { - console.log("Upgrading settings from version 0.3.3 to 0.4.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_0_3_3; - const newData: VaultExplorerPluginSettings_0_5_5 = { - ...typedData, - filters: { - ...typedData.filters, - properties: { - ...typedData.filters.properties, - groups: [] - } - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.0.0")) { - console.log("Upgrading settings from version 0.5.5 to 1.0.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_0_5_5; - const newData: VaultExplorerPluginSettings_1_0_1 = { - ...typedData, - logLevel: LOG_LEVEL_WARN, - filters: { - ...typedData.filters, - properties: { - ...typedData.filters.properties, - groups: typedData.filters.properties.groups.map(group => { - const { id, name, filters, isEnabled } = group; - return { - id, - name, - filters, - isEnabled - } - }) - } - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.1.0")) { - console.log("Upgrading settings from version 1.0.1 to 1.1.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_0_1; - const newData: VaultExplorerPluginSettings_1_2_0 = { - ...typedData, - views: { - currentView: typedData.currentView as unknown as ViewType_1_2_0, - order: [ViewType_1_2_0.GRID, ViewType_1_2_0.LIST] - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.2.1")) { - console.log("Upgrading settings from version 1.2.0 to 1.2.1"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_0; - const newData: VaultExplorerPluginSettings_1_2_1 = { - ...typedData, - views: { - ...typedData.views, - titleWrapping: "normal" - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.3.0")) { - console.log("Upgrading settings from version 1.2.1 to 1.3.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_1; - const groups = typedData.filters.properties.groups; - - const updatedGroups: PropertyFilterGroup_1_5_0[] = groups.map(group => { - const updatedFilters: PropertyFilter_1_5_0[] = group.filters.map(filter => { - return { - ...filter, - type: filter.type as any, - matchWhenPropertyDNE: false - } - }); - return { - ...group, - filters: updatedFilters - } - }); - - const newData: VaultExplorerPluginSettings_1_5_0 = { - ...typedData, - filters: { - ...typedData.filters, - properties: { - ...typedData.filters.properties, - groups: updatedGroups, - } - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.6.0")) { - console.log("Upgrading settings from version 1.5.0 to 1.6.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_5_0; - const newData: VaultExplorerPluginSettings_1_6_0 = { - ...typedData, - properties: { - ...typedData.properties, - creationDate: "", - modifiedDate: "" - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.6.1")) { - console.log("Upgrading settings from version 1.6.0 to 1.6.1"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_6_0; - const newData: VaultExplorerPluginSettings_1_8_1 = { - ...typedData, - properties: { - ...typedData.properties, - createdDate: "", - modifiedDate: "" - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.9.0")) { - console.log("Upgrading settings from version 1.8.1 to 1.9.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_8_1; - const newData: VaultExplorerPluginSettings_1_9_1 = { - ...typedData, - filters: { - ...typedData.filters, - custom: { - selectedGroupId: typedData.filters.properties.selectedGroupId, - groups: typedData.filters.properties.groups.map(group => { - const rules = group.filters.map(filter => { - return { - ...filter, - valueData: "", - type: filter.type as any - } - }); - return { - ...group, - rules - } - }) - } - } - } - delete (newData.filters as any).properties; - for (const group of newData.filters.custom.groups as any) { - delete group.filters; - } - data = newData as unknown as Record; - } - } + const loadedData: Record | null = await this.loadData(); - if (isVersionLessThan(settingsVersion, "1.10.0")) { - console.log("Upgrading settings from version 1.9.1 to 1.10.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_9_1; - const newData: VaultExplorerPluginSettings_1_12_1 = { - ...typedData, - filters: { - ...typedData.filters, - custom: { - ...typedData.filters.custom, - groups: typedData.filters.custom.groups.map(group => { - const rules = group.rules.map(rule => { - return { - ...rule, - type: FilterRuleType.PROPERTY as any, - propertyType: rule.type as any, - } - }); - return { - ...group, - rules - } - }) - } - } - } - delete (newData.filters as any).folder; - delete (newData.filters as any).properties; - for (const group of newData.filters.custom.groups as any) { - delete group.filters; - } - data = newData as unknown as Record; - } + let currentData: Record = {}; - if (isVersionLessThan(settingsVersion, "1.13.0")) { - console.log("Upgrading settings from version 1.12.1 to 1.13.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_12_1; - const newData: VaultExplorerPluginSettings_1_13_1 = { - ...typedData, - views: { - ...typedData.views, - enableClockUpdates: true - }, - filters: { - ...typedData.filters, - custom: { - ...typedData.filters.custom, - groups: typedData.filters.custom.groups.map(group => { - return { - ...group, - isSticky: false - } - }) - } - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.14.0")) { - console.log("Upgrading settings from version 1.13.1 to 1.14.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_13_1; - const newData: VaultExplorerPluginSettings_1_14_2 = { - ...typedData, - filters: { - ...typedData.filters, - search: { - isEnabled: true, - value: typedData.filters.search - }, - favorites: { - isEnabled: true, - value: typedData.filters.onlyFavorites - }, - timestamp: { - isEnabled: true, - value: typedData.filters.timestamp - }, - sort: { - isEnabled: true, - value: typedData.filters.sort - }, - custom: { - isEnabled: true, - ...typedData.filters.custom - }, - }, - enableScrollButtons: true, - } - delete (newData.filters as any).onlyFavorites; - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.15.0")) { - console.log("Upgrading settings from version 1.14.2 to 1.15.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_14_2; - const newData: VaultExplorerPluginSettings_1_16_0 = { - ...typedData, - views: { - ...typedData.views, - order: [...typedData.views.order, ViewType_1_16_0.FEED], - } - } - data = newData as unknown as Record; - } - - if (isVersionLessThan(settingsVersion, "1.17.0")) { - console.log("Upgrading settings from version 1.16.0 to 1.17.0"); - const typedData = (data as unknown) as VaultExplorerPluginSettings_1_16_0; - const newData: VaultExplorerPluginSettings = { - ...typedData, - views: { - dashboard: { - isEnabled: false - }, - grid: { - isEnabled: true - }, - list: { - isEnabled: true - }, - table: { - isEnabled: false - }, - feed: { - isEnabled: true - }, - recommended: { - isEnabled: false - }, - related: { - isEnabled: false - } - }, - viewOrder: typedData.views.order as unknown as TExplorerView[], - enableClockUpdates: typedData.views.enableClockUpdates, - currentView: typedData.views.currentView as unknown as TExplorerView, - titleWrapping: typedData.views.titleWrapping - } - delete (newData as any).views.order; - delete (newData as any).views.currentView; - delete (newData as any).views.enableClockUpdates; - delete (newData as any).views.titleWrapping; - data = newData as unknown as Record; + if (loadedData !== null) { + //This will be undefined if the settings are from a version before 0.3.0 + const loadedVersion = loadedData["pluginVersion"] as string ?? null; + if (loadedVersion !== null) { + const newData = preformMigrations(loadedVersion, loadedData); + currentData = newData; } } - //Apply default settings. This will make it so we don't need to do migrations for just adding new settings - this.settings = Object.assign({}, DEFAULT_SETTINGS, data); + //Apply default settings + this.settings = Object.assign({}, DEFAULT_SETTINGS, currentData); //Update the plugin version to the current version this.settings.pluginVersion = this.manifest.version; await this.saveSettings(); diff --git a/src/migrations/index.ts b/src/migrations/index.ts new file mode 100644 index 0000000..70365ec --- /dev/null +++ b/src/migrations/index.ts @@ -0,0 +1,99 @@ +import { TMigration } from "./types"; +import Migrate_0_4_0 from "./migrate_0_4_0"; +import Migrate_1_1_0 from "./migrate_1_1_0"; +import Migrate_1_0_0 from "./migrate_1_0_0"; +import Migrate_1_2_1 from "./migrate_1_2_1"; +import Migrate_1_3_0 from "./migrate_1_3_0"; +import Migrate_1_6_0 from "./migrate_1_6_0"; +import Migrate_1_6_1 from "./migrate_1_6_1"; +import Migrate_1_9_0 from "./migrate_1_9_0"; +import Migrate_1_14_0 from "./migrate_1_14_0"; +import Migrate_1_15_0 from "./migrate_1_15_0"; +import Migrate_1_17_0 from "./migrate_1_17_0"; +import Migrate_1_13_0 from "./migrate_1_13_0"; +import Migrate_1_10_0 from "./migrate_1_10_0"; +import { isVersionLessThan } from "src/utils"; + +const migrations: TMigration[] = [ + { + from: "0.3.3", + to: "0.4.0", + migrate: Migrate_0_4_0, + }, + { + from: "0.5.5", + to: "1.0.0", + migrate: Migrate_1_0_0, + }, + { + from: "1.0.1", + to: "1.1.0", + migrate: Migrate_1_1_0, + }, + { + from: "1.2.0", + to: "1.2.1", + migrate: Migrate_1_2_1, + }, + { + from: "1.2.1", + to: "1.3.0", + migrate: Migrate_1_3_0, + }, + { + from: "1.5.0", + to: "1.6.0", + migrate: Migrate_1_6_0, + }, + { + from: "1.6.0", + to: "1.6.1", + migrate: Migrate_1_6_1, + }, + { + from: "1.8.1", + to: "1.9.0", + migrate: Migrate_1_9_0, + }, + { + from: "1.9.1", + to: "1.10.0", + migrate: Migrate_1_10_0, + }, + { + from: "1.12.1", + to: "1.13.0", + migrate: Migrate_1_13_0, + }, + { + from: "1.13.1", + to: "1.14.0", + migrate: Migrate_1_14_0, + }, + { + from: "1.14.2", + to: "1.15.0", + migrate: Migrate_1_15_0, + }, + { + from: "1.16.0", + to: "1.17.0", + migrate: Migrate_1_17_0, + }, +]; + +export const preformMigrations = (settingsVersion: string, data: Record) => { + let updatedData = structuredClone(data); + + for (const migration of migrations) { + const { from, to } = migration; + if (isVersionLessThan(settingsVersion, to)) { + console.log(`Upgrading settings from version ${from} to ${to}`); + const migrator = new migration.migrate(); + const newData = migrator.migrate(updatedData); + updatedData = newData; + } + } + + return updatedData; +} diff --git a/src/migrations/migrate_0_4_0.ts b/src/migrations/migrate_0_4_0.ts new file mode 100644 index 0000000..81960af --- /dev/null +++ b/src/migrations/migrate_0_4_0.ts @@ -0,0 +1,20 @@ +import { VaultExplorerPluginSettings_0_5_5 } from "src/types/types-0.5.5"; +import { VaultExplorerPluginSettings_0_3_3 } from "src/types/types-0.3.3"; +import MigrationInterface from "./migration_interface"; + +export default class Migrate_0_4_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_0_3_3; + const newData: VaultExplorerPluginSettings_0_5_5 = { + ...typedData, + filters: { + ...typedData.filters, + properties: { + ...typedData.filters.properties, + groups: [] + } + }, + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_0_0.ts b/src/migrations/migrate_1_0_0.ts new file mode 100644 index 0000000..94b7b2e --- /dev/null +++ b/src/migrations/migrate_1_0_0.ts @@ -0,0 +1,30 @@ +import { VaultExplorerPluginSettings_0_5_5 } from "src/types/types-0.5.5"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_0_1 } from "src/types/types-1.0.1"; +import { LOG_LEVEL_WARN } from "src/logger/constants"; + +export default class Migrate_1_0_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_0_5_5; + const newData: VaultExplorerPluginSettings_1_0_1 = { + ...typedData, + logLevel: LOG_LEVEL_WARN, + filters: { + ...typedData.filters, + properties: { + ...typedData.filters.properties, + groups: typedData.filters.properties.groups.map(group => { + const { id, name, filters, isEnabled } = group; + return { + id, + name, + filters, + isEnabled + } + }) + } + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_10_0.ts b/src/migrations/migrate_1_10_0.ts new file mode 100644 index 0000000..3c33707 --- /dev/null +++ b/src/migrations/migrate_1_10_0.ts @@ -0,0 +1,37 @@ +import { FilterRuleType_1_12_1, VaultExplorerPluginSettings_1_12_1 } from "src/types/types-1.12.1"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_9_1 } from "src/types/types-1.9.1"; + +export default class Migrate_1_10_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_9_1; + const newData: VaultExplorerPluginSettings_1_12_1 = { + ...typedData, + filters: { + ...typedData.filters, + custom: { + ...typedData.filters.custom, + groups: typedData.filters.custom.groups.map(group => { + const rules = group.rules.map(rule => { + return { + ...rule, + type: FilterRuleType_1_12_1.PROPERTY as any, + propertyType: rule.type as any, + } + }); + return { + ...group, + rules + } + }) + } + } + } + delete (newData.filters as any).folder; + delete (newData.filters as any).properties; + for (const group of newData.filters.custom.groups as any) { + delete group.filters; + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_13_0.ts b/src/migrations/migrate_1_13_0.ts new file mode 100644 index 0000000..80d503a --- /dev/null +++ b/src/migrations/migrate_1_13_0.ts @@ -0,0 +1,29 @@ +import { VaultExplorerPluginSettings_1_13_1 } from "src/types/types-1.13.1"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_12_1 } from "src/types/types-1.12.1"; + +export default class Migrate_1_13_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_12_1; + const newData: VaultExplorerPluginSettings_1_13_1 = { + ...typedData, + views: { + ...typedData.views, + enableClockUpdates: true + }, + filters: { + ...typedData.filters, + custom: { + ...typedData.filters.custom, + groups: typedData.filters.custom.groups.map(group => { + return { + ...group, + isSticky: false + } + }) + } + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_14_0.ts b/src/migrations/migrate_1_14_0.ts new file mode 100644 index 0000000..b5f313f --- /dev/null +++ b/src/migrations/migrate_1_14_0.ts @@ -0,0 +1,38 @@ +import { VaultExplorerPluginSettings_1_14_2 } from "src/types/types-1.14.2"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_13_1 } from "src/types/types-1.13.1"; + +export default class Migrate_1_14_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_13_1; + const newData: VaultExplorerPluginSettings_1_14_2 = { + ...typedData, + filters: { + ...typedData.filters, + search: { + isEnabled: true, + value: typedData.filters.search + }, + favorites: { + isEnabled: true, + value: typedData.filters.onlyFavorites + }, + timestamp: { + isEnabled: true, + value: typedData.filters.timestamp + }, + sort: { + isEnabled: true, + value: typedData.filters.sort + }, + custom: { + isEnabled: true, + ...typedData.filters.custom + }, + }, + enableScrollButtons: true, + } + delete (newData.filters as any).onlyFavorites; + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_15_0.ts b/src/migrations/migrate_1_15_0.ts new file mode 100644 index 0000000..6af05e0 --- /dev/null +++ b/src/migrations/migrate_1_15_0.ts @@ -0,0 +1,17 @@ +import { VaultExplorerPluginSettings_1_16_0, ViewType_1_16_0 } from "src/types/types-1.16.0"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_14_2 } from "src/types/types-1.14.2"; + +export default class Migrate_1_15_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_14_2; + const newData: VaultExplorerPluginSettings_1_16_0 = { + ...typedData, + views: { + ...typedData.views, + order: [...typedData.views.order, ViewType_1_16_0.FEED], + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_17_0.ts b/src/migrations/migrate_1_17_0.ts new file mode 100644 index 0000000..4a8b4c3 --- /dev/null +++ b/src/migrations/migrate_1_17_0.ts @@ -0,0 +1,44 @@ +import { TExplorerView, VaultExplorerPluginSettings } from "src/types"; +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_16_0 } from "src/types/types-1.16.0"; + +export default class Migrate_1_17_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_16_0; + const newData: VaultExplorerPluginSettings = { + ...typedData, + views: { + dashboard: { + isEnabled: false + }, + grid: { + isEnabled: true + }, + list: { + isEnabled: true + }, + table: { + isEnabled: false + }, + feed: { + isEnabled: true + }, + recommended: { + isEnabled: false + }, + related: { + isEnabled: false + } + }, + viewOrder: typedData.views.order as unknown as TExplorerView[], + enableClockUpdates: typedData.views.enableClockUpdates, + currentView: typedData.views.currentView as unknown as TExplorerView, + titleWrapping: typedData.views.titleWrapping + } + delete (newData as any).views.order; + delete (newData as any).views.currentView; + delete (newData as any).views.enableClockUpdates; + delete (newData as any).views.titleWrapping; + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_17_2.ts b/src/migrations/migrate_1_17_2.ts new file mode 100644 index 0000000..bfc1b35 --- /dev/null +++ b/src/migrations/migrate_1_17_2.ts @@ -0,0 +1,9 @@ +import License from "src/svelte/shared/services/license"; +import MigrationInterface from "./migration_interface"; + +export default class Migrate_1_17_2 implements MigrationInterface { + migrate(data: Record) { + License.getInstance().setStoredDeviceRegistered(false); + return data as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_1_0.ts b/src/migrations/migrate_1_1_0.ts new file mode 100644 index 0000000..e8c541d --- /dev/null +++ b/src/migrations/migrate_1_1_0.ts @@ -0,0 +1,17 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_0_1 } from "src/types/types-1.0.1"; +import { VaultExplorerPluginSettings_1_2_0, ViewType_1_2_0 } from "src/types/types-1.2.0"; + +export default class Migrate_1_1_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_0_1; + const newData: VaultExplorerPluginSettings_1_2_0 = { + ...typedData, + views: { + currentView: typedData.currentView as unknown as ViewType_1_2_0, + order: [ViewType_1_2_0.GRID, ViewType_1_2_0.LIST] + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_2_1.ts b/src/migrations/migrate_1_2_1.ts new file mode 100644 index 0000000..a4c5aa2 --- /dev/null +++ b/src/migrations/migrate_1_2_1.ts @@ -0,0 +1,17 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_2_0 } from "src/types/types-1.2.0"; +import { VaultExplorerPluginSettings_1_2_1 } from "src/types/types-1.2.1"; + +export default class Migrate_1_2_1 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_0; + const newData: VaultExplorerPluginSettings_1_2_1 = { + ...typedData, + views: { + ...typedData.views, + titleWrapping: "normal" + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_3_0.ts b/src/migrations/migrate_1_3_0.ts new file mode 100644 index 0000000..c1c4b23 --- /dev/null +++ b/src/migrations/migrate_1_3_0.ts @@ -0,0 +1,36 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_2_1 } from "src/types/types-1.2.1"; +import { PropertyFilterGroup_1_5_0, PropertyFilter_1_5_0, VaultExplorerPluginSettings_1_5_0 } from "src/types/types-1.5.0"; + +export default class Migrate_1_3_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_2_1; + const groups = typedData.filters.properties.groups; + + const updatedGroups: PropertyFilterGroup_1_5_0[] = groups.map(group => { + const updatedFilters: PropertyFilter_1_5_0[] = group.filters.map(filter => { + return { + ...filter, + type: filter.type as any, + matchWhenPropertyDNE: false + } + }); + return { + ...group, + filters: updatedFilters + } + }); + + const newData: VaultExplorerPluginSettings_1_5_0 = { + ...typedData, + filters: { + ...typedData.filters, + properties: { + ...typedData.filters.properties, + groups: updatedGroups, + } + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_6_0.ts b/src/migrations/migrate_1_6_0.ts new file mode 100644 index 0000000..ff59330 --- /dev/null +++ b/src/migrations/migrate_1_6_0.ts @@ -0,0 +1,18 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_5_0 } from "src/types/types-1.5.0"; +import { VaultExplorerPluginSettings_1_6_0 } from "src/types/types-1.6.0"; + +export default class Migrate_1_6_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_5_0; + const newData: VaultExplorerPluginSettings_1_6_0 = { + ...typedData, + properties: { + ...typedData.properties, + creationDate: "", + modifiedDate: "" + } + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_6_1.ts b/src/migrations/migrate_1_6_1.ts new file mode 100644 index 0000000..e97092a --- /dev/null +++ b/src/migrations/migrate_1_6_1.ts @@ -0,0 +1,19 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_6_0 } from "src/types/types-1.6.0"; +import { VaultExplorerPluginSettings_1_8_1 } from "src/types/types-1.8.1"; + +export default class Migrate_1_6_1 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_6_0; + const newData: VaultExplorerPluginSettings_1_8_1 = { + ...typedData, + properties: { + ...typedData.properties, + createdDate: "", + modifiedDate: "" + } + } + delete (newData.properties as any).creationDate; + return newData as unknown as Record; + } +} diff --git a/src/migrations/migrate_1_9_0.ts b/src/migrations/migrate_1_9_0.ts new file mode 100644 index 0000000..55f5baa --- /dev/null +++ b/src/migrations/migrate_1_9_0.ts @@ -0,0 +1,36 @@ +import MigrationInterface from "./migration_interface"; +import { VaultExplorerPluginSettings_1_8_1 } from "src/types/types-1.8.1"; +import { VaultExplorerPluginSettings_1_9_1 } from "src/types/types-1.9.1"; + +export default class Migrate_1_9_0 implements MigrationInterface { + migrate(data: Record) { + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_8_1; + const newData: VaultExplorerPluginSettings_1_9_1 = { + ...typedData, + filters: { + ...typedData.filters, + custom: { + selectedGroupId: typedData.filters.properties.selectedGroupId, + groups: typedData.filters.properties.groups.map(group => { + const rules = group.filters.map(filter => { + return { + ...filter, + valueData: "", + type: filter.type as any + } + }); + return { + ...group, + rules + } + }) + } + } + } + delete (newData.filters as any).properties; + for (const group of newData.filters.custom.groups as any) { + delete group.filters; + } + return newData as unknown as Record; + } +} diff --git a/src/migrations/migration_interface.ts b/src/migrations/migration_interface.ts new file mode 100644 index 0000000..eeb6362 --- /dev/null +++ b/src/migrations/migration_interface.ts @@ -0,0 +1,3 @@ +export default abstract class MigrationInterface { + abstract migrate(previous: Record): Record; +} diff --git a/src/migrations/types.ts b/src/migrations/types.ts new file mode 100644 index 0000000..9a478d1 --- /dev/null +++ b/src/migrations/types.ts @@ -0,0 +1,7 @@ +import MigrationInterface from "./migration_interface"; + +export interface TMigration { + from: string; + to: string; + migrate: new () => MigrationInterface; +} diff --git a/src/svelte/app/index.svelte b/src/svelte/app/index.svelte index 050d9ee..1552b55 100644 --- a/src/svelte/app/index.svelte +++ b/src/svelte/app/index.svelte @@ -313,7 +313,7 @@ if (data.length > 0 && data[0] instanceof TFile) { const file = data[0] as TFile; const content = await plugin.app.vault.cachedRead(file); - console.log(content); + const updatedContentForFiles = contentForFiles.map((entry) => { if (entry.path === file.path) { return { @@ -658,7 +658,7 @@ let filteredCustom: TFile[] = []; $: if (frontmatterCacheTime && customFilter.groups) { - console.log("Frontmatter cache time", frontmatterCacheTime); + Logger.debug(`Frontmatter cache time: ${frontmatterCacheTime}`); filteredCustom = files.filter((file) => { const { name, path } = file; const frontmatter = diff --git a/src/svelte/shared/services/license.ts b/src/svelte/shared/services/license.ts index cd6986f..738eb94 100644 --- a/src/svelte/shared/services/license.ts +++ b/src/svelte/shared/services/license.ts @@ -7,6 +7,8 @@ export const LICENSE_KEY_LENGTH = 8; const LOCAL_STORAGE_LICENSE_KEY = "vault-explorer-license-key"; +const LOCAL_STORAGE_DEVICE_REGISTERED = "vault-explorer-device-registration"; + export default class License { private isDeviceRegistered: boolean; private licenseKey: string; @@ -16,10 +18,16 @@ export default class License { private static instance: License; constructor() { - this.isDeviceRegistered = false; - this.isDeviceRegisteredStore.set(false); + const storedDeviceRegistered = this.getStoredDeviceRegistered(); + this.isDeviceRegistered = storedDeviceRegistered; + this.isDeviceRegisteredStore.set(storedDeviceRegistered); + Logger.debug({ fileName: "license.ts", functionName: "constructor", message: "loaded storedDeviceRegistered", }, storedDeviceRegistered); + this.responseMessage = ""; - this.licenseKey = localStorage.getItem(LOCAL_STORAGE_LICENSE_KEY) ?? ""; + + const storedKey = this.getStoredLicenseKey(); + this.licenseKey = storedKey; + Logger.debug({ fileName: "license.ts", functionName: "constructor", message: "loaded storedKey" }, storedKey); } async registerDevice(licenseKey: string) { @@ -28,9 +36,8 @@ export default class License { const deviceId = readDeviceId(); const result = await this.postRegisterDevice(licenseKey, deviceId); if (result) { - this.isDeviceRegistered = true; - this.isDeviceRegisteredStore.set(true); - this.setLicenseKey(licenseKey); + this.updateDeviceRegistered(true); + this.updateLicenseKey(licenseKey); } return result; } @@ -41,9 +48,8 @@ export default class License { const deviceId = readDeviceId(); const result = await this.postUnregisterDevice(this.licenseKey, deviceId); if (result) { - this.isDeviceRegistered = false; - this.isDeviceRegisteredStore.set(false); - this.setLicenseKey(""); + this.updateLicenseKey(""); + this.updateDeviceRegistered(false); } return result; } @@ -63,8 +69,9 @@ export default class License { const result = await this.postVerifyDevice(this.licenseKey, deviceId); if (result) { - this.isDeviceRegistered = true; - this.isDeviceRegisteredStore.set(true); + this.updateDeviceRegistered(true); + } else { + this.updateDeviceRegistered(false); } } @@ -88,6 +95,13 @@ export default class License { } catch (err: unknown) { const error = err as Error; Logger.error({ fileName: "license.ts", functionName: "postVerifyDevice", message: "error verifying device" }, error.message); + + if (error.message.contains("net::ERR_INTERNET_DISCONNECTED")) { + const deviceRegistered = License.getInstance().getIsDeviceRegistered(); + Logger.debug({ fileName: "license.ts", functionName: "postVerifyDevice", message: "returning last deviceRegistered state", }, deviceRegistered); + return deviceRegistered; + + } return false; } }; @@ -172,14 +186,53 @@ export default class License { } this.responseMessage = message; + Logger.error({ fileName: "license.ts", functionName: "postUnregisterDevice", message: "error unregistering device" }, error.message); return false; } } - private setLicenseKey(value: string) { - localStorage.setItem(LOCAL_STORAGE_LICENSE_KEY, value); + /** + * Sets the class licenseKey and updates local storage + * @param value - The license key + */ + private updateLicenseKey(value: string) { + Logger.trace({ filename: "license.ts", functionName: "updateLicenseKey", message: "called" }); this.licenseKey = value; + this.setStoredLicenseKey(value); + } + + /** + * Sets the class registration flag and updates local storage + * @param value - The registration status of the device + */ + private updateDeviceRegistered(value: boolean) { + Logger.trace({ filename: "license.ts", functionName: "updateDeviceRegistered", message: "called" }); + this.isDeviceRegistered = value; + this.isDeviceRegisteredStore.set(value); + this.setStoredDeviceRegistered(value); + } + + private setStoredLicenseKey(value: string) { + Logger.trace({ filename: "license.ts", functionName: "setStoredLicenseKey", message: "called" }); + localStorage.setItem(LOCAL_STORAGE_LICENSE_KEY, value); + } + + private getStoredLicenseKey() { + return localStorage.getItem(LOCAL_STORAGE_LICENSE_KEY) ?? "" + } + + private getStoredDeviceRegistered() { + const value = localStorage.getItem(LOCAL_STORAGE_DEVICE_REGISTERED); + if (value) { + return value === "true"; + } + return false; + } + + setStoredDeviceRegistered(value: boolean) { + Logger.trace({ filename: "license.ts", functionName: "setStoredDeviceRegistered", message: "called" }); + localStorage.setItem(LOCAL_STORAGE_DEVICE_REGISTERED, value.toString()); } getIsDeviceRegistered() { diff --git a/src/types/index.guard.ts b/src/types/index.guard.ts new file mode 100644 index 0000000..e0b6936 --- /dev/null +++ b/src/types/index.guard.ts @@ -0,0 +1,643 @@ +/* + * Generated type guards for "index.ts". + * WARNING: Do not manually change this file. + */ +import { FilterRuleType, TextFilterCondition, NumberFilterCondition, DateFilterCondition, CheckboxFilterCondition, ListFilterCondition, ContentFilterCondition, FolderFilterCondition, FileNameFilterCondition, PropertyType, TExplorerView, VaultExplorerPluginSettings } from "./index"; + +export function isVaultExplorerPluginSettings(obj: unknown): obj is VaultExplorerPluginSettings { + const typedObj = obj as VaultExplorerPluginSettings + return ( + (typedObj !== null && + typeof typedObj === "object" || + typeof typedObj === "function") && + (typedObj["properties"] !== null && + typeof typedObj["properties"] === "object" || + typeof typedObj["properties"] === "function") && + typeof typedObj["properties"]["favorite"] === "string" && + typeof typedObj["properties"]["url"] === "string" && + typeof typedObj["properties"]["createdDate"] === "string" && + typeof typedObj["properties"]["modifiedDate"] === "string" && + typeof typedObj["properties"]["custom1"] === "string" && + typeof typedObj["properties"]["custom2"] === "string" && + typeof typedObj["properties"]["custom3"] === "string" && + (typedObj["filters"] !== null && + typeof typedObj["filters"] === "object" || + typeof typedObj["filters"] === "function") && + (typedObj["filters"]["search"] !== null && + typeof typedObj["filters"]["search"] === "object" || + typeof typedObj["filters"]["search"] === "function") && + typeof typedObj["filters"]["search"]["isEnabled"] === "boolean" && + typeof typedObj["filters"]["search"]["value"] === "string" && + (typedObj["filters"]["favorites"] !== null && + typeof typedObj["filters"]["favorites"] === "object" || + typeof typedObj["filters"]["favorites"] === "function") && + typeof typedObj["filters"]["favorites"]["isEnabled"] === "boolean" && + typeof typedObj["filters"]["favorites"]["value"] === "boolean" && + (typedObj["filters"]["sort"] !== null && + typeof typedObj["filters"]["sort"] === "object" || + typeof typedObj["filters"]["sort"] === "function") && + typeof typedObj["filters"]["sort"]["isEnabled"] === "boolean" && + (typedObj["filters"]["sort"]["value"] === "file-name-asc" || + typedObj["filters"]["sort"]["value"] === "file-name-desc" || + typedObj["filters"]["sort"]["value"] === "modified-asc" || + typedObj["filters"]["sort"]["value"] === "modified-desc") && + (typedObj["filters"]["timestamp"] !== null && + typeof typedObj["filters"]["timestamp"] === "object" || + typeof typedObj["filters"]["timestamp"] === "function") && + typeof typedObj["filters"]["timestamp"]["isEnabled"] === "boolean" && + (typedObj["filters"]["timestamp"]["value"] === "created-today" || + typedObj["filters"]["timestamp"]["value"] === "modified-today" || + typedObj["filters"]["timestamp"]["value"] === "created-this-week" || + typedObj["filters"]["timestamp"]["value"] === "modified-this-week" || + typedObj["filters"]["timestamp"]["value"] === "created-2-weeks" || + typedObj["filters"]["timestamp"]["value"] === "modified-2-weeks" || + typedObj["filters"]["timestamp"]["value"] === "all") && + (typedObj["filters"]["custom"] !== null && + typeof typedObj["filters"]["custom"] === "object" || + typeof typedObj["filters"]["custom"] === "function") && + typeof typedObj["filters"]["custom"]["isEnabled"] === "boolean" && + typeof typedObj["filters"]["custom"]["selectedGroupId"] === "string" && + Array.isArray(typedObj["filters"]["custom"]["groups"]) && + typedObj["filters"]["custom"]["groups"].every((e: any) => + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + typeof e["name"] === "string" && + Array.isArray(e["rules"]) && + e["rules"].every((e: any) => + ((e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.PROPERTY && + e["propertyType"] === PropertyType.TEXT && + typeof e["propertyName"] === "string" && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST) || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.PROPERTY && + e["propertyType"] === PropertyType.NUMBER && + typeof e["propertyName"] === "string" && + (e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST) || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.PROPERTY && + e["propertyType"] === PropertyType.LIST && + typeof e["propertyName"] === "string" && + (e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST) || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.PROPERTY && + e["propertyType"] === PropertyType.CHECKBOX && + typeof e["propertyName"] === "string" && + (e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST) || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.PROPERTY && + (e["propertyType"] === PropertyType.DATE || + e["propertyType"] === PropertyType.DATETIME) && + typeof e["propertyName"] === "string" && + (e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST) && + typeof e["valueData"] === "string" || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.FOLDER && + (e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT) && + typeof e["includeSubfolders"] === "boolean" || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.FILE_NAME && + (e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) || + (e !== null && + typeof e === "object" || + typeof e === "function") && + typeof e["id"] === "string" && + (e["operator"] === "and" || + e["operator"] === "or") && + (e["type"] === FilterRuleType.PROPERTY || + e["type"] === FilterRuleType.FOLDER || + e["type"] === FilterRuleType.FILE_NAME || + e["type"] === FilterRuleType.CONTENT) && + (e["condition"] === TextFilterCondition.IS || + e["condition"] === TextFilterCondition.IS_NOT || + e["condition"] === TextFilterCondition.CONTAINS || + e["condition"] === TextFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === TextFilterCondition.STARTS_WITH || + e["condition"] === TextFilterCondition.ENDS_WITH || + e["condition"] === TextFilterCondition.EXISTS || + e["condition"] === TextFilterCondition.DOES_NOT_EXIST || + e["condition"] === NumberFilterCondition.IS_EQUAL || + e["condition"] === NumberFilterCondition.IS_NOT_EQUAL || + e["condition"] === NumberFilterCondition.IS_GREATER || + e["condition"] === NumberFilterCondition.IS_LESS || + e["condition"] === NumberFilterCondition.IS_GREATER_OR_EQUAL || + e["condition"] === NumberFilterCondition.IS_LESS_OR_EQUAL || + e["condition"] === NumberFilterCondition.EXISTS || + e["condition"] === NumberFilterCondition.DOES_NOT_EXIST || + e["condition"] === DateFilterCondition.IS || + e["condition"] === DateFilterCondition.IS_BEFORE || + e["condition"] === DateFilterCondition.IS_AFTER || + e["condition"] === DateFilterCondition.IS_ON_OR_BEFORE || + e["condition"] === DateFilterCondition.IS_ON_OR_AFTER || + e["condition"] === DateFilterCondition.EXISTS || + e["condition"] === DateFilterCondition.DOES_NOT_EXIST || + e["condition"] === CheckboxFilterCondition.IS || + e["condition"] === CheckboxFilterCondition.IS_NOT || + e["condition"] === CheckboxFilterCondition.EXISTS || + e["condition"] === CheckboxFilterCondition.DOES_NOT_EXIST || + e["condition"] === ListFilterCondition.CONTAINS || + e["condition"] === ListFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ListFilterCondition.EXISTS || + e["condition"] === ListFilterCondition.DOES_NOT_EXIST || + e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY || + e["condition"] === FolderFilterCondition.IS || + e["condition"] === FolderFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.IS || + e["condition"] === FileNameFilterCondition.IS_NOT || + e["condition"] === FileNameFilterCondition.CONTAINS || + e["condition"] === FileNameFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === FileNameFilterCondition.STARTS_WITH || + e["condition"] === FileNameFilterCondition.ENDS_WITH) && + typeof e["isEnabled"] === "boolean" && + typeof e["value"] === "string" && + typeof e["matchWhenPropertyDNE"] === "boolean" && + e["type"] === FilterRuleType.CONTENT && + (e["condition"] === ContentFilterCondition.CONTAINS || + e["condition"] === ContentFilterCondition.DOES_NOT_CONTAIN || + e["condition"] === ContentFilterCondition.IS_EMPTY || + e["condition"] === ContentFilterCondition.IS_NOT_EMPTY)) + ) && + typeof e["isEnabled"] === "boolean" && + typeof e["isSticky"] === "boolean" + ) && + (typedObj["views"] !== null && + typeof typedObj["views"] === "object" || + typeof typedObj["views"] === "function") && + (typedObj["views"]["dashboard"] !== null && + typeof typedObj["views"]["dashboard"] === "object" || + typeof typedObj["views"]["dashboard"] === "function") && + typeof typedObj["views"]["dashboard"]["isEnabled"] === "boolean" && + (typedObj["views"]["grid"] !== null && + typeof typedObj["views"]["grid"] === "object" || + typeof typedObj["views"]["grid"] === "function") && + typeof typedObj["views"]["grid"]["isEnabled"] === "boolean" && + (typedObj["views"]["list"] !== null && + typeof typedObj["views"]["list"] === "object" || + typeof typedObj["views"]["list"] === "function") && + typeof typedObj["views"]["list"]["isEnabled"] === "boolean" && + (typedObj["views"]["table"] !== null && + typeof typedObj["views"]["table"] === "object" || + typeof typedObj["views"]["table"] === "function") && + typeof typedObj["views"]["table"]["isEnabled"] === "boolean" && + (typedObj["views"]["feed"] !== null && + typeof typedObj["views"]["feed"] === "object" || + typeof typedObj["views"]["feed"] === "function") && + typeof typedObj["views"]["feed"]["isEnabled"] === "boolean" && + (typedObj["views"]["recommended"] !== null && + typeof typedObj["views"]["recommended"] === "object" || + typeof typedObj["views"]["recommended"] === "function") && + typeof typedObj["views"]["recommended"]["isEnabled"] === "boolean" && + (typedObj["views"]["related"] !== null && + typeof typedObj["views"]["related"] === "object" || + typeof typedObj["views"]["related"] === "function") && + typeof typedObj["views"]["related"]["isEnabled"] === "boolean" && + (typedObj["titleWrapping"] === "normal" || + typedObj["titleWrapping"] === "break-word") && + typeof typedObj["enableClockUpdates"] === "boolean" && + (typedObj["currentView"] === null || + typedObj["currentView"] === TExplorerView.DASHBOARD || + typedObj["currentView"] === TExplorerView.GRID || + typedObj["currentView"] === TExplorerView.LIST || + typedObj["currentView"] === TExplorerView.FEED || + typedObj["currentView"] === TExplorerView.TABLE || + typedObj["currentView"] === TExplorerView.RECOMMENDED || + typedObj["currentView"] === TExplorerView.RELATED) && + typeof typedObj["enableScrollButtons"] === "boolean" && + typeof typedObj["pageSize"] === "number" && + (typedObj["pluginVersion"] === null || + typeof typedObj["pluginVersion"] === "string") && + Array.isArray(typedObj["viewOrder"]) && + typedObj["viewOrder"].every((e: any) => + (e === TExplorerView.DASHBOARD || + e === TExplorerView.GRID || + e === TExplorerView.LIST || + e === TExplorerView.FEED || + e === TExplorerView.TABLE || + e === TExplorerView.RECOMMENDED || + e === TExplorerView.RELATED) + ) && + typeof typedObj["logLevel"] === "string" + ) +} diff --git a/src/types/index.ts b/src/types/index.ts index 5369044..6d4a6a5 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,4 @@ +/** @see {isVaultExplorerPluginSettings} ts-auto-guard:type-guard */ export interface VaultExplorerPluginSettings { properties: { favorite: string; diff --git a/src/types/types-0.3.0.ts b/src/types/types-0.3.3.ts similarity index 95% rename from src/types/types-0.3.0.ts rename to src/types/types-0.3.3.ts index 716c695..9011b25 100644 --- a/src/types/types-0.3.0.ts +++ b/src/types/types-0.3.3.ts @@ -22,6 +22,8 @@ export interface VaultExplorerPluginSettings_0_3_3 { pluginVersion: string | null; } +export { TextFilterCondition as TextFilterCondition_0_3_3 }; + interface TextPropertyFilter extends BasePropertyFilter { condition: TextFilterCondition; value: string; diff --git a/src/types/types-0.5.5.ts b/src/types/types-0.5.5.ts index dbb990a..389d0e5 100644 --- a/src/types/types-0.5.5.ts +++ b/src/types/types-0.5.5.ts @@ -22,6 +22,8 @@ export interface VaultExplorerPluginSettings_0_5_5 { pluginVersion: string | null; } +export { TextFilterCondition as TextFilterCondition_0_5_5, PropertyFilterType as PropertyFilterType_0_5_5, NumberFilterCondition as NumberFilterCondition_0_5_5, ListFilterCondition as ListFilterCondition_0_5_5, CheckboxFilterCondition as CheckboxFilterCondition_0_5_5, DateFilterCondition as DateFilterCondition_0_5_5 }; + export type FilterOperator = "and" | "or"; export enum TextFilterCondition { diff --git a/src/types/types-1.12.1.ts b/src/types/types-1.12.1.ts index ec468fd..682c1eb 100644 --- a/src/types/types-1.12.1.ts +++ b/src/types/types-1.12.1.ts @@ -28,16 +28,18 @@ export interface VaultExplorerPluginSettings_1_12_1 { pluginVersion: string | null; } -export type WordBreak = "normal" | "break-word"; +export { FilterRuleType as FilterRuleType_1_12_1 }; -export enum ViewType { +type WordBreak = "normal" | "break-word"; + +enum ViewType { GRID = "grid", LIST = "list", } -export type FilterOperator = "and" | "or"; +type FilterOperator = "and" | "or"; -export enum TextFilterCondition { +enum TextFilterCondition { IS = "is", IS_NOT = "is-not", CONTAINS = "contains", @@ -48,14 +50,14 @@ export enum TextFilterCondition { DOES_NOT_EXIST = "does-not-exist", } -export enum ListFilterCondition { +enum ListFilterCondition { CONTAINS = "contains", DOES_NOT_CONTAIN = "does-not-contain", EXISTS = "exists", DOES_NOT_EXIST = "does-not-exist", } -export enum NumberFilterCondition { +enum NumberFilterCondition { IS_EQUAL = "is-equal", IS_NOT_EQUAL = "is-not-equal", IS_GREATER = "is-greater", @@ -66,14 +68,14 @@ export enum NumberFilterCondition { DOES_NOT_EXIST = "does-not-exist", } -export enum CheckboxFilterCondition { +enum CheckboxFilterCondition { IS = "is", IS_NOT = "is-not", EXISTS = "exists", DOES_NOT_EXIST = "does-not-exist", } -export enum DateFilterCondition { +enum DateFilterCondition { IS = "is", IS_BEFORE = "is-before", IS_AFTER = "is-after", @@ -83,19 +85,19 @@ export enum DateFilterCondition { DOES_NOT_EXIST = "does-not-exist", } -export enum ContentFilterCondition { +enum ContentFilterCondition { CONTAINS = "contains", DOES_NOT_CONTAIN = "does-not-contain", IS_EMPTY = "is-empty", IS_NOT_EMPTY = "is-not-empty", } -export enum FolderFilterCondition { +enum FolderFilterCondition { IS = "is", IS_NOT = "is-not", } -export enum FileNameFilterCondition { +enum FileNameFilterCondition { IS = "is", IS_NOT = "is-not", CONTAINS = "contains", @@ -104,10 +106,10 @@ export enum FileNameFilterCondition { ENDS_WITH = "ends-with", } -export type FilterCondition = TextFilterCondition | NumberFilterCondition | DateFilterCondition | CheckboxFilterCondition | ListFilterCondition | ContentFilterCondition | FolderFilterCondition | FileNameFilterCondition; +type FilterCondition = TextFilterCondition | NumberFilterCondition | DateFilterCondition | CheckboxFilterCondition | ListFilterCondition | ContentFilterCondition | FolderFilterCondition | FileNameFilterCondition; //This matches the Obsidian property types -export enum PropertyType { +enum PropertyType { TEXT = "text", NUMBER = "number", LIST = "list", @@ -116,14 +118,14 @@ export enum PropertyType { DATETIME = "datetime", } -export enum FilterRuleType { +enum FilterRuleType { PROPERTY = "property", FOLDER = "folder", FILE_NAME = "file-name", CONTENT = "content", } -export enum DatePropertyFilterValue { +enum DatePropertyFilterValue { TODAY = "today", TOMORROW = "tomorrow", YESTERDAY = "yesterday", @@ -144,35 +146,35 @@ interface BaseFilterRule { matchWhenPropertyDNE: boolean; } -export interface TextPropertyFilterRule extends BaseFilterRule { +interface TextPropertyFilterRule extends BaseFilterRule { type: FilterRuleType.PROPERTY; propertyType: PropertyType.TEXT; propertyName: string; condition: TextFilterCondition; } -export interface NumberPropertyFilterRule extends BaseFilterRule { +interface NumberPropertyFilterRule extends BaseFilterRule { type: FilterRuleType.PROPERTY; propertyType: PropertyType.NUMBER; propertyName: string; condition: NumberFilterCondition; } -export interface ListPropertyFilterRule extends BaseFilterRule { +interface ListPropertyFilterRule extends BaseFilterRule { type: FilterRuleType.PROPERTY; propertyType: PropertyType.LIST; propertyName: string; condition: ListFilterCondition; } -export interface CheckboxPropertyFilterRule extends BaseFilterRule { +interface CheckboxPropertyFilterRule extends BaseFilterRule { type: FilterRuleType.PROPERTY; propertyType: PropertyType.CHECKBOX; propertyName: string; condition: CheckboxFilterCondition; } -export interface DatePropertyFilterRule extends BaseFilterRule { +interface DatePropertyFilterRule extends BaseFilterRule { type: FilterRuleType.PROPERTY; propertyType: PropertyType.DATE | PropertyType.DATETIME; propertyName: string; @@ -180,32 +182,32 @@ export interface DatePropertyFilterRule extends BaseFilterRule { valueData: string; } -export interface FolderFilterRule extends BaseFilterRule { +interface FolderFilterRule extends BaseFilterRule { type: FilterRuleType.FOLDER; condition: FolderFilterCondition; includeSubfolders: boolean; } -export interface FileNameFilterRule extends BaseFilterRule { +interface FileNameFilterRule extends BaseFilterRule { type: FilterRuleType.FILE_NAME; condition: FileNameFilterCondition; } -export interface ContentFilterRule extends BaseFilterRule { +interface ContentFilterRule extends BaseFilterRule { type: FilterRuleType.CONTENT; condition: ContentFilterCondition; } -export type FilterRule = PropertyFilterRule | FolderFilterRule | FileNameFilterRule | ContentFilterRule; -export type PropertyFilterRule = TextPropertyFilterRule | NumberPropertyFilterRule | ListPropertyFilterRule | CheckboxPropertyFilterRule | DatePropertyFilterRule; +type FilterRule = PropertyFilterRule | FolderFilterRule | FileNameFilterRule | ContentFilterRule; +type PropertyFilterRule = TextPropertyFilterRule | NumberPropertyFilterRule | ListPropertyFilterRule | CheckboxPropertyFilterRule | DatePropertyFilterRule; -export interface FilterGroup { +interface FilterGroup { id: string; name: string; rules: FilterRule[]; isEnabled: boolean; } -export type SortFilter = "file-name-asc" | "file-name-desc" | "modified-asc" | "modified-desc"; +type SortFilter = "file-name-asc" | "file-name-desc" | "modified-asc" | "modified-desc"; -export type TimestampFilter = "created-today" | "modified-today" | "created-this-week" | "modified-this-week" | "created-2-weeks" | "modified-2-weeks" | "all"; +type TimestampFilter = "created-today" | "modified-today" | "created-this-week" | "modified-this-week" | "created-2-weeks" | "modified-2-weeks" | "all"; diff --git a/tests/integration/preform-migration.test.ts b/tests/integration/preform-migration.test.ts new file mode 100644 index 0000000..1edd199 --- /dev/null +++ b/tests/integration/preform-migration.test.ts @@ -0,0 +1,189 @@ +import { preformMigrations } from "src/migrations"; +import { isVaultExplorerPluginSettings } from "src/types/index.guard"; +import { TextFilterCondition_0_3_3, VaultExplorerPluginSettings_0_3_3 } from "src/types/types-0.3.3"; +import { CheckboxFilterCondition_0_5_5, DateFilterCondition_0_5_5, ListFilterCondition_0_5_5, NumberFilterCondition_0_5_5, PropertyFilterType_0_5_5, TextFilterCondition_0_5_5, VaultExplorerPluginSettings_0_5_5 } from "src/types/types-0.5.5"; + +describe("preformMigrations", () => { + it("should migrate from 0.3.3 to the latest version", () => { + //Arrange + const settingsData: VaultExplorerPluginSettings_0_3_3 = { + "properties": { + "favorite": "note-123", + "url": "https://example.com", + "custom1": "custom-value-1", + "custom2": "custom-value-2", + "custom3": "custom-value-3" + }, + "filters": { + "folder": "MyNotes", + "search": "project", + "onlyFavorites": true, + "sort": "file-name-asc", + "timestamp": "created-today", + "properties": { + "selectedGroupId": "group-1", + "groups": [ + { + "id": "group-1", + "name": "Project Filters", + "filters": [ + { + "id": "filter-1", + "propertyName": "status", + "operator": "and", + "isEnabled": true, + "condition": TextFilterCondition_0_3_3.IS, + "value": "active" + }, + { + "id": "filter-2", + "propertyName": "priority", + "operator": "or", + "isEnabled": false, + "condition": TextFilterCondition_0_3_3.CONTAINS, + "value": "high" + } + ], + "position": 0, + "isEnabled": true + }, + { + "id": "group-2", + "name": "Personal Filters", + "filters": [ + { + "id": "filter-3", + "propertyName": "tag", + "operator": "and", + "isEnabled": true, + "condition": TextFilterCondition_0_3_3.STARTS_WITH, + "value": "work" + }, + { + "id": "filter-4", + "propertyName": "deadline", + "operator": "or", + "isEnabled": true, + "condition": TextFilterCondition_0_3_3.IS_NOT_EMPTY, + "value": "" + } + ], + "position": 1, + "isEnabled": false + } + ] + } + }, + "currentView": "grid", + "pageSize": 20, + "pluginVersion": "0.3.3" + } + + //Same guard clause as in main.js + if (settingsData.pluginVersion === null) return; + + //Act + const result = preformMigrations(settingsData.pluginVersion, settingsData as unknown as Record); + + //Assert + expect(isVaultExplorerPluginSettings(result)).toBe(true); + }); + + it("should migrate from 0.4.0 to the latest version", () => { + //Arrange + const settingsData: VaultExplorerPluginSettings_0_5_5 = { + properties: { + favorite: "yes", + url: "https://example.com", + custom1: "customValue1", + custom2: "customValue2", + custom3: "customValue3" + }, + filters: { + folder: "root", + search: "example search", + onlyFavorites: true, + sort: "file-name-asc", + timestamp: "created-today", + properties: { + selectedGroupId: "group1", + groups: [ + { + id: "group1", + name: "Group 1", + filters: [ + { + id: "filter1", + propertyName: "name", + operator: "and", + type: PropertyFilterType_0_5_5.TEXT, + isEnabled: true, + value: "example", + condition: TextFilterCondition_0_5_5.CONTAINS + }, + { + id: "filter2", + propertyName: "size", + operator: "or", + type: PropertyFilterType_0_5_5.NUMBER, + isEnabled: true, + value: "100", + condition: NumberFilterCondition_0_5_5.IS_GREATER + } + ], + position: 1, + isEnabled: true + }, + { + id: "group2", + name: "Group 2", + filters: [ + { + id: "filter3", + propertyName: "tags", + operator: "and", + type: PropertyFilterType_0_5_5.LIST, + isEnabled: true, + value: "important", + condition: ListFilterCondition_0_5_5.CONTAINS + }, + { + id: "filter4", + propertyName: "isArchived", + operator: "or", + type: PropertyFilterType_0_5_5.CHECKBOX, + isEnabled: true, + value: "true", + condition: CheckboxFilterCondition_0_5_5.IS + }, + { + id: "filter5", + propertyName: "dateCreated", + operator: "and", + type: PropertyFilterType_0_5_5.DATE, + isEnabled: true, + value: "2023-01-01", + condition: DateFilterCondition_0_5_5.IS_AFTER + } + ], + position: 2, + isEnabled: true + } + ] + } + }, + currentView: "list", + pageSize: 20, + pluginVersion: "0.4.0" + }; + + //This the same guard clause as in main.js + if (settingsData.pluginVersion === null) return; + + //Act + const result = preformMigrations(settingsData.pluginVersion, settingsData as unknown as Record); + + //Assert + expect(isVaultExplorerPluginSettings(result)).toBe(true); + }); +}); diff --git a/tests/unit/match-number-property-filter.test.ts b/tests/unit/match-number-property-filter.test.ts index ae070cf..51c6738 100644 --- a/tests/unit/match-number-property-filter.test.ts +++ b/tests/unit/match-number-property-filter.test.ts @@ -156,9 +156,7 @@ describe('matchNumberPropertyFilter', () => { const matchIfNull = false; // Act & Assert - expect(() => matchNumberPropertyFilter(propertyValue, compare, condition, matchIfNull)).toThrow( - `Number filter condition not supported: ${condition}` - ); + expect(() => matchNumberPropertyFilter(propertyValue, compare, condition, matchIfNull)).toThrow() }); }); }); diff --git a/versions.json b/versions.json index 1f0c3bd..882a783 100644 --- a/versions.json +++ b/versions.json @@ -74,5 +74,6 @@ "1.15.0": "1.4.13", "1.16.0": "1.4.13", "1.17.0": "1.4.13", - "1.17.1": "1.4.13" + "1.17.1": "1.4.13", + "1.17.2": "1.4.13" }