Initial commit

This commit is contained in:
david-swift 2024-10-04 00:35:31 +02:00
commit f69910b2fa
14 changed files with 594 additions and 0 deletions

40
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Bug report
description: Something is not working as expected.
title: Description of the bug
labels: bug
body:
- type: textarea
attributes:
label: Describe the bug
description: >-
A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: To Reproduce
description: >-
Steps to reproduce the behavior.
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: >-
A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: >-
Add any other context about the problem here.

View File

@ -0,0 +1,36 @@
name: Feature request
description: Suggest an idea for this project
title: Description of the feature request
labels: enhancement
body:
- type: input
attributes:
label: Is your feature request related to a problem? Please describe.
placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: false
- type: textarea
attributes:
label: Describe the solution you'd like
placeholder: >-
A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Describe alternatives you've considered
placeholder: >-
A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
attributes:
label: Additional context
placeholder: >-
Add any other context or screenshots about the feature request here.
validations:
required: true

11
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,11 @@
## Steps
- [ ] Build the project on your machine. If it does not compile, fix the errors.
- [ ] Describe the purpose and approach of your pull request below.
- [ ] Submit the pull request. Thank you very much for your contribution!
## Purpose
_Describe the problem or feature._
_If there is a related issue, add the link._
## Approach
_Describe how this pull request solves the problem or adds the feature._

45
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: Deploy Docs
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
Deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Build Docs
run: |
xcrun xcodebuild docbuild \
-scheme Meta \
-destination 'generic/platform=macOS' \
-derivedDataPath "$PWD/.derivedData" \
-skipPackagePluginValidation
xcrun docc process-archive transform-for-static-hosting \
"$PWD/.derivedData/Build/Products/Debug/Meta.doccarchive" \
--output-path "docs" \
--hosting-base-path "Meta"
- name: Modify Docs
run: |
echo "<script>window.location.href += \"/documentation/meta\"</script>" > docs/index.html;
sed -i '' 's/,2px/,10px/g' docs/css/index.*.css
- name: Upload Artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'docs'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

30
.github/workflows/swiftlint.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: SwiftLint
on:
push:
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
pull_request:
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
workflow_dispatch:
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
jobs:
SwiftLint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: SwiftLint
uses: norio-nomura/action-swiftlint@3.2.1
with:
args: --strict
env:
WORKING_DIRECTORY: Source

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
/Package.resolved
.Ulysses-Group.plist
/.docc-build
/io.github.AparokshaUI.Generation.json
/.vscode

163
.swiftlint.yml Normal file
View File

