Initial Commit.
This commit is contained in:
commit
92ac8e8263
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
||||||
|
|
||||||
|
/.vscode
|
||||||
11
.swift-format
Normal file
11
.swift-format
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"lineLength": 100,
|
||||||
|
"indentation": {
|
||||||
|
"spaces": 4
|
||||||
|
},
|
||||||
|
"maximumBlankLines": 1,
|
||||||
|
"respectsExistingLineBreaks": true,
|
||||||
|
"lineBreakBeforeControlFlowKeywords": true,
|
||||||
|
"lineBreakBeforeEachArgument": true
|
||||||
|
}
|
||||||
15
Package.resolved
Normal file
15
Package.resolved
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "d88be4258c389a35639a4f2bbde8f9f0c10823cb590d44070870e9cf382a9629",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "meta",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://git.aparoksha.dev/aparoksha/meta",
|
||||||
|
"state" : {
|
||||||
|
"branch" : "main",
|
||||||
|
"revision" : "ce9c5bf7d1e8da54d64515f3d0e0fa3b05ad4355"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
39
Package.swift
Normal file
39
Package.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// swift-tools-version: 6.0
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "meta-json",
|
||||||
|
platforms: [
|
||||||
|
.macOS(.v10_15)
|
||||||
|
],
|
||||||
|
products: [
|
||||||
|
.library(
|
||||||
|
name: "MetaJSON",
|
||||||
|
targets: ["MetaJSON"]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://git.aparoksha.dev/aparoksha/meta", branch: "main")
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
.target(
|
||||||
|
name: "MetaJSON",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "Meta", package: "meta")
|
||||||
|
],
|
||||||
|
path: "Sources"
|
||||||
|
|
||||||
|
),
|
||||||
|
.executableTarget(
|
||||||
|
name: "Tests",
|
||||||
|
dependencies: ["MetaJSON"],
|
||||||
|
path: "Tests"
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
swiftLanguageModes: [
|
||||||
|
.v5
|
||||||
|
]
|
||||||
|
)
|
||||||
68
Sources/MetaJSON/State.swift
Normal file
68
Sources/MetaJSON/State.swift
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import Foundation
|
||||||
|
import Meta
|
||||||
|
|
||||||
|
extension State where Value: Codable {
|
||||||
|
|
||||||
|
/// Initialize a property remembered between launches using a JSON file.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - wrappedValue: The default value if no stored value exists.
|
||||||
|
/// - stateID: Unique key for the value.
|
||||||
|
/// - forceUpdates: Whether to force update all available views when modified.
|
||||||
|
public init(
|
||||||
|
wrappedValue: @autoclosure @escaping () -> Value,
|
||||||
|
_ stateID: String,
|
||||||
|
forceUpdates: Bool = false
|
||||||
|
) {
|
||||||
|
self.init(
|
||||||
|
wrappedValue: {
|
||||||
|
guard let data = try? Data(contentsOf: URL(fileURLWithPath: JSONDatabase.path)),
|
||||||
|
let storage = try? JSONDecoder().decode([String: Data].self, from: data),
|
||||||
|
let storedValueData = storage[stateID],
|
||||||
|
let value = try? JSONDecoder().decode(Value.self, from: storedValueData)
|
||||||
|
else {
|
||||||
|
return wrappedValue()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
writeValue: { value in
|
||||||
|
var storage: [String: Data] = [:]
|
||||||
|
let url = URL(fileURLWithPath: JSONDatabase.path)
|
||||||
|
|
||||||
|
if let data = try? Data(contentsOf: url),
|
||||||
|
let decoded = try? JSONDecoder().decode([String: Data].self, from: data)
|
||||||
|
{
|
||||||
|
storage = decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
if let encodedValue = try? JSONEncoder().encode(value) {
|
||||||
|
storage[stateID] = encodedValue
|
||||||
|
|
||||||
|
let encoder = JSONEncoder()
|
||||||
|
encoder.outputFormatting = .prettyPrinted
|
||||||
|
|
||||||
|
if let newData = try? encoder.encode(storage) {
|
||||||
|
try? FileManager.default.createDirectory(
|
||||||
|
at: url.deletingLastPathComponent(),
|
||||||
|
withIntermediateDirectories: true
|
||||||
|
)
|
||||||
|
try? newData.write(to: url, options: .atomic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
forceUpdates: forceUpdates
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum JSONDatabase {
|
||||||
|
|
||||||
|
/// The path to the JSON file.
|
||||||
|
static var path = "./database.json"
|
||||||
|
|
||||||
|
/// Optionally allow customization of the path.
|
||||||
|
public static func setPath(_ newPath: String) {
|
||||||
|
self.path = newPath
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Tests/Test.swift
Normal file
16
Tests/Test.swift
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import Meta
|
||||||
|
import MetaJSON
|
||||||
|
|
||||||
|
/// The test function.
|
||||||
|
func main() {
|
||||||
|
@State("test")
|
||||||
|
var test = 0
|
||||||
|
@State("other")
|
||||||
|
var other = 3
|
||||||
|
print(test)
|
||||||
|
print(other)
|
||||||
|
test = 1
|
||||||
|
other = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user