feat(train): weight, entered on Progress and read from Health Connect, sealed and synced (ADR 0030, D63)
A person's weights are each a sealed `body_weight` row, as the days and
the places: the weight in grams, when it was measured (UTC), where it
came from and, for Health Connect's, the record's id and app are the
payload; the server sees the space and the ciphertext alone.
Progress gets a Weight card after Your body: the latest and its day,
its line over time (held, each weight and its day), the plus to enter
one (a comma taken as a point, 20 to 400 kg, when measured, today by
default) and All, the list to delete one. The latest weight is also
Your body's, which the band's and the zones' figures work from. In
kilograms alone: Train is metric throughout and has no units setting
yet.
Health Connect's weight records are read in when switched on in its
screen (READ_WEIGHT, asked as the others): each record once, its id kept
in health_connect.json also after it is deleted here, never Train's own,
and none within 10 minutes and 0.1 kg of a weight entered in Train.
The migration (20261103204323683-body-weights):
- creates (or replaces, unchanged) `gen_random_uuid_v7()`, the
default of every UUID id, as each of Serverpod's migrations does;
- CREATE TABLE "body_weight": "id" uuid primary key defaulting to a
UUID v7, "spaceId" bigint (the sync space), "keyId" text (the key
that sealed it), "payload" bytea NOT NULL (the sealed content),
"nonce" bytea;
- CREATE INDEX "body_weight_space_idx" on "spaceId", for a space's
rows as the sync reads them;
- a foreign key from "spaceId" to "offline_sync_spaces"("id"),
ON DELETE CASCADE, so that an account's deletion takes its weights
with its space;
- the version rows of Train's and every module's migrations.
Nothing existing changes, so nothing is lost.
Tests: the row written and read back in its owner's space, and the
denials: another person reads none of them, and writing one into
another's space throws OfflineSyncSpaceMembershipException and leaves
it empty; an account's deletion takes them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
984527a632
commit
b975659690
8 changed files with 23591 additions and 9 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"__className__": "serverpod.DatabaseMigration",
|
||||
"actions": [
|
||||
{
|
||||
"__className__": "serverpod.DatabaseMigrationAction",
|
||||
"type": "createTable",
|
||||
"createTable": {
|
||||
"__className__": "serverpod.TableDefinition",
|
||||
"name": "body_weight",
|
||||
"dartName": "BodyWeight",
|
||||
"module": "halkyon_train",
|
||||
"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": "body_weight_fk_0",
|
||||
"columns": [
|
||||
"spaceId"
|
||||
],
|
||||
"referenceTable": "offline_sync_spaces",
|
||||
"referenceTableSchema": "public",
|
||||
"referenceColumns": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": 3,
|
||||
"onDelete": 4
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"__className__": "serverpod.IndexDefinition",
|
||||
"indexName": "body_weight_space_idx",
|
||||
"elements": [
|
||||
{
|
||||
"__className__": "serverpod.IndexElementDefinition",
|
||||
"type": 0,
|
||||
"definition": "spaceId"
|
||||
}
|
||||
],
|
||||
"type": "btree",
|
||||
"isUnique": false,
|
||||
"isPrimary": false
|
||||
}
|
||||
],
|
||||
"managed": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"warnings": [],
|
||||
"migrationApiVersion": 1
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ part '20261028211508606-plans/migration.dart';
|
|||
part '20261028231042668-routes/migration.dart';
|
||||
part '20261102103211357-training-places/migration.dart';
|
||||
part '20261102113104496-strength-plans/migration.dart';
|
||||
part '20261103204323683-body-weights/migration.dart';
|
||||
|
||||
/// Migration registry for the client-side database.
|
||||
class MigrationRegistry {
|
||||
|
|
@ -24,6 +25,7 @@ class MigrationRegistry {
|
|||
_Migration20261028231042668_routes(),
|
||||
_Migration20261102103211357_training_places(),
|
||||
_Migration20261102113104496_strength_plans(),
|
||||
_Migration20261103204323683_body_weights(),
|
||||
];
|
||||
|
||||
/// List of all client-side database migration versions.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import 'search/search_refused.dart' as _ihbxkwke;
|
|||
import 'strength/strength_plan.dart' as _imwvu2mn;
|
||||
import 'weather/weather_hour.dart' as _i9m2f53e;
|
||||
import 'weather/weather_refused.dart' as _ieu1vbq0;
|
||||
import 'weight/body_weight.dart' as _i1mqkkn3;
|
||||
import 'workout/workout.dart' as _i5b9b17z;
|
||||
import 'workout/workout_series.dart' as _i92mefto;
|
||||
export 'day/day.dart';
|
||||
|
|
@ -73,6 +74,7 @@ export 'search/search_refused.dart';
|
|||
export 'strength/strength_plan.dart';
|
||||
export 'weather/weather_hour.dart';
|
||||
export 'weather/weather_refused.dart';
|
||||
export 'weight/body_weight.dart';
|
||||
export 'workout/workout.dart';
|
||||
export 'workout/workout_series.dart';
|
||||
export 'client.dart';
|
||||
|
|
@ -86,6 +88,73 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
static final Protocol _instance = Protocol._().._registerHostProtocols();
|
||||
|
||||
static List<_isd.TableDefinition> get targetTableDefinitions => [
|
||||
_isd.TableDefinition(
|
||||
name: 'body_weight',
|
||||
dartName: 'BodyWeight',
|
||||
schema: 'public',
|
||||
module: 'halkyon_train',
|
||||
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: 'body_weight_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: 'body_weight_space_idx',
|
||||
tableSpace: null,
|
||||
elements: [
|
||||
_isd.IndexElementDefinition(
|
||||
type: _isd.IndexElementDefinitionType.column,
|
||||
definition: 'spaceId',
|
||||
),
|
||||
],
|
||||
type: 'btree',
|
||||
isUnique: false,
|
||||
isPrimary: false,
|
||||
),
|
||||
],
|
||||
managed: true,
|
||||
),
|
||||
_isd.TableDefinition(
|
||||
name: 'content_key',
|
||||
dartName: 'ContentKey',
|
||||
|
|
@ -992,6 +1061,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (t == _ieu1vbq0.WeatherRefused) {
|
||||
return _ieu1vbq0.WeatherRefused.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i1mqkkn3.BodyWeight) {
|
||||
return _i1mqkkn3.BodyWeight.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i5b9b17z.Workout) {
|
||||
return _i5b9b17z.Workout.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -1070,6 +1142,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return (data != null ? _ieu1vbq0.WeatherRefused.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i1mqkkn3.BodyWeight?>()) {
|
||||
return (data != null ? _i1mqkkn3.BodyWeight.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_i5b9b17z.Workout?>()) {
|
||||
return (data != null ? _i5b9b17z.Workout.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -1156,6 +1231,7 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
_imwvu2mn.StrengthPlan => 'StrengthPlan',
|
||||
_i9m2f53e.WeatherHour => 'WeatherHour',
|
||||
_ieu1vbq0.WeatherRefused => 'WeatherRefused',
|
||||
_i1mqkkn3.BodyWeight => 'BodyWeight',
|
||||
_i5b9b17z.Workout => 'Workout',
|
||||
_i92mefto.WorkoutSeries => 'WorkoutSeries',
|
||||
_ => null,
|
||||
|
|
@ -1219,6 +1295,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return 'WeatherHour';
|
||||
case _ieu1vbq0.WeatherRefused():
|
||||
return 'WeatherRefused';
|
||||
case _i1mqkkn3.BodyWeight():
|
||||
return 'BodyWeight';
|
||||
case _i5b9b17z.Workout():
|
||||
return 'Workout';
|
||||
case _i92mefto.WorkoutSeries():
|
||||
|
|
@ -1325,6 +1403,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (dataClassName == 'WeatherRefused') {
|
||||
return deserialize<_ieu1vbq0.WeatherRefused>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'BodyWeight') {
|
||||
return deserialize<_i1mqkkn3.BodyWeight>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Workout') {
|
||||
return deserialize<_i5b9b17z.Workout>(data['data']);
|
||||
}
|
||||
|
|
@ -1428,6 +1509,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return _i0mgeh8t.SavedRoute.t;
|
||||
case _imwvu2mn.StrengthPlan:
|
||||
return _imwvu2mn.StrengthPlan.t;
|
||||
case _i1mqkkn3.BodyWeight:
|
||||
return _i1mqkkn3.BodyWeight.t;
|
||||
case _i5b9b17z.Workout:
|
||||
return _i5b9b17z.Workout.t;
|
||||
case _i92mefto.WorkoutSeries:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'privacy/content_key.dart' as _imed3x5d;
|
|||
import 'profile/profile.dart' as _ia5j8fch;
|
||||
import 'route/route.dart' as _i0mgeh8t;
|
||||
import 'strength/strength_plan.dart' as _imwvu2mn;
|
||||
import 'weight/body_weight.dart' as _i1mqkkn3;
|
||||
import 'workout/workout.dart' as _i5b9b17z;
|
||||
import 'workout/workout_series.dart' as _i92mefto;
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ import 'workout/workout_series.dart' as _i92mefto;
|
|||
/// `serverpod_offline_sync` package, including the ones owned by modules and
|
||||
/// shared packages.
|
||||
final List<_isd.Table> syncTables = [
|
||||
_i1mqkkn3.BodyWeight.t,
|
||||
_imed3x5d.ContentKey.t,
|
||||
_ikmv9f3y.Day.t,
|
||||
_ir1ofny6.DaySeries.t,
|
||||
|
|
|
|||
|
|
@ -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 weight the person measured (ADR 0030, D63): when, how heavy and where
|
||||
/// it came from (entered in Train, or read from Health Connect with that
|
||||
/// record's ID, so that it is read once), in its sealed payload (D7); the
|
||||
/// instance sees that it exists, its size and when it changed. A row each
|
||||
/// measurement. Synced.
|
||||
abstract class BodyWeight
|
||||
implements _isd.TableRow<_isc.UuidValue?>, _isc.ProtocolSerialization {
|
||||
BodyWeight._({
|
||||
this.id,
|
||||
this.spaceId,
|
||||
this.keyId,
|
||||
required this.payload,
|
||||
this.nonce,
|
||||
});
|
||||
|
||||
factory BodyWeight({
|
||||
_isc.UuidValue? id,
|
||||
int? spaceId,
|
||||
String? keyId,
|
||||
required _idt.ByteData payload,
|
||||
_idt.ByteData? nonce,
|
||||
}) = _BodyWeightImpl;
|
||||
|
||||
factory BodyWeight.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return BodyWeight(
|
||||
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 = BodyWeightTable();
|
||||
|
||||
static const db = BodyWeightRepository._();
|
||||
|
||||
@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 Train.
|
||||
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 [BodyWeight]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
BodyWeight copyWith({
|
||||
_isc.UuidValue? id,
|
||||
int? spaceId,
|
||||
String? keyId,
|
||||
_idt.ByteData? payload,
|
||||
_idt.ByteData? nonce,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'BodyWeight',
|
||||
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__': 'BodyWeight',
|
||||
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 BodyWeightInclude include() {
|
||||
return BodyWeightInclude._();
|
||||
}
|
||||
|
||||
static BodyWeightIncludeList includeList({
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? where,
|
||||
int? limit,
|
||||
int? offset,
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
BodyWeightInclude? include,
|
||||
}) {
|
||||
return BodyWeightIncludeList._(
|
||||
where: where,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.t),
|
||||
include: include,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _BodyWeightImpl extends BodyWeight {
|
||||
_BodyWeightImpl({
|
||||
_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 [BodyWeight]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
BodyWeight copyWith({
|
||||
Object? id = _Undefined,
|
||||
Object? spaceId = _Undefined,
|
||||
Object? keyId = _Undefined,
|
||||
_idt.ByteData? payload,
|
||||
Object? nonce = _Undefined,
|
||||
}) {
|
||||
return BodyWeight(
|
||||
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 BodyWeightUpdateTable extends _isd.UpdateTable<BodyWeightTable> {
|
||||
BodyWeightUpdateTable(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 BodyWeightTable extends _isd.Table<_isc.UuidValue?> {
|
||||
BodyWeightTable({super.tableRelation}) : super(tableName: 'body_weight') {
|
||||
updateTable = BodyWeightUpdateTable(this);
|
||||
spaceId = _isd.ColumnInt(
|
||||
'spaceId',
|
||||
this,
|
||||
);
|
||||
keyId = _isd.ColumnString(
|
||||
'keyId',
|
||||
this,
|
||||
);
|
||||
payload = _isd.ColumnByteData(
|
||||
'payload',
|
||||
this,
|
||||
);
|
||||
nonce = _isd.ColumnByteData(
|
||||
'nonce',
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
late final BodyWeightUpdateTable 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 Train.
|
||||
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 BodyWeightInclude extends _isd.IncludeObject {
|
||||
BodyWeightInclude._();
|
||||
|
||||
@override
|
||||
Map<String, _isd.Include?> get includes => {};
|
||||
|
||||
@override
|
||||
_isd.Table<_isc.UuidValue?> get table => BodyWeight.t;
|
||||
}
|
||||
|
||||
class BodyWeightIncludeList extends _isd.IncludeList {
|
||||
BodyWeightIncludeList._({
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? where,
|
||||
super.limit,
|
||||
super.offset,
|
||||
super.orderBy,
|
||||
super.orderByList,
|
||||
super.include,
|
||||
}) {
|
||||
super.where = where?.call(BodyWeight.t);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, _isd.Include?> get includes => include?.includes ?? {};
|
||||
|
||||
@override
|
||||
_isd.Table<_isc.UuidValue?> get table => BodyWeight.t;
|
||||
}
|
||||
|
||||
class BodyWeightRepository {
|
||||
const BodyWeightRepository._();
|
||||
|
||||
/// Returns a list of [BodyWeight]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<BodyWeight>> find(
|
||||
_isd.DatabaseSession session, {
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? where,
|
||||
int? limit,
|
||||
int? offset,
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
return session.db.find<BodyWeight>(
|
||||
where: where?.call(BodyWeight.t),
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.t),
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the first matching [BodyWeight] 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<BodyWeight?> findFirstRow(
|
||||
_isd.DatabaseSession session, {
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? where,
|
||||
int? offset,
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
return session.db.findFirstRow<BodyWeight>(
|
||||
where: where?.call(BodyWeight.t),
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.t),
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds a single [BodyWeight] by its [id] or null if no such row exists.
|
||||
Future<BodyWeight?> findById(
|
||||
_isd.DatabaseSession session,
|
||||
_isc.UuidValue id, {
|
||||
_isd.Transaction? transaction,
|
||||
_isd.LockMode? lockMode,
|
||||
_isd.LockBehavior? lockBehavior,
|
||||
}) async {
|
||||
return session.db.findById<BodyWeight>(
|
||||
id,
|
||||
transaction: transaction,
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
);
|
||||
}
|
||||
|
||||
/// Inserts all [BodyWeight]s in the list and returns the inserted rows.
|
||||
///
|
||||
/// The returned [BodyWeight]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<BodyWeight>> insert(
|
||||
_isd.DatabaseSession session,
|
||||
List<BodyWeight> rows, {
|
||||
_isd.Transaction? transaction,
|
||||
bool ignoreConflicts = false,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.insert<BodyWeight>(
|
||||
rows,
|
||||
transaction: transaction,
|
||||
ignoreConflicts: ignoreConflicts,
|
||||
noReturn: noReturn,
|
||||
);
|
||||
}
|
||||
|
||||
/// Inserts a single [BodyWeight] and returns the inserted row.
|
||||
///
|
||||
/// The returned [BodyWeight] will have its `id` field set.
|
||||
Future<BodyWeight> insertRow(
|
||||
_isd.DatabaseSession session,
|
||||
BodyWeight row, {
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.insertRow<BodyWeight>(
|
||||
row,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Upserts all [BodyWeight]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 [BodyWeight]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<BodyWeight>> upsert(
|
||||
_isd.DatabaseSession session,
|
||||
List<BodyWeight> rows, {
|
||||
required _isd.ColumnSelections<BodyWeightTable> conflictColumns,
|
||||
_isd.ColumnSelections<BodyWeightTable>? updateColumns,
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? updateWhere,
|
||||
_isd.Transaction? transaction,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.upsert<BodyWeight>(
|
||||
rows,
|
||||
conflictColumns: conflictColumns(BodyWeight.t),
|
||||
updateColumns: updateColumns?.call(BodyWeight.t),
|
||||
updateWhere: updateWhere?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
noReturn: noReturn,
|
||||
);
|
||||
}
|
||||
|
||||
/// Upserts a single [BodyWeight] 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 [BodyWeight] will have its `id` field set.
|
||||
Future<BodyWeight?> upsertRow(
|
||||
_isd.DatabaseSession session,
|
||||
BodyWeight row, {
|
||||
required _isd.ColumnSelections<BodyWeightTable> conflictColumns,
|
||||
_isd.ColumnSelections<BodyWeightTable>? updateColumns,
|
||||
_isd.WhereExpressionBuilder<BodyWeightTable>? updateWhere,
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.upsertRow<BodyWeight>(
|
||||
row,
|
||||
conflictColumns: conflictColumns(BodyWeight.t),
|
||||
updateColumns: updateColumns?.call(BodyWeight.t),
|
||||
updateWhere: updateWhere?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates all [BodyWeight]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<BodyWeight>> update(
|
||||
_isd.DatabaseSession session,
|
||||
List<BodyWeight> rows, {
|
||||
_isd.ColumnSelections<BodyWeightTable>? columns,
|
||||
_isd.Transaction? transaction,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.update<BodyWeight>(
|
||||
rows,
|
||||
columns: columns?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
noReturn: noReturn,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates a single [BodyWeight]. 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<BodyWeight> updateRow(
|
||||
_isd.DatabaseSession session,
|
||||
BodyWeight row, {
|
||||
_isd.ColumnSelections<BodyWeightTable>? columns,
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.updateRow<BodyWeight>(
|
||||
row,
|
||||
columns: columns?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates a single [BodyWeight] by its [id] with the specified [columnValues].
|
||||
/// Returns the updated row or null if no row with the given id exists.
|
||||
Future<BodyWeight?> updateById(
|
||||
_isd.DatabaseSession session,
|
||||
_isc.UuidValue id, {
|
||||
required _isd.ColumnValueListBuilder<BodyWeightUpdateTable> columnValues,
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.updateById<BodyWeight>(
|
||||
id,
|
||||
columnValues: columnValues(BodyWeight.t.updateTable),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates all [BodyWeight]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<BodyWeight>> updateWhere(
|
||||
_isd.DatabaseSession session, {
|
||||
required _isd.ColumnValueListBuilder<BodyWeightUpdateTable> columnValues,
|
||||
required _isd.WhereExpressionBuilder<BodyWeightTable> where,
|
||||
int? limit,
|
||||
int? offset,
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.updateWhere<BodyWeight>(
|
||||
columnValues: columnValues(BodyWeight.t.updateTable),
|
||||
where: where(BodyWeight.t),
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
noReturn: noReturn,
|
||||
);
|
||||
}
|
||||
|
||||
/// Deletes all [BodyWeight]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<BodyWeight>> delete(
|
||||
_isd.DatabaseSession session,
|
||||
List<BodyWeight> rows, {
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.delete<BodyWeight>(
|
||||
rows,
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.t),
|
||||
transaction: transaction,
|
||||
noReturn: noReturn,
|
||||
);
|
||||
}
|
||||
|
||||
/// Deletes a single [BodyWeight].
|
||||
Future<BodyWeight> deleteRow(
|
||||
_isd.DatabaseSession session,
|
||||
BodyWeight row, {
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.deleteRow<BodyWeight>(
|
||||
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<BodyWeight>> deleteWhere(
|
||||
_isd.DatabaseSession session, {
|
||||
required _isd.WhereExpressionBuilder<BodyWeightTable> where,
|
||||
_isd.OrderByBuilder<BodyWeightTable>? orderBy,
|
||||
_isd.OrderByListBuilder<BodyWeightTable>? orderByList,
|
||||
_isd.Transaction? transaction,
|
||||
bool noReturn = false,
|
||||
}) async {
|
||||
return session.db.deleteWhere<BodyWeight>(
|
||||
where: where(BodyWeight.t),
|
||||
orderBy: orderBy?.call(BodyWeight.t),
|
||||
orderByList: orderByList?.call(BodyWeight.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<BodyWeightTable>? where,
|
||||
int? limit,
|
||||
_isd.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.count<BodyWeight>(
|
||||
where: where?.call(BodyWeight.t),
|
||||
limit: limit,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Acquires row-level locks on [BodyWeight] rows matching the [where] expression.
|
||||
Future<void> lockRows(
|
||||
_isd.DatabaseSession session, {
|
||||
required _isd.WhereExpressionBuilder<BodyWeightTable> where,
|
||||
required _isd.LockMode lockMode,
|
||||
required _isd.Transaction transaction,
|
||||
_isd.LockBehavior lockBehavior = _isd.LockBehavior.wait,
|
||||
}) async {
|
||||
return session.db.lockRows<BodyWeight>(
|
||||
where: where(BodyWeight.t),
|
||||
lockMode: lockMode,
|
||||
lockBehavior: lockBehavior,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue