fix: Preserve shared model and SQLite value types during sync (#118)

This commit is contained in:
Marcelo Mendonça Soares 2026-09-16 00:07:51 -03:00 • committed by GitHub
commit 1f5501ff97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 25604 additions and 51 deletions

View file

@ -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 ## 0.0.6
- refactor: BREAKING. Rename integration APIs and ownership scopes: - refactor: BREAKING. Rename integration APIs and ownership scopes:

View file

@ -659,8 +659,18 @@ WHERE (${domainColumnPredicate('spaceId', spaceId)})
) async { ) async {
if (rowIds.isEmpty || updates.isEmpty) return; if (rowIds.isEmpty || updates.isEmpty) return;
final columns = {
for (final column in syncTableByName[tableName]!.columns)
column.columnName: column,
};
final assignments = updates.entries 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(', '); .join(', ');
await database.unsafeExecute( await database.unsafeExecute(

View file

@ -259,6 +259,21 @@ String canonicalProjectionValue(Object? value) {
@internal @internal
bool projectionValuesEqual(Object? left, Object? right) { bool projectionValuesEqual(Object? left, Object? right) {
if (left == null || right == null) return left == 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 leftUuid = tryUuidValue(left);
final rightUuid = tryUuidValue(right); final rightUuid = tryUuidValue(right);
if (leftUuid != null && rightUuid != null) { if (leftUuid != null && rightUuid != null) {

View file

@ -598,6 +598,9 @@ class CrdtMutationRecorder {
data[column.fieldName] = planned[column.columnName]; 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 = final className =
_session.db.serializationManager.getClassNameForObject(row) ?? _session.db.serializationManager.getClassNameForObject(row) ??
data['__className__'] as String?; data['__className__'] as String?;

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:clock/clock.dart'; import 'package:clock/clock.dart';
import 'package:serverpod_database/serverpod_database.dart'; import 'package:serverpod_database/serverpod_database.dart';
@ -97,14 +98,6 @@ class OfflineSyncEngine {
if (definition.dartName != null) definition.name: definition.dartName!, 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. /// The deterministic hash representing the current synchronized schema.
late final String currentSyncTablesHash = computeSyncTablesHash( late final String currentSyncTablesHash = computeSyncTablesHash(
_syncTables, _syncTables,
@ -835,7 +828,10 @@ class OfflineSyncEngine {
DomainRowOwnerCache ownerCache, DomainRowOwnerCache ownerCache,
) async { ) async {
final cols = table.columns final cols = table.columns
.map((column) => '"${column.columnName.escapeIdentifier()}"') .map(
(column) =>
'${_outboundColumnExpression(session, column)} AS "${column.columnName.escapeIdentifier()}"',
)
.join(', '); .join(', ');
final encodedRowId = rowId.sqlLiteral(); final encodedRowId = rowId.sqlLiteral();
final encodedSpaceId = spaceId.sqlLiteral(); final encodedSpaceId = spaceId.sqlLiteral();
@ -851,16 +847,32 @@ class OfflineSyncEngine {
} }
ownerCache[(tableName, rowId)] = (exists: true, spaceId: spaceId); ownerCache[(tableName, rowId)] = (exists: true, spaceId: spaceId);
final columnMap = result.first.toColumnMap() final rawColumns = result.first.toColumnMap();
// Domain columns hold visible/materialized FK values; restore attempted final columnMap =
// values for override columns before building the outbound merge payload. <String, dynamic>{
..applyAuthoredAttemptedValues(attemptedValueFields) for (final column in table.columns)
// spaceId is local ownership metadata; it is never emitted on the wire. column.columnName: _decodeStructuredValue(
..remove('spaceId'); 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({ // A table definition names its class the way its own package spells it, so
'className': dartName, // a model owned by a shared package reports the unprefixed name while the
'data': columnMap, // 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); return (exists: true, ownerSpaceId: spaceId, row: row);
} }
@ -895,8 +907,11 @@ class OfflineSyncEngine {
final encodedRowId = rowId.sqlLiteral(); final encodedRowId = rowId.sqlLiteral();
final encodedSpaceId = spaceId.sqlLiteral(); final encodedSpaceId = spaceId.sqlLiteral();
final escapedTableName = tableName.escapeIdentifier(); final escapedTableName = tableName.escapeIdentifier();
final column = _syncTablesByName[tableName]!.columns.singleWhere(
(c) => c.columnName == columnName,
);
final result = await session.db.unsafeQuery( final result = await session.db.unsafeQuery(
'SELECT "${columnName.escapeIdentifier()}" ' 'SELECT ${_outboundColumnExpression(session, column)} '
'FROM "$escapedTableName" ' 'FROM "$escapedTableName" '
'WHERE "id" = $encodedRowId AND "spaceId" = $encodedSpaceId ' 'WHERE "id" = $encodedRowId AND "spaceId" = $encodedSpaceId '
'LIMIT 1', 'LIMIT 1',
@ -906,7 +921,11 @@ class OfflineSyncEngine {
return ( return (
exists: true, exists: true,
ownerSpaceId: spaceId, 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; return fieldsByRowId;
} }
dynamic _decodeColumnValue(String tableName, String columnName, Object? value) { String _outboundColumnExpression(DatabaseSession session, Column column) {
if (value == null) return null; final identifier = '"${column.columnName.escapeIdentifier()}"';
if (session.db.dialect == DatabaseDialect.sqlite && column is ColumnStructured) {
final definition = _columnDefinitionsByTableName[tableName]?[columnName]; return 'json($identifier)';
final dartType = definition?.dartType; }
if (dartType == null) return value; return identifier;
final className = _classNameForDartType(dartType);
return switch (className) {
'bool' || 'double' || 'int' || 'String' => value,
_ => _serializationManager.deserializeByClassName({
'className': className,
'data': value,
}),
};
} }
String _classNameForDartType(String dartType) { /// Temporary workaround for raw queries bypassing Serverpod's column-aware
final withoutNullable = dartType.endsWith('?') /// result normalization. [_outboundColumnExpression] converts SQLite JSONB to
? dartType.substring(0, dartType.length - 1) /// JSON text so this method can decode both JSON and JSONB before deserialization.
: dartType; ///
return withoutNullable.split(':').last; /// 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( static String _computeCanonicalSyncTablesSignature(

View file

@ -11,6 +11,7 @@ workspace:
- packages/serverpod_offline_sync_server - packages/serverpod_offline_sync_server
- test/serverpod_offline_sync_test_client - test/serverpod_offline_sync_test_client
- test/serverpod_offline_sync_test_server - test/serverpod_offline_sync_test_server
- test/serverpod_offline_sync_test_shared
dev_dependencies: dev_dependencies:
melos: ^7.5.1 melos: ^7.5.1

View file

@ -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
}

View file

@ -13,6 +13,7 @@ part '20260902195734685/migration.dart';
part '20260907165715131/migration.dart'; part '20260907165715131/migration.dart';
part '20260907170602693/migration.dart'; part '20260907170602693/migration.dart';
part '20260914144112288/migration.dart'; part '20260914144112288/migration.dart';
part '20260914165608984/migration.dart';
/// Migration registry for the client-side database. /// Migration registry for the client-side database.
class MigrationRegistry { class MigrationRegistry {
@ -28,6 +29,7 @@ class MigrationRegistry {
_Migration20260907165715131(), _Migration20260907165715131(),
_Migration20260907170602693(), _Migration20260907170602693(),
_Migration20260914144112288(), _Migration20260914144112288(),
_Migration20260914165608984(),
]; ];
/// List of all client-side database migration versions. /// List of all client-side database migration versions.

View file

@ -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_database/serverpod_database.dart' as _isd;
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart' import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart'
as _ipulbpi2; as _ipulbpi2;
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
as _i2ap9bqs;
import 'address.dart' as _ilb4pipw; import 'address.dart' as _ilb4pipw;
import 'city.dart' as _ior3absd; import 'city.dart' as _ior3absd;
import 'company.dart' as _i6pnc270; 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_no_action_child.dart' as _itlfbi2f;
import 'required_set_null_child.dart' as _i1huw131; import 'required_set_null_child.dart' as _i1huw131;
import 'restrict_child.dart' as _isrf0aof; import 'restrict_child.dart' as _isrf0aof;
import 'sync_document.dart' as _ix6xayzv;
import 'town.dart' as _iytblq2r; import 'town.dart' as _iytblq2r;
import 'types.dart' as _iwxwszsz; import 'types.dart' as _iwxwszsz;
import 'types_enum.dart' as _ire5m5mj; import 'types_enum.dart' as _ire5m5mj;
@ -71,6 +74,7 @@ export 'required_cascade_child.dart';
export 'required_no_action_child.dart'; export 'required_no_action_child.dart';
export 'required_set_null_child.dart'; export 'required_set_null_child.dart';
export 'restrict_child.dart'; export 'restrict_child.dart';
export 'sync_document.dart';
export 'town.dart'; export 'town.dart';
export 'types.dart'; export 'types.dart';
export 'types_enum.dart'; export 'types_enum.dart';
@ -1373,6 +1377,30 @@ class Protocol extends _isd.DatabaseSerializationManager {
isNullable: true, isNullable: true,
dartType: 'UuidValue?', 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: [ foreignKeys: [
_isd.ForeignKeyDefinition( _isd.ForeignKeyDefinition(
@ -1385,6 +1413,16 @@ class Protocol extends _isd.DatabaseSerializationManager {
onDelete: _isd.ForeignKeyAction.cascade, onDelete: _isd.ForeignKeyAction.cascade,
matchType: null, 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: [ indexes: [
_isd.IndexDefinition( _isd.IndexDefinition(
@ -2348,6 +2386,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
? (_ipulbpi2.Protocol() as _isd.DatabaseSerializationManager) ? (_ipulbpi2.Protocol() as _isd.DatabaseSerializationManager)
.getTargetTableDefinitions() .getTargetTableDefinitions()
: [], : [],
..._i2ap9bqs.Protocol() is _isd.DatabaseSerializationManager
? (_i2ap9bqs.Protocol() as _isd.DatabaseSerializationManager)
.getTargetTableDefinitions()
: [],
]; ];
static String? getClassNameFromObjectJson(dynamic data) { static String? getClassNameFromObjectJson(dynamic data) {
@ -2434,6 +2476,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (t == _isrf0aof.RestrictChild) { if (t == _isrf0aof.RestrictChild) {
return _isrf0aof.RestrictChild.fromJson(data) as T; return _isrf0aof.RestrictChild.fromJson(data) as T;
} }
if (t == _ix6xayzv.SyncDocument) {
return _ix6xayzv.SyncDocument.fromJson(data) as T;
}
if (t == _iytblq2r.Town) { if (t == _iytblq2r.Town) {
return _iytblq2r.Town.fromJson(data) as T; return _iytblq2r.Town.fromJson(data) as T;
} }
@ -2576,6 +2621,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null) return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null)
as T; as T;
} }
if (t == _isc.getType<_ix6xayzv.SyncDocument?>()) {
return (data != null ? _ix6xayzv.SyncDocument.fromJson(data) : null) as T;
}
if (t == _isc.getType<_iytblq2r.Town?>()) { if (t == _isc.getType<_iytblq2r.Town?>()) {
return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T; return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T;
} }
@ -2668,6 +2716,15 @@ class Protocol extends _isd.DatabaseSerializationManager {
: null) : null)
as T; 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>) { if (t == List<dynamic>) {
return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T; return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T;
} }
@ -2680,6 +2737,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
try { try {
return _ipulbpi2.Protocol().deserialize<T>(data, t); return _ipulbpi2.Protocol().deserialize<T>(data, t);
} on _isc.DeserializationTypeNotFoundException catch (_) {} } on _isc.DeserializationTypeNotFoundException catch (_) {}
try {
return _i2ap9bqs.Protocol().deserialize<T>(data, t);
} on _isc.DeserializationTypeNotFoundException catch (_) {}
return super.deserialize<T>(data, t); return super.deserialize<T>(data, t);
} }
@ -2704,6 +2764,7 @@ class Protocol extends _isd.DatabaseSerializationManager {
_itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild', _itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild',
_i1huw131.RequiredSetNullChild => 'RequiredSetNullChild', _i1huw131.RequiredSetNullChild => 'RequiredSetNullChild',
_isrf0aof.RestrictChild => 'RestrictChild', _isrf0aof.RestrictChild => 'RestrictChild',
_ix6xayzv.SyncDocument => 'SyncDocument',
_iytblq2r.Town => 'Town', _iytblq2r.Town => 'Town',
_iwxwszsz.Types => 'Types', _iwxwszsz.Types => 'Types',
_ire5m5mj.TypesEnum => 'TypesEnum', _ire5m5mj.TypesEnum => 'TypesEnum',
@ -2775,6 +2836,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
return 'RequiredSetNullChild'; return 'RequiredSetNullChild';
case _isrf0aof.RestrictChild(): case _isrf0aof.RestrictChild():
return 'RestrictChild'; return 'RestrictChild';
case _ix6xayzv.SyncDocument():
return 'SyncDocument';
case _iytblq2r.Town(): case _iytblq2r.Town():
return 'Town'; return 'Town';
case _iwxwszsz.Types(): case _iwxwszsz.Types():
@ -2820,6 +2883,12 @@ class Protocol extends _isd.DatabaseSerializationManager {
? className ? className
: 'serverpod_offline_sync.$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; return null;
} }
@ -2886,6 +2955,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (dataClassName == 'RestrictChild') { if (dataClassName == 'RestrictChild') {
return deserialize<_isrf0aof.RestrictChild>(data['data']); return deserialize<_isrf0aof.RestrictChild>(data['data']);
} }
if (dataClassName == 'SyncDocument') {
return deserialize<_ix6xayzv.SyncDocument>(data['data']);
}
if (dataClassName == 'Town') { if (dataClassName == 'Town') {
return deserialize<_iytblq2r.Town>(data['data']); return deserialize<_iytblq2r.Town>(data['data']);
} }
@ -2942,6 +3014,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
data['className'] = dataClassName.substring(23); data['className'] = dataClassName.substring(23);
return _ipulbpi2.Protocol().deserializeByClassName(data); 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); return super.deserializeByClassName(data);
} }
@ -2951,6 +3027,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
'serverpod_offline_sync_test', 'serverpod_offline_sync_test',
this, this,
); );
_i2ap9bqs.Protocol().registerHostProtocol(
'serverpod_offline_sync_test',
this,
);
} }
@override @override
@ -2973,6 +3053,15 @@ class Protocol extends _isd.DatabaseSerializationManager {
return table; 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) { switch (t) {
case _ilb4pipw.Address: case _ilb4pipw.Address:
return _ilb4pipw.Address.t; return _ilb4pipw.Address.t;

View 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(),
);
}
}

View file

@ -11,6 +11,8 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes // ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_database/serverpod_database.dart' as _isd; 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 'address.dart' as _ilb4pipw;
import 'city.dart' as _ior3absd; import 'city.dart' as _ior3absd;
import 'company.dart' as _i6pnc270; import 'company.dart' as _i6pnc270;
@ -68,6 +70,8 @@ final List<_isd.Table> syncTables = [
_itlfbi2f.RequiredNoActionChild.t, _itlfbi2f.RequiredNoActionChild.t,
_i1huw131.RequiredSetNullChild.t, _i1huw131.RequiredSetNullChild.t,
_isrf0aof.RestrictChild.t, _isrf0aof.RestrictChild.t,
_i2ap9bqs.SharedChild.t,
_i2ap9bqs.SharedParent.t,
_iytblq2r.Town.t, _iytblq2r.Town.t,
_iwxwszsz.Types.t, _iwxwszsz.Types.t,
_ivpwn84u.Unique.t, _ivpwn84u.Unique.t,

View file

@ -8,11 +8,16 @@
// ignore_for_file: type_literal_in_constant_pattern // ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters // ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member // 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 // ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:typed_data' as _idt; import 'dart:typed_data' as _idt;
import 'package:serverpod_client/serverpod_client.dart' as _isc; import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd; 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; import 'types_enum.dart' as _ire5m5mj;
abstract class Types abstract class Types
@ -30,6 +35,11 @@ abstract class Types
this.anEnum, this.anEnum,
this.optionalText, this.optionalText,
this.optionalUuid, this.optionalUuid,
this.parentId,
this.parent,
this.jsonDocument,
this.jsonbDocument,
this.jsonbNumbers,
}); });
factory Types({ factory Types({
@ -45,6 +55,11 @@ abstract class Types
_ire5m5mj.TypesEnum? anEnum, _ire5m5mj.TypesEnum? anEnum,
String? optionalText, String? optionalText,
_isc.UuidValue? optionalUuid, _isc.UuidValue? optionalUuid,
_isc.UuidValue? parentId,
_iwxwszsz.Types? parent,
_ix6xayzv.SyncDocument? jsonDocument,
_ix6xayzv.SyncDocument? jsonbDocument,
List<int>? jsonbNumbers,
}) = _TypesImpl; }) = _TypesImpl;
factory Types.fromJson(Map<String, dynamic> jsonSerialization) { factory Types.fromJson(Map<String, dynamic> jsonSerialization) {
@ -71,6 +86,29 @@ abstract class Types
: _isc.UuidValueJsonExtension.fromJson( : _isc.UuidValueJsonExtension.fromJson(
jsonSerialization['optionalUuid'], 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? optionalUuid;
_isc.UuidValue? parentId;
_iwxwszsz.Types? parent;
_ix6xayzv.SyncDocument? jsonDocument;
_ix6xayzv.SyncDocument? jsonbDocument;
List<int>? jsonbNumbers;
@override @override
_isd.Table<_isc.UuidValue?> get table => t; _isd.Table<_isc.UuidValue?> get table => t;
@ -123,6 +171,11 @@ abstract class Types
_ire5m5mj.TypesEnum? anEnum, _ire5m5mj.TypesEnum? anEnum,
String? optionalText, String? optionalText,
_isc.UuidValue? optionalUuid, _isc.UuidValue? optionalUuid,
_isc.UuidValue? parentId,
_iwxwszsz.Types? parent,
_ix6xayzv.SyncDocument? jsonDocument,
_ix6xayzv.SyncDocument? jsonbDocument,
List<int>? jsonbNumbers,
}); });
@override @override
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -140,6 +193,11 @@ abstract class Types
if (anEnum != null) 'anEnum': anEnum?.toJson(), if (anEnum != null) 'anEnum': anEnum?.toJson(),
if (optionalText != null) 'optionalText': optionalText, if (optionalText != null) 'optionalText': optionalText,
if (optionalUuid != null) 'optionalUuid': optionalUuid?.toJson(), 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 (anEnum != null) 'anEnum': anEnum?.toJson(),
if (optionalText != null) 'optionalText': optionalText, if (optionalText != null) 'optionalText': optionalText,
if (optionalUuid != null) 'optionalUuid': optionalUuid?.toJson(), 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() { static TypesInclude include({_iwxwszsz.TypesInclude? parent}) {
return TypesInclude._(); return TypesInclude._(parent: parent);
} }
static TypesIncludeList includeList({ static TypesIncludeList includeList({
@ -206,6 +271,11 @@ class _TypesImpl extends Types {
_ire5m5mj.TypesEnum? anEnum, _ire5m5mj.TypesEnum? anEnum,
String? optionalText, String? optionalText,
_isc.UuidValue? optionalUuid, _isc.UuidValue? optionalUuid,
_isc.UuidValue? parentId,
_iwxwszsz.Types? parent,
_ix6xayzv.SyncDocument? jsonDocument,
_ix6xayzv.SyncDocument? jsonbDocument,
List<int>? jsonbNumbers,
}) : super._( }) : super._(
id: id, id: id,
spaceId: spaceId, spaceId: spaceId,
@ -219,6 +289,11 @@ class _TypesImpl extends Types {
anEnum: anEnum, anEnum: anEnum,
optionalText: optionalText, optionalText: optionalText,
optionalUuid: optionalUuid, optionalUuid: optionalUuid,
parentId: parentId,
parent: parent,
jsonDocument: jsonDocument,
jsonbDocument: jsonbDocument,
jsonbNumbers: jsonbNumbers,
); );
/// Returns a shallow copy of this [Types] /// Returns a shallow copy of this [Types]
@ -238,6 +313,11 @@ class _TypesImpl extends Types {
Object? anEnum = _Undefined, Object? anEnum = _Undefined,
Object? optionalText = _Undefined, Object? optionalText = _Undefined,
Object? optionalUuid = _Undefined, Object? optionalUuid = _Undefined,
Object? parentId = _Undefined,
Object? parent = _Undefined,
Object? jsonDocument = _Undefined,
Object? jsonbDocument = _Undefined,
Object? jsonbNumbers = _Undefined,
}) { }) {
return Types( return Types(
id: id is _isc.UuidValue? ? id : this.id, id: id is _isc.UuidValue? ? id : this.id,
@ -254,6 +334,17 @@ class _TypesImpl extends Types {
optionalUuid: optionalUuid is _isc.UuidValue? optionalUuid: optionalUuid is _isc.UuidValue?
? optionalUuid ? optionalUuid
: this.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, table.optionalUuid,
value, 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?> { class TypesTable extends _isd.Table<_isc.UuidValue?> {
@ -372,6 +489,22 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
'optionalUuid', 'optionalUuid',
this, 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; late final TypesUpdateTable updateTable;
@ -399,6 +532,29 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
late final _isd.ColumnUuid optionalUuid; 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 @override
List<_isd.Column> get columns => [ List<_isd.Column> get columns => [
id, id,
@ -413,14 +569,30 @@ class TypesTable extends _isd.Table<_isc.UuidValue?> {
anEnum, anEnum,
optionalText, optionalText,
optionalUuid, optionalUuid,
parentId,
jsonDocument,
jsonbDocument,
jsonbNumbers,
]; ];
@override
_isd.Table? getRelationTable(String relationField) {
if (relationField == 'parent') {
return parent;
}
return null;
}
} }
class TypesInclude extends _isd.IncludeObject { class TypesInclude extends _isd.IncludeObject {
TypesInclude._(); TypesInclude._({_iwxwszsz.TypesInclude? parent}) {
_parent = parent;
}
_iwxwszsz.TypesInclude? _parent;
@override @override
Map<String, _isd.Include?> get includes => {}; Map<String, _isd.Include?> get includes => {'parent': _parent};
@override @override
_isd.Table<_isc.UuidValue?> get table => Types.t; _isd.Table<_isc.UuidValue?> get table => Types.t;
@ -448,6 +620,10 @@ class TypesIncludeList extends _isd.IncludeList {
class TypesRepository { class TypesRepository {
const TypesRepository._(); const TypesRepository._();
final attachRow = const TypesAttachRowRepository._();
final detachRow = const TypesDetachRowRepository._();
/// Returns a list of [Types]s matching the given query parameters. /// Returns a list of [Types]s matching the given query parameters.
/// ///
/// Use [where] to specify which items to include in the return value. /// Use [where] to specify which items to include in the return value.
@ -478,6 +654,7 @@ class TypesRepository {
_isd.OrderByBuilder<TypesTable>? orderBy, _isd.OrderByBuilder<TypesTable>? orderBy,
_isd.OrderByListBuilder<TypesTable>? orderByList, _isd.OrderByListBuilder<TypesTable>? orderByList,
_isd.Transaction? transaction, _isd.Transaction? transaction,
TypesInclude? include,
_isd.LockMode? lockMode, _isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior, _isd.LockBehavior? lockBehavior,
}) async { }) async {
@ -488,6 +665,7 @@ class TypesRepository {
limit: limit, limit: limit,
offset: offset, offset: offset,
transaction: transaction, transaction: transaction,
include: include,
lockMode: lockMode, lockMode: lockMode,
lockBehavior: lockBehavior, lockBehavior: lockBehavior,
); );
@ -517,6 +695,7 @@ class TypesRepository {
_isd.OrderByBuilder<TypesTable>? orderBy, _isd.OrderByBuilder<TypesTable>? orderBy,
_isd.OrderByListBuilder<TypesTable>? orderByList, _isd.OrderByListBuilder<TypesTable>? orderByList,
_isd.Transaction? transaction, _isd.Transaction? transaction,
TypesInclude? include,
_isd.LockMode? lockMode, _isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior, _isd.LockBehavior? lockBehavior,
}) async { }) async {
@ -526,6 +705,7 @@ class TypesRepository {
orderByList: orderByList?.call(Types.t), orderByList: orderByList?.call(Types.t),
offset: offset, offset: offset,
transaction: transaction, transaction: transaction,
include: include,
lockMode: lockMode, lockMode: lockMode,
lockBehavior: lockBehavior, lockBehavior: lockBehavior,
); );
@ -536,12 +716,14 @@ class TypesRepository {
_isd.DatabaseSession session, _isd.DatabaseSession session,
_isc.UuidValue id, { _isc.UuidValue id, {
_isd.Transaction? transaction, _isd.Transaction? transaction,
TypesInclude? include,
_isd.LockMode? lockMode, _isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior, _isd.LockBehavior? lockBehavior,
}) async { }) async {
return session.db.findById<Types>( return session.db.findById<Types>(
id, id,
transaction: transaction, transaction: transaction,
include: include,
lockMode: lockMode, lockMode: lockMode,
lockBehavior: lockBehavior, 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,
);
}
}

View file

@ -13,3 +13,5 @@ dependencies:
serverpod_database: 4.0.0 serverpod_database: 4.0.0
serverpod_offline_sync_client: serverpod_offline_sync_client:
path: ../../packages/serverpod_offline_sync_client path: ../../packages/serverpod_offline_sync_client
serverpod_offline_sync_test_shared:
path: ../serverpod_offline_sync_test_shared

View file

@ -5,6 +5,9 @@ serialize_as_jsonb_by_default: true
client_package_path: ../serverpod_offline_sync_test_client client_package_path: ../serverpod_offline_sync_test_client
server_test_tools_path: test/integration/test_tools server_test_tools_path: test/integration/test_tools
shared_packages:
- ../serverpod_offline_sync_test_shared
experimental_features: experimental_features:
databaseSync: true databaseSync: true

View file

@ -17,6 +17,8 @@ import 'package:serverpod_auth_core_server/serverpod_auth_core_server.dart'
as _iacs; as _iacs;
import 'package:serverpod_offline_sync_server/serverpod_offline_sync_server.dart' import 'package:serverpod_offline_sync_server/serverpod_offline_sync_server.dart'
as _izehhkf5; as _izehhkf5;
import 'package:serverpod_offline_sync_test_shared/serverpod_offline_sync_test_shared.dart'
as _i2ap9bqs;
import 'address.dart' as _ilb4pipw; import 'address.dart' as _ilb4pipw;
import 'city.dart' as _ior3absd; import 'city.dart' as _ior3absd;
import 'company.dart' as _i6pnc270; 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_no_action_child.dart' as _itlfbi2f;
import 'required_set_null_child.dart' as _i1huw131; import 'required_set_null_child.dart' as _i1huw131;
import 'restrict_child.dart' as _isrf0aof; import 'restrict_child.dart' as _isrf0aof;
import 'sync_document.dart' as _ix6xayzv;
import 'town.dart' as _iytblq2r; import 'town.dart' as _iytblq2r;
import 'types.dart' as _iwxwszsz; import 'types.dart' as _iwxwszsz;
import 'types_enum.dart' as _ire5m5mj; import 'types_enum.dart' as _ire5m5mj;
@ -71,6 +74,7 @@ export 'required_cascade_child.dart';
export 'required_no_action_child.dart'; export 'required_no_action_child.dart';
export 'required_set_null_child.dart'; export 'required_set_null_child.dart';
export 'restrict_child.dart'; export 'restrict_child.dart';
export 'sync_document.dart';
export 'town.dart'; export 'town.dart';
export 'types.dart'; export 'types.dart';
export 'types_enum.dart'; export 'types_enum.dart';
@ -1372,6 +1376,30 @@ class Protocol extends _is.DatabaseSerializationManager {
isNullable: true, isNullable: true,
dartType: 'UuidValue?', 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: [ foreignKeys: [
_isp.ForeignKeyDefinition( _isp.ForeignKeyDefinition(
@ -1384,6 +1412,16 @@ class Protocol extends _is.DatabaseSerializationManager {
onDelete: _isp.ForeignKeyAction.cascade, onDelete: _isp.ForeignKeyAction.cascade,
matchType: null, 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: [ indexes: [
_isp.IndexDefinition( _isp.IndexDefinition(
@ -2341,6 +2379,10 @@ class Protocol extends _is.DatabaseSerializationManager {
), ),
..._iacs.Protocol.targetTableDefinitions, ..._iacs.Protocol.targetTableDefinitions,
..._izehhkf5.Protocol.targetTableDefinitions, ..._izehhkf5.Protocol.targetTableDefinitions,
..._i2ap9bqs.Protocol() is _is.DatabaseSerializationManager
? (_i2ap9bqs.Protocol() as _is.DatabaseSerializationManager)
.getTargetTableDefinitions()
: [],
..._isp.Protocol.targetTableDefinitions, ..._isp.Protocol.targetTableDefinitions,
]; ];
@ -2428,6 +2470,9 @@ class Protocol extends _is.DatabaseSerializationManager {
if (t == _isrf0aof.RestrictChild) { if (t == _isrf0aof.RestrictChild) {
return _isrf0aof.RestrictChild.fromJson(data) as T; return _isrf0aof.RestrictChild.fromJson(data) as T;
} }
if (t == _ix6xayzv.SyncDocument) {
return _ix6xayzv.SyncDocument.fromJson(data) as T;
}
if (t == _iytblq2r.Town) { if (t == _iytblq2r.Town) {
return _iytblq2r.Town.fromJson(data) as T; return _iytblq2r.Town.fromJson(data) as T;
} }
@ -2570,6 +2615,9 @@ class Protocol extends _is.DatabaseSerializationManager {
return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null) return (data != null ? _isrf0aof.RestrictChild.fromJson(data) : null)
as T; as T;
} }
if (t == _is.getType<_ix6xayzv.SyncDocument?>()) {
return (data != null ? _ix6xayzv.SyncDocument.fromJson(data) : null) as T;
}
if (t == _is.getType<_iytblq2r.Town?>()) { if (t == _is.getType<_iytblq2r.Town?>()) {
return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T; return (data != null ? _iytblq2r.Town.fromJson(data) : null) as T;
} }
@ -2662,6 +2710,15 @@ class Protocol extends _is.DatabaseSerializationManager {
: null) : null)
as T; 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>) { if (t == List<dynamic>) {
return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T; return (data as List).map((e) => deserialize<dynamic>(e)).toList() as T;
} }
@ -2674,6 +2731,9 @@ class Protocol extends _is.DatabaseSerializationManager {
try { try {
return _izehhkf5.Protocol().deserialize<T>(data, t); return _izehhkf5.Protocol().deserialize<T>(data, t);
} on _is.DeserializationTypeNotFoundException catch (_) {} } on _is.DeserializationTypeNotFoundException catch (_) {}
try {
return _i2ap9bqs.Protocol().deserialize<T>(data, t);
} on _is.DeserializationTypeNotFoundException catch (_) {}
try { try {
return _isp.Protocol().deserialize<T>(data, t); return _isp.Protocol().deserialize<T>(data, t);
} on _is.DeserializationTypeNotFoundException catch (_) {} } on _is.DeserializationTypeNotFoundException catch (_) {}
@ -2701,6 +2761,7 @@ class Protocol extends _is.DatabaseSerializationManager {
_itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild', _itlfbi2f.RequiredNoActionChild => 'RequiredNoActionChild',
_i1huw131.RequiredSetNullChild => 'RequiredSetNullChild', _i1huw131.RequiredSetNullChild => 'RequiredSetNullChild',
_isrf0aof.RestrictChild => 'RestrictChild', _isrf0aof.RestrictChild => 'RestrictChild',
_ix6xayzv.SyncDocument => 'SyncDocument',
_iytblq2r.Town => 'Town', _iytblq2r.Town => 'Town',
_iwxwszsz.Types => 'Types', _iwxwszsz.Types => 'Types',
_ire5m5mj.TypesEnum => 'TypesEnum', _ire5m5mj.TypesEnum => 'TypesEnum',
@ -2772,6 +2833,8 @@ class Protocol extends _is.DatabaseSerializationManager {
return 'RequiredSetNullChild'; return 'RequiredSetNullChild';
case _isrf0aof.RestrictChild(): case _isrf0aof.RestrictChild():
return 'RestrictChild'; return 'RestrictChild';
case _ix6xayzv.SyncDocument():
return 'SyncDocument';
case _iytblq2r.Town(): case _iytblq2r.Town():
return 'Town'; return 'Town';
case _iwxwszsz.Types(): case _iwxwszsz.Types():
@ -2817,6 +2880,12 @@ class Protocol extends _is.DatabaseSerializationManager {
? className ? className
: 'serverpod_offline_sync.$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); className = _isp.Protocol().getClassNameForObject(data);
if (className != null) { if (className != null) {
return className.contains('.') ? className : 'serverpod.$className'; return className.contains('.') ? className : 'serverpod.$className';
@ -2887,6 +2956,9 @@ class Protocol extends _is.DatabaseSerializationManager {
if (dataClassName == 'RestrictChild') { if (dataClassName == 'RestrictChild') {
return deserialize<_isrf0aof.RestrictChild>(data['data']); return deserialize<_isrf0aof.RestrictChild>(data['data']);
} }
if (dataClassName == 'SyncDocument') {
return deserialize<_ix6xayzv.SyncDocument>(data['data']);
}
if (dataClassName == 'Town') { if (dataClassName == 'Town') {
return deserialize<_iytblq2r.Town>(data['data']); return deserialize<_iytblq2r.Town>(data['data']);
} }
@ -2943,6 +3015,10 @@ class Protocol extends _is.DatabaseSerializationManager {
data['className'] = dataClassName.substring(23); data['className'] = dataClassName.substring(23);
return _izehhkf5.Protocol().deserializeByClassName(data); 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.')) { if (dataClassName.startsWith('serverpod.')) {
data['className'] = dataClassName.substring(10); data['className'] = dataClassName.substring(10);
return _isp.Protocol().deserializeByClassName(data); return _isp.Protocol().deserializeByClassName(data);
@ -2956,6 +3032,10 @@ class Protocol extends _is.DatabaseSerializationManager {
'serverpod_offline_sync_test', 'serverpod_offline_sync_test',
this, this,
); );
_i2ap9bqs.Protocol().registerHostProtocol(
'serverpod_offline_sync_test',
this,
);
} }
@override @override
@ -2972,6 +3052,15 @@ class Protocol extends _is.DatabaseSerializationManager {
return table; 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); var table = _isp.Protocol().getTableForType(t);
if (table != null) { if (table != null) {

View 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(),
);
}
}

View file

@ -11,6 +11,8 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes // ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod/serverpod.dart' as _is; 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 'address.dart' as _ilb4pipw;
import 'city.dart' as _ior3absd; import 'city.dart' as _ior3absd;
import 'company.dart' as _i6pnc270; import 'company.dart' as _i6pnc270;
@ -68,6 +70,8 @@ final List<_is.Table> syncTables = [
_itlfbi2f.RequiredNoActionChild.t, _itlfbi2f.RequiredNoActionChild.t,
_i1huw131.RequiredSetNullChild.t, _i1huw131.RequiredSetNullChild.t,
_isrf0aof.RestrictChild.t, _isrf0aof.RestrictChild.t,
_i2ap9bqs.SharedChild.t,
_i2ap9bqs.SharedParent.t,
_iytblq2r.Town.t, _iytblq2r.Town.t,
_iwxwszsz.Types.t, _iwxwszsz.Types.t,
_ivpwn84u.Unique.t, _ivpwn84u.Unique.t,

Some files were not shown because too many files have changed in this diff Show more