(defNew [&prop :String archiveDir] [:Array systems [] // Parse all entries into a dictionary of id => entry :Map entries (let [entryDir (joinPath archiveDir "entries") componentDir (joinPath archiveDir "components") filesDir (joinPath archiveDir "files")] (assert (FileSystem.exists archiveDir) "Archive directory $archiveDir does not exist") (assert (FileSystem.isDirectory archiveDir) "$archiveDir is not a directory") (FileSystem.createDirectory entryDir) (FileSystem.createDirectory componentDir) (FileSystem.createDirectory filesDir) (let [entryFiles (FileSystem.readDirectory entryDir)] (for file entryFiles =>(file.withoutExtension) (the Entry (Json.parse (File.getContent (joinPath archiveDir "entries" file)))))))]) (method addSystem [:System system] // Assign entries to the Systems that care about them (doFor =>id entry entries (system.checkEntryInOrOut this entry)) (systems.push system) system) (method processSystems [] (doFor system systems (system.process this))) (method :Entry createEntry [:Entry->Dynamic initializer] // initializer returns Dynamic so ->:Void isn't required (let [e (_newEntry)] (initializer e) (dictSet entries e.id e) (refreshEntry e) e)) // After modifying an entry, this must be called. If you are writing in a createEntry // initializer or a system's processEntry function, this will happen automatically. // Also most functions that only affect the Entry, not its components' contents, // will call this automatically though (withWritableEntry). // When changing components, use the (withWritableComponents) macro in Lib.kiss (method refreshEntry [:Entry e] (_saveEntry e) (doFor system systems (system.checkEntryInOrOut this e))) (method _saveEntry [:Entry e] (File.saveContent (joinPath archiveDir "entries" (e.id.withExtension "json")) (Json.stringify e))) (method fullString [:Entry e] (haxe.Json.stringify e null "\t")) (function :Entry _newEntry [] (object id (Uuid.v4) components (new Map) files []))