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. 20
      PadelClubData/Data/Gen/BaseTeamRegistration.swift
  15. 17
      PadelClubData/Data/Gen/BaseTeamScore.swift
  16. 21
      PadelClubData/Data/Gen/BaseTournament.swift
  17. 204
      PadelClubData/Data/Gen/generator.py
  18. 99
      PadelClubDataTests/SyncDataAccessTests.swift

@ -142,10 +142,24 @@ public class BaseClub: SyncedModelObject, SyncedStorable {
self.timezone = club.timezone 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 [ 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 self.indoor = court.indoor
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ 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 self.hideUmpirePhone = customuser.hideUmpirePhone
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [] 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 self.endDate = dateinterval.endDate
} }
public static func parentRelationships() -> [Relationship] {
return []
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] { public static func relationships() -> [Relationship] {
return [] return []
} }

@ -92,10 +92,21 @@ public class BaseDrawLog: SyncedModelObject, SyncedStorable {
self.drawType = drawlog.drawType self.drawType = drawlog.drawType
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ 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 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 [ return [
Relationship(type: CustomUser.self, keyPath: \BaseEvent.creator, mainStoreLookup: false), Relationship(type: Tournament.self, keyPath: \BaseTournament.event, storeLookup: .same),
Relationship(type: Club.self, keyPath: \BaseEvent.club, mainStoreLookup: false),
] ]
} }
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 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 [ 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 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 [ return [
Relationship(type: Round.self, keyPath: \BaseMatch.round, mainStoreLookup: false), Relationship(type: TeamScore.self, keyPath: \BaseTeamScore.match, storeLookup: .same),
Relationship(type: GroupStage.self, keyPath: \BaseMatch.groupStage, mainStoreLookup: false),
] ]
} }
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 self.simultaneousStart = matchscheduler.simultaneousStart
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ 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 self.fileModelIdentifier = monthdata.fileModelIdentifier
} }
public static func parentRelationships() -> [Relationship] {
return []
}
public static func childrenRelationships() -> [Relationship] {
return []
}
public static func relationships() -> [Relationship] { public static func relationships() -> [Relationship] {
return [] return []
} }

@ -219,10 +219,21 @@ public class BasePlayerRegistration: SyncedModelObject, SyncedStorable {
self.paymentId = playerregistration.paymentId self.paymentId = playerregistration.paymentId
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ 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 self.expirationDate = purchase.expirationDate
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ 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 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 [ 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 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 [ return [
Relationship(type: Tournament.self, keyPath: \BaseTeamRegistration.tournament, mainStoreLookup: true), Relationship(type: TeamScore.self, keyPath: \BaseTeamScore.teamRegistration, storeLookup: .same),
Relationship(type: GroupStage.self, keyPath: \BaseTeamRegistration.groupStage, mainStoreLookup: false), 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 self.luckyLoser = teamscore.luckyLoser
} }
public static func relationships() -> [Relationship] { public static func parentRelationships() -> [Relationship] {
return [ return [
Relationship(type: Match.self, keyPath: \BaseTeamScore.match, mainStoreLookup: false), Relationship(type: Match.self, keyPath: \BaseTeamScore.match, storeLookup: .same),
Relationship(type: TeamRegistration.self, keyPath: \BaseTeamScore.teamRegistration, mainStoreLookup: false), 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 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 [ 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 import os
from pathlib import Path from pathlib import Path
from typing import Dict, List, Any from typing import Dict, List, Any
from collections import defaultdict
import argparse import argparse
import sys import sys
import logging import logging
from datetime import datetime from datetime import datetime
import inflect 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: class LeStorageGenerator:
def __init__(self, json_data: Dict[str, Any]): def __init__(self, json_data: Dict[str, Any], relationship_analyzer: RelationshipAnalyzer = None):
self.data = json_data self.json_data = json_data
self.relationship_analyzer = relationship_analyzer
self.pluralizer = inflect.engine() self.pluralizer = inflect.engine()
def generate_model(self, model_data: Dict[str, Any]) -> str: def generate_model(self, model_data: Dict[str, Any]) -> str:
@ -441,30 +504,45 @@ class LeStorageGenerator:
] ]
def _generate_relationships(self, model_name, properties: List[Dict[str, Any]]) -> List[str]: def _generate_relationships(self, model_name, properties: List[Dict[str, Any]]) -> List[str]:
# Find all properties with foreign keys # if not self.relationship_analyzer:
foreign_key_props = [p for p in properties if "foreignKey" in p] # # Fallback to old behavior if no analyzer provided
# return self._generate_legacy_relationships(model_name, properties)
lines = []
if not foreign_key_props: # Generate parentRelationships method
# If no foreign keys, return empty array 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 [ return [
" public static func relationships() -> [Relationship] {", " public static func parentRelationships() -> [Relationship] {",
" return []", " return []",
" }" " }"
] ]
lines = [ lines = [
" public static func relationships() -> [Relationship] {", " public static func parentRelationships() -> [Relationship] {",
" return [" " return ["
] ]
# Generate relationship entries for rel in parent_rels:
for prop in foreign_key_props: # main_store = "true" if rel["storeLookup"] else "false"
name = prop["name"] lines.append(f" Relationship(type: {rel['foreignKey']}.self, keyPath: \\Base{model_name}.{rel['name']}, storeLookup: {rel["storeLookup"]}),")
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}),")
# Close the array and function
lines.extend([ lines.extend([
" ]", " ]",
" }" " }"
@ -472,6 +550,93 @@ class LeStorageGenerator:
return lines 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: def _get_default_value(self, type_name: str) -> str:
"""Get default value for non-optional types""" """Get default value for non-optional types"""
if "String" in type_name: if "String" in type_name:
@ -516,14 +681,21 @@ def process_directory(input_dir: str, output_dir: str, logger: logging.Logger, d
return 0 return 0
logger.info(f"Found {len(json_files)} JSON files to process") 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 successful_files = 0
# Second pass: Generate models with complete relationship information
for json_file in json_files: for json_file in json_files:
try: try:
with open(json_file, 'r') as f: with open(json_file, 'r') as f:
json_data = json.load(f) json_data = json.load(f)
generator = LeStorageGenerator(json_data) generator = LeStorageGenerator(json_data, relationship_analyzer)
# Generate each model in the JSON file # Generate each model in the JSON file
for model in json_data["models"]: for model in json_data["models"]:

@ -293,6 +293,65 @@ struct SyncDataAccessTests {
#expect(eventColB.first?.club == club2A.id) #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: /// In this test, the first user:
/// - creates one event /// - creates one event
/// - shares the event with a second user /// - shares the event with a second user
@ -430,6 +489,46 @@ struct SyncDataAccessTests {
} }
@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 // needs to run on a postgreSQL, otherwise fails because of sqlite database locks
@Test func testDataAccessForChildren() async throws { @Test func testDataAccessForChildren() async throws {

Loading…
Cancel
Save