@ -0,0 +1,163 @@
# Opt-In Rules
opt_in_rules:
- anonymous_argument_in_multiline_closure
- array_init
- attributes
- closure_body_length
- closure_end_indentation
- closure_spacing
- collection_alignment
- comma_inheritance
- conditional_returns_on_newline
- contains_over_filter_count
- contains_over_filter_is_empty
- contains_over_first_not_nil
- contains_over_range_nil_comparison
- convenience_type
- discouraged_none_name
- discouraged_object_literal
- discouraged_optional_boolean
- discouraged_optional_collection
- empty_collection_literal
- empty_count
- empty_string
- enum_case_associated_values_count
- explicit_init
- fallthrough
- file_header
- file_name
- file_name_no_space
- first_where
- flatmap_over_map_reduce
- force_unwrapping
- function_default_parameter_at_end
- identical_operands
- implicit_return
- implicitly_unwrapped_optional
- joined_default_parameter
- last_where
- legacy_multiple
- let_var_whitespace
- literal_expression_end_indentation
- local_doc_comment
- lower_acl_than_parent
- missing_docs
- modifier_order
- multiline_arguments
- multiline_arguments_brackets
- multiline_function_chains
- multiline_literal_brackets
- multiline_parameters
- multiline_parameters_brackets
- no_extension_access_modifier
- no_grouping_extension
- no_magic_numbers
- number_separator
- operator_usage_whitespace
- optional_enum_case_matching
- prefer_self_in_static_references
- prefer_self_type_over_type_of_self
- prefer_zero_over_explicit_init
- prohibited_interface_builder
- redundant_nil_coalescing
- redundant_type_annotation
- return_value_from_void_function
- shorthand_optional_binding
- sorted_first_last
- sorted_imports
- static_operator
- strict_fileprivate
- switch_case_on_newline
- toggle_bool
- trailing_closure
- type_contents_order
- unneeded_parentheses_in_closure_argument
- yoda_condition
# Disabled Rules
disabled_rules:
- block_based_kvo
- class_delegate_protocol
- dynamic_inline
- is_disjoint
- no_fallthrough_only
- notification_center_detachment
- ns_number_init_as_function_reference
- nsobject_prefer_isequal
- private_over_fileprivate
- redundant_objc_attribute
- self_in_property_initialization
- todo
- unavailable_condition
- valid_ibinspectable
- xctfail_message
# Custom Rules
custom_rules:
github_issue:
name: 'GitHub Issue'
regex: '//.(TODO|FIXME):.(?!.*(https://github\.com/AparokshaUI/meta-sqlite/issues/\d))'
message: 'The related GitHub issue must be included in a TODO or FIXME.'
severity: warning
fatal_error:
name: 'Fatal Error'
regex: 'fatalError.*\(.*\)'
message: 'Fatal error should not be used.'
severity: error
enum_case_parameter:
name: 'Enum Case Parameter'
regex: 'case [a-zA-Z0-9]*\([a-zA-Z0-9\.<>?,\n\t =]+\)'
message: 'The associated values of an enum case should have parameters.'
severity: warning
tab:
name: 'Whitespaces Instead of Tab'
regex: '\t'
message: 'Spaces should be used instead of tabs.'
severity: warning
# Thanks to the creator of the SwiftLint rule
# "empty_first_line"
# https://github.com/coteditor/CotEditor/blob/main/.swiftlint.yml
# in the GitHub repository
# "CotEditor"
# https://github.com/coteditor/CotEditor
empty_first_line:
name: 'Empty First Line'
regex: '(^[ a-zA-Z ]*(?:protocol|extension|class|struct) (?!(?:var|let))[ a-zA-Z:]*\{\n *\S+)'
message: 'There should be an empty line after a declaration'
severity: error
# Analyzer Rules
analyzer_rules:
- unused_declaration
- unused_import
# Options
file_header:
required_pattern: '(// swift-tools-version: .+)?//\n// .*.swift\n// meta-sqlite\n//\n// Created by .* on .*\.(\n// Edited by (.*,)+\.)*\n(\n// Thanks to .* for the .*:\n// ".*"\n// https://.* \(\d\d.\d\d.\d\d\))*//\n'
missing_docs:
warning: [internal, private]
error: [open, public]
excludes_inherited_types: false
type_contents_order:
order:
- case
- type_alias
- associated_type
- type_property
- instance_property
- ib_inspectable
- ib_outlet
- subscript
- initializer
- deinitializer
- subtype
- type_method
- view_life_cycle_method
- ib_action
- other_method
excluded:
- .build/

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 david-swift
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

41
Package.swift Normal file
View File

@ -0,0 +1,41 @@
// swift-tools-version: 6.0
//
// Package.swift
// meta-sqlite
//
// Created by david-swift on 04.10.24.
//
import PackageDescription
/// The meta-sqlite package is part of the Aparoksha project.
let package = Package(
name: "meta-sqlite",
platforms: [
.macOS(.v10_15),
.iOS(.v13)
],
products: [
.library(
name: "MetaSQLite",
targets: ["MetaSQLite"]
)
],
dependencies: [
.package(url: "https://github.com/AparokshaUI/Meta", branch: "main"),
.package(url: "https://github.com/stephencelis/SQLite.swift", from: "0.15.3")
],
targets: [
.target(
name: "MetaSQLite",
dependencies: ["Meta", .product(name: "SQLite", package: "SQLite.swift")],
path: "Sources"
),
.executableTarget(
name: "Tests",
dependencies: ["MetaSQLite"],
path: "Tests"
)
],
swiftLanguageModes: [.v5]
)

28
README.md Normal file
View File

@ -0,0 +1,28 @@
<p align="center">
<h1 align="center">SQLite for Meta</h1>
</p>
<p align="center">
<a href="https://aparokshaui.github.io/meta-sqlite/">
Documentation
</a>
·
<a href="https://github.com/AparokshaUI/meta-sqlite">
GitHub
</a>
</p>
_SQLite for Meta_ is a simple extension for the [Meta](https://aparokshaui.github.io/Meta) framework remembering state data between app launches.
## Thanks
### Dependencies
- [Meta](https://github.com/AparokshaUI/Meta) licensed under the [MIT License](https://github.com/AparokshaUI/Meta/blob/main/LICENSE.md)
- [SQLite.swift](https://github.com/stephencelis/SQLite.swift) licensed under the [MIT License](https://github.com/stephencelis/SQLite.swift/blob/master/LICENSE.txt)
### Other Thanks
- [DocC](https://github.com/apple/swift-docc) used for the documentation
- [SwiftLint](https://github.com/realm/SwiftLint) for checking whether code style conventions are violated
- The programming language [Swift](https://github.com/swiftlang/swift)

93
Sources/State.swift Normal file
View File

@ -0,0 +1,93 @@
//
// State.swift
// meta-sqlite
//
// Created by david-swift on 04.10.24.
//
import Foundation
import Meta
import SQLite
extension State where Value: Codable {
/// Initialize a property being remembered between launches of the app.
/// - Parameters:
/// - wrappedValue: The wrapped value, used as an initial value if no stored value is found.
/// - stateID: The identifier for the stored value.
/// - forceUpdates: Whether to force update all available views when the property gets modified.
///
/// Define a custom path for storing the data with ``DatabaseInformation/setPath(_:)``.
public init(wrappedValue: @autoclosure @escaping () -> Value, _ stateID: String, forceUpdates: Bool = false) {
self.init(
wrappedValue: {
let query = DatabaseInformation.table
.filter(DatabaseInformation.id == stateID)
.limit(1)
var data: Data?
guard let rows = try? DatabaseInformation.connection?.prepare(query) else {
return wrappedValue()
}
for row in rows {
data = row[DatabaseInformation.data]
}
guard let data else {
return wrappedValue()
}
let value = try? JSONDecoder().decode(Value.self, from: data)
return value ?? wrappedValue()
},
writeValue: { value in
if let data = try? JSONEncoder().encode(value) {
_ = try? DatabaseInformation.connection?.run(
DatabaseInformation.table.insert(
or: .replace,
DatabaseInformation.id <- stateID,
DatabaseInformation.data <- data
)
)
}
},
forceUpdates: forceUpdates
)
}
}
/// Information about the database.
public enum DatabaseInformation {
/// The path.
static var path = "./database.sqlite"
/// The table.
static let table = Table("data")
/// The ID field.
static let id = SQLite.Expression<String>("id")
/// The data field.
static let data = SQLite.Expression<Data>("data")
/// The SQLite connection.
private static var privateConnection: Connection?
/// The SQLite connection.
static var connection: Connection? {
if let privateConnection {
return privateConnection
}
let connection = try? Connection(path)
privateConnection = connection
_ = try? connection?.run(table.create { table in
table.column(id, primaryKey: true)
table.column(data)
})
return connection
}
/// Set the path to the SQLite file.
/// - Parameter path: The path.
///
/// Call this function before accessing any state values (when setting up the app storage).
public static func setPath(_ path: String) {
self.path = path
}
}

View File

@ -0,0 +1,4 @@
# ``MetaSQLite``
_SQLite for Meta_ is a simple extension for the [Meta](https://aparokshaui.github.io/Meta) framework remembering state data between app launches.

View File

@ -0,0 +1,45 @@
{
"theme": {
"border-radius": "10px",
"button": {
"border-radius": "20px"
},
"color": {
"button-background": "#ea3358",
"button-background-active": "#ea3358",
"button-background-hover": "#fc557a",
"button-text": "#ffffff",
"header": "#7f313b",
"documentation-intro-accent": "var(--color-header)",
"link": "#ea3358",
"nav-link-color": "#ea3358",
"nav-dark-link-color": "#ea3358",
"tutorials-overview-link": "#fb4469",
"step-background": {
"light": "#fffaff",
"dark": "#302c2d"
},
"step-focused": "#ea3358",
"tabnav-item-border-color": "#ea3358",
"tutorial-background": {
"light": "",
"dark": "#1d1d1f"
},
"tutorials-overview-background": "linear-gradient(180deg, rgba(43,20,23,1) 0%, rgba(41, 3, 8, 0.808) 60%, rgba(0,0,0,1) 100%)",
"fill-light-blue-secondary": "#ea3358",
"fill-blue": "#ea3358",
"figure-blue": "#ea3358",
"standard-blue-documentation-intro-fill": "#ea3358",
"figure-blue": "#ea3358",
"tutorial-hero-background": "#100a0b",
"navigator-item-hover": {
"light": "#ea335815",
"dark": "#7f313b"
}
},
"additionalProperties": "#ea3358",
"tutorial-step": {
"border-radius": "15px"
}
}
}

23
Tests/Test.swift Normal file
View File

@ -0,0 +1,23 @@
//
// Test.swift
// meta-sqlite
//
// Created by david-swift on 04.10.24.
//
import Meta
import MetaSQLite
/// The test function.
func main() {
@State("test")
var test = 0
@State("other")
var other = 3
print(test)
print(other)
test = 1
other = 0
}
main()