Improve generator to reference relationships both ways

sync3
Laurent 5 months ago
parent a0f3a35492
commit eff7e40198
  1. 18
      PadelClubData/Data/Gen/BaseClub.swift
  2. 15
      PadelClubData/Data/Gen/BaseCourt.swift
  3. 17
      PadelClubData/Data/Gen/BaseCustomUser.swift
  4. 8
      PadelClubData/Data/Gen/BaseDateInterval.swift
  5. 15
      PadelClubData/Data/Gen/BaseDrawLog.swift
  6. 19
      PadelClubData/Data/Gen/BaseEvent.swift
  7. 18
      PadelClubData/Data/Gen/BaseGroupStage.swift
  8. 19
      PadelClubData/Data/Gen/BaseMatch.swift
  9. 15
      PadelClubData/Data/Gen/BaseMatchScheduler.swift
  10. 8
      PadelClubData/Data/Gen/BaseMonthData.swift
  11. 15
      PadelClubData/Data/Gen/BasePlayerRegistration.swift
  12. 15
      PadelClubData/Data/Gen/BasePurchase.swift
  13. 17
      PadelClubData/Data/Gen/BaseRound.swift
  14. 22
      PadelClubData/Data/Gen/BaseTeamRegistration.swift
  15. 17
      PadelClubData/Data/Gen/BaseTeamScore.swift
  16. 21
      PadelClubData/Data/Gen/BaseTournament.swift
  17. 214
      PadelClubData/Data/Gen/generator.py
  18. 99
      PadelClubDataTests/SyncDataAccessTests.swift

@ -142,10 +142,24 @@ public class BaseClub: SyncedModelObject, SyncedStorable {
self.timezone = club.timezone
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: CustomUser.self, keyPath: \BaseClub.creator, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: CustomUser.self, keyPath: \BaseClub.creator, mainStoreLookup: false),
Relationship(type: Event.self, keyPath: \BaseEvent.club, storeLookup: .same),
Relationship(type: Court.self, keyPath: \BaseCourt.club, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -85,10 +85,21 @@ public class BaseCourt: SyncedModelObject, SyncedStorable {
self.indoor = court.indoor
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Club.self, keyPath: \BaseCourt.club, mainStoreLookup: false),
Relationship(type: Club.self, keyPath: \BaseCourt.club, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -256,8 +256,23 @@ public class BaseCustomUser: SyncedModelObject, SyncedStorable {
self.hideUmpirePhone = customuser.hideUmpirePhone
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return []
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Club.self, keyPath: \BaseClub.creator, storeLookup: .same),
Relationship(type: Event.self, keyPath: \BaseEvent.creator, storeLookup: .same),
Relationship(type: Purchase.self, keyPath: \BasePurchase.user, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -74,6 +74,14 @@ public class BaseDateInterval: SyncedModelObject, SyncedStorable {
self.endDate = dateinterval.endDate
}
public static func parentRelationships() -> [Relationship] {
return []
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
return []
}

@ -92,10 +92,21 @@ public class BaseDrawLog: SyncedModelObject, SyncedStorable {
self.drawType = drawlog.drawType
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseDrawLog.tournament, mainStoreLookup: true),
Relationship(type: Tournament.self, keyPath: \BaseDrawLog.tournament, storeLookup: .main),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -91,11 +91,24 @@ public class BaseEvent: SyncedModelObject, SyncedStorable {
self.tenupId = event.tenupId
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: CustomUser.self, keyPath: \BaseEvent.creator, storeLookup: .same),
Relationship(type: Club.self, keyPath: \BaseEvent.club, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: CustomUser.self, keyPath: \BaseEvent.creator, mainStoreLookup: false),
Relationship(type: Club.self, keyPath: \BaseEvent.club, mainStoreLookup: false),
Relationship(type: Tournament.self, keyPath: \BaseTournament.event, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -112,10 +112,24 @@ public class BaseGroupStage: SyncedModelObject, SyncedStorable {
self.plannedStartDate = groupstage.plannedStartDate
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseGroupStage.tournament, storeLookup: .main),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseGroupStage.tournament, mainStoreLookup: true),
Relationship(type: Match.self, keyPath: \BaseMatch.groupStage, storeLookup: .same),
Relationship(type: TeamRegistration.self, keyPath: \BaseTeamRegistration.groupStage, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -160,11 +160,24 @@ public class BaseMatch: SyncedModelObject, SyncedStorable {
self.plannedStartDate = match.plannedStartDate
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Round.self, keyPath: \BaseMatch.round, storeLookup: .same),
Relationship(type: GroupStage.self, keyPath: \BaseMatch.groupStage, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Round.self, keyPath: \BaseMatch.round, mainStoreLookup: false),
Relationship(type: GroupStage.self, keyPath: \BaseMatch.groupStage, mainStoreLookup: false),
Relationship(type: TeamScore.self, keyPath: \BaseTeamScore.match, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -155,10 +155,21 @@ public class BaseMatchScheduler: BaseModelObject, Storable {
self.simultaneousStart = matchscheduler.simultaneousStart
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseMatchScheduler.tournament, mainStoreLookup: true),
Relationship(type: Tournament.self, keyPath: \BaseMatchScheduler.tournament, storeLookup: .main),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -116,6 +116,14 @@ public class BaseMonthData: BaseModelObject, Storable {
self.fileModelIdentifier = monthdata.fileModelIdentifier
}
public static func parentRelationships() -> [Relationship] {
return []
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
return []
}

@ -219,10 +219,21 @@ public class BasePlayerRegistration: SyncedModelObject, SyncedStorable {
self.paymentId = playerregistration.paymentId
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: TeamRegistration.self, keyPath: \BasePlayerRegistration.teamRegistration, mainStoreLookup: false),
Relationship(type: TeamRegistration.self, keyPath: \BasePlayerRegistration.teamRegistration, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -91,10 +91,21 @@ public class BasePurchase: SyncedModelObject, SyncedStorable {
self.expirationDate = purchase.expirationDate
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: CustomUser.self, keyPath: \BasePurchase.user, mainStoreLookup: false),
Relationship(type: CustomUser.self, keyPath: \BasePurchase.user, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -112,10 +112,23 @@ public class BaseRound: SyncedModelObject, SyncedStorable {
self.plannedStartDate = round.plannedStartDate
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseRound.tournament, storeLookup: .main),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseRound.tournament, mainStoreLookup: true),
Relationship(type: Match.self, keyPath: \BaseMatch.round, storeLookup: .same),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -195,11 +195,25 @@ public class BaseTeamRegistration: SyncedModelObject, SyncedStorable {
self.pointsEarned = teamregistration.pointsEarned
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseTeamRegistration.tournament, storeLookup: .main),
Relationship(type: GroupStage.self, keyPath: \BaseTeamRegistration.groupStage, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Tournament.self, keyPath: \BaseTeamRegistration.tournament, mainStoreLookup: true),
Relationship(type: GroupStage.self, keyPath: \BaseTeamRegistration.groupStage, mainStoreLookup: false),
Relationship(type: TeamScore.self, keyPath: \BaseTeamScore.teamRegistration, storeLookup: .same),
Relationship(type: PlayerRegistration.self, keyPath: \BasePlayerRegistration.teamRegistration, storeLookup: .same),
]
}
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -90,11 +90,22 @@ public class BaseTeamScore: SyncedModelObject, SyncedStorable {
self.luckyLoser = teamscore.luckyLoser
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Match.self, keyPath: \BaseTeamScore.match, mainStoreLookup: false),
Relationship(type: TeamRegistration.self, keyPath: \BaseTeamScore.teamRegistration, mainStoreLookup: false),
Relationship(type: Match.self, keyPath: \BaseTeamScore.match, storeLookup: .same),
Relationship(type: TeamRegistration.self, keyPath: \BaseTeamScore.teamRegistration, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -596,10 +596,27 @@ public class BaseTournament: SyncedModelObject, SyncedStorable {
self.showTeamsInProg = tournament.showTeamsInProg
}
public static func relationships() -> [Relationship] {
public static func parentRelationships() -> [Relationship] {
return [
Relationship(type: Event.self, keyPath: \BaseTournament.event, storeLookup: .same),
]
}
public static func childrenRelationships() -> [Relationship] {
return [
Relationship(type: Event.self, keyPath: \BaseTournament.event, mainStoreLookup: false),
Relationship(type: GroupStage.self, keyPath: \BaseGroupStage.tournament, storeLookup: .child),
Relationship(type: MatchScheduler.self, keyPath: \BaseMatchScheduler.tournament, storeLookup: .child),
Relationship(type: Round.self, keyPath: \BaseRound.tournament, storeLookup: .child),
Relationship(type: TeamRegistration.self, keyPath: \BaseTeamRegistration.tournament, storeLookup: .child),
Relationship(type: DrawLog.self, keyPath: \BaseDrawLog.tournament, storeLookup: .child),
]
}
public static func relationships() -> [Relationship] {
var relationships: [Relationship] = []
relationships.append(contentsOf: parentRelationships())
relationships.append(contentsOf: childrenRelationships())
return relationships
}
}

@ -3,15 +3,78 @@ import re
import os
from pathlib import Path
from typing import Dict, List, Any
from collections import defaultdict
import argparse
import sys
import logging
from datetime import datetime
import inflect
class RelationshipAnalyzer:
def __init__(self):
self.parent_relationships = defaultdict(list) # model_name -> list of parent relationships
self.children_relationships = defaultdict(list) # model_name -> list of children relationships
def analyze_all_models(self, input_dir: str) -> None:
"""Analyze all JSON files to build complete relationship map."""
input_path = Path(input_dir)
json_files = list(input_path.glob("*.json"))
for json_file in json_files:
with open(json_file, 'r') as f:
json_data = json.load(f)
for model in json_data["models"]:
model_name = model["name"]
properties = model.get("properties", [])
# Find foreign key properties (parents)
for prop in properties:
if "foreignKey" in prop:
foreign_key = prop["foreignKey"].rstrip('###')
located_on_main_store = prop["foreignKey"].endswith('###')
if located_on_main_store:
# Store parent relationship
self.parent_relationships[model_name].append({
"name": prop["name"],
"foreignKey": foreign_key,
"storeLookup": ".main"
})
# Store children relationship (reverse)
self.children_relationships[foreign_key].append({
"name": prop["name"],
"childModel": model_name,
"storeLookup": ".child"
})
else:
# Store parent relationship
self.parent_relationships[model_name].append({
"name": prop["name"],
"foreignKey": foreign_key,
"storeLookup": ".same"
})
# Store children relationship (reverse)
self.children_relationships[foreign_key].append({
"name": prop["name"],
"childModel": model_name,
"storeLookup": ".same"
})
def get_parent_relationships(self, model_name: str) -> List[Dict[str, Any]]:
"""Get parent relationships for a model."""
return self.parent_relationships.get(model_name, [])
def get_children_relationships(self, model_name: str) -> List[Dict[str, Any]]:
"""Get children relationships for a model."""
return self.children_relationships.get(model_name, [])
class LeStorageGenerator:
def __init__(self, json_data: Dict[str, Any]):
self.data = json_data
def __init__(self, json_data: Dict[str, Any], relationship_analyzer: RelationshipAnalyzer = None):
self.json_data = json_data
self.relationship_analyzer = relationship_analyzer
self.pluralizer = inflect.engine()
def generate_model(self, model_data: Dict[str, Any]) -> str:
@ -117,7 +180,7 @@ class LeStorageGenerator:
def _generate_constructor(self, model_name: str, properties: List[Dict[str, Any]]) -> List[str]:
"""Generate a constructor with all properties as parameters with default values."""
lines = [" public init("]
# Generate parameter list
@ -158,15 +221,15 @@ class LeStorageGenerator:
lines.append(f" self.{name} = {name}")
lines.append(" }")
lines.extend([
" required public override init() {",
" super.init()",
" }",
])
return lines
def _generate_didset_methods(self, properties) -> List[str]:
@ -410,7 +473,7 @@ class LeStorageGenerator:
name = prop["name"]
foreign_key = prop["foreignKey"].rstrip('###') # Remove asterisk if present
foreign_variable = name + "Value"
# Generate the foreign key check and deletion logic
lines.append(f" if {model_variable}.{name} != self.{name}, let {name}Object = self.{foreign_variable}(), {name}Object.shared == true, let store = {name}Object.store {{")
lines.append(f" store.deleteUnusedShared({name}Object)")
@ -441,30 +504,45 @@ class LeStorageGenerator:
]
def _generate_relationships(self, model_name, properties: List[Dict[str, Any]]) -> List[str]:
# Find all properties with foreign keys
foreign_key_props = [p for p in properties if "foreignKey" in p]
# if not self.relationship_analyzer:
# # Fallback to old behavior if no analyzer provided
# return self._generate_legacy_relationships(model_name, properties)
lines = []
if not foreign_key_props:
# If no foreign keys, return empty array
# Generate parentRelationships method
lines.extend(self._generate_parent_relationships(model_name))
lines.append("")
# Generate childrenRelationships method
lines.extend(self._generate_children_relationships(model_name))
lines.append("")
# Generate combined relationships method
lines.extend(self._generate_combined_relationships(model_name))
return lines
def _generate_parent_relationships(self, model_name: str) -> List[str]:
"""Generate parentRelationships() method."""
parent_rels = self.relationship_analyzer.get_parent_relationships(model_name)
if not parent_rels:
return [
" public static func relationships() -> [Relationship] {",
" public static func parentRelationships() -> [Relationship] {",
" return []",
" }"
]
lines = [
" public static func relationships() -> [Relationship] {",
" public static func parentRelationships() -> [Relationship] {",
" return ["
]
# Generate relationship entries
for prop in foreign_key_props:
name = prop["name"]
located_on_main_store = "true" if prop["foreignKey"].endswith('###') else "false"
foreign_key = prop["foreignKey"].rstrip('###') # Remove asterisk if present
lines.append(f" Relationship(type: {foreign_key}.self, keyPath: \\Base{model_name}.{name}, mainStoreLookup: {located_on_main_store}),")
for rel in parent_rels:
# main_store = "true" if rel["storeLookup"] else "false"
lines.append(f" Relationship(type: {rel['foreignKey']}.self, keyPath: \\Base{model_name}.{rel['name']}, storeLookup: {rel["storeLookup"]}),")
# Close the array and function
lines.extend([
" ]",
" }"
@ -472,6 +550,93 @@ class LeStorageGenerator:
return lines
def _generate_children_relationships(self, model_name: str) -> List[str]:
"""Generate childrenRelationships() method."""
children_rels = self.relationship_analyzer.get_children_relationships(model_name)
if not children_rels:
return [
" public static func childrenRelationships() -> [Relationship] {",
" return []",
" }"
]
lines = [
" public static func childrenRelationships() -> [Relationship] {",
" return ["
]
for rel in children_rels:
# main_store = "true" if rel["storeLookup"] else "false"
lines.append(f" Relationship(type: {rel['childModel']}.self, keyPath: \\Base{rel['childModel']}.{rel['name']}, storeLookup: {rel["storeLookup"]}),")
lines.extend([
" ]",
" }"
])
return lines
def _generate_combined_relationships(self, model_name: str) -> List[str]:
"""Generate relationships() method that combines parent and children."""
parent_rels = self.relationship_analyzer.get_parent_relationships(model_name)
children_rels = self.relationship_analyzer.get_children_relationships(model_name)
if not parent_rels and not children_rels:
return [
" public static func relationships() -> [Relationship] {",
" return []",
" }"
]
lines = [
" public static func relationships() -> [Relationship] {",
" var relationships: [Relationship] = []",
" relationships.append(contentsOf: parentRelationships())",
" relationships.append(contentsOf: childrenRelationships())",
" return relationships",
" }"
]
return lines
# def _generate_legacy_relationships(self, model_name, properties: List[Dict[str, Any]]) -> List[str]:
# """Legacy relationship generation for backward compatibility."""
# # Find all properties with foreign keys
# foreign_key_props = [p for p in properties if "foreignKey" in p]
#
# if not foreign_key_props:
# # If no foreign keys, return empty array
# return [
# " public static func relationships() -> [Relationship] {",
# " return []",
# " }"
# ]
#
# lines = [
# " public static func relationships() -> [Relationship] {",
# " return ["
# ]
#
# # Generate relationship entries
# for prop in foreign_key_props:
# name = prop["name"]
# located_on_main_store = "true" if prop["foreignKey"].endswith('###') else "false"
# foreign_key = prop["foreignKey"].rstrip('###') # Remove asterisk if present
#
# if located_on_main_store:
# lines.append(f" Relationship(type: {foreign_key}.self, keyPath: \\Base{model_name}.{name}, storeLookup: {located_on_main_store}),")
# else:
# lines.append(f" Relationship(type: {foreign_key}.self, keyPath: \\Base{model_name}.{name}, storeLookup: {located_on_main_store}),")
#
# # Close the array and function
# lines.extend([
# " ]",
# " }"
# ])
#
# return lines
def _get_default_value(self, type_name: str) -> str:
"""Get default value for non-optional types"""
if "String" in type_name:
@ -516,14 +681,21 @@ def process_directory(input_dir: str, output_dir: str, logger: logging.Logger, d
return 0
logger.info(f"Found {len(json_files)} JSON files to process")
# First pass: Analyze all relationships
logger.info("Analyzing relationships across all models...")
relationship_analyzer = RelationshipAnalyzer()
relationship_analyzer.analyze_all_models(input_dir)
successful_files = 0
# Second pass: Generate models with complete relationship information
for json_file in json_files:
try:
with open(json_file, 'r') as f:
json_data = json.load(f)
generator = LeStorageGenerator(json_data)
generator = LeStorageGenerator(json_data, relationship_analyzer)
# Generate each model in the JSON file
for model in json_data["models"]:

@ -293,6 +293,65 @@ struct SyncDataAccessTests {
#expect(eventColB.first?.club == club2A.id)
}
/// In this test, the first user:
/// - creates one event and 2 clubs
/// - shares the event with a second user
/// - changes the club on the event
/// Here we want to test that the first Club is removed and the second one is received
@Test func testRelationshipChangeFromSharedUser() async throws {
guard let userId1 = self.storeCenterA.userId else {
throw TestError.notAuthenticated
}
guard let userId2 = self.storeCenterB.userId else {
throw TestError.notAuthenticated
}
// Setup
let eventColA: SyncedCollection<Event> = await self.storeCenterA.mainStore.asyncLoadingSynchronizedCollection()
let clubColA: SyncedCollection<Club> = await self.storeCenterA.mainStore.asyncLoadingSynchronizedCollection()
let eventColB: SyncedCollection<Event> = await self.storeCenterB.mainStore.asyncLoadingSynchronizedCollection()
let clubColB: SyncedCollection<Club> = await self.storeCenterB.mainStore.asyncLoadingSynchronizedCollection()
if let dataAccessCollection = self.storeCenterA.dataAccessCollection {
try await dataAccessCollection.deleteAsync(contentOfs: Array(dataAccessCollection))
}
try await eventColA.deleteAsync(contentOfs: Array(eventColA))
try await clubColA.deleteAsync(contentOfs: Array(clubColA))
let _ = try await self.storeCenterB.testSynchronizeOnceAsync()
#expect(eventColB.count == 0)
#expect(clubColB.count == 0)
let eventA = Event(creator: userId1, name: "event 1")
try await eventColA.addOrUpdateAsync(instance: eventA)
// Share with user2
try await self.storeCenterA.setAuthorizedUsersAsync(for: eventA, users: [userId2])
let _ = try await self.storeCenterB.testSynchronizeOnceAsync()
#expect(eventColB.count == 1)
let eventB = eventColB.first!
// Create
let club1B = Club(creator: userId2, name: "Club 1", acronym: "C1")
try await clubColB.addOrUpdateAsync(instance: club1B)
// Change the club
eventB.club = club1B.id
try await eventColB.addOrUpdateAsync(instance: eventB)
let dataA = try await self.storeCenterA.testSynchronizeOnceAsync()
print("club1A = \(club1B.id)")
#expect(eventColA.first != nil)
#expect(eventColA.first?.club == club1B.id)
#expect(clubColA.first?.id == club1B.id)
}
/// In this test, the first user:
/// - creates one event
/// - shares the event with a second user
@ -429,6 +488,46 @@ struct SyncDataAccessTests {
#expect(matchesColB.count == 44)
}
@Test func testBuildEverythingFromShared() async throws {
guard let _ = StoreCenter.main.userId else {
throw TestError.notAuthenticated
}
guard let userId2 = self.storeCenterB.userId else {
throw TestError.notAuthenticated
}
// Cleanup
let tournamentColA: SyncedCollection<Tournament> = await StoreCenter.main.mainStore.asyncLoadingSynchronizedCollection()
let tournamentColB: SyncedCollection<Tournament> = await self.storeCenterB.mainStore.asyncLoadingSynchronizedCollection()
let tournamentsToDelete: [Tournament] = try await StoreCenter.main.service().get()
try await tournamentColA.deleteAsync(contentOfs: tournamentsToDelete)
// Setup tournament + build everything
let tournament = Tournament()
try await tournamentColA.addOrUpdateAsync(instance: tournament)
// todo add sharing
try await StoreCenter.main.setAuthorizedUsersAsync(for: tournament, users: [userId2])
// Sync with 2nd store
try await self.storeCenterB.testSynchronizeOnceAsync()
#expect(tournamentColB.count == 1)
let tournamentB = tournamentColB.first!
try await tournamentB.deleteAndBuildEverythingAsync()
#expect(tournamentColB.count == 1)
// Sync with 2nd store
let data = try await self.storeCenterA.testSynchronizeOnceAsync()
let _ = try SyncData(data: data, storeCenter: self.storeCenterA)
#expect(tournamentColA.count == 1)
}
// needs to run on a postgreSQL, otherwise fails because of sqlite database locks
@Test func testDataAccessForChildren() async throws {

Loading…
Cancel
Save