Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.2"),
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "600.0.1"),
.package(url: "https://github.com/omochi/CodableToTypeScript.git", from: "2.11.0"),
.package(url: "https://github.com/omochi/SwiftTypeReader.git", from: "2.8.0"),
.package(url: "https://github.com/omochi/CodableToTypeScript.git", from: "3.0.1"),
.package(url: "https://github.com/omochi/SwiftTypeReader.git", from: "3.1.0"),
.package(url: "https://github.com/vapor/vapor.git", from: "4.106.7"),
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.5.0"),
],
Expand Down
13 changes: 12 additions & 1 deletion Sources/CallableKitMacros/CallableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public struct CallableMacro: PeerMacro {
}

let protocolName = `protocol`.name.trimmedDescription
let serviceName = protocolName.replacingOccurrences(of: "ServiceProtocol", with: "")
let serviceName = protocolName.trimmingSuffix("Protocol").trimmingSuffix("Service")

let functions = `protocol`.memberBlock.members.compactMap { item in
return item.decl.as(FunctionDeclSyntax.self)
Expand Down Expand Up @@ -42,3 +42,14 @@ public struct CallableMacro: PeerMacro {
return [DeclSyntax(configureFunc)]
}
}

extension String {
fileprivate func trimmingSuffix(_ suffix: String) -> String {
if self.hasSuffix(suffix) {
var copy = self
copy.removeLast(suffix.count)
return copy
}
return self
}
}
8 changes: 4 additions & 4 deletions Sources/CodegenImpl/GenerateTSClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ struct FlatRawRepresentableConverter: TypeConverter {
}
}

func decodePresence() throws -> CodecPresence {
return isTransferringRawValueType ? .identity : .required
func hasDecode() -> Bool {
return !isTransferringRawValueType
}

func decodeDecl() throws -> TSFunctionDecl? {
Expand All @@ -288,8 +288,8 @@ struct FlatRawRepresentableConverter: TypeConverter {
return decl
}

func encodePresence() throws -> CodecPresence {
return isTransferringRawValueType ? .identity : .required
func hasEncode() -> Bool {
return !isTransferringRawValueType
}

func encodeDecl() throws -> TSFunctionDecl? {
Expand Down
15 changes: 13 additions & 2 deletions Sources/CodegenImpl/ServiceProtocolScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ enum ServiceProtocolScanner {

static func scan(_ stype: any SType) -> ServiceProtocolType? {
guard let ptype = stype as? ProtocolType,
ptype.name.hasSuffix("ServiceProtocol"),
ptype.decl.attributes.contains(where: { $0.name == "Callable" }),
!ptype.decl.functions.isEmpty
else { return nil }

let serviceName = ptype.name.replacingOccurrences(of: "ServiceProtocol", with: "")
let serviceName = ptype.name.trimmingSuffix("Protocol").trimmingSuffix("Service")

let functions = ptype.decl.functions.compactMap { fdecl -> ServiceProtocolType.Function? in
guard fdecl.parameters.count <= 1 else {
Expand Down Expand Up @@ -77,3 +77,14 @@ enum ServiceProtocolScanner {
)
}
}

extension String {
fileprivate func trimmingSuffix(_ suffix: String) -> String {
if self.hasSuffix(suffix) {
var copy = self
copy.removeLast(suffix.count)
return copy
}
return self
}
}
16 changes: 8 additions & 8 deletions example/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/TSClient/src/Gen/APIDefinition/Account.gen.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IStubClient } from "../CallableKit.gen.js";
import { CodableResult, CodableResult_JSON, CodableResult_decode } from "../OtherDependency/CodableResult.gen.js";
import { CodableResult, CodableResult$JSON, CodableResult_decode } from "../OtherDependency/CodableResult.gen.js";
import { TagRecord, identity } from "../common.gen.js";
import { SubmitError } from "./Entity/SubmitError.gen.js";

Expand All @@ -10,7 +10,7 @@ export interface IAccountClient {
export const bindAccount = (stub: IStubClient): IAccountClient => {
return {
async signin(request: AccountSignin_Request): Promise<CodableResult<AccountSignin_Response, SubmitError<AccountSignin_Error>>> {
const json = await stub.send(request, "Account/signin") as CodableResult_JSON<AccountSignin_Response, SubmitError<AccountSignin_Error>>;
const json = await stub.send(request, "Account/signin") as CodableResult$JSON<AccountSignin_Response, SubmitError<AccountSignin_Error>>;
return CodableResult_decode<
AccountSignin_Response,
AccountSignin_Response,
Expand Down
62 changes: 31 additions & 31 deletions example/TSClient/src/Gen/APIDefinition/Echo.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import {
import {
Student,
Student2,
Student2_JSON,
Student2$JSON,
Student2_decode,
Student2_encode,
Student3,
Student3_JSON,
Student3$JSON,
Student3_decode,
Student3_encode,
Student4,
Student4_JSON,
Student4$JSON,
Student4_decode,
Student4_encode,
Student5
Expand Down Expand Up @@ -50,7 +50,7 @@ export const bindEcho = (stub: IStubClient): IEchoClient => {
return await stub.send(request, "Echo/testTypicalEntity") as User;
},
async testComplexType(request: TestComplexType_Request): Promise<TestComplexType_Response> {
const json = await stub.send(request, "Echo/testComplexType") as TestComplexType_Response_JSON;
const json = await stub.send(request, "Echo/testComplexType") as TestComplexType_Response$JSON;
return TestComplexType_Response_decode(json);
},
async emptyRequestAndResponse(): Promise<void> {
Expand All @@ -60,15 +60,15 @@ export const bindEcho = (stub: IStubClient): IEchoClient => {
return await stub.send(request, "Echo/testTypeAliasToRawRepr") as Student;
},
async testRawRepr(request: Student2): Promise<Student2> {
const json = await stub.send(Student2_encode(request), "Echo/testRawRepr") as Student2_JSON;
const json = await stub.send(Student2_encode(request), "Echo/testRawRepr") as Student2$JSON;
return Student2_decode(json);
},
async testRawRepr2(request: Student3): Promise<Student3> {
const json = await stub.send(Student3_encode(request), "Echo/testRawRepr2") as Student3_JSON;
const json = await stub.send(Student3_encode(request), "Echo/testRawRepr2") as Student3$JSON;
return Student3_decode(json);
},
async testRawRepr3(request: Student4): Promise<Student4> {
const json = await stub.send(Student4_encode(request), "Echo/testRawRepr3") as Student4_JSON;
const json = await stub.send(Student4_encode(request), "Echo/testRawRepr3") as Student4$JSON;
return Student4_decode(json);
},
async testRawRepr4(request: Student5): Promise<Student5> {
Expand All @@ -91,18 +91,18 @@ export type TestComplexType_K<T> = {
x: T;
} & TagRecord<"TestComplexType_K", [T]>;

export type TestComplexType_K_JSON<T_JSON> = {
x: T_JSON;
export type TestComplexType_K$JSON<T$JSON> = {
x: T$JSON;
};

export function TestComplexType_K_decode<T, T_JSON>(json: TestComplexType_K_JSON<T_JSON>, T_decode: (json: T_JSON) => T): TestComplexType_K<T> {
export function TestComplexType_K_decode<T, T$JSON>(json: TestComplexType_K$JSON<T$JSON>, T_decode: (json: T$JSON) => T): TestComplexType_K<T> {
const x = T_decode(json.x);
return {
x: x
};
}

export function TestComplexType_K_encode<T, T_JSON>(entity: TestComplexType_K<T>, T_encode: (entity: T) => T_JSON): TestComplexType_K_JSON<T_JSON> {
export function TestComplexType_K_encode<T, T$JSON>(entity: TestComplexType_K<T>, T_encode: (entity: T) => T$JSON): TestComplexType_K$JSON<T$JSON> {
const x = T_encode(entity.x);
return {
x: x
Expand All @@ -124,9 +124,9 @@ export type TestComplexType_E<T> = ({
n: {};
}) & TagRecord<"TestComplexType_E", [T]>;

export type TestComplexType_E_JSON<T_JSON> = {
export type TestComplexType_E$JSON<T$JSON> = {
k: {
_0: TestComplexType_K_JSON<T_JSON>;
_0: TestComplexType_K$JSON<T$JSON>;
};
} | {
i: {
Expand All @@ -136,10 +136,10 @@ export type TestComplexType_E_JSON<T_JSON> = {
n: {};
};

export function TestComplexType_E_decode<T, T_JSON>(json: TestComplexType_E_JSON<T_JSON>, T_decode: (json: T_JSON) => T): TestComplexType_E<T> {
export function TestComplexType_E_decode<T, T$JSON>(json: TestComplexType_E$JSON<T$JSON>, T_decode: (json: T$JSON) => T): TestComplexType_E<T> {
if ("k" in json) {
const j = json.k;
const _0 = TestComplexType_K_decode<T, T_JSON>(j._0, T_decode);
const _0 = TestComplexType_K_decode<T, T$JSON>(j._0, T_decode);
return {
kind: "k",
k: {
Expand All @@ -165,12 +165,12 @@ export function TestComplexType_E_decode<T, T_JSON>(json: TestComplexType_E_JSON
}
}

export function TestComplexType_E_encode<T, T_JSON>(entity: TestComplexType_E<T>, T_encode: (entity: T) => T_JSON): TestComplexType_E_JSON<T_JSON> {
export function TestComplexType_E_encode<T, T$JSON>(entity: TestComplexType_E<T>, T_encode: (entity: T) => T$JSON): TestComplexType_E$JSON<T$JSON> {
switch (entity.kind) {
case "k":
{
const e = entity.k;
const _0 = TestComplexType_K_encode<T, T_JSON>(e._0, T_encode);
const _0 = TestComplexType_K_encode<T, T$JSON>(e._0, T_encode);
return {
k: {
_0: _0
Expand Down Expand Up @@ -207,15 +207,15 @@ export type TestComplexType_Request = {
a?: TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>;
} & TagRecord<"TestComplexType_Request">;

export type TestComplexType_Request_JSON = {
a?: TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>;
export type TestComplexType_Request$JSON = {
a?: TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>;
};

export function TestComplexType_Request_decode(json: TestComplexType_Request_JSON): TestComplexType_Request {
const a = OptionalField_decode<TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>, TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>>(json.a, (json: TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>): TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]> => {
return TestComplexType_K_decode<(TestComplexType_E<TestComplexType_L> | null)[], (TestComplexType_E_JSON<TestComplexType_L> | null)[]>(json, (json: (TestComplexType_E_JSON<TestComplexType_L> | null)[]): (TestComplexType_E<TestComplexType_L> | null)[] => {
return Array_decode<TestComplexType_E<TestComplexType_L> | null, TestComplexType_E_JSON<TestComplexType_L> | null>(json, (json: TestComplexType_E_JSON<TestComplexType_L> | null): TestComplexType_E<TestComplexType_L> | null => {
return Optional_decode<TestComplexType_E<TestComplexType_L>, TestComplexType_E_JSON<TestComplexType_L>>(json, (json: TestComplexType_E_JSON<TestComplexType_L>): TestComplexType_E<TestComplexType_L> => {
export function TestComplexType_Request_decode(json: TestComplexType_Request$JSON): TestComplexType_Request {
const a = OptionalField_decode<TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>, TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>>(json.a, (json: TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>): TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]> => {
return TestComplexType_K_decode<(TestComplexType_E<TestComplexType_L> | null)[], (TestComplexType_E$JSON<TestComplexType_L> | null)[]>(json, (json: (TestComplexType_E$JSON<TestComplexType_L> | null)[]): (TestComplexType_E<TestComplexType_L> | null)[] => {
return Array_decode<TestComplexType_E<TestComplexType_L> | null, TestComplexType_E$JSON<TestComplexType_L> | null>(json, (json: TestComplexType_E$JSON<TestComplexType_L> | null): TestComplexType_E<TestComplexType_L> | null => {
return Optional_decode<TestComplexType_E<TestComplexType_L>, TestComplexType_E$JSON<TestComplexType_L>>(json, (json: TestComplexType_E$JSON<TestComplexType_L>): TestComplexType_E<TestComplexType_L> => {
return TestComplexType_E_decode<TestComplexType_L, TestComplexType_L>(json, identity);
});
});
Expand All @@ -230,15 +230,15 @@ export type TestComplexType_Response = {
a?: TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>;
} & TagRecord<"TestComplexType_Response">;

export type TestComplexType_Response_JSON = {
a?: TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>;
export type TestComplexType_Response$JSON = {
a?: TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>;
};

export function TestComplexType_Response_decode(json: TestComplexType_Response_JSON): TestComplexType_Response {
const a = OptionalField_decode<TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>, TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>>(json.a, (json: TestComplexType_K_JSON<(TestComplexType_E_JSON<TestComplexType_L> | null)[]>): TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]> => {
return TestComplexType_K_decode<(TestComplexType_E<TestComplexType_L> | null)[], (TestComplexType_E_JSON<TestComplexType_L> | null)[]>(json, (json: (TestComplexType_E_JSON<TestComplexType_L> | null)[]): (TestComplexType_E<TestComplexType_L> | null)[] => {
return Array_decode<TestComplexType_E<TestComplexType_L> | null, TestComplexType_E_JSON<TestComplexType_L> | null>(json, (json: TestComplexType_E_JSON<TestComplexType_L> | null): TestComplexType_E<TestComplexType_L> | null => {
return Optional_decode<TestComplexType_E<TestComplexType_L>, TestComplexType_E_JSON<TestComplexType_L>>(json, (json: TestComplexType_E_JSON<TestComplexType_L>): TestComplexType_E<TestComplexType_L> => {
export function TestComplexType_Response_decode(json: TestComplexType_Response$JSON): TestComplexType_Response {
const a = OptionalField_decode<TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]>, TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>>(json.a, (json: TestComplexType_K$JSON<(TestComplexType_E$JSON<TestComplexType_L> | null)[]>): TestComplexType_K<(TestComplexType_E<TestComplexType_L> | null)[]> => {
return TestComplexType_K_decode<(TestComplexType_E<TestComplexType_L> | null)[], (TestComplexType_E$JSON<TestComplexType_L> | null)[]>(json, (json: (TestComplexType_E$JSON<TestComplexType_L> | null)[]): (TestComplexType_E<TestComplexType_L> | null)[] => {
return Array_decode<TestComplexType_E<TestComplexType_L> | null, TestComplexType_E$JSON<TestComplexType_L> | null>(json, (json: TestComplexType_E$JSON<TestComplexType_L> | null): TestComplexType_E<TestComplexType_L> | null => {
return Optional_decode<TestComplexType_E<TestComplexType_L>, TestComplexType_E$JSON<TestComplexType_L>>(json, (json: TestComplexType_E$JSON<TestComplexType_L>): TestComplexType_E<TestComplexType_L> => {
return TestComplexType_E_decode<TestComplexType_L, TestComplexType_L>(json, identity);
});
});
Expand Down
Loading
Loading