fix: Preserve shared model and SQLite value types during sync (#118)
This commit is contained in:
parent
27d875ee39
commit
1f5501ff97
47 changed files with 25604 additions and 51 deletions
|
|
@ -1,3 +1,10 @@
|
|||
## Unreleased
|
||||
|
||||
- fix: Resolve shared-package models and enums during projection and sync.
|
||||
- fix: Preserve boolean types when syncing SQLite column updates.
|
||||
- fix: Preserve JSON and JSONB field types and values through inserts, updates,
|
||||
and explicit nulls.
|
||||
|
||||
## 0.0.6
|
||||
|
||||
- refactor: BREAKING. Rename integration APIs and ownership scopes:
|
||||
|
|
|
|||
|
|
@ -659,8 +659,18 @@ WHERE (${domainColumnPredicate('spaceId', spaceId)})
|
|||
) async {
|
||||
if (rowIds.isEmpty || updates.isEmpty) return;
|
||||
|
||||
final columns = {
|
||||
for (final column in syncTableByName[tableName]!.columns)
|
||||
column.columnName: column,
|
||||
};
|
||||
final assignments = updates.entries
|
||||
.map((e) => '"${e.key.escapeIdentifier()}" = ${e.value.sqlLiteral()}')
|
||||
.map((entry) {
|
||||
final value = ValueEncoder.instance.encodeColumnValue(
|
||||
columns[entry.key]!,
|
||||
entry.value,
|
||||
);
|
||||
return '"${entry.key.escapeIdentifier()}" = $value';
|
||||
})
|
||||
.join(', ');
|
||||
|
||||
await database.unsafeExecute(
|
||||
|
|
|
|||
|
|
@ -259,6 +259,21 @@ String canonicalProjectionValue(Object? value) {
|
|||
@internal
|
||||
bool projectionValuesEqual(Object? left, Object? right) {
|
||||
if (left == null || right == null) return left == right;
|
||||
if (left is Map && right is Map) {
|
||||
return left.length == right.length &&
|
||||
left.entries.every(
|
||||
(entry) =>
|
||||
right.containsKey(entry.key) &&
|
||||
projectionValuesEqual(entry.value, right[entry.key]),
|
||||
);
|
||||
}
|
||||
if (left is List && right is List) {
|
||||
if (left.length != right.length) return false;
|
||||
for (var index = 0; index < left.length; index++) {
|
||||
if (!projectionValuesEqual(left[index], right[index])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
final leftUuid = tryUuidValue(left);
|
||||
final rightUuid = tryUuidValue(right);
|
||||
if (leftUuid != null && rightUuid != null) {
|
||||
|
|
|
|||
|
|
@ -598,6 +598,9 @@ class CrdtMutationRecorder {
|
|||
data[column.fieldName] = planned[column.columnName];
|
||||
}
|
||||
}
|
||||
// Ask the serialization manager for the name it resolves this row by. A
|
||||
// model from a shared package writes its own unprefixed `__className__`,
|
||||
// while the host protocol only answers to the prefixed form.
|
||||
final className =
|
||||
_session.db.serializationManager.getClassNameForObject(row) ??
|
||||
data['__className__'] as String?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:serverpod_database/serverpod_database.dart';
|
||||
|
|
@ -97,14 +98,6 @@ class OfflineSyncEngine {
|
|||
if (definition.dartName != null) definition.name: definition.dartName!,
|
||||
};
|
||||
|
||||
late final Map<String, Map<String, ColumnDefinition>> _columnDefinitionsByTableName =
|
||||
{
|
||||
for (final definition in _serializationManager.getTargetTableDefinitions())
|
||||
definition.name: {
|
||||
for (final column in definition.columns) column.name: column,
|
||||
},
|
||||
};
|
||||
|
||||
/// The deterministic hash representing the current synchronized schema.
|
||||
late final String currentSyncTablesHash = computeSyncTablesHash(
|
||||
_syncTables,
|
||||
|
|
@ -835,7 +828,10 @@ class OfflineSyncEngine {
|
|||
DomainRowOwnerCache ownerCache,
|
||||
) async {
|
||||
final cols = table.columns
|
||||
.map((column) => '"${column.columnName.escapeIdentifier()}"')
|
||||
.map(
|
||||
(column) =>
|
||||
'${_outboundColumnExpression(session, column)} AS "${column.columnName.escapeIdentifier()}"',
|
||||
)
|
||||
.join(', ');
|
||||
final encodedRowId = rowId.sqlLiteral();
|
||||
final encodedSpaceId = spaceId.sqlLiteral();
|
||||
|
|
@ -851,16 +847,32 @@ class OfflineSyncEngine {
|
|||
}
|
||||
ownerCache[(tableName, rowId)] = (exists: true, spaceId: spaceId);
|
||||
|
||||
final columnMap = result.first.toColumnMap()
|
||||
// Domain columns hold visible/materialized FK values; restore attempted
|
||||
// values for override columns before building the outbound merge payload.
|
||||
..applyAuthoredAttemptedValues(attemptedValueFields)
|
||||
// spaceId is local ownership metadata; it is never emitted on the wire.
|
||||
..remove('spaceId');
|
||||
final rawColumns = result.first.toColumnMap();
|
||||
final columnMap =
|
||||
<String, dynamic>{
|
||||
for (final column in table.columns)
|
||||
column.columnName: _decodeStructuredValue(
|
||||
session,
|
||||
column,
|
||||
rawColumns[column.columnName],
|
||||
),
|
||||
}
|
||||
// Domain columns hold visible/materialized FK values; restore attempted
|
||||
// values for override columns before building the outbound merge payload.
|
||||
..applyAuthoredAttemptedValues(attemptedValueFields)
|
||||
// spaceId is local ownership metadata; it is never emitted on the wire.
|
||||
..remove('spaceId');
|
||||
|
||||
final row = session.db.serializationManager.deserializeByClassName({
|
||||
'className': dartName,
|
||||
'data': columnMap,
|
||||
// A table definition names its class the way its own package spells it, so
|
||||
// a model owned by a shared package reports the unprefixed name while the
|
||||
// host protocol answers only to the package-prefixed one. Carrying the name
|
||||
// in the payload lets the host fall through to the protocol that owns the
|
||||
// model rather than failing on a name it does not know.
|
||||
// `Object` rather than `dynamic`: a dynamic target is read as a wrapped
|
||||
// dynamic field instead of a model payload.
|
||||
final row = session.db.serializationManager.deserialize<Object>({
|
||||
...columnMap,
|
||||
'__className__': dartName,
|
||||
});
|
||||
return (exists: true, ownerSpaceId: spaceId, row: row);
|
||||
}
|
||||
|
|
@ -895,8 +907,11 @@ class OfflineSyncEngine {
|
|||
final encodedRowId = rowId.sqlLiteral();
|
||||
final encodedSpaceId = spaceId.sqlLiteral();
|
||||
final escapedTableName = tableName.escapeIdentifier();
|
||||
final column = _syncTablesByName[tableName]!.columns.singleWhere(
|
||||
(c) => c.columnName == columnName,
|
||||
);
|
||||
final result = await session.db.unsafeQuery(
|
||||
'SELECT "${columnName.escapeIdentifier()}" '
|
||||
'SELECT ${_outboundColumnExpression(session, column)} '
|
||||
'FROM "$escapedTableName" '
|
||||
'WHERE "id" = $encodedRowId AND "spaceId" = $encodedSpaceId '
|
||||
'LIMIT 1',
|
||||
|
|
@ -906,7 +921,11 @@ class OfflineSyncEngine {
|
|||
return (
|
||||
exists: true,
|
||||
ownerSpaceId: spaceId,
|
||||
value: _decodeColumnValue(tableName, columnName, result.first[0]),
|
||||
value: _decodeColumnValue(
|
||||
tableName,
|
||||
columnName,
|
||||
_decodeStructuredValue(session, column, result.first[0]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1031,28 +1050,45 @@ class OfflineSyncEngine {
|
|||
return fieldsByRowId;
|
||||
}
|
||||
|
||||
dynamic _decodeColumnValue(String tableName, String columnName, Object? value) {
|
||||
if (value == null) return null;
|
||||
|
||||
final definition = _columnDefinitionsByTableName[tableName]?[columnName];
|
||||
final dartType = definition?.dartType;
|
||||
if (dartType == null) return value;
|
||||
|
||||
final className = _classNameForDartType(dartType);
|
||||
return switch (className) {
|
||||
'bool' || 'double' || 'int' || 'String' => value,
|
||||
_ => _serializationManager.deserializeByClassName({
|
||||
'className': className,
|
||||
'data': value,
|
||||
}),
|
||||
};
|
||||
String _outboundColumnExpression(DatabaseSession session, Column column) {
|
||||
final identifier = '"${column.columnName.escapeIdentifier()}"';
|
||||
if (session.db.dialect == DatabaseDialect.sqlite && column is ColumnStructured) {
|
||||
return 'json($identifier)';
|
||||
}
|
||||
return identifier;
|
||||
}
|
||||
|
||||
String _classNameForDartType(String dartType) {
|
||||
final withoutNullable = dartType.endsWith('?')
|
||||
? dartType.substring(0, dartType.length - 1)
|
||||
: dartType;
|
||||
return withoutNullable.split(':').last;
|
||||
/// Temporary workaround for raw queries bypassing Serverpod's column-aware
|
||||
/// result normalization. [_outboundColumnExpression] converts SQLite JSONB to
|
||||
/// JSON text so this method can decode both JSON and JSONB before deserialization.
|
||||
///
|
||||
/// TODO: Serverpod needs a public API for adapter-specific, column-aware decoding
|
||||
/// of raw query results across supported types and databases. Replace this helper
|
||||
/// and [_outboundColumnExpression] with that upstream API when it is available.
|
||||
dynamic _decodeStructuredValue(
|
||||
DatabaseSession session,
|
||||
Column column,
|
||||
Object? value,
|
||||
) {
|
||||
if (session.db.dialect == DatabaseDialect.sqlite &&
|
||||
(column is ColumnStructured || column is ColumnSerializable) &&
|
||||
value is String) {
|
||||
return jsonDecode(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
dynamic _decodeColumnValue(
|
||||
String tableName,
|
||||
String columnName,
|
||||
Object? value,
|
||||
) {
|
||||
if (value == null) return null;
|
||||
|
||||
final column = _syncTablesByName[tableName]!.columns.singleWhere(
|
||||
(column) => column.columnName == columnName,
|
||||
);
|
||||
return _serializationManager.deserialize<dynamic>(value, column.type);
|
||||
}
|
||||
|
||||
static String _computeCanonicalSyncTablesSignature(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ workspace:
|
|||
- packages/serverpod_offline_sync_server
|
||||
- test/serverpod_offline_sync_test_client
|
||||
- test/serverpod_offline_sync_test_server
|
||||
- test/serverpod_offline_sync_test_shared
|
||||
|
||||
dev_dependencies:
|
||||
melos: ^7.5.1
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,216 @@
|
|||
{
|
||||
"__className__": "serverpod.DatabaseMigration",
|
||||
"actions": [
|
||||
{
|
||||
"__className__": "serverpod.DatabaseMigrationAction",
|
||||
"type": "createTable",
|
||||
"createTable": {
|
||||
"__className__": "serverpod.TableDefinition",
|
||||
"name": "shared_child",
|
||||
"dartName": "SharedChild",
|
||||
"module": "serverpod_offline_sync_test",
|
||||
"schema": "public",
|
||||
"columns": [
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "id",
|
||||
"fieldName": "id",
|
||||
"columnType": 7,
|
||||
"isNullable": false,
|
||||
"columnDefault": "random_v7",
|
||||
"dartType": "UuidValue?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "spaceId",
|
||||
"fieldName": "spaceId",
|
||||
"columnType": 6,
|
||||
"isNullable": true,
|
||||
"dartType": "int?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "name",
|
||||
"fieldName": "name",
|
||||
"columnType": 0,
|
||||
"isNullable": false,
|
||||
"dartType": "String"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "flavor",
|
||||
"fieldName": "flavor",
|
||||
"columnType": 0,
|
||||
"isNullable": false,
|
||||
"columnDefault": "'plain'",
|
||||
"dartType": "serverpod_offline_sync_test_shared:SharedFlavor"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "parentId",
|
||||
"fieldName": "parentId",
|
||||
"columnType": 7,
|
||||
"isNullable": true,
|
||||
"dartType": "UuidValue?"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"__className__": "serverpod.ForeignKeyDefinition",
|
||||
"constraintName": "shared_child_fk_0",
|
||||
"columns": [
|
||||
"spaceId"
|
||||
],
|
||||
"referenceTable": "offline_sync_spaces",
|
||||
"referenceTableSchema": "public",
|
||||
"referenceColumns": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": 3,
|
||||
"onDelete": 4
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ForeignKeyDefinition",
|
||||
"constraintName": "shared_child_fk_1",
|
||||
"columns": [
|
||||
"parentId"
|
||||
],
|
||||
"referenceTable": "shared_parent",
|
||||
"referenceTableSchema": "public",
|
||||
"referenceColumns": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": 3,
|
||||
"onDelete": 0,
|
||||
"deferrable": "initiallyDeferred"
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"managed": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.DatabaseMigrationAction",
|
||||
"type": "createTable",
|
||||
"createTable": {
|
||||
"__className__": "serverpod.TableDefinition",
|
||||
"name": "shared_parent",
|
||||
"dartName": "SharedParent",
|
||||
"module": "serverpod_offline_sync_test",
|
||||
"schema": "public",
|
||||
"columns": [
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "id",
|
||||
"fieldName": "id",
|
||||
"columnType": 7,
|
||||
"isNullable": false,
|
||||
"columnDefault": "random_v7",
|
||||
"dartType": "UuidValue?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "spaceId",
|
||||
"fieldName": "spaceId",
|
||||
"columnType": 6,
|
||||
"isNullable": true,
|
||||
"dartType": "int?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "name",
|
||||
"fieldName": "name",
|
||||
"columnType": 0,
|
||||
"isNullable": false,
|
||||
"dartType": "String"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"__className__": "serverpod.ForeignKeyDefinition",
|
||||
"constraintName": "shared_parent_fk_0",
|
||||
"columns": [
|
||||
"spaceId"
|
||||
],
|
||||
"referenceTable": "offline_sync_spaces",
|
||||
"referenceTableSchema": "public",
|
||||
"referenceColumns": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": 3,
|
||||
"onDelete": 4
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"managed": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.DatabaseMigrationAction",
|
||||
"type": "alterTable",
|
||||
"alterTable": {
|
||||
"__className__": "serverpod.TableMigration",
|
||||
"name": "types",
|
||||
"schema": "public",
|
||||
"addColumns": [
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "parentId",
|
||||
"fieldName": "parentId",
|
||||
"columnType": 7,
|
||||
"isNullable": true,
|
||||
"dartType": "UuidValue?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "jsonDocument",
|
||||
"fieldName": "jsonDocument",
|
||||
"columnType": 8,
|
||||
"isNullable": true,
|
||||
"dartType": "protocol:SyncDocument?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "jsonbDocument",
|
||||
"fieldName": "jsonbDocument",
|
||||
"columnType": 14,
|
||||
"isNullable": true,
|
||||
"dartType": "protocol:SyncDocument?"
|
||||
},
|
||||
{
|
||||
"__className__": "serverpod.ColumnDefinition",
|
||||
"name": "jsonbNumbers",
|
||||
"fieldName": "jsonbNumbers",
|
||||
"columnType": 14,
|
||||
"isNullable": true,
|
||||
"dartType": "List<int>?"
|
||||
}
|
||||
],
|
||||
"deleteColumns": [],
|
||||
"modifyColumns": [],
|
||||
"addIndexes": [],
|
||||
"deleteIndexes": [],
|
||||
"addForeignKeys": [
|
||||
{
|
||||
"__className__": "serverpod.ForeignKeyDefinition",
|
||||
"constraintName": "types_fk_1",
|
||||
"columns": [
|
||||
"parentId"
|
||||
],
|
||||
"referenceTable": "types",
|
||||
"referenceTableSchema": "public",
|
||||
"referenceColumns": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": 3,
|
||||
"onDelete": 3
|
||||
}
|
||||
],
|
||||
"deleteForeignKeys": [],
|
||||
"warnings": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"warnings": [],
|
||||
"migrationApiVersion": 1
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ part '20260902195734685/migration.dart';
|
|||
part '20260907165715131/migration.dart';
|
||||
part '20260907170602693/migration.dart';
|
||||
part '20260914144112288/migration.dart';
|
||||
part '20260914165608984/migration.dart';
|
||||
|
||||
/// Migration registry for the client-side database.
|
||||
class MigrationRegistry {
|
||||
|
|
@ -28,6 +29,7 @@ class MigrationRegistry {
|
|||
_Migration20260907165715131(),
|
||||
_Migration20260907170602693(),
|
||||
_Migration20260914144112288(),
|
||||
_Migration20260914165608984(),
|
||||
];
|
||||
|
||||
/// List of all client-side database migration versions.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
|||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart'
|
||||
as _ipulbpi2;
|
||||
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
|
||||
as _i2ap9bqs;
|
||||
import 'address.dart' as _ilb4pipw;
|
||||
import 'city.dart' as _ior3absd;
|
||||
import 'company.dart' as _i6pnc270;
|
||||
|
|
@ -36,6 +38,7 @@ import 'required_cascade_child.dart' as _ivx9jyda;
|
|||
import 'required_no_action_child.dart' as _itlfbi2f;
|
||||
import 'required_set_null_child.dart' as _i1huw131;
|
||||
import 'restrict_child.dart' as _isrf0aof;
|
||||
import 'sync_document.dart' as _ix6xayzv;
|
||||
import 'town.dart' as _iytblq2r;
|
||||
import 'types.dart' as _iwxwszsz;
|
||||
import 'types_enum.dart' as _ire5m5mj;
|
||||
|
|
@ -71,6 +74,7 @@ export 'required_cascade_child.dart';
|
|||
export 'required_no_action_child.dart';
|
||||
export 'required_set_null_child.dart';
|
||||
export 'restrict_child.dart';
|
||||
export 'sync_document.dart';
|
||||
export 'town.dart';
|
||||
export 'types.dart';
|
||||
export 'types_enum.dart';
|
||||
|
|
@ -1373,6 +1377,30 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
isNullable: true,
|
||||
dartType: 'UuidValue?',
|
||||
),
|
||||
_isd.ColumnDefinition(
|
||||
name: 'parentId',
|
||||
columnType: _isd.ColumnType.uuid,
|
||||
isNullable: true,
|
||||
dartType: 'UuidValue?',
|
||||
),
|
||||
_isd.ColumnDefinition(
|
||||
name: 'jsonDocument',
|
||||
columnType: _isd.ColumnType.json,
|
||||
isNullable: true,
|
||||
dartType: 'protocol:SyncDocument?',
|
||||
),
|
||||
_isd.ColumnDefinition(
|
||||
name: 'jsonbDocument',
|
||||
columnType: _isd.ColumnType.jsonb,
|
||||
isNullable: true,
|
||||
dartType: 'protocol:SyncDocument?',
|
||||
),
|
||||
_isd.ColumnDefinition(
|
||||
name: 'jsonbNumbers',
|
||||
columnType: _isd.ColumnType.jsonb,
|
||||
isNullable: true,
|
||||
dartType: 'List<int>?',
|
||||
),
|
||||
],
|
||||
foreignKeys: [
|
||||
_isd.ForeignKeyDefinition(
|
||||
|
|
@ -1385,6 +1413,16 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
onDelete: _isd.ForeignKeyAction.cascade,
|
||||
matchType: null,
|
||||
),
|
||||
_isd.ForeignKeyDefinition(
|
||||
constraintName: 'types_fk_1',
|
||||
columns: ['parentId'],
|
||||
referenceTable: 'types',
|
||||
referenceTableSchema: 'public',
|
||||
referenceColumns: ['id'],
|
||||
onUpdate: _isd.ForeignKeyAction.noAction,
|
||||
onDelete: _isd.ForeignKeyAction.noAction,
|
||||
matchType: null,
|
||||
),
|
||||
],
|
||||
indexes: [
|
||||
_isd.IndexDefinition(
|
||||
|
|
@ -2348,6 +2386,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
? (_ipulbpi2.Protocol() as _isd.DatabaseSerializationManager)
|
||||
.getTargetTableDefinitions()
|
||||
: [],
|
||||
..._i2ap9bqs.Protocol() is _isd.DatabaseSerializationManager
|
||||
? (_i2ap9bqs.Protocol() as _isd.DatabaseSerializationManager)
|
||||
.getTargetTableDefinitions()
|
||||
: [],
|
||||
];
|
||||
|
||||
static String? getClassNameFromObjectJson(dynamic data) {
|
||||
|
|
@ -2434,6 +2476,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (t == _isrf0aof.RestrictChild) {
|
||||
return _isrf0aof.RestrictChild.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ix6xayzv.SyncDocument) {
|
||||
return _ix6xayzv.SyncDocument.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iytblq2r.Town) {
|
||||
return _iytblq2r.Town.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -2576,6 +2621,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ix6xayzv.SyncDocument?>()) {
|
||||
return (data != null ? _ix6xayzv.SyncDocument.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_iytblq2r.Town?>()) {
|
||||
return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -2668,6 +2716,15 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == List<int>) {
|
||||
return (data as List).map((e) => deserialize<int>(e)).toList() as T;
|
||||
}
|
||||
if (t == _isc.getType<List<int>?>()) {
|
||||
return (data != null
|
||||
? (data as List).map((e) => deserialize<int>(e)).toList()
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == List<dynamic>) {
|
||||
return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T;
|
||||
}
|
||||
|
|
@ -2680,6 +2737,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
try {
|
||||
return _ipulbpi2.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
try {
|
||||
return _i2ap9bqs.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
return super.deserialize<T>(data, t);
|
||||
}
|
||||
|
||||
|
|
@ -2704,6 +2764,7 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
_itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild',
|
||||
_i1huw131.RequiredSetNullChild => 'RequiredSetNullChild',
|
||||
_isrf0aof.RestrictChild => 'RestrictChild',
|
||||
_ix6xayzv.SyncDocument => 'SyncDocument',
|
||||
_iytblq2r.Town => 'Town',
|
||||
_iwxwszsz.Types => 'Types',
|
||||
_ire5m5mj.TypesEnum => 'TypesEnum',
|
||||
|
|
@ -2775,6 +2836,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return 'RequiredSetNullChild';
|
||||
case _isrf0aof.RestrictChild():
|
||||
return 'RestrictChild';
|
||||
case _ix6xayzv.SyncDocument():
|
||||
return 'SyncDocument';
|
||||
case _iytblq2r.Town():
|
||||
return 'Town';
|
||||
case _iwxwszsz.Types():
|
||||
|
|
@ -2820,6 +2883,12 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
? className
|
||||
: 'serverpod_offline_sync.$className';
|
||||
}
|
||||
className = _i2ap9bqs.Protocol().getClassNameForObject(data);
|
||||
if (className != null) {
|
||||
return className.contains('.')
|
||||
? className
|
||||
: 'serverpod_offline_sync_test_shared.$className';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -2886,6 +2955,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (dataClassName == 'RestrictChild') {
|
||||
return deserialize<_isrf0aof.RestrictChild>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'SyncDocument') {
|
||||
return deserialize<_ix6xayzv.SyncDocument>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Town') {
|
||||
return deserialize<_iytblq2r.Town>(data['data']);
|
||||
}
|
||||
|
|
@ -2942,6 +3014,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
data['className'] = dataClassName.substring(23);
|
||||
return _ipulbpi2.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName.startsWith('serverpod_offline_sync_test_shared.')) {
|
||||
data['className'] = dataClassName.substring(35);
|
||||
return _i2ap9bqs.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
return super.deserializeByClassName(data);
|
||||
}
|
||||
|
||||
|
|
@ -2951,6 +3027,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
'serverpod_offline_sync_test',
|
||||
this,
|
||||
);
|
||||
_i2ap9bqs.Protocol().registerHostProtocol(
|
||||
'serverpod_offline_sync_test',
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -2973,6 +3053,15 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return table;
|
||||
}
|
||||
}
|
||||
{
|
||||
var protocol = _i2ap9bqs.Protocol();
|
||||
var table = protocol is _isd.DatabaseSerializationManager
|
||||
? (protocol as _isd.DatabaseSerializationManager).getTableForType(t)
|
||||
: null;
|
||||
if (table != null) {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
switch (t) {
|
||||
case _ilb4pipw.Address:
|
||||
return _ilb4pipw.Address.t;
|
||||
|
|
|
|||
107
test/serverpod_offline_sync_test_client/lib/src/protocol/sync_document.dart
generated
Normal file
107
test/serverpod_offline_sync_test_client/lib/src/protocol/sync_document.dart
generated
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import 'package:serverpod_offline_sync_test_client/src/protocol/protocol.dart'
|
||||
as _imkb9kra;
|
||||
|
||||
abstract class SyncDocument
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
SyncDocument._({
|
||||
required this.title,
|
||||
required this.enabled,
|
||||
required this.numbers,
|
||||
});
|
||||
|
||||
factory SyncDocument({
|
||||
required String title,
|
||||
required bool enabled,
|
||||
required List<int> numbers,
|
||||
}) = _SyncDocumentImpl;
|
||||
|
||||
factory SyncDocument.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return SyncDocument(
|
||||
title: jsonSerialization['title'] as String,
|
||||
enabled: _isc.BoolJsonExtension.fromJson(jsonSerialization['enabled']),
|
||||
numbers: _imkb9kra.Protocol().deserialize<List<int>>(
|
||||
jsonSerialization['numbers'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String title;
|
||||
|
||||
bool enabled;
|
||||
|
||||
List<int> numbers;
|
||||
|
||||
/// Returns a shallow copy of this [SyncDocument]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
SyncDocument copyWith({
|
||||
String? title,
|
||||
bool? enabled,
|
||||
List<int>? numbers,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'SyncDocument',
|
||||
'title': title,
|
||||
'enabled': enabled,
|
||||
'numbers': numbers.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'SyncDocument',
|
||||
'title': title,
|
||||
'enabled': enabled,
|
||||
'numbers': numbers.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _SyncDocumentImpl extends SyncDocument {
|
||||
_SyncDocumentImpl({
|
||||
required String title,
|
||||
required bool enabled,
|
||||
required List<int> numbers,
|
||||
}) : super._(
|
||||
title: title,
|
||||
enabled: enabled,
|
||||
numbers: numbers,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [SyncDocument]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
SyncDocument copyWith({
|
||||
String? title,
|
||||
bool? enabled,
|
||||
List<int>? numbers,
|
||||
}) {
|
||||
return SyncDocument(
|
||||
title: title ?? this.title,
|
||||
enabled: enabled ?? this.enabled,
|
||||
numbers: numbers ?? this.numbers.map((e0) => e0).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
|
||||
as _i2ap9bqs;
|
||||
import 'address.dart' as _ilb4pipw;
|
||||
import 'city.dart' as _ior3absd;
|
||||
import 'company.dart' as _i6pnc270;
|
||||
|
|
@ -68,6 +70,8 @@ final List<_isd.Table> syncTables = [
|
|||
_itlfbi2f.RequiredNoActionChild.t,
|
||||
_i1huw131.RequiredSetNullChild.t,
|
||||
_isrf0aof.RestrictChild.t,
|
||||
_i2ap9bqs.SharedChild.t,
|
||||
_i2ap9bqs.SharedParent.t,
|
||||
_iytblq2r.Town.t,
|
||||
_iwxwszsz.Types.t,
|
||||
_ivpwn84u.Unique.t,
|
||||
|
|
|
|||
|
|
@ -8,11 +8,16 @@
|
|||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: dead_code, unnecessary_null_comparison
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:typed_data' as _idt;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import 'package:serverpod_database/serverpod_database.dart' as _isd;
|
||||
import 'package:serverpod_offline_sync_test_client/src/protocol/protocol.dart'
|
||||
as _imkb9kra;
|
||||
import 'sync_document.dart' as _ix6xayzv;
|
||||
import 'types.dart' as _iwxwszsz;
|
||||
import 'types_enum.dart' as _ire5m5mj;
|
||||
|
||||
abstract class Types
|
||||
|
|
@ -30,6 +35,11 @@ abstract class Types
|
|||
this.anEnum,
|
||||
this.optionalText,
|
||||
this.optionalUuid,
|
||||
this.parentId,
|
||||
this.parent,
|
||||
this.jsonDocument,
|
||||
this.jsonbDocument,
|
||||
this.jsonbNumbers,
|
||||
});
|
||||
|
||||
factory Types({
|
||||
|
|
@ -45,6 +55,11 @@ abstract class Types
|
|||
_ire5m5mj.TypesEnum? anEnum,
|
||||
String? optionalText,
|
||||
_isc.UuidValue? optionalUuid,
|
||||
_isc.UuidValue? parentId,
|
||||
_iwxwszsz.Types? parent,
|
||||
_ix6xayzv.SyncDocument? jsonDocument,
|
||||
_ix6xayzv.SyncDocument? jsonbDocument,
|
||||
List<int>? jsonbNumbers,
|
||||
}) = _TypesImpl;
|
||||
|
||||
factory Types.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
|
|
@ -71,6 +86,29 @@ abstract class Types
|
|||
: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['optionalUuid'],
|
||||
),
|
||||
parentId: jsonSerialization['parentId'] == null
|
||||
? null
|
||||
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['parentId']),
|
||||
parent: jsonSerialization['parent'] == null
|
||||
? null
|
||||
: _imkb9kra.Protocol().deserialize<_iwxwszsz.Types>(
|
||||
jsonSerialization['parent'],
|
||||
),
|
||||
jsonDocument: jsonSerialization['jsonDocument'] == null
|
||||
? null
|
||||
: _imkb9kra.Protocol().deserialize<_ix6xayzv.SyncDocument>(
|
||||
jsonSerialization['jsonDocument'],
|
||||
),
|
||||
jsonbDocument: jsonSerialization['jsonbDocument'] == null
|
||||
? null
|
||||
: _imkb9kra.Protocol().deserialize<_ix6xayzv.SyncDocument>(
|
||||
jsonSerialization['jsonbDocument'],
|
||||
),
|
||||
jsonbNumbers: jsonSerialization['jsonbNumbers'] == null
|
||||
? null
|
||||
: _imkb9kra.Protocol().deserialize<List<int>>(
|
||||
jsonSerialization['jsonbNumbers'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +142,16 @@ abstract class Types
|
|||
|
||||
_isc.UuidValue? optionalUuid;
|
||||
|
||||
_isc.UuidValue? parentId;
|
||||
|
||||
_iwxwszsz.Types? parent;
|
||||
|
||||
_ix6xayzv.SyncDocument? jsonDocument;
|
||||
|
||||
_ix6xayzv.SyncDocument? jsonbDocument;
|
||||
|
||||
List<int>? jsonbNumbers;
|
||||
|
||||
@override
|
||||
_isd.Table<_isc.UuidValue?> get table => t;
|
||||
|
||||
|
|
@ -123,6 +171,11 @@ abstract class Types
|
|||
_ire5m5mj.TypesEnum? anEnum,
|
||||
String? optionalText,
|
||||
_isc.UuidValue? optionalUuid,
|
||||
_isc.UuidValue? parentId,
|
||||
_iwxwszsz.Types? parent,
|
||||
_ix6xayzv.SyncDocument? jsonDocument,
|
||||
_ix6xayzv.SyncDocument? jsonbDocument,
|
||||
List<int>? jsonbNumbers,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -140,6 +193,11 @@ abstract class Types
|
|||
if (anEnum != null) 'anEnum': anEnum?.toJson(),
|
||||
if (optionalText != null) 'optionalText': optionalText,
|
||||
if (optionalUuid != null) 'optionalUuid': optionalUuid?.toJson(),
|
||||
if (parentId != null) 'parentId': parentId?.toJson(),
|
||||
if (parent != null) 'parent': parent?.toJson(),
|
||||
if (jsonDocument != null) 'jsonDocument': jsonDocument?.toJson(),
|
||||
if (jsonbDocument != null) 'jsonbDocument': jsonbDocument?.toJson(),
|
||||
if (jsonbNumbers != null) 'jsonbNumbers': jsonbNumbers?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -159,11 +217,18 @@ abstract class Types
|
|||
if (anEnum != null) 'anEnum': anEnum?.toJson(),
|
||||
if (optionalText != null) 'optionalText': optionalText,
|
||||
if (optionalUuid != null) 'optionalUuid': optionalUuid?.toJson(),
|
||||
if (parentId != null) 'parentId': parentId?.toJson(),
|
||||
if (parent != null) 'parent': parent?.toJsonForProtocol(),
|
||||
if (jsonDocument != null)
|
||||
'jsonDocument': jsonDocument?.toJsonForProtocol(),
|
||||
if (jsonbDocument != null)
|
||||
'jsonbDocument': jsonbDocument?.toJsonForProtocol(),
|
||||
if (jsonbNumbers != null) 'jsonbNumbers': jsonbNumbers?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
static TypesInclude include() {
|
||||
return TypesInclude._();
|
||||
static TypesInclude include({_iwxwszsz.TypesInclude? parent}) {
|
||||
return TypesInclude._(parent: parent);
|
||||
}
|
||||
|
||||
static TypesIncludeList includeList({
|
||||
|
|
@ -206,6 +271,11 @@ class _TypesImpl extends Types {
|
|||
_ire5m5mj.TypesEnum? anEnum,
|
||||
String? optionalText,
|
||||
_isc.UuidValue? optionalUuid,
|
||||
_isc.UuidValue? parentId,
|
||||
_iwxwszsz.Types? parent,
|
||||
_ix6xayzv.SyncDocument? jsonDocument,
|
||||
_ix6xayzv.SyncDocument? jsonbDocument,
|
||||
List<int>? jsonbNumbers,
|
||||
}) : super._(
|
||||
id: id,
|
||||
spaceId: spaceId,
|
||||
|
|
@ -219,6 +289,11 @@ class _TypesImpl extends Types {
|
|||
anEnum: anEnum,
|
||||
optionalText: optionalText,
|
||||
optionalUuid: optionalUuid,
|
||||
parentId: parentId,
|
||||
parent: parent,
|
||||
jsonDocument: jsonDocument,
|
||||
jsonbDocument: jsonbDocument,
|
||||
jsonbNumbers: jsonbNumbers,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [Types]
|
||||
|
|
@ -238,6 +313,11 @@ class _TypesImpl extends Types {
|
|||
Object? anEnum = _Undefined,
|
||||
Object? optionalText = _Undefined,
|
||||
Object? optionalUuid = _Undefined,
|
||||
Object? parentId = _Undefined,
|
||||
Object? parent = _Undefined,
|
||||
Object? jsonDocument = _Undefined,
|
||||
Object? jsonbDocument = _Undefined,
|
||||
Object? jsonbNumbers = _Undefined,
|
||||
}) {
|
||||
return Types(
|
||||
id: id is _isc.UuidValue? ? id : this.id,
|
||||
|
|
@ -254,6 +334,17 @@ class _TypesImpl extends Types {
|
|||
optionalUuid: optionalUuid is _isc.UuidValue?
|
||||
? optionalUuid
|
||||
: this.optionalUuid,
|
||||
parentId: parentId is _isc.UuidValue? ? parentId : this.parentId,
|
||||
parent: parent is _iwxwszsz.Types? ? parent : this.parent?.copyWith(),
|
||||
jsonDocument: jsonDocument is _ix6xayzv.SyncDocument?
|
||||
? jsonDocument
|
||||
: this.jsonDocument?.copyWith(),
|
||||
jsonbDocument: jsonbDocument is _ix6xayzv.SyncDocument?
|
||||
? jsonbDocument
|
||||
: this.jsonbDocument?.copyWith(),
|
||||
jsonbNumbers: jsonbNumbers is List<int>?
|
||||
? jsonbNumbers
|
||||
: this.jsonbNumbers?.map((e0) => e0).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +413,32 @@ class TypesUpdateTable extends _isd.UpdateTable<TypesTable> {
|
|||
table.optionalUuid,
|
||||
value,
|
||||
);
|
||||
|
||||
_isd.ColumnValue<_isc.UuidValue, _isc.UuidValue> parentId(
|
||||
_isc.UuidValue? value,
|
||||
) => _isd.ColumnValue(
|
||||
table.parentId,
|
||||
value,
|
||||
);
|
||||
|
||||
_isd.ColumnValue<_ix6xayzv.SyncDocument, _ix6xayzv.SyncDocument> jsonDocument(
|
||||
_ix6xayzv.SyncDocument? value,
|
||||
) => _isd.ColumnValue(
|
||||
table.jsonDocument,
|
||||
value,
|
||||
);
|
||||
|
||||
_isd.ColumnValue<_ix6xayzv.SyncDocument, _ix6xayzv.SyncDocument>
|
||||
jsonbDocument(_ix6xayzv.SyncDocument? value) => _isd.ColumnValue(
|
||||
table.jsonbDocument,
|
||||
value,
|
||||
);
|
||||
|
||||
_isd.ColumnValue<List<int>, List<int>> jsonbNumbers(List<int>? value) =>
|
||||
_isd.ColumnValue(
|
||||
table.jsonbNumbers,
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
class TypesTable extends _isd.Table<_isc.UuidValue?> {
|
||||
|
|
@ -372,6 +489,22 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
|
|||
'optionalUuid',
|
||||
this,
|
||||
);
|
||||
parentId = _isd.ColumnUuid(
|
||||
'parentId',
|
||||
this,
|
||||
);
|
||||
jsonDocument = _isd.ColumnSerializable<_ix6xayzv.SyncDocument>(
|
||||
'jsonDocument',
|
||||
this,
|
||||
);
|
||||
jsonbDocument = _isd.ColumnStructured<_ix6xayzv.SyncDocument>(
|
||||
'jsonbDocument',
|
||||
this,
|
||||
);
|
||||
jsonbNumbers = _isd.ColumnStructured<List<int>>(
|
||||
'jsonbNumbers',
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
late final TypesUpdateTable updateTable;
|
||||
|
|
@ -399,6 +532,29 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
|
|||
|
||||
late final _isd.ColumnUuid optionalUuid;
|
||||
|
||||
late final _isd.ColumnUuid parentId;
|
||||
|
||||
_iwxwszsz.TypesTable? _parent;
|
||||
|
||||
late final _isd.ColumnSerializable<_ix6xayzv.SyncDocument> jsonDocument;
|
||||
|
||||
late final _isd.ColumnStructured<_ix6xayzv.SyncDocument> jsonbDocument;
|
||||
|
||||
late final _isd.ColumnStructured<List<int>> jsonbNumbers;
|
||||
|
||||
_iwxwszsz.TypesTable get parent {
|
||||
if (_parent != null) return _parent!;
|
||||
_parent = _isd.createRelationTable(
|
||||
relationFieldName: 'parent',
|
||||
field: Types.t.parentId,
|
||||
foreignField: _iwxwszsz.Types.t.id,
|
||||
tableRelation: tableRelation,
|
||||
createTable: (foreignTableRelation) =>
|
||||
_iwxwszsz.TypesTable(tableRelation: foreignTableRelation),
|
||||
);
|
||||
return _parent!;
|
||||
}
|
||||
|
||||
@override
|
||||
List<_isd.Column> get columns => [
|
||||
id,
|
||||
|
|
@ -413,14 +569,30 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
|
|||
anEnum,
|
||||
optionalText,
|
||||
optionalUuid,
|
||||
parentId,
|
||||
jsonDocument,
|
||||
jsonbDocument,
|
||||
jsonbNumbers,
|
||||
];
|
||||
|
||||
@override
|
||||
_isd.Table? getRelationTable(String relationField) {
|
||||
if (relationField == 'parent') {
|
||||
return parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class TypesInclude extends _isd.IncludeObject {
|
||||
TypesInclude._();
|
||||
TypesInclude._({_iwxwszsz.TypesInclude? parent}) {
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
_iwxwszsz.TypesInclude? _parent;
|
||||
|
||||
@override
|
||||
Map<String, _isd.Include?> get includes => {};
|
||||
Map<String, _isd.Include?> get includes => {'parent': _parent};
|
||||
|
||||
@override
|
||||
_isd.Table<_isc.UuidValue?> get table => Types.t;
|
||||
|
|
@ -448,6 +620,10 @@ class TypesIncludeList extends _isd.IncludeList {
|
|||
class TypesRepository {
|
||||
const TypesRepository._();
|
||||
|
||||
final attachRow = const TypesAttachRowRepository._();
|
||||
|
||||
final detachRow = const TypesDetachRowRepository._();
|
||||
|
||||
/// Returns a list of [Types]s matching the given query parameters.
|
||||
///
|
||||
/// Use [where] to specify which items to include in the return value.
|
||||
|
|
@ -478,6 +654,7 @@ class TypesRepository {
|
|||
_isd.OrderByBuilder<TypesTable>? orderBy,
|
||||
_isd.OrderByListBuilder<TypesTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
TypesInclude? include,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
|
|
@ -488,6 +665,7 @@ class TypesRepository {
|
|||
limit: limit,
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
include: include,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
|
|
@ -517,6 +695,7 @@ class TypesRepository {
|
|||
_isd.OrderByBuilder<TypesTable>? orderBy,
|
||||
_isd.OrderByListBuilder<TypesTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
TypesInclude? include,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
|
|
@ -526,6 +705,7 @@ class TypesRepository {
|
|||
orderByList: orderByList?.call(Types.t),
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
include: include,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
|
|
@ -536,12 +716,14 @@ class TypesRepository {
|
|||
_isd.DatabaseSession session,
|
||||
_isc.UuidValue id, {
|
||||
_isd.Transaction? transaction,
|
||||
TypesInclude? include,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
return session.db.findById<Types>(
|
||||
id,
|
||||
transaction: transaction,
|
||||
include: include,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
|
|
@ -839,3 +1021,56 @@ class TypesRepository {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TypesAttachRowRepository {
|
||||
const TypesAttachRowRepository._();
|
||||
|
||||
/// Creates a relation between the given [Types] and [Types]
|
||||
/// by setting the [Types]'s foreign key `parentId` to refer to the [Types].
|
||||
Future<void> parent(
|
||||
_isd.DatabaseSession session,
|
||||
Types types,
|
||||
_iwxwszsz.Types parent, {
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
if (types.id == null) {
|
||||
throw ArgumentError.notNull('types.id');
|
||||
}
|
||||
if (parent.id == null) {
|
||||
throw ArgumentError.notNull('parent.id');
|
||||
}
|
||||
|
||||
var $types = types.copyWith(parentId: parent.id);
|
||||
await session.db.updateRow<Types>(
|
||||
$types,
|
||||
columns: [Types.t.parentId],
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TypesDetachRowRepository {
|
||||
const TypesDetachRowRepository._();
|
||||
|
||||
/// Detaches the relation between this [Types] and the [Types] set in `parent`
|
||||
/// by setting the [Types]'s foreign key `parentId` to `null`.
|
||||
///
|
||||
/// This removes the association between the two models without deleting
|
||||
/// the related record.
|
||||
Future<void> parent(
|
||||
_isd.DatabaseSession session,
|
||||
Types types, {
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
if (types.id == null) {
|
||||
throw ArgumentError.notNull('types.id');
|
||||
}
|
||||
|
||||
var $types = types.copyWith(parentId: null);
|
||||
await session.db.updateRow<Types>(
|
||||
$types,
|
||||
columns: [Types.t.parentId],
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,3 +13,5 @@ dependencies:
|
|||
serverpod_database: 4.0.0
|
||||
serverpod_offline_sync_client:
|
||||
path: ../../packages/serverpod_offline_sync_client
|
||||
serverpod_offline_sync_test_shared:
|
||||
path: ../serverpod_offline_sync_test_shared
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ serialize_as_jsonb_by_default: true
|
|||
client_package_path: ../serverpod_offline_sync_test_client
|
||||
server_test_tools_path: test/integration/test_tools
|
||||
|
||||
shared_packages:
|
||||
- ../serverpod_offline_sync_test_shared
|
||||
|
||||
experimental_features:
|
||||
databaseSync: true
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import 'package:serverpod_auth_core_server/serverpod_auth_core_server.dart'
|
|||
as _iacs;
|
||||
import 'package:serverpod_offline_sync_server/serverpod_offline_sync_server.dart'
|
||||
as _izehhkf5;
|
||||
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
|
||||
as _i2ap9bqs;
|
||||
import 'address.dart' as _ilb4pipw;
|
||||
import 'city.dart' as _ior3absd;
|
||||
import 'company.dart' as _i6pnc270;
|
||||
|
|
@ -36,6 +38,7 @@ import 'required_cascade_child.dart' as _ivx9jyda;
|
|||
import 'required_no_action_child.dart' as _itlfbi2f;
|
||||
import 'required_set_null_child.dart' as _i1huw131;
|
||||
import 'restrict_child.dart' as _isrf0aof;
|
||||
import 'sync_document.dart' as _ix6xayzv;
|
||||
import 'town.dart' as _iytblq2r;
|
||||
import 'types.dart' as _iwxwszsz;
|
||||
import 'types_enum.dart' as _ire5m5mj;
|
||||
|
|
@ -71,6 +74,7 @@ export 'required_cascade_child.dart';
|
|||
export 'required_no_action_child.dart';
|
||||
export 'required_set_null_child.dart';
|
||||
export 'restrict_child.dart';
|
||||
export 'sync_document.dart';
|
||||
export 'town.dart';
|
||||
export 'types.dart';
|
||||
export 'types_enum.dart';
|
||||
|
|
@ -1372,6 +1376,30 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
isNullable: true,
|
||||
dartType: 'UuidValue?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'parentId',
|
||||
columnType: _isp.ColumnType.uuid,
|
||||
isNullable: true,
|
||||
dartType: 'UuidValue?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'jsonDocument',
|
||||
columnType: _isp.ColumnType.json,
|
||||
isNullable: true,
|
||||
dartType: 'protocol:SyncDocument?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'jsonbDocument',
|
||||
columnType: _isp.ColumnType.jsonb,
|
||||
isNullable: true,
|
||||
dartType: 'protocol:SyncDocument?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'jsonbNumbers',
|
||||
columnType: _isp.ColumnType.jsonb,
|
||||
isNullable: true,
|
||||
dartType: 'List<int>?',
|
||||
),
|
||||
],
|
||||
foreignKeys: [
|
||||
_isp.ForeignKeyDefinition(
|
||||
|
|
@ -1384,6 +1412,16 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
onDelete: _isp.ForeignKeyAction.cascade,
|
||||
matchType: null,
|
||||
),
|
||||
_isp.ForeignKeyDefinition(
|
||||
constraintName: 'types_fk_1',
|
||||
columns: ['parentId'],
|
||||
referenceTable: 'types',
|
||||
referenceTableSchema: 'public',
|
||||
referenceColumns: ['id'],
|
||||
onUpdate: _isp.ForeignKeyAction.noAction,
|
||||
onDelete: _isp.ForeignKeyAction.noAction,
|
||||
matchType: null,
|
||||
),
|
||||
],
|
||||
indexes: [
|
||||
_isp.IndexDefinition(
|
||||
|
|
@ -2341,6 +2379,10 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
),
|
||||
..._iacs.Protocol.targetTableDefinitions,
|
||||
..._izehhkf5.Protocol.targetTableDefinitions,
|
||||
..._i2ap9bqs.Protocol() is _is.DatabaseSerializationManager
|
||||
? (_i2ap9bqs.Protocol() as _is.DatabaseSerializationManager)
|
||||
.getTargetTableDefinitions()
|
||||
: [],
|
||||
..._isp.Protocol.targetTableDefinitions,
|
||||
];
|
||||
|
||||
|
|
@ -2428,6 +2470,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
if (t == _isrf0aof.RestrictChild) {
|
||||
return _isrf0aof.RestrictChild.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ix6xayzv.SyncDocument) {
|
||||
return _ix6xayzv.SyncDocument.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iytblq2r.Town) {
|
||||
return _iytblq2r.Town.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -2570,6 +2615,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _is.getType<_ix6xayzv.SyncDocument?>()) {
|
||||
return (data != null ? _ix6xayzv.SyncDocument.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _is.getType<_iytblq2r.Town?>()) {
|
||||
return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -2662,6 +2710,15 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == List<int>) {
|
||||
return (data as List).map((e) => deserialize<int>(e)).toList() as T;
|
||||
}
|
||||
if (t == _is.getType<List<int>?>()) {
|
||||
return (data != null
|
||||
? (data as List).map((e) => deserialize<int>(e)).toList()
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == List<dynamic>) {
|
||||
return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T;
|
||||
}
|
||||
|
|
@ -2674,6 +2731,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
try {
|
||||
return _izehhkf5.Protocol().deserialize<T>(data, t);
|
||||
} on _is.DeserializationTypeNotFoundException catch (_) {}
|
||||
try {
|
||||
return _i2ap9bqs.Protocol().deserialize<T>(data, t);
|
||||
} on _is.DeserializationTypeNotFoundException catch (_) {}
|
||||
try {
|
||||
return _isp.Protocol().deserialize<T>(data, t);
|
||||
} on _is.DeserializationTypeNotFoundException catch (_) {}
|
||||
|
|
@ -2701,6 +2761,7 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
_itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild',
|
||||
_i1huw131.RequiredSetNullChild => 'RequiredSetNullChild',
|
||||
_isrf0aof.RestrictChild => 'RestrictChild',
|
||||
_ix6xayzv.SyncDocument => 'SyncDocument',
|
||||
_iytblq2r.Town => 'Town',
|
||||
_iwxwszsz.Types => 'Types',
|
||||
_ire5m5mj.TypesEnum => 'TypesEnum',
|
||||
|
|
@ -2772,6 +2833,8 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
return 'RequiredSetNullChild';
|
||||
case _isrf0aof.RestrictChild():
|
||||
return 'RestrictChild';
|
||||
case _ix6xayzv.SyncDocument():
|
||||
return 'SyncDocument';
|
||||
case _iytblq2r.Town():
|
||||
return 'Town';
|
||||
case _iwxwszsz.Types():
|
||||
|
|
@ -2817,6 +2880,12 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
? className
|
||||
: 'serverpod_offline_sync.$className';
|
||||
}
|
||||
className = _i2ap9bqs.Protocol().getClassNameForObject(data);
|
||||
if (className != null) {
|
||||
return className.contains('.')
|
||||
? className
|
||||
: 'serverpod_offline_sync_test_shared.$className';
|
||||
}
|
||||
className = _isp.Protocol().getClassNameForObject(data);
|
||||
if (className != null) {
|
||||
return className.contains('.') ? className : 'serverpod.$className';
|
||||
|
|
@ -2887,6 +2956,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
if (dataClassName == 'RestrictChild') {
|
||||
return deserialize<_isrf0aof.RestrictChild>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'SyncDocument') {
|
||||
return deserialize<_ix6xayzv.SyncDocument>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Town') {
|
||||
return deserialize<_iytblq2r.Town>(data['data']);
|
||||
}
|
||||
|
|
@ -2943,6 +3015,10 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
data['className'] = dataClassName.substring(23);
|
||||
return _izehhkf5.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName.startsWith('serverpod_offline_sync_test_shared.')) {
|
||||
data['className'] = dataClassName.substring(35);
|
||||
return _i2ap9bqs.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName.startsWith('serverpod.')) {
|
||||
data['className'] = dataClassName.substring(10);
|
||||
return _isp.Protocol().deserializeByClassName(data);
|
||||
|
|
@ -2956,6 +3032,10 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
'serverpod_offline_sync_test',
|
||||
this,
|
||||
);
|
||||
_i2ap9bqs.Protocol().registerHostProtocol(
|
||||
'serverpod_offline_sync_test',
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -2972,6 +3052,15 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
return table;
|
||||
}
|
||||
}
|
||||
{
|
||||
var protocol = _i2ap9bqs.Protocol();
|
||||
var table = protocol is _is.DatabaseSerializationManager
|
||||
? (protocol as _is.DatabaseSerializationManager).getTableForType(t)
|
||||
: null;
|
||||
if (table != null) {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
{
|
||||
var table = _isp.Protocol().getTableForType(t);
|
||||
if (table != null) {
|
||||
|
|
|
|||
107
test/serverpod_offline_sync_test_server/lib/src/generated/sync_document.dart
generated
Normal file
107
test/serverpod_offline_sync_test_server/lib/src/generated/sync_document.dart
generated
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
|
||||
/* To generate run: "serverpod generate" */
|
||||
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: public_member_api_docs
|
||||
// ignore_for_file: type_literal_in_constant_pattern
|
||||
// ignore_for_file: use_super_parameters
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod/serverpod.dart' as _is;
|
||||
import 'package:serverpod_offline_sync_test_server/src/generated/protocol.dart'
|
||||
as _ixxccm81;
|
||||
|
||||
abstract class SyncDocument
|
||||
implements _is.SerializableModel, _is.ProtocolSerialization {
|
||||
SyncDocument._({
|
||||
required this.title,
|
||||
required this.enabled,
|
||||
required this.numbers,
|
||||
});
|
||||
|
||||
factory SyncDocument({
|
||||
required String title,
|
||||
required bool enabled,
|
||||
required List<int> numbers,
|
||||
}) = _SyncDocumentImpl;
|
||||
|
||||
factory SyncDocument.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return SyncDocument(
|
||||
title: jsonSerialization['title'] as String,
|
||||
enabled: _is.BoolJsonExtension.fromJson(jsonSerialization['enabled']),
|
||||
numbers: _ixxccm81.Protocol().deserialize<List<int>>(
|
||||
jsonSerialization['numbers'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String title;
|
||||
|
||||
bool enabled;
|
||||
|
||||
List<int> numbers;
|
||||
|
||||
/// Returns a shallow copy of this [SyncDocument]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_is.useResult
|
||||
SyncDocument copyWith({
|
||||
String? title,
|
||||
bool? enabled,
|
||||
List<int>? numbers,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'SyncDocument',
|
||||
'title': title,
|
||||
'enabled': enabled,
|
||||
'numbers': numbers.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'SyncDocument',
|
||||
'title': title,
|
||||
'enabled': enabled,
|
||||
'numbers': numbers.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _is.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _SyncDocumentImpl extends SyncDocument {
|
||||
_SyncDocumentImpl({
|
||||
required String title,
|
||||
required bool enabled,
|
||||
required List<int> numbers,
|
||||
}) : super._(
|
||||
title: title,
|
||||
enabled: enabled,
|
||||
numbers: numbers,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [SyncDocument]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_is.useResult
|
||||
@override
|
||||
SyncDocument copyWith({
|
||||
String? title,
|
||||
bool? enabled,
|
||||
List<int>? numbers,
|
||||
}) {
|
||||
return SyncDocument(
|
||||
title: title ?? this.title,
|
||||
enabled: enabled ?? this.enabled,
|
||||
numbers: numbers ?? this.numbers.map((e0) => e0).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod/serverpod.dart' as _is;
|
||||
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
|
||||
as _i2ap9bqs;
|
||||
import 'address.dart' as _ilb4pipw;
|
||||
import 'city.dart' as _ior3absd;
|
||||
import 'company.dart' as _i6pnc270;
|
||||
|
|
@ -68,6 +70,8 @@ final List<_is.Table> syncTables = [
|
|||
_itlfbi2f.RequiredNoActionChild.t,
|
||||
_i1huw131.RequiredSetNullChild.t,
|
||||
_isrf0aof.RestrictChild.t,
|
||||
_i2ap9bqs.SharedChild.t,
|
||||
_i2ap9bqs.SharedParent.t,
|
||||
_iytblq2r.Town.t,
|
||||
_iwxwszsz.Types.t,
|
||||
_ivpwn84u.Unique.t,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue