feat(todo): sections, tasks and labels on the server (ADR 0033, D6)

Three more synced tables, each a sealed payload alone, as project's:
section, task and label; deleted with the person's space.

The migration only adds: the three tables (id uuid defaulting to
gen_random_uuid_v7(), spaceId, keyId, payload, nonce), each indexed on
spaceId and cascading with its space (ON DELETE CASCADE to
offline_sync_spaces), and the modules' version rows. Nothing is dropped
or changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-01 01:06:24 +01:00
commit 128bcb127b
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
10 changed files with 22399 additions and 7 deletions

View file

@ -0,0 +1,447 @@
{
"__className__": "serverpod.DatabaseDefinition",
"schemaVersion": 2,
"moduleName": "halkyon_todo",
"tables": [
{
"__className__": "serverpod.TableDefinition",
"name": "content_key",
"dartName": "ContentKey",
"module": "halkyon_todo",
"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": "dataKeyId",
"fieldName": "dataKeyId",
"columnType": 0,
"isNullable": false,
"dartType": "String"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "sealedKey",
"fieldName": "sealedKey",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "content_key_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "content_key_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "label",
"dartName": "Label",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "label_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "label_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "project",
"dartName": "Project",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "project_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "project_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "section",
"dartName": "Section",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "section_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "section_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "task",
"dartName": "Task",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "task_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "task_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
],
"installedModules": [
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "halkyon_base",
"version": "20261026140329453-assistant-budgets"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod",
"version": "20260824182259319"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_auth_idp",
"version": "20260924105404509"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_offline_sync",
"version": "20260914143806119"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "halkyon_oidc",
"version": "20261023180644988"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_auth_core",
"version": "20260924105232991"
}
],
"migrationApiVersion": 1
}

View file

@ -0,0 +1,268 @@
{
"__className__": "serverpod.DatabaseMigration",
"actions": [
{
"__className__": "serverpod.DatabaseMigrationAction",
"type": "createTable",
"createTable": {
"__className__": "serverpod.TableDefinition",
"name": "label",
"dartName": "Label",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "label_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "label_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
},
{
"__className__": "serverpod.DatabaseMigrationAction",
"type": "createTable",
"createTable": {
"__className__": "serverpod.TableDefinition",
"name": "section",
"dartName": "Section",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "section_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "section_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
},
{
"__className__": "serverpod.DatabaseMigrationAction",
"type": "createTable",
"createTable": {
"__className__": "serverpod.TableDefinition",
"name": "task",
"dartName": "Task",
"module": "halkyon_todo",
"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": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "task_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "task_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
}
],
"warnings": [],
"migrationApiVersion": 1
}

View file

@ -5,6 +5,7 @@ library;
import 'package:serverpod_database/serverpod_database.dart';
part '20261101000019144-projects/migration.dart';
part '20261101000604776-tasks/migration.dart';
/// Migration registry for the client-side database.
class MigrationRegistry {
@ -12,6 +13,7 @@ class MigrationRegistry {
/// New migrations are always appended at the end.
static final List<MigrationVersionSql> migrations = [
_Migration20261101000019144_projects(),
_Migration20261101000604776_tasks(),
];
/// List of all client-side database migration versions.

View file

@ -0,0 +1,671 @@
/* 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 'dart:typed_data' as _idt;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd;
/// A label (ADR 0033, D6): its name, colour and place among the others, in
/// its sealed payload (D5); the instance sees that it exists, its size and
/// when it changed. Changed when edited, the last writer winning. Synced.
abstract class Label
implements _isd.TableRow<_isc.UuidValue?>, _isc.ProtocolSerialization {
Label._({
this.id,
this.spaceId,
this.keyId,
required this.payload,
this.nonce,
});
factory Label({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) = _LabelImpl;
factory Label.fromJson(Map<String, dynamic> jsonSerialization) {
return Label(
id: jsonSerialization['id'] == null
? null
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
spaceId: jsonSerialization['spaceId'] as int?,
keyId: jsonSerialization['keyId'] as String?,
payload: _isc.ByteDataJsonExtension.fromJson(
jsonSerialization['payload'],
),
nonce: jsonSerialization['nonce'] == null
? null
: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
);
}
static final t = LabelTable();
static const db = LabelRepository._();
@override
_isc.UuidValue? id;
/// The space owning this row. Maintained by the sync engine.
int? spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
String? keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
_idt.ByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
_idt.ByteData? nonce;
@override
_isd.Table<_isc.UuidValue?> get table => t;
/// Returns a shallow copy of this [Label]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
Label copyWith({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
_idt.ByteData? payload,
_idt.ByteData? nonce,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'Label',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'Label',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
static LabelInclude include() {
return LabelInclude._();
}
static LabelIncludeList includeList({
_isd.WhereExpressionBuilder<LabelTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
LabelInclude? include,
}) {
return LabelIncludeList._(
where: where,
limit: limit,
offset: offset,
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
include: include,
);
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _LabelImpl extends Label {
_LabelImpl({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) : super._(
id: id,
spaceId: spaceId,
keyId: keyId,
payload: payload,
nonce: nonce,
);
/// Returns a shallow copy of this [Label]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
Label copyWith({
Object? id = _Undefined,
Object? spaceId = _Undefined,
Object? keyId = _Undefined,
_idt.ByteData? payload,
Object? nonce = _Undefined,
}) {
return Label(
id: id is _isc.UuidValue? ? id : this.id,
spaceId: spaceId is int? ? spaceId : this.spaceId,
keyId: keyId is String? ? keyId : this.keyId,
payload: payload ?? this.payload.clone(),
nonce: nonce is _idt.ByteData? ? nonce : this.nonce?.clone(),
);
}
}
class LabelUpdateTable extends _isd.UpdateTable<LabelTable> {
LabelUpdateTable(super.table);
_isd.ColumnValue<int, int> spaceId(int? value) => _isd.ColumnValue(
table.spaceId,
value,
);
_isd.ColumnValue<String, String> keyId(String? value) => _isd.ColumnValue(
table.keyId,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> payload(_idt.ByteData value) =>
_isd.ColumnValue(
table.payload,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> nonce(_idt.ByteData? value) =>
_isd.ColumnValue(
table.nonce,
value,
);
}
class LabelTable extends _isd.Table<_isc.UuidValue?> {
LabelTable({super.tableRelation}) : super(tableName: 'label') {
updateTable = LabelUpdateTable(this);
spaceId = _isd.ColumnInt(
'spaceId',
this,
);
keyId = _isd.ColumnString(
'keyId',
this,
);
payload = _isd.ColumnByteData(
'payload',
this,
);
nonce = _isd.ColumnByteData(
'nonce',
this,
);
}
late final LabelUpdateTable updateTable;
/// The space owning this row. Maintained by the sync engine.
late final _isd.ColumnInt spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
late final _isd.ColumnString keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
late final _isd.ColumnByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
late final _isd.ColumnByteData nonce;
@override
List<_isd.Column> get columns => [
id,
spaceId,
keyId,
payload,
nonce,
];
}
class LabelInclude extends _isd.IncludeObject {
LabelInclude._();
@override
Map<String, _isd.Include?> get includes => {};
@override
_isd.Table<_isc.UuidValue?> get table => Label.t;
}
class LabelIncludeList extends _isd.IncludeList {
LabelIncludeList._({
_isd.WhereExpressionBuilder<LabelTable>? where,
super.limit,
super.offset,
super.orderBy,
super.orderByList,
super.include,
}) {
super.where = where?.call(Label.t);
}
@override
Map<String, _isd.Include?> get includes => include?.includes ?? {};
@override
_isd.Table<_isc.UuidValue?> get table => Label.t;
}
class LabelRepository {
const LabelRepository._();
/// Returns a list of [Label]s matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order of the items use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// The maximum number of items can be set by [limit]. If no limit is set,
/// all items matching the query will be returned.
///
/// [offset] defines how many items to skip, after which [limit] (or all)
/// items are read from the database.
///
/// ```dart
/// var persons = await Persons.db.find(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.firstName,
/// limit: 100,
/// );
/// ```
Future<List<Label>> find(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<LabelTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.find<Label>(
where: where?.call(Label.t),
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
limit: limit,
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Returns the first matching [Label] matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// [offset] defines how many items to skip, after which the next one will be picked.
///
/// ```dart
/// var youngestPerson = await Persons.db.findFirstRow(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.age,
/// );
/// ```
Future<Label?> findFirstRow(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<LabelTable>? where,
int? offset,
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findFirstRow<Label>(
where: where?.call(Label.t),
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Finds a single [Label] by its [id] or null if no such row exists.
Future<Label?> findById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findById<Label>(
id,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Inserts all [Label]s in the list and returns the inserted rows.
///
/// The returned [Label]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails to
/// insert, none of the rows will be inserted.
///
/// If [ignoreConflicts] is set to `true`, rows that conflict with existing
/// rows are silently skipped, and only the successfully inserted rows are
/// returned.
///
/// If [noReturn] is set to `true`, the inserted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> insert(
_isd.DatabaseSession session,
List<Label> rows, {
_isd.Transaction? transaction,
bool ignoreConflicts = false,
bool noReturn = false,
}) async {
return session.db.insert<Label>(
rows,
transaction: transaction,
ignoreConflicts: ignoreConflicts,
noReturn: noReturn,
);
}
/// Inserts a single [Label] and returns the inserted row.
///
/// The returned [Label] will have its `id` field set.
Future<Label> insertRow(
_isd.DatabaseSession session,
Label row, {
_isd.Transaction? transaction,
}) async {
return session.db.insertRow<Label>(
row,
transaction: transaction,
);
}
/// Upserts all [Label]s in the list and returns the resulting rows.
///
/// If a row conflicts on the given [conflictColumns], the existing row is
/// updated with the new values. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies to rows matching the
/// given expression. Conflicting rows that don't match are skipped and not
/// returned, so the resulting list may be shorter than [rows].
///
/// The returned [Label]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails,
/// none of the rows will be affected.
///
/// If [noReturn] is set to `true`, the resulting rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> upsert(
_isd.DatabaseSession session,
List<Label> rows, {
required _isd.ColumnSelections<LabelTable> conflictColumns,
_isd.ColumnSelections<LabelTable>? updateColumns,
_isd.WhereExpressionBuilder<LabelTable>? updateWhere,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.upsert<Label>(
rows,
conflictColumns: conflictColumns(Label.t),
updateColumns: updateColumns?.call(Label.t),
updateWhere: updateWhere?.call(Label.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Upserts a single [Label] and returns the resulting row.
///
/// If the row conflicts on the given [conflictColumns], the existing row is
/// updated. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies when the existing
/// row matches the expression. Returns `null` if no row was affected — for
/// example when [updateWhere] does not match the conflicting row.
///
/// The returned [Label] will have its `id` field set.
Future<Label?> upsertRow(
_isd.DatabaseSession session,
Label row, {
required _isd.ColumnSelections<LabelTable> conflictColumns,
_isd.ColumnSelections<LabelTable>? updateColumns,
_isd.WhereExpressionBuilder<LabelTable>? updateWhere,
_isd.Transaction? transaction,
}) async {
return session.db.upsertRow<Label>(
row,
conflictColumns: conflictColumns(Label.t),
updateColumns: updateColumns?.call(Label.t),
updateWhere: updateWhere?.call(Label.t),
transaction: transaction,
);
}
/// Updates all [Label]s in the list and returns the updated rows. If
/// [columns] is provided, only those columns will be updated. Defaults to
/// all columns.
/// This is an atomic operation, meaning that if one of the rows fails to
/// update, none of the rows will be updated.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> update(
_isd.DatabaseSession session,
List<Label> rows, {
_isd.ColumnSelections<LabelTable>? columns,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.update<Label>(
rows,
columns: columns?.call(Label.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Updates a single [Label]. The row needs to have its id set.
/// Optionally, a list of [columns] can be provided to only update those
/// columns. Defaults to all columns.
Future<Label> updateRow(
_isd.DatabaseSession session,
Label row, {
_isd.ColumnSelections<LabelTable>? columns,
_isd.Transaction? transaction,
}) async {
return session.db.updateRow<Label>(
row,
columns: columns?.call(Label.t),
transaction: transaction,
);
}
/// Updates a single [Label] by its [id] with the specified [columnValues].
/// Returns the updated row or null if no row with the given id exists.
Future<Label?> updateById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
required _isd.ColumnValueListBuilder<LabelUpdateTable> columnValues,
_isd.Transaction? transaction,
}) async {
return session.db.updateById<Label>(
id,
columnValues: columnValues(Label.t.updateTable),
transaction: transaction,
);
}
/// Updates all [Label]s matching the [where] expression with the specified [columnValues].
/// Returns the list of updated rows.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> updateWhere(
_isd.DatabaseSession session, {
required _isd.ColumnValueListBuilder<LabelUpdateTable> columnValues,
required _isd.WhereExpressionBuilder<LabelTable> where,
int? limit,
int? offset,
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.updateWhere<Label>(
columnValues: columnValues(Label.t.updateTable),
where: where(Label.t),
limit: limit,
offset: offset,
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes all [Label]s in the list and returns the deleted rows.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// This is an atomic operation, meaning that if one of the rows fail to
/// be deleted, none of the rows will be deleted.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> delete(
_isd.DatabaseSession session,
List<Label> rows, {
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.delete<Label>(
rows,
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes a single [Label].
Future<Label> deleteRow(
_isd.DatabaseSession session,
Label row, {
_isd.Transaction? transaction,
}) async {
return session.db.deleteRow<Label>(
row,
transaction: transaction,
);
}
/// Deletes all rows matching the [where] expression.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Label>> deleteWhere(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<LabelTable> where,
_isd.OrderByBuilder<LabelTable>? orderBy,
_isd.OrderByListBuilder<LabelTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.deleteWhere<Label>(
where: where(Label.t),
orderBy: orderBy?.call(Label.t),
orderByList: orderByList?.call(Label.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Counts the number of rows matching the [where] expression. If omitted,
/// will return the count of all rows in the table.
Future<int> count(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<LabelTable>? where,
int? limit,
_isd.Transaction? transaction,
}) async {
return session.db.count<Label>(
where: where?.call(Label.t),
limit: limit,
transaction: transaction,
);
}
/// Acquires row-level locks on [Label] rows matching the [where] expression.
Future<void> lockRows(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<LabelTable> where,
required _isd.LockMode lockMode,
required _isd.Transaction transaction,
_isd.LockBehavior lockBehavior = _isd.LockBehavior.wait,
}) async {
return session.db.lockRows<Label>(
where: where(Label.t),
lockMode: lockMode,
lockBehavior: lockBehavior,
transaction: transaction,
);
}
}

View file

@ -0,0 +1,672 @@
/* 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 'dart:typed_data' as _idt;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd;
/// A section of a project (ADR 0033, D6): its name, description, project and
/// place among the project's sections, all in its sealed payload (D5); the
/// instance sees that it exists, its size and when it changed. Changed when
/// edited, the last writer winning. Synced.
abstract class Section
implements _isd.TableRow<_isc.UuidValue?>, _isc.ProtocolSerialization {
Section._({
this.id,
this.spaceId,
this.keyId,
required this.payload,
this.nonce,
});
factory Section({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) = _SectionImpl;
factory Section.fromJson(Map<String, dynamic> jsonSerialization) {
return Section(
id: jsonSerialization['id'] == null
? null
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
spaceId: jsonSerialization['spaceId'] as int?,
keyId: jsonSerialization['keyId'] as String?,
payload: _isc.ByteDataJsonExtension.fromJson(
jsonSerialization['payload'],
),
nonce: jsonSerialization['nonce'] == null
? null
: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
);
}
static final t = SectionTable();
static const db = SectionRepository._();
@override
_isc.UuidValue? id;
/// The space owning this row. Maintained by the sync engine.
int? spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
String? keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
_idt.ByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
_idt.ByteData? nonce;
@override
_isd.Table<_isc.UuidValue?> get table => t;
/// Returns a shallow copy of this [Section]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
Section copyWith({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
_idt.ByteData? payload,
_idt.ByteData? nonce,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'Section',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'Section',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
static SectionInclude include() {
return SectionInclude._();
}
static SectionIncludeList includeList({
_isd.WhereExpressionBuilder<SectionTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
SectionInclude? include,
}) {
return SectionIncludeList._(
where: where,
limit: limit,
offset: offset,
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
include: include,
);
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _SectionImpl extends Section {
_SectionImpl({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) : super._(
id: id,
spaceId: spaceId,
keyId: keyId,
payload: payload,
nonce: nonce,
);
/// Returns a shallow copy of this [Section]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
Section copyWith({
Object? id = _Undefined,
Object? spaceId = _Undefined,
Object? keyId = _Undefined,
_idt.ByteData? payload,
Object? nonce = _Undefined,
}) {
return Section(
id: id is _isc.UuidValue? ? id : this.id,
spaceId: spaceId is int? ? spaceId : this.spaceId,
keyId: keyId is String? ? keyId : this.keyId,
payload: payload ?? this.payload.clone(),
nonce: nonce is _idt.ByteData? ? nonce : this.nonce?.clone(),
);
}
}
class SectionUpdateTable extends _isd.UpdateTable<SectionTable> {
SectionUpdateTable(super.table);
_isd.ColumnValue<int, int> spaceId(int? value) => _isd.ColumnValue(
table.spaceId,
value,
);
_isd.ColumnValue<String, String> keyId(String? value) => _isd.ColumnValue(
table.keyId,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> payload(_idt.ByteData value) =>
_isd.ColumnValue(
table.payload,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> nonce(_idt.ByteData? value) =>
_isd.ColumnValue(
table.nonce,
value,
);
}
class SectionTable extends _isd.Table<_isc.UuidValue?> {
SectionTable({super.tableRelation}) : super(tableName: 'section') {
updateTable = SectionUpdateTable(this);
spaceId = _isd.ColumnInt(
'spaceId',
this,
);
keyId = _isd.ColumnString(
'keyId',
this,
);
payload = _isd.ColumnByteData(
'payload',
this,
);
nonce = _isd.ColumnByteData(
'nonce',
this,
);
}
late final SectionUpdateTable updateTable;
/// The space owning this row. Maintained by the sync engine.
late final _isd.ColumnInt spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
late final _isd.ColumnString keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
late final _isd.ColumnByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
late final _isd.ColumnByteData nonce;
@override
List<_isd.Column> get columns => [
id,
spaceId,
keyId,
payload,
nonce,
];
}
class SectionInclude extends _isd.IncludeObject {
SectionInclude._();
@override
Map<String, _isd.Include?> get includes => {};
@override
_isd.Table<_isc.UuidValue?> get table => Section.t;
}
class SectionIncludeList extends _isd.IncludeList {
SectionIncludeList._({
_isd.WhereExpressionBuilder<SectionTable>? where,
super.limit,
super.offset,
super.orderBy,
super.orderByList,
super.include,
}) {
super.where = where?.call(Section.t);
}
@override
Map<String, _isd.Include?> get includes => include?.includes ?? {};
@override
_isd.Table<_isc.UuidValue?> get table => Section.t;
}
class SectionRepository {
const SectionRepository._();
/// Returns a list of [Section]s matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order of the items use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// The maximum number of items can be set by [limit]. If no limit is set,
/// all items matching the query will be returned.
///
/// [offset] defines how many items to skip, after which [limit] (or all)
/// items are read from the database.
///
/// ```dart
/// var persons = await Persons.db.find(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.firstName,
/// limit: 100,
/// );
/// ```
Future<List<Section>> find(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<SectionTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.find<Section>(
where: where?.call(Section.t),
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
limit: limit,
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Returns the first matching [Section] matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// [offset] defines how many items to skip, after which the next one will be picked.
///
/// ```dart
/// var youngestPerson = await Persons.db.findFirstRow(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.age,
/// );
/// ```
Future<Section?> findFirstRow(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<SectionTable>? where,
int? offset,
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findFirstRow<Section>(
where: where?.call(Section.t),
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Finds a single [Section] by its [id] or null if no such row exists.
Future<Section?> findById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findById<Section>(
id,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Inserts all [Section]s in the list and returns the inserted rows.
///
/// The returned [Section]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails to
/// insert, none of the rows will be inserted.
///
/// If [ignoreConflicts] is set to `true`, rows that conflict with existing
/// rows are silently skipped, and only the successfully inserted rows are
/// returned.
///
/// If [noReturn] is set to `true`, the inserted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> insert(
_isd.DatabaseSession session,
List<Section> rows, {
_isd.Transaction? transaction,
bool ignoreConflicts = false,
bool noReturn = false,
}) async {
return session.db.insert<Section>(
rows,
transaction: transaction,
ignoreConflicts: ignoreConflicts,
noReturn: noReturn,
);
}
/// Inserts a single [Section] and returns the inserted row.
///
/// The returned [Section] will have its `id` field set.
Future<Section> insertRow(
_isd.DatabaseSession session,
Section row, {
_isd.Transaction? transaction,
}) async {
return session.db.insertRow<Section>(
row,
transaction: transaction,
);
}
/// Upserts all [Section]s in the list and returns the resulting rows.
///
/// If a row conflicts on the given [conflictColumns], the existing row is
/// updated with the new values. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies to rows matching the
/// given expression. Conflicting rows that don't match are skipped and not
/// returned, so the resulting list may be shorter than [rows].
///
/// The returned [Section]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails,
/// none of the rows will be affected.
///
/// If [noReturn] is set to `true`, the resulting rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> upsert(
_isd.DatabaseSession session,
List<Section> rows, {
required _isd.ColumnSelections<SectionTable> conflictColumns,
_isd.ColumnSelections<SectionTable>? updateColumns,
_isd.WhereExpressionBuilder<SectionTable>? updateWhere,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.upsert<Section>(
rows,
conflictColumns: conflictColumns(Section.t),
updateColumns: updateColumns?.call(Section.t),
updateWhere: updateWhere?.call(Section.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Upserts a single [Section] and returns the resulting row.
///
/// If the row conflicts on the given [conflictColumns], the existing row is
/// updated. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies when the existing
/// row matches the expression. Returns `null` if no row was affected — for
/// example when [updateWhere] does not match the conflicting row.
///
/// The returned [Section] will have its `id` field set.
Future<Section?> upsertRow(
_isd.DatabaseSession session,
Section row, {
required _isd.ColumnSelections<SectionTable> conflictColumns,
_isd.ColumnSelections<SectionTable>? updateColumns,
_isd.WhereExpressionBuilder<SectionTable>? updateWhere,
_isd.Transaction? transaction,
}) async {
return session.db.upsertRow<Section>(
row,
conflictColumns: conflictColumns(Section.t),
updateColumns: updateColumns?.call(Section.t),
updateWhere: updateWhere?.call(Section.t),
transaction: transaction,
);
}
/// Updates all [Section]s in the list and returns the updated rows. If
/// [columns] is provided, only those columns will be updated. Defaults to
/// all columns.
/// This is an atomic operation, meaning that if one of the rows fails to
/// update, none of the rows will be updated.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> update(
_isd.DatabaseSession session,
List<Section> rows, {
_isd.ColumnSelections<SectionTable>? columns,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.update<Section>(
rows,
columns: columns?.call(Section.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Updates a single [Section]. The row needs to have its id set.
/// Optionally, a list of [columns] can be provided to only update those
/// columns. Defaults to all columns.
Future<Section> updateRow(
_isd.DatabaseSession session,
Section row, {
_isd.ColumnSelections<SectionTable>? columns,
_isd.Transaction? transaction,
}) async {
return session.db.updateRow<Section>(
row,
columns: columns?.call(Section.t),
transaction: transaction,
);
}
/// Updates a single [Section] by its [id] with the specified [columnValues].
/// Returns the updated row or null if no row with the given id exists.
Future<Section?> updateById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
required _isd.ColumnValueListBuilder<SectionUpdateTable> columnValues,
_isd.Transaction? transaction,
}) async {
return session.db.updateById<Section>(
id,
columnValues: columnValues(Section.t.updateTable),
transaction: transaction,
);
}
/// Updates all [Section]s matching the [where] expression with the specified [columnValues].
/// Returns the list of updated rows.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> updateWhere(
_isd.DatabaseSession session, {
required _isd.ColumnValueListBuilder<SectionUpdateTable> columnValues,
required _isd.WhereExpressionBuilder<SectionTable> where,
int? limit,
int? offset,
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.updateWhere<Section>(
columnValues: columnValues(Section.t.updateTable),
where: where(Section.t),
limit: limit,
offset: offset,
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes all [Section]s in the list and returns the deleted rows.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// This is an atomic operation, meaning that if one of the rows fail to
/// be deleted, none of the rows will be deleted.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> delete(
_isd.DatabaseSession session,
List<Section> rows, {
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.delete<Section>(
rows,
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes a single [Section].
Future<Section> deleteRow(
_isd.DatabaseSession session,
Section row, {
_isd.Transaction? transaction,
}) async {
return session.db.deleteRow<Section>(
row,
transaction: transaction,
);
}
/// Deletes all rows matching the [where] expression.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Section>> deleteWhere(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<SectionTable> where,
_isd.OrderByBuilder<SectionTable>? orderBy,
_isd.OrderByListBuilder<SectionTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.deleteWhere<Section>(
where: where(Section.t),
orderBy: orderBy?.call(Section.t),
orderByList: orderByList?.call(Section.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Counts the number of rows matching the [where] expression. If omitted,
/// will return the count of all rows in the table.
Future<int> count(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<SectionTable>? where,
int? limit,
_isd.Transaction? transaction,
}) async {
return session.db.count<Section>(
where: where?.call(Section.t),
limit: limit,
transaction: transaction,
);
}
/// Acquires row-level locks on [Section] rows matching the [where] expression.
Future<void> lockRows(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<SectionTable> where,
required _isd.LockMode lockMode,
required _isd.Transaction transaction,
_isd.LockBehavior lockBehavior = _isd.LockBehavior.wait,
}) async {
return session.db.lockRows<Section>(
where: where(Section.t),
lockMode: lockMode,
lockBehavior: lockBehavior,
transaction: transaction,
);
}
}

View file

@ -21,10 +21,16 @@ 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 'label/label.dart' as _ivak08z4;
import 'privacy/content_key.dart' as _imed3x5d;
import 'project/project.dart' as _i9c44spp;
import 'project/section.dart' as _imadkvi9;
import 'task/task.dart' as _ib4f8uyw;
export 'label/label.dart';
export 'privacy/content_key.dart';
export 'project/project.dart';
export 'project/section.dart';
export 'task/task.dart';
export 'client.dart';
export 'sync_tables.dart';
@ -97,6 +103,73 @@ class Protocol extends _isd.DatabaseSerializationManager {
],
managed: true,
),
_isd.TableDefinition(
name: 'label',
dartName: 'Label',
schema: 'public',
module: 'halkyon_todo',
columns: [
_isd.ColumnDefinition(
name: 'id',
columnType: _isd.ColumnType.uuid,
isNullable: false,
dartType: 'UuidValue?',
columnDefault: 'random_v7',
),
_isd.ColumnDefinition(
name: 'spaceId',
columnType: _isd.ColumnType.bigint,
isNullable: true,
dartType: 'int?',
),
_isd.ColumnDefinition(
name: 'keyId',
columnType: _isd.ColumnType.text,
isNullable: true,
dartType: 'String?',
),
_isd.ColumnDefinition(
name: 'payload',
columnType: _isd.ColumnType.bytea,
isNullable: false,
dartType: 'dart:typed_data:ByteData',
),
_isd.ColumnDefinition(
name: 'nonce',
columnType: _isd.ColumnType.bytea,
isNullable: true,
dartType: 'dart:typed_data:ByteData?',
),
],
foreignKeys: [
_isd.ForeignKeyDefinition(
constraintName: 'label_fk_0',
columns: ['spaceId'],
referenceTable: 'offline_sync_spaces',
referenceTableSchema: 'public',
referenceColumns: ['id'],
onUpdate: _isd.ForeignKeyAction.noAction,
onDelete: _isd.ForeignKeyAction.cascade,
matchType: null,
),
],
indexes: [
_isd.IndexDefinition(
indexName: 'label_space_idx',
tableSpace: null,
elements: [
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'spaceId',
),
],
type: 'btree',
isUnique: false,
isPrimary: false,
),
],
managed: true,
),
_isd.TableDefinition(
name: 'project',
dartName: 'Project',
@ -164,6 +237,140 @@ class Protocol extends _isd.DatabaseSerializationManager {
],
managed: true,
),
_isd.TableDefinition(
name: 'section',
dartName: 'Section',
schema: 'public',
module: 'halkyon_todo',
columns: [
_isd.ColumnDefinition(
name: 'id',
columnType: _isd.ColumnType.uuid,
isNullable: false,
dartType: 'UuidValue?',
columnDefault: 'random_v7',
),
_isd.ColumnDefinition(
name: 'spaceId',
columnType: _isd.ColumnType.bigint,
isNullable: true,
dartType: 'int?',
),
_isd.ColumnDefinition(
name: 'keyId',
columnType: _isd.ColumnType.text,
isNullable: true,
dartType: 'String?',
),
_isd.ColumnDefinition(
name: 'payload',
columnType: _isd.ColumnType.bytea,
isNullable: false,
dartType: 'dart:typed_data:ByteData',
),
_isd.ColumnDefinition(
name: 'nonce',
columnType: _isd.ColumnType.bytea,
isNullable: true,
dartType: 'dart:typed_data:ByteData?',
),
],
foreignKeys: [
_isd.ForeignKeyDefinition(
constraintName: 'section_fk_0',
columns: ['spaceId'],
referenceTable: 'offline_sync_spaces',
referenceTableSchema: 'public',
referenceColumns: ['id'],
onUpdate: _isd.ForeignKeyAction.noAction,
onDelete: _isd.ForeignKeyAction.cascade,
matchType: null,
),
],
indexes: [
_isd.IndexDefinition(
indexName: 'section_space_idx',
tableSpace: null,
elements: [
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'spaceId',
),
],
type: 'btree',
isUnique: false,
isPrimary: false,
),
],
managed: true,
),
_isd.TableDefinition(
name: 'task',
dartName: 'Task',
schema: 'public',
module: 'halkyon_todo',
columns: [
_isd.ColumnDefinition(
name: 'id',
columnType: _isd.ColumnType.uuid,
isNullable: false,
dartType: 'UuidValue?',
columnDefault: 'random_v7',
),
_isd.ColumnDefinition(
name: 'spaceId',
columnType: _isd.ColumnType.bigint,
isNullable: true,
dartType: 'int?',
),
_isd.ColumnDefinition(
name: 'keyId',
columnType: _isd.ColumnType.text,
isNullable: true,
dartType: 'String?',
),
_isd.ColumnDefinition(
name: 'payload',
columnType: _isd.ColumnType.bytea,
isNullable: false,
dartType: 'dart:typed_data:ByteData',
),
_isd.ColumnDefinition(
name: 'nonce',
columnType: _isd.ColumnType.bytea,
isNullable: true,
dartType: 'dart:typed_data:ByteData?',
),
],
foreignKeys: [
_isd.ForeignKeyDefinition(
constraintName: 'task_fk_0',
columns: ['spaceId'],
referenceTable: 'offline_sync_spaces',
referenceTableSchema: 'public',
referenceColumns: ['id'],
onUpdate: _isd.ForeignKeyAction.noAction,
onDelete: _isd.ForeignKeyAction.cascade,
matchType: null,
),
],
indexes: [
_isd.IndexDefinition(
indexName: 'task_space_idx',
tableSpace: null,
elements: [
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'spaceId',
),
],
type: 'btree',
isUnique: false,
isPrimary: false,
),
],
managed: true,
),
..._ihk4p5t7.Protocol() is _isd.DatabaseSerializationManager
? (_ihk4p5t7.Protocol() as _isd.DatabaseSerializationManager)
.getTargetTableDefinitions()
@ -213,18 +420,36 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
}
if (t == _ivak08z4.Label) {
return _ivak08z4.Label.fromJson(data) as T;
}
if (t == _imed3x5d.ContentKey) {
return _imed3x5d.ContentKey.fromJson(data) as T;
}
if (t == _i9c44spp.Project) {
return _i9c44spp.Project.fromJson(data) as T;
}
if (t == _imadkvi9.Section) {
return _imadkvi9.Section.fromJson(data) as T;
}
if (t == _ib4f8uyw.Task) {
return _ib4f8uyw.Task.fromJson(data) as T;
}
if (t == _isc.getType<_ivak08z4.Label?>()) {
return (data != null ? _ivak08z4.Label.fromJson(data) : null) as T;
}
if (t == _isc.getType<_imed3x5d.ContentKey?>()) {
return (data != null ? _imed3x5d.ContentKey.fromJson(data) : null) as T;
}
if (t == _isc.getType<_i9c44spp.Project?>()) {
return (data != null ? _i9c44spp.Project.fromJson(data) : null) as T;
}
if (t == _isc.getType<_imadkvi9.Section?>()) {
return (data != null ? _imadkvi9.Section.fromJson(data) : null) as T;
}
if (t == _isc.getType<_ib4f8uyw.Task?>()) {
return (data != null ? _ib4f8uyw.Task.fromJson(data) : null) as T;
}
try {
return _ihk4p5t7.Protocol().deserialize<T>(data, t);
} on _isc.DeserializationTypeNotFoundException catch (_) {}
@ -245,8 +470,11 @@ class Protocol extends _isd.DatabaseSerializationManager {
static String? getClassNameForType(Type type) {
return switch (type) {
_ivak08z4.Label => 'Label',
_imed3x5d.ContentKey => 'ContentKey',
_i9c44spp.Project => 'Project',
_imadkvi9.Section => 'Section',
_ib4f8uyw.Task => 'Task',
_ => null,
};
}
@ -264,10 +492,16 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
switch (data) {
case _ivak08z4.Label():
return 'Label';
case _imed3x5d.ContentKey():
return 'ContentKey';
case _i9c44spp.Project():
return 'Project';
case _imadkvi9.Section():
return 'Section';
case _ib4f8uyw.Task():
return 'Task';
}
className = _ihk4p5t7.Protocol().getClassNameForObject(data);
if (className != null) {
@ -304,12 +538,21 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (dataClassName is! String) {
return super.deserializeByClassName(data);
}
if (dataClassName == 'Label') {
return deserialize<_ivak08z4.Label>(data['data']);
}
if (dataClassName == 'ContentKey') {
return deserialize<_imed3x5d.ContentKey>(data['data']);
}
if (dataClassName == 'Project') {
return deserialize<_i9c44spp.Project>(data['data']);
}
if (dataClassName == 'Section') {
return deserialize<_imadkvi9.Section>(data['data']);
}
if (dataClassName == 'Task') {
return deserialize<_ib4f8uyw.Task>(data['data']);
}
if (dataClassName.startsWith('halkyon_base.')) {
data['className'] = dataClassName.substring(13);
return _ihk4p5t7.Protocol().deserializeByClassName(data);
@ -389,10 +632,16 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
}
switch (t) {
case _ivak08z4.Label:
return _ivak08z4.Label.t;
case _imed3x5d.ContentKey:
return _imed3x5d.ContentKey.t;
case _i9c44spp.Project:
return _i9c44spp.Project.t;
case _imadkvi9.Section:
return _imadkvi9.Section.t;
case _ib4f8uyw.Task:
return _ib4f8uyw.Task.t;
}
return null;
}

View file

@ -11,13 +11,19 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_database/serverpod_database.dart' as _isd;
import 'label/label.dart' as _ivak08z4;
import 'privacy/content_key.dart' as _imed3x5d;
import 'project/project.dart' as _i9c44spp;
import 'project/section.dart' as _imadkvi9;
import 'task/task.dart' as _ib4f8uyw;
/// The tables synchronized between client and server by the
/// `serverpod_offline_sync` package, including the ones owned by modules and
/// shared packages.
final List<_isd.Table> syncTables = [
_imed3x5d.ContentKey.t,
_ivak08z4.Label.t,
_i9c44spp.Project.t,
_imadkvi9.Section.t,
_ib4f8uyw.Task.t,
];

View file

@ -0,0 +1,674 @@
/* 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 'dart:typed_data' as _idt;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd;
/// A task (ADR 0033, D6): everything about it is in its sealed payload (D5):
/// its title and description, its project, section and parent (a sub-task's),
/// its place among its siblings, its date, deadline, priority and labels,
/// when it was completed; the instance sees that it exists, its size and
/// when it changed, nor which project it is in. Changed when edited, the
/// last writer winning. Synced.
abstract class Task
implements _isd.TableRow<_isc.UuidValue?>, _isc.ProtocolSerialization {
Task._({
this.id,
this.spaceId,
this.keyId,
required this.payload,
this.nonce,
});
factory Task({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) = _TaskImpl;
factory Task.fromJson(Map<String, dynamic> jsonSerialization) {
return Task(
id: jsonSerialization['id'] == null
? null
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
spaceId: jsonSerialization['spaceId'] as int?,
keyId: jsonSerialization['keyId'] as String?,
payload: _isc.ByteDataJsonExtension.fromJson(
jsonSerialization['payload'],
),
nonce: jsonSerialization['nonce'] == null
? null
: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
);
}
static final t = TaskTable();
static const db = TaskRepository._();
@override
_isc.UuidValue? id;
/// The space owning this row. Maintained by the sync engine.
int? spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
String? keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
_idt.ByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
_idt.ByteData? nonce;
@override
_isd.Table<_isc.UuidValue?> get table => t;
/// Returns a shallow copy of this [Task]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
Task copyWith({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
_idt.ByteData? payload,
_idt.ByteData? nonce,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'Task',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'Task',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
static TaskInclude include() {
return TaskInclude._();
}
static TaskIncludeList includeList({
_isd.WhereExpressionBuilder<TaskTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
TaskInclude? include,
}) {
return TaskIncludeList._(
where: where,
limit: limit,
offset: offset,
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
include: include,
);
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _TaskImpl extends Task {
_TaskImpl({
_isc.UuidValue? id,
int? spaceId,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) : super._(
id: id,
spaceId: spaceId,
keyId: keyId,
payload: payload,
nonce: nonce,
);
/// Returns a shallow copy of this [Task]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
Task copyWith({
Object? id = _Undefined,
Object? spaceId = _Undefined,
Object? keyId = _Undefined,
_idt.ByteData? payload,
Object? nonce = _Undefined,
}) {
return Task(
id: id is _isc.UuidValue? ? id : this.id,
spaceId: spaceId is int? ? spaceId : this.spaceId,
keyId: keyId is String? ? keyId : this.keyId,
payload: payload ?? this.payload.clone(),
nonce: nonce is _idt.ByteData? ? nonce : this.nonce?.clone(),
);
}
}
class TaskUpdateTable extends _isd.UpdateTable<TaskTable> {
TaskUpdateTable(super.table);
_isd.ColumnValue<int, int> spaceId(int? value) => _isd.ColumnValue(
table.spaceId,
value,
);
_isd.ColumnValue<String, String> keyId(String? value) => _isd.ColumnValue(
table.keyId,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> payload(_idt.ByteData value) =>
_isd.ColumnValue(
table.payload,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> nonce(_idt.ByteData? value) =>
_isd.ColumnValue(
table.nonce,
value,
);
}
class TaskTable extends _isd.Table<_isc.UuidValue?> {
TaskTable({super.tableRelation}) : super(tableName: 'task') {
updateTable = TaskUpdateTable(this);
spaceId = _isd.ColumnInt(
'spaceId',
this,
);
keyId = _isd.ColumnString(
'keyId',
this,
);
payload = _isd.ColumnByteData(
'payload',
this,
);
nonce = _isd.ColumnByteData(
'nonce',
this,
);
}
late final TaskUpdateTable updateTable;
/// The space owning this row. Maintained by the sync engine.
late final _isd.ColumnInt spaceId;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
late final _isd.ColumnString keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
late final _isd.ColumnByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
late final _isd.ColumnByteData nonce;
@override
List<_isd.Column> get columns => [
id,
spaceId,
keyId,
payload,
nonce,
];
}
class TaskInclude extends _isd.IncludeObject {
TaskInclude._();
@override
Map<String, _isd.Include?> get includes => {};
@override
_isd.Table<_isc.UuidValue?> get table => Task.t;
}
class TaskIncludeList extends _isd.IncludeList {
TaskIncludeList._({
_isd.WhereExpressionBuilder<TaskTable>? where,
super.limit,
super.offset,
super.orderBy,
super.orderByList,
super.include,
}) {
super.where = where?.call(Task.t);
}
@override
Map<String, _isd.Include?> get includes => include?.includes ?? {};
@override
_isd.Table<_isc.UuidValue?> get table => Task.t;
}
class TaskRepository {
const TaskRepository._();
/// Returns a list of [Task]s matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order of the items use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// The maximum number of items can be set by [limit]. If no limit is set,
/// all items matching the query will be returned.
///
/// [offset] defines how many items to skip, after which [limit] (or all)
/// items are read from the database.
///
/// ```dart
/// var persons = await Persons.db.find(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.firstName,
/// limit: 100,
/// );
/// ```
Future<List<Task>> find(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<TaskTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.find<Task>(
where: where?.call(Task.t),
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
limit: limit,
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Returns the first matching [Task] matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// [offset] defines how many items to skip, after which the next one will be picked.
///
/// ```dart
/// var youngestPerson = await Persons.db.findFirstRow(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.age,
/// );
/// ```
Future<Task?> findFirstRow(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<TaskTable>? where,
int? offset,
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findFirstRow<Task>(
where: where?.call(Task.t),
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Finds a single [Task] by its [id] or null if no such row exists.
Future<Task?> findById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findById<Task>(
id,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Inserts all [Task]s in the list and returns the inserted rows.
///
/// The returned [Task]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails to
/// insert, none of the rows will be inserted.
///
/// If [ignoreConflicts] is set to `true`, rows that conflict with existing
/// rows are silently skipped, and only the successfully inserted rows are
/// returned.
///
/// If [noReturn] is set to `true`, the inserted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> insert(
_isd.DatabaseSession session,
List<Task> rows, {
_isd.Transaction? transaction,
bool ignoreConflicts = false,
bool noReturn = false,
}) async {
return session.db.insert<Task>(
rows,
transaction: transaction,
ignoreConflicts: ignoreConflicts,
noReturn: noReturn,
);
}
/// Inserts a single [Task] and returns the inserted row.
///
/// The returned [Task] will have its `id` field set.
Future<Task> insertRow(
_isd.DatabaseSession session,
Task row, {
_isd.Transaction? transaction,
}) async {
return session.db.insertRow<Task>(
row,
transaction: transaction,
);
}
/// Upserts all [Task]s in the list and returns the resulting rows.
///
/// If a row conflicts on the given [conflictColumns], the existing row is
/// updated with the new values. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies to rows matching the
/// given expression. Conflicting rows that don't match are skipped and not
/// returned, so the resulting list may be shorter than [rows].
///
/// The returned [Task]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails,
/// none of the rows will be affected.
///
/// If [noReturn] is set to `true`, the resulting rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> upsert(
_isd.DatabaseSession session,
List<Task> rows, {
required _isd.ColumnSelections<TaskTable> conflictColumns,
_isd.ColumnSelections<TaskTable>? updateColumns,
_isd.WhereExpressionBuilder<TaskTable>? updateWhere,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.upsert<Task>(
rows,
conflictColumns: conflictColumns(Task.t),
updateColumns: updateColumns?.call(Task.t),
updateWhere: updateWhere?.call(Task.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Upserts a single [Task] and returns the resulting row.
///
/// If the row conflicts on the given [conflictColumns], the existing row is
/// updated. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies when the existing
/// row matches the expression. Returns `null` if no row was affected — for
/// example when [updateWhere] does not match the conflicting row.
///
/// The returned [Task] will have its `id` field set.
Future<Task?> upsertRow(
_isd.DatabaseSession session,
Task row, {
required _isd.ColumnSelections<TaskTable> conflictColumns,
_isd.ColumnSelections<TaskTable>? updateColumns,
_isd.WhereExpressionBuilder<TaskTable>? updateWhere,
_isd.Transaction? transaction,
}) async {
return session.db.upsertRow<Task>(
row,
conflictColumns: conflictColumns(Task.t),
updateColumns: updateColumns?.call(Task.t),
updateWhere: updateWhere?.call(Task.t),
transaction: transaction,
);
}
/// Updates all [Task]s in the list and returns the updated rows. If
/// [columns] is provided, only those columns will be updated. Defaults to
/// all columns.
/// This is an atomic operation, meaning that if one of the rows fails to
/// update, none of the rows will be updated.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> update(
_isd.DatabaseSession session,
List<Task> rows, {
_isd.ColumnSelections<TaskTable>? columns,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.update<Task>(
rows,
columns: columns?.call(Task.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Updates a single [Task]. The row needs to have its id set.
/// Optionally, a list of [columns] can be provided to only update those
/// columns. Defaults to all columns.
Future<Task> updateRow(
_isd.DatabaseSession session,
Task row, {
_isd.ColumnSelections<TaskTable>? columns,
_isd.Transaction? transaction,
}) async {
return session.db.updateRow<Task>(
row,
columns: columns?.call(Task.t),
transaction: transaction,
);
}
/// Updates a single [Task] by its [id] with the specified [columnValues].
/// Returns the updated row or null if no row with the given id exists.
Future<Task?> updateById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
required _isd.ColumnValueListBuilder<TaskUpdateTable> columnValues,
_isd.Transaction? transaction,
}) async {
return session.db.updateById<Task>(
id,
columnValues: columnValues(Task.t.updateTable),
transaction: transaction,
);
}
/// Updates all [Task]s matching the [where] expression with the specified [columnValues].
/// Returns the list of updated rows.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> updateWhere(
_isd.DatabaseSession session, {
required _isd.ColumnValueListBuilder<TaskUpdateTable> columnValues,
required _isd.WhereExpressionBuilder<TaskTable> where,
int? limit,
int? offset,
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.updateWhere<Task>(
columnValues: columnValues(Task.t.updateTable),
where: where(Task.t),
limit: limit,
offset: offset,
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes all [Task]s in the list and returns the deleted rows.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// This is an atomic operation, meaning that if one of the rows fail to
/// be deleted, none of the rows will be deleted.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> delete(
_isd.DatabaseSession session,
List<Task> rows, {
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.delete<Task>(
rows,
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes a single [Task].
Future<Task> deleteRow(
_isd.DatabaseSession session,
Task row, {
_isd.Transaction? transaction,
}) async {
return session.db.deleteRow<Task>(
row,
transaction: transaction,
);
}
/// Deletes all rows matching the [where] expression.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Task>> deleteWhere(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<TaskTable> where,
_isd.OrderByBuilder<TaskTable>? orderBy,
_isd.OrderByListBuilder<TaskTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.deleteWhere<Task>(
where: where(Task.t),
orderBy: orderBy?.call(Task.t),
orderByList: orderByList?.call(Task.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Counts the number of rows matching the [where] expression. If omitted,
/// will return the count of all rows in the table.
Future<int> count(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<TaskTable>? where,
int? limit,
_isd.Transaction? transaction,
}) async {
return session.db.count<Task>(
where: where?.call(Task.t),
limit: limit,
transaction: transaction,
);
}
/// Acquires row-level locks on [Task] rows matching the [where] expression.
Future<void> lockRows(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<TaskTable> where,
required _isd.LockMode lockMode,
required _isd.Transaction transaction,
_isd.LockBehavior lockBehavior = _isd.LockBehavior.wait,
}) async {
return session.db.lockRows<Task>(
where: where(Task.t),
lockMode: lockMode,
lockBehavior: lockBehavior,
transaction: transaction,
);
}
}