Add proxy routing and sing-box support

This commit is contained in:
Fabian Freund
2026-05-22 18:16:31 +02:00
parent 51289f1266
commit a5974617aa
262 changed files with 32003 additions and 3962 deletions
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:drift/drift.dart';
import 'package:weblibre/features/user/data/database/daos/proxy_profile.drift.dart';
import 'package:weblibre/features/user/data/database/database.dart';
import 'package:weblibre/features/user/data/database/definitions.drift.dart';
@DriftAccessor()
class ProxyProfileDao extends DatabaseAccessor<UserDatabase>
with $ProxyProfileDaoMixin {
ProxyProfileDao(super.attachedDatabase);
Selectable<ProxyProfile> watch() {
return db.proxyProfile.select()
..orderBy([(t) => OrderingTerm.asc(t.createdAt)]);
}
Future<List<ProxyProfile>> fetchAll() => watch().get();
Future<ProxyProfile?> findById(String id) {
return (db.proxyProfile.select()
..where((t) => t.id.equals(id))
..limit(1))
.getSingleOrNull();
}
Future<void> upsert(ProxyProfile profile) {
return db.proxyProfile.insertOne(
profile,
onConflict: DoUpdate(
(_) => ProxyProfileCompanion(
name: Value(profile.name),
type: Value(profile.type),
configJson: Value(profile.configJson),
dnsOverrideJson: Value(profile.dnsOverrideJson),
updatedAt: Value(profile.updatedAt),
),
target: [db.proxyProfile.id],
),
);
}
Future<void> deleteById(String id) {
return (db.proxyProfile.delete()..where((t) => t.id.equals(id))).go();
}
}
@@ -0,0 +1,13 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:weblibre/features/user/data/database/database.dart' as i1;
mixin $ProxyProfileDaoMixin on i0.DatabaseAccessor<i1.UserDatabase> {
ProxyProfileDaoManager get managers => ProxyProfileDaoManager(this);
}
class ProxyProfileDaoManager {
final $ProxyProfileDaoMixin _db;
ProxyProfileDaoManager(this._db);
}
@@ -23,6 +23,7 @@ import 'package:drift_dev/api/migrations_native.dart';
import 'package:flutter/foundation.dart';
import 'package:weblibre/features/user/data/database/daos/cache.dart';
import 'package:weblibre/features/user/data/database/daos/onboarding.dart';
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart';
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart';
import 'package:weblibre/features/user/data/database/daos/setting.dart';
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart';
@@ -37,11 +38,12 @@ import 'package:weblibre/features/user/data/database/database.steps.dart';
OnboardingDao,
ToolbarButtonConfigDao,
SearchTokensDao,
ProxyProfileDao,
],
)
class UserDatabase extends $UserDatabase {
@override
final int schemaVersion = 5;
final int schemaVersion = 8;
@override
MigrationStrategy get migration => MigrationStrategy(
@@ -103,5 +105,21 @@ class UserDatabase extends $UserDatabase {
await m.addColumn(schema.searchTokens, schema.searchTokens.reservedAt);
await m.createIndex(schema.idxSearchTokensReservedAt);
},
from5To6: (m, schema) async {
await m.createTable(schema.proxyProfile);
await m.createIndex(schema.idxProxyProfileUpdatedAt);
await m.createTable(schema.proxyRoutingSetting);
},
from6To7: (m, schema) async {
await m.addColumn(
schema.proxyProfile,
schema.proxyProfile.dnsOverrideJson,
);
},
from7To8: (m, schema) async {
await m.database.customStatement(
'DROP TABLE IF EXISTS proxy_routing_setting',
);
},
);
}
@@ -12,13 +12,16 @@ import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.
as i6;
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart'
as i7;
import 'package:drift/internal/modular.dart' as i8;
import 'package:sqlite3/common.dart' as i9;
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart'
as i8;
import 'package:drift/internal/modular.dart' as i9;
import 'package:sqlite3/common.dart' as i10;
abstract class $UserDatabase extends i0.GeneratedDatabase {
$UserDatabase(i0.QueryExecutor e) : super(e);
$UserDatabaseManager get managers => $UserDatabaseManager(this);
late final i1.Setting setting = i1.Setting(this);
late final i1.ProxyProfileTable proxyProfile = i1.ProxyProfileTable(this);
late final i1.IconCache iconCache = i1.IconCache(this);
late final i1.Onboarding onboarding = i1.Onboarding(this);
late final i1.Riverpod riverpod = i1.Riverpod(this);
@@ -35,7 +38,10 @@ abstract class $UserDatabase extends i0.GeneratedDatabase {
late final i7.SearchTokensDao searchTokensDao = i7.SearchTokensDao(
this as i3.UserDatabase,
);
i1.DefinitionsDrift get definitionsDrift => i8.ReadDatabaseContainer(
late final i8.ProxyProfileDao proxyProfileDao = i8.ProxyProfileDao(
this as i3.UserDatabase,
);
i1.DefinitionsDrift get definitionsDrift => i9.ReadDatabaseContainer(
this,
).accessor<i1.DefinitionsDrift>(i1.DefinitionsDrift.new);
@override
@@ -44,6 +50,8 @@ abstract class $UserDatabase extends i0.GeneratedDatabase {
@override
List<i0.DatabaseSchemaEntity> get allSchemaEntities => [
setting,
proxyProfile,
i1.idxProxyProfileUpdatedAt,
iconCache,
onboarding,
riverpod,
@@ -60,6 +68,8 @@ class $UserDatabaseManager {
$UserDatabaseManager(this._db);
i1.$SettingTableManager get setting =>
i1.$SettingTableManager(_db, _db.setting);
i1.$ProxyProfileTableTableManager get proxyProfile =>
i1.$ProxyProfileTableTableManager(_db, _db.proxyProfile);
i1.$IconCacheTableManager get iconCache =>
i1.$IconCacheTableManager(_db, _db.iconCache);
i1.$OnboardingTableManager get onboarding =>
@@ -72,7 +82,7 @@ class $UserDatabaseManager {
i1.$SearchTokensTableManager(_db, _db.searchTokens);
}
extension DefineFunctions on i9.CommonDatabase {
extension DefineFunctions on i10.CommonDatabase {
void defineFunctions({
required String Function(int, String?) lexoRankNext,
required String Function(int, String?) lexoRankPrevious,
@@ -86,7 +96,7 @@ extension DefineFunctions on i9.CommonDatabase {
}) {
createFunction(
functionName: 'lexo_rank_next',
argumentCount: const i9.AllowedArgumentCount(2),
argumentCount: const i10.AllowedArgumentCount(2),
function: (args) {
final arg0 = args[0] as int;
final arg1 = args[1] as String?;
@@ -95,7 +105,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'lexo_rank_previous',
argumentCount: const i9.AllowedArgumentCount(2),
argumentCount: const i10.AllowedArgumentCount(2),
function: (args) {
final arg0 = args[0] as int;
final arg1 = args[1] as String?;
@@ -104,7 +114,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'lexo_rank_reorder_after',
argumentCount: const i9.AllowedArgumentCount(2),
argumentCount: const i10.AllowedArgumentCount(2),
function: (args) {
final arg0 = args[0] as String?;
final arg1 = args[1] as String?;
@@ -113,7 +123,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'lexo_rank_reorder_before',
argumentCount: const i9.AllowedArgumentCount(2),
argumentCount: const i10.AllowedArgumentCount(2),
function: (args) {
final arg0 = args[0] as String?;
final arg1 = args[1] as String?;
@@ -122,14 +132,14 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'generate_content_hash',
argumentCount: const i9.AllowedArgumentCount(0),
argumentCount: const i10.AllowedArgumentCount(0),
function: (args) {
return generateContentHash();
},
);
createFunction(
functionName: 'url_indexable',
argumentCount: const i9.AllowedArgumentCount(1),
argumentCount: const i10.AllowedArgumentCount(1),
function: (args) {
final arg0 = args[0] as String?;
return urlIndexable(arg0);
@@ -137,7 +147,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'url_canonical',
argumentCount: const i9.AllowedArgumentCount(1),
argumentCount: const i10.AllowedArgumentCount(1),
function: (args) {
final arg0 = args[0] as String?;
return urlCanonical(arg0);
@@ -145,7 +155,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'url_host',
argumentCount: const i9.AllowedArgumentCount(1),
argumentCount: const i10.AllowedArgumentCount(1),
function: (args) {
final arg0 = args[0] as String?;
return urlHost(arg0);
@@ -153,7 +163,7 @@ extension DefineFunctions on i9.CommonDatabase {
);
createFunction(
functionName: 'url_path',
argumentCount: const i9.AllowedArgumentCount(1),
argumentCount: const i10.AllowedArgumentCount(1),
function: (args) {
final arg0 = args[0] as String?;
return urlPath(arg0);
@@ -563,11 +563,536 @@ i1.GeneratedColumn<int> _column_19(String aliasedName) =>
type: i1.DriftSqlType.int,
$customConstraints: '',
);
final class Schema6 extends i0.VersionedSchema {
Schema6({required super.database}) : super(version: 6);
@override
late final List<i1.DatabaseSchemaEntity> entities = [
setting,
proxyProfile,
idxProxyProfileUpdatedAt,
proxyRoutingSetting,
iconCache,
onboarding,
riverpod,
toolbarButtonConfigs,
idxToolbarOrderKey,
searchTokens,
idxSearchTokensInsertedAt,
idxSearchTokensReservedAt,
];
late final Shape0 setting = Shape0(
source: i0.VersionedTable(
entityName: 'setting',
withoutRowId: false,
isStrict: true,
tableConstraints: [],
columns: [_column_0, _column_1, _column_2],
attachedDatabase: database,
),
alias: null,
);
late final Shape7 proxyProfile = Shape7(
source: i0.VersionedTable(
entityName: 'proxy_profile',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [
_column_20,
_column_21,
_column_22,
_column_23,
_column_24,
_column_25,
],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxProxyProfileUpdatedAt = i1.Index(
'idx_proxy_profile_updated_at',
'CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile (updated_at)',
);
late final Shape8 proxyRoutingSetting = Shape8(
source: i0.VersionedTable(
entityName: 'proxy_routing_setting',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_26, _column_27, _column_28, _column_29],
attachedDatabase: database,
),
alias: null,
);
late final Shape1 iconCache = Shape1(
source: i0.VersionedTable(
entityName: 'icon_cache',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_3, _column_4, _column_5],
attachedDatabase: database,
),
alias: null,
);
late final Shape2 onboarding = Shape2(
source: i0.VersionedTable(
entityName: 'onboarding',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_6, _column_7],
attachedDatabase: database,
),
alias: null,
);
late final Shape3 riverpod = Shape3(
source: i0.VersionedTable(
entityName: 'riverpod',
withoutRowId: true,
isStrict: false,
tableConstraints: [],
columns: [_column_0, _column_8, _column_9, _column_10],
attachedDatabase: database,
),
alias: null,
);
late final Shape4 toolbarButtonConfigs = Shape4(
source: i0.VersionedTable(
entityName: 'toolbar_button_configs',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_11, _column_12, _column_13, _column_14],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxToolbarOrderKey = i1.Index(
'idx_toolbar_order_key',
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
);
late final Shape6 searchTokens = Shape6(
source: i0.VersionedTable(
entityName: 'search_tokens',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_15, _column_16, _column_17, _column_18, _column_19],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxSearchTokensInsertedAt = i1.Index(
'idx_search_tokens_inserted_at',
'CREATE INDEX idx_search_tokens_inserted_at ON search_tokens (inserted_at)',
);
final i1.Index idxSearchTokensReservedAt = i1.Index(
'idx_search_tokens_reserved_at',
'CREATE INDEX idx_search_tokens_reserved_at ON search_tokens (reserved_at)',
);
}
class Shape7 extends i0.VersionedTable {
Shape7({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<String> get id =>
columnsByName['id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get name =>
columnsByName['name']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get type =>
columnsByName['type']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get configJson =>
columnsByName['config_json']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get createdAt =>
columnsByName['created_at']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<int> get updatedAt =>
columnsByName['updated_at']! as i1.GeneratedColumn<int>;
}
i1.GeneratedColumn<String> _column_20(String aliasedName) =>
i1.GeneratedColumn<String>(
'id',
aliasedName,
false,
type: i1.DriftSqlType.string,
$customConstraints: 'NOT NULL PRIMARY KEY',
);
i1.GeneratedColumn<String> _column_21(String aliasedName) =>
i1.GeneratedColumn<String>(
'name',
aliasedName,
false,
type: i1.DriftSqlType.string,
$customConstraints: 'NOT NULL',
);
i1.GeneratedColumn<String> _column_22(String aliasedName) =>
i1.GeneratedColumn<String>(
'type',
aliasedName,
false,
type: i1.DriftSqlType.string,
$customConstraints: 'NOT NULL',
);
i1.GeneratedColumn<String> _column_23(String aliasedName) =>
i1.GeneratedColumn<String>(
'config_json',
aliasedName,
false,
type: i1.DriftSqlType.string,
$customConstraints: 'NOT NULL',
);
i1.GeneratedColumn<int> _column_24(String aliasedName) =>
i1.GeneratedColumn<int>(
'created_at',
aliasedName,
false,
type: i1.DriftSqlType.int,
$customConstraints: 'NOT NULL DEFAULT CURRENT_TIMESTAMP',
defaultValue: const i1.CustomExpression('CURRENT_TIMESTAMP'),
);
i1.GeneratedColumn<int> _column_25(String aliasedName) =>
i1.GeneratedColumn<int>(
'updated_at',
aliasedName,
false,
type: i1.DriftSqlType.int,
$customConstraints: 'NOT NULL DEFAULT CURRENT_TIMESTAMP',
defaultValue: const i1.CustomExpression('CURRENT_TIMESTAMP'),
);
class Shape8 extends i0.VersionedTable {
Shape8({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<int> get id =>
columnsByName['id']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get regularTabsMode =>
columnsByName['regular_tabs_mode']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get regularTabsProxyConnectionId =>
columnsByName['regular_tabs_proxy_connection_id']!
as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get privateTabsProxyConnectionId =>
columnsByName['private_tabs_proxy_connection_id']!
as i1.GeneratedColumn<String>;
}
i1.GeneratedColumn<int> _column_26(String aliasedName) =>
i1.GeneratedColumn<int>(
'id',
aliasedName,
false,
type: i1.DriftSqlType.int,
$customConstraints: 'NOT NULL PRIMARY KEY CHECK (id = 1)',
);
i1.GeneratedColumn<String> _column_27(String aliasedName) =>
i1.GeneratedColumn<String>(
'regular_tabs_mode',
aliasedName,
false,
type: i1.DriftSqlType.string,
$customConstraints: 'NOT NULL',
);
i1.GeneratedColumn<String> _column_28(String aliasedName) =>
i1.GeneratedColumn<String>(
'regular_tabs_proxy_connection_id',
aliasedName,
true,
type: i1.DriftSqlType.string,
$customConstraints: '',
);
i1.GeneratedColumn<String> _column_29(String aliasedName) =>
i1.GeneratedColumn<String>(
'private_tabs_proxy_connection_id',
aliasedName,
true,
type: i1.DriftSqlType.string,
$customConstraints: '',
);
final class Schema7 extends i0.VersionedSchema {
Schema7({required super.database}) : super(version: 7);
@override
late final List<i1.DatabaseSchemaEntity> entities = [
setting,
proxyProfile,
idxProxyProfileUpdatedAt,
proxyRoutingSetting,
iconCache,
onboarding,
riverpod,
toolbarButtonConfigs,
idxToolbarOrderKey,
searchTokens,
idxSearchTokensInsertedAt,
idxSearchTokensReservedAt,
];
late final Shape0 setting = Shape0(
source: i0.VersionedTable(
entityName: 'setting',
withoutRowId: false,
isStrict: true,
tableConstraints: [],
columns: [_column_0, _column_1, _column_2],
attachedDatabase: database,
),
alias: null,
);
late final Shape9 proxyProfile = Shape9(
source: i0.VersionedTable(
entityName: 'proxy_profile',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [
_column_20,
_column_21,
_column_22,
_column_23,
_column_30,
_column_24,
_column_25,
],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxProxyProfileUpdatedAt = i1.Index(
'idx_proxy_profile_updated_at',
'CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile (updated_at)',
);
late final Shape8 proxyRoutingSetting = Shape8(
source: i0.VersionedTable(
entityName: 'proxy_routing_setting',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_26, _column_27, _column_28, _column_29],
attachedDatabase: database,
),
alias: null,
);
late final Shape1 iconCache = Shape1(
source: i0.VersionedTable(
entityName: 'icon_cache',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_3, _column_4, _column_5],
attachedDatabase: database,
),
alias: null,
);
late final Shape2 onboarding = Shape2(
source: i0.VersionedTable(
entityName: 'onboarding',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_6, _column_7],
attachedDatabase: database,
),
alias: null,
);
late final Shape3 riverpod = Shape3(
source: i0.VersionedTable(
entityName: 'riverpod',
withoutRowId: true,
isStrict: false,
tableConstraints: [],
columns: [_column_0, _column_8, _column_9, _column_10],
attachedDatabase: database,
),
alias: null,
);
late final Shape4 toolbarButtonConfigs = Shape4(
source: i0.VersionedTable(
entityName: 'toolbar_button_configs',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_11, _column_12, _column_13, _column_14],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxToolbarOrderKey = i1.Index(
'idx_toolbar_order_key',
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
);
late final Shape6 searchTokens = Shape6(
source: i0.VersionedTable(
entityName: 'search_tokens',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_15, _column_16, _column_17, _column_18, _column_19],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxSearchTokensInsertedAt = i1.Index(
'idx_search_tokens_inserted_at',
'CREATE INDEX idx_search_tokens_inserted_at ON search_tokens (inserted_at)',
);
final i1.Index idxSearchTokensReservedAt = i1.Index(
'idx_search_tokens_reserved_at',
'CREATE INDEX idx_search_tokens_reserved_at ON search_tokens (reserved_at)',
);
}
class Shape9 extends i0.VersionedTable {
Shape9({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<String> get id =>
columnsByName['id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get name =>
columnsByName['name']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get type =>
columnsByName['type']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get configJson =>
columnsByName['config_json']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get dnsOverrideJson =>
columnsByName['dns_override_json']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get createdAt =>
columnsByName['created_at']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<int> get updatedAt =>
columnsByName['updated_at']! as i1.GeneratedColumn<int>;
}
i1.GeneratedColumn<String> _column_30(String aliasedName) =>
i1.GeneratedColumn<String>(
'dns_override_json',
aliasedName,
true,
type: i1.DriftSqlType.string,
$customConstraints: '',
);
final class Schema8 extends i0.VersionedSchema {
Schema8({required super.database}) : super(version: 8);
@override
late final List<i1.DatabaseSchemaEntity> entities = [
setting,
proxyProfile,
idxProxyProfileUpdatedAt,
iconCache,
onboarding,
riverpod,
toolbarButtonConfigs,
idxToolbarOrderKey,
searchTokens,
idxSearchTokensInsertedAt,
idxSearchTokensReservedAt,
];
late final Shape0 setting = Shape0(
source: i0.VersionedTable(
entityName: 'setting',
withoutRowId: false,
isStrict: true,
tableConstraints: [],
columns: [_column_0, _column_1, _column_2],
attachedDatabase: database,
),
alias: null,
);
late final Shape9 proxyProfile = Shape9(
source: i0.VersionedTable(
entityName: 'proxy_profile',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [
_column_20,
_column_21,
_column_22,
_column_23,
_column_30,
_column_24,
_column_25,
],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxProxyProfileUpdatedAt = i1.Index(
'idx_proxy_profile_updated_at',
'CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile (updated_at)',
);
late final Shape1 iconCache = Shape1(
source: i0.VersionedTable(
entityName: 'icon_cache',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_3, _column_4, _column_5],
attachedDatabase: database,
),
alias: null,
);
late final Shape2 onboarding = Shape2(
source: i0.VersionedTable(
entityName: 'onboarding',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_6, _column_7],
attachedDatabase: database,
),
alias: null,
);
late final Shape3 riverpod = Shape3(
source: i0.VersionedTable(
entityName: 'riverpod',
withoutRowId: true,
isStrict: false,
tableConstraints: [],
columns: [_column_0, _column_8, _column_9, _column_10],
attachedDatabase: database,
),
alias: null,
);
late final Shape4 toolbarButtonConfigs = Shape4(
source: i0.VersionedTable(
entityName: 'toolbar_button_configs',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_11, _column_12, _column_13, _column_14],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxToolbarOrderKey = i1.Index(
'idx_toolbar_order_key',
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
);
late final Shape6 searchTokens = Shape6(
source: i0.VersionedTable(
entityName: 'search_tokens',
withoutRowId: false,
isStrict: false,
tableConstraints: [],
columns: [_column_15, _column_16, _column_17, _column_18, _column_19],
attachedDatabase: database,
),
alias: null,
);
final i1.Index idxSearchTokensInsertedAt = i1.Index(
'idx_search_tokens_inserted_at',
'CREATE INDEX idx_search_tokens_inserted_at ON search_tokens (inserted_at)',
);
final i1.Index idxSearchTokensReservedAt = i1.Index(
'idx_search_tokens_reserved_at',
'CREATE INDEX idx_search_tokens_reserved_at ON search_tokens (reserved_at)',
);
}
i0.MigrationStepWithVersion migrationSteps({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
}) {
return (currentVersion, database) async {
switch (currentVersion) {
@@ -591,6 +1116,21 @@ i0.MigrationStepWithVersion migrationSteps({
final migrator = i1.Migrator(database, schema);
await from4To5(migrator, schema);
return 5;
case 5:
final schema = Schema6(database: database);
final migrator = i1.Migrator(database, schema);
await from5To6(migrator, schema);
return 6;
case 6:
final schema = Schema7(database: database);
final migrator = i1.Migrator(database, schema);
await from6To7(migrator, schema);
return 7;
case 7:
final schema = Schema8(database: database);
final migrator = i1.Migrator(database, schema);
await from7To8(migrator, schema);
return 8;
default:
throw ArgumentError.value('Unknown migration from $currentVersion');
}
@@ -602,11 +1142,17 @@ i1.OnUpgrade stepByStep({
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
}) => i0.VersionedSchema.stepByStepHelper(
step: migrationSteps(
from1To2: from1To2,
from2To3: from2To3,
from3To4: from3To4,
from4To5: from4To5,
from5To6: from5To6,
from6To7: from6To7,
from7To8: from7To8,
),
);
@@ -1,9 +1,23 @@
import 'package:flutter_singbox_proxy/flutter_singbox_proxy.dart';
CREATE TABLE setting (
"key" TEXT PRIMARY KEY NOT NULL,
partition_key TEXT,
"value" ANY
) STRICT;
CREATE TABLE proxy_profile (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
type ENUMNAME(SingboxProxyProfileType) NOT NULL,
config_json TEXT NOT NULL,
dns_override_json TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) AS ProxyProfile;
CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile(updated_at);
CREATE TABLE icon_cache (
origin TEXT PRIMARY KEY NOT NULL,
icon_data BLOB NOT NULL,
@@ -104,4 +118,4 @@ evictCacheEntries:
FROM icon_cache
ORDER BY fetch_date DESC
LIMIT -1 OFFSET :limit
);
);
File diff suppressed because it is too large Load Diff