refactor: change zig to swift

This commit is contained in:
Konrad Geletey 2024-12-29 14:19:59 +03:00
parent d9ea5cf7d6
commit c0f664d287
Signed by: kglt
GPG key ID: 386DEE24B60BD996
4 changed files with 93 additions and 210 deletions

14
Package.swift Normal file
View file

@ -0,0 +1,14 @@
// 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: "wacli",
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "wacli"),
]
)

79
Sources/main.swift Normal file
View file

@ -0,0 +1,79 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book
enum Types {
case path
case method
case bin
case uri
}
struct Aliases {
enum Alias {
case single(String)
case multiple([String])
}
var alias: Alias,
var type: Types,
var description: String?,
var content: String
}
struct Tool {
var integrity: String,
var source: String,
var installPath: String,
var alias: String?,
var version: string,
}
typealias Tools = [String : Tool]
struct LockFile {
var fileVersion: Int = 1,
var bins: Tools,
var ains: Tools
}
struct OauthFlows {
var implict: struct {
var authrizationUrl: String
var scopes: [String: String]
}
}
struct SettingsAuth {
enum Scheme {
case basic
case bearer
case oauth2
}
var scheme: Scheme?,
var tokenName: String?
var flows: OauthFlows?
}
struct WellKnownSettings {
var contentType: String = "application/json"
var headers: [String]?
var aliases: [Aliases]?
var auth: SettingsAuth?
}
struct UserSettings {
dbPath: String = "$HOME/.cache/wacrd.db",
installDir: String = "$HOME/.local/bin",
uriSchems: [String : String]?
}
struct WellKnownSchema = struct {
enum Path {
var path
}
var api: String?
var registry: Boolean?
var manifests: [String: Path]?
var bin: [String : [String : String]]?
var settings: WellKnownSettings?
}

View file

@ -1,70 +0,0 @@
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "wacli",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// This declares intent for the executable to be installed into the
// standard location when the user invokes the "install" step (the default
// step when running `zig build`).
b.installArtifact(exe);
// This *creates* a Run step in the build graph, to be executed when another
// step is evaluated that depends on it. The next line below will establish
// such a dependency.
const run_cmd = b.addRunArtifact(exe);
// By making the run step depend on the install step, it will be run from the
// installation directory rather than directly from within the cache directory.
// This is not necessary, however, if the application depends on other installed
// files, this ensures they will be present and in the expected location.
run_cmd.step.dependOn(b.getInstallStep());
// This allows the user to pass arguments to the application in the build
// command itself, like this: `zig build run -- arg1 arg2 etc`
if (b.args) |args| {
run_cmd.addArgs(args);
}
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build run`
// This will evaluate the `run` step rather than the default, which is "install".
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}

View file

@ -1,140 +0,0 @@
const std = @import("std");
/// The cow is not mine, but a BratishkaErik
const Samsa = union(enum) {
array: []const []const u8,
string: []const u8,
pub fn jsonParse(allocator: std.mem.Allocator, source: anytype, options: std.json.ParseOptions) !Samsa {
return switch (try source.peekNextTokenType()) {
.array_begin => .{ .array = try std.json.innerParse([]const []const u8, allocator, source, options) },
.string => .{ .string = try std.json.innerParse([]const u8, allocator, source, options) },
else => error.UnexpectedToken,
};
}
};
const Aliases = struct {
alias: Samsa,
type: enum { path, method, bin, uri },
description: ?[]const u8 = null,
content: []const u8,
};
const Tools = std.json.ArrayHashMap(struct {
integrity: [std.crypto.hash.sha256.Sha256.digest_length]u8,
source: []const u8,
installPath: []const u8,
alias: ?[]const u8 = null,
version: []const u8,
});
const LockFile = struct {
fileVersion: i8 = 1,
bins: Tools,
ains: Tools
};
const OauthFlows = struct { implict: struct { authrizationUrl: []const u8, scopes: std.json.ArrayHashMap([]const u8) } };
const WellKnownSettings = struct {
contentType: []const u8 = "application/json",
headers: ?[]const []const u8 = null,
aliases: ?[]const Aliases = null,
auth: ?struct { scheme: enum { basic, bearer, oauth2 }, tokenName: ?[]const u8 = null, flows: ?OauthFlows = null } = null,
};
const WellKnownSchema = struct { api: ?[]const u8 = null, registry: ?bool = false, manifests: ?std.json.ArrayHashMap(struct { path: []const u8 }) = null, bin: ?std.json.ArrayHashMap([]const std.json.ArrayHashMap([]const u8)) = null, settings: ?WellKnownSettings = null };
const UserSettings = struct { db_path: []const u8 = "$HOME/.cache/wacrd.db", install_dir: []const u8 = "$HOME/.local/bin", uri_schemes: ?std.json.ArrayHashMap([]const u8) = null };
pub fn getHomeDir() !?std.fs.Dir {
return try std.fs.openDirAbsolute(std.posix.getenv("HOME") orelse {
return null;
}, .{ .iterate = true });
}
pub fn getXDGConfigHomeDir() !?std.fs.Dir {
return try std.fs.openDirAbsolute(std.posix.getenv("XDG_CONFIG_HOME") orelse {
return null;
}, .{ .iterate = true });
}
pub fn readTypedConfig(allocator: std.mem.Allocator, comptime T: type, filePath: []const u8, buffer_size: usize) !std.json.Parsed(T) {
const contents = try std.fs.cwd().readFileAlloc(allocator, filePath, buffer_size);
defer allocator.free(contents);
return std.json.parseFromSlice(T, allocator, contents, .{
.allocate = .alloc_always,
.ignore_unknown_fields = true,
});
}
pub fn fetchResource(allocator: std.mem.Allocator, api: ?[]const u8,) !struct{ std.http.Status, std.ArrayList(u8)} {
const http = std.http;
var client = http.Client{ .allocator = allocator };
defer client.deinit();
var list = std.ArrayList(u8).init(allocator);
const fetch = try client.fetch(.{.location = .{.url = api.?}, .method = .GET, .response_storage = .{.dynamic = &list}});
return .{ fetch.status, list};
}
pub fn main() !void {}
test "fetch openapi schema" {
const parsedWaCLISchema = try readTypedConfig(std.testing.allocator, WellKnownSchema, "examples/git.0ut0f.space/.well-known/wacli.json", 2048);
defer parsedWaCLISchema.deinit();
const waCLISchema = parsedWaCLISchema.value;
const status, const data = try fetchResource(std.testing.allocator,waCLISchema.api);
defer data.deinit();
std.debug.print("{u}\n",.{status});
std.debug.print("{s}\n",.{data.items});
}
test "parse registry schema:" {
const parsedExampleSettings = try readTypedConfig(std.testing.allocator, UserSettings, "examples/settings.json", 512);
const parsedWaCLISchema = try readTypedConfig(std.testing.allocator, WellKnownSchema, "examples/wacli.ofs.lol/.well-known/wacli.json", 512);
defer {
parsedExampleSettings.deinit();
parsedWaCLISchema.deinit();
}
const waCLISettings = parsedExampleSettings.value;
const waCLISchema = parsedWaCLISchema.value;
// const uri_schemes = waCLISettings.uri_schemes.?.map;
// std.debug.print("{any}\n", .{waCLISchema});
try std.testing.expect(waCLISchema.registry == true);
try std.testing.expect(waCLISchema.api == null);
try std.testing.expect(std.mem.eql(u8, waCLISettings.db_path, "$HOME/.cache/wacrd.db"));
}
test "parse schema:" {
const parsedWaCLISchema = try readTypedConfig(std.testing.allocator, WellKnownSchema, "examples/git.0ut0f.space/.well-known/wacli.json", 2048);
var AliasesArray = std.MultiArrayList(Aliases){};
defer {
parsedWaCLISchema.deinit();
AliasesArray.deinit(std.testing.allocator);
}
const waCLISchema = parsedWaCLISchema.value;
//const binaryPathLinux = waCLISchema.bin.?.map.get("linux").?[0].map.get("x86").?;
//std.debug.print("{s}\n", .{binaryPathLinux});
try std.testing.expect(std.mem.eql(u8, waCLISchema.api.?, "https://git.0ut0f.space/swagger.v1.json"));
try AliasesArray.insert(std.testing.allocator, 0, .{
.alias = .{ .string = "issues" },
.type = .path,
.content = "/repos/{owner}/{repo}/issues",
});
try AliasesArray.append(std.testing.allocator, .{
.alias = .{ .array = &[_][]const u8{ "c", "create" } },
.type = .method,
.content = "POST",
});
try AliasesArray.append(std.testing.allocator, .{ .alias = .{ .array = &[_][]const u8{ "d", "delete" } }, .type = .method, .content = "DELETE" });
try AliasesArray.append(std.testing.allocator, .{ .alias = .{ .string = "tea" }, .type = .bin, .content = "tea" });
try std.testing.expect(@TypeOf(AliasesArray.get(0)) == @TypeOf(waCLISchema.settings.?.aliases.?[0]));
}