Skip to content

Releases: nikolainobadi/NnFileKit

0.9.1

Choose a tag to compare

@nikolainobadi nikolainobadi released this 20 Oct 13:45

NnFileTesting now re-exports NnFileKit, so tests using import NnFileTesting can access NnFileKit public APIs without a separate import NnFileKit. Existing imports can remain; no migration is required.

0.9.0

Choose a tag to compare

@nikolainobadi nikolainobadi released this 15 Oct 17:32

NnFileKit 0.9.0 adds Sendable requirements to its file system abstractions and synchronized state to its test doubles. This release includes breaking changes to deployment targets and public APIs.

Breaking changes and migration

  • Deployment targets: The package previously declared no explicit platform minimums; it now requires macOS 15 or iOS 18. Raise consuming projects’ deployment targets accordingly.
  • Custom conformers: Directory and FileSystem now inherit Sendable. Update custom implementations to satisfy Swift’s Sendable requirements, including protecting mutable state where needed.
  • Test doubles: MockDirectory and MockFileSystem changed from classes to Sendable structs. Replace class-only usage, such as identity comparisons and weak references, with assertions on exposed state. Copies share synchronized mutable state, so recorded calls and state changes remain visible through every copy; create a new mock when you need independent state.
  • File manager injection: DefaultFileSystem(fileManager:) has been removed. Replace calls using the default manager with DefaultFileSystem(), which uses FileManager.default. If you depend on a custom file manager, provide a custom FileSystem implementation.

Concurrency support

Values typed as any Directory or any FileSystem can now cross concurrency boundaries. CopiedDirectory and CopiedFile also conform to Sendable, allowing recorded copy operations to be passed across those boundaries.

0.8.0

Choose a tag to compare

@nikolainobadi nikolainobadi released this 13 Sep 23:57

NnFileKit 0.8.0

This release adds copying, byte-level file comparison, and helpers for nested and absolute directory paths. It also makes named: parameters accept only a single path component. Code that passed nested paths through named:, code that implements Directory or FileSystem, and tests that use MockDirectory may need changes.

Breaking changes

New protocol requirements

Directory now requires copy(to:overwrite:), copyFile(named:to:overwrite:), and fileContentsEqual(named:in:). FileSystem now requires createDirectory(at:).

Who is affected: projects with their own types that conform to Directory or FileSystem. DefaultDirectory, DefaultFileSystem, and the NnFileTesting mocks already implement these methods.

Action: add the four methods to your conforming types.

named: parameters accept a single path component

Previously: a name containing /, such as subdirectory(named: "assets/images"), was appended to the directory's path, so the method reached the nested location.

Now: a name containing / makes throwing methods throw FileSystemError.invalidName, and makes containsFile(named:) and containsSubdirectory(named:) return false.

Action: switch nested lookups and creation to the relative-path methods:

// Before
let images = try directory.subdirectory(named: "assets/images")

// After
let images = try directory.subdirectory(atRelativePath: "assets/images")
let created = try directory.createSubdirectory(atRelativePath: "assets/images")

For file operations such as readFile(named:) or createFile(named:contents:) on nested files, resolve the containing directory first, then pass only the file name.

New FileSystemError.invalidName case

FileSystemError has a new case. A switch over FileSystemError without a default clause will no longer compile.

Action: handle .invalidName(String) or add a default clause.

MockDirectory.createSubdirectory(named:) throws for existing names

Previously: the mock returned the existing subdirectory. Now: it throws, the same way DefaultDirectory does.

Action: tests that rely on get-or-create behavior should call createSubfolderIfNeeded(named:) instead.

Copying and comparing

  • copy(to:overwrite:) copies a directory, including nested contents and symlinks, into a parent directory under its own name. It returns the copy.
  • copyFile(named:to:overwrite:) copies one file into another directory under the same name. It returns the new file's path.
  • In DefaultDirectory, both methods throw if the destination already exists and overwrite is false. With overwrite: true, the existing destination is deleted before the copy starts. That step is not atomic: if the copy fails afterward, the original destination is already gone.
  • fileContentsEqual(named:in:) checks whether a file has the same bytes as the file with that name in another directory. Binary files work. It returns false if the other directory doesn't have the file, and throws FileSystemError.fileNotFound if the receiving directory doesn't.

Nested and absolute paths

  • FileSystem.createDirectory(at:) returns the directory at an absolute path. If the directory or any parent is missing, it creates them first.
  • Directory.subdirectory(atRelativePath:) opens a nested subdirectory. createSubdirectory(atRelativePath:) does the same but creates any missing folders along the way. Both throw FileSystemError.invalidName for a path that starts with /, and return the receiving directory when the path is empty.

Testing support

MockDirectory records directory copies in copiedToParents and file copies in copiedFiles, including the overwrite flag. Tests can assert on both. The mock doesn't enforce overwrite. When the destination is a MockDirectory, a successful copy also adds the copied item to it.

Full changelog: 0.7.0...0.8.0

0.7.0

Choose a tag to compare

@nikolainobadi nikolainobadi released this 16 Aug 21:59
b938f71

NnFileKit 0.7.0

Testing-focused release. NnFileTesting's mocks gain error injection and write recording, and the NnFileKit skill now ships from this repo.

Added

  • throwError on MockFileSystem and MockDirectory — one flag fails every throwing operation, for exercising error paths.
  • fileContentsToRead on MockFileSystem — stub readFile(at:) by absolute path, no directory wiring needed.
  • writtenFilePath / writtenFileContents on MockFileSystem — assert a write happened without configuring a directory.

Changed

  • ⚠️ Breaking: MockDirectory(autoCreateSubdirectories:) now defaults to false. subdirectory(named:) throws for unknown names instead of synthesizing one, which keeps containsSubdirectory(named:) honest. Pass true to restore the old behavior.
  • MockDirectory.createSubdirectory(named:) now registers the new subdirectory in subdirectories.

Fixed

  • NnFileKitTests was missing its NnFileTesting dependency, so swift test did not compile. Adding it surfaced — and this release fixes — the mock gaps above.
  • MockFileSystem.readFile(at:) throws FileSystemError.fileNotFound instead of an opaque NSError.

Upgrading

.package(url: "https://github.com/nikolainobadi/NnFileKit.git", from: "0.7.0")

Tests relying on subdirectory(named:) always succeeding need autoCreateSubdirectories: true.

0.6.0

Choose a tag to compare

@nikolainobadi nikolainobadi released this 22 Mar 22:36
a180181

NnFileKit 0.6.0 Release Notes

NnConfigKit — a new module for type-safe JSON configuration management, built on NnFileKit's existing FileSystem and Directory protocols.

What's New

  • NnConfigManager<Config: Codable> — generic manager for loading, saving, and updating JSON config files at ~/.config/NnConfigList/{projectName}/
  • Nested config file support — create, append, remove, and delete files within config directory hierarchies
  • Fully testable — accepts an injected FileSystem, works with MockFileSystem/MockDirectory out of the box
  • Sendable — safe for Swift 6 strict concurrency

Quick Start

import NnConfigKit

struct AppConfig: Codable {
    var theme: String
    var maxRetries: Int
}

let manager = NnConfigManager<AppConfig>(projectName: "MyApp")
try manager.saveConfig(AppConfig(theme: "dark", maxRetries: 3))
let config = try manager.loadConfig()

Installation

.product(name: "NnConfigKit", package: "NnFileKit")

0.5.0

Choose a tag to compare

@nikolainobadi nikolainobadi released this 13 Feb 00:52

0.5.0

Initial release of NnFileKit.

Highlights

  • FileSystem and Directory protocols for abstracting file system operations
  • DefaultFileSystem and DefaultDirectory implementations backed by FileManager
  • NnFileTesting module with MockFileSystem and MockDirectory test doubles
  • Recursive file search with optional extension filtering
  • Trash support, directory traversal, and file read/write operations
  • Swift 6 strict concurrency support (Sendable conformance)