Skip to content

Commit

Permalink
Merge pull request #106 from oscartbeaumont/channel
Browse files Browse the repository at this point in the history
ipc::Channel support
  • Loading branch information
oscartbeaumont authored Jul 31, 2024
2 parents afe62fd + ed72657 commit d511a29
Show file tree
Hide file tree
Showing 9 changed files with 609 additions and 669 deletions.
1,009 changes: 471 additions & 538 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ rustdoc-args = ["--cfg", "docsrs"]
javascript = ["dep:specta-typescript"]
typescript = ["dep:specta-typescript"]

# TODO: https://github.com/tauri-apps/tauri/pull/10435
UNSTABLE_channels = []

[dependencies]
# Public
specta = { workspace = true, features = ["function"] }
Expand All @@ -38,10 +41,10 @@ indoc = "2.0.5"

[workspace]
members = [
"examples/app/src-tauri",
"examples/custom-plugin/app/src-tauri",
"examples/custom-plugin/plugin",
"macros",
"examples/app/src-tauri",
"examples/custom-plugin/app/src-tauri",
"examples/custom-plugin/plugin",
"macros",
]

[workspace.dependencies]
Expand All @@ -51,6 +54,9 @@ specta-util = { version = "0.0.3" }
specta-typescript = { version = "0.0.3" }

[patch.crates-io]
# tauri = { git = "https://github.com/oscartbeaumont/tauri.git", branch = "fix-channel-specta-remote-impl" }
# tauri-build = { git = "https://github.com/oscartbeaumont/tauri.git", branch = "fix-channel-specta-remote-impl" }

specta = { path = "../specta/specta" }
specta-util = { path = "../specta/specta-util" }
specta-typescript = { path = "../specta/specta-typescript" }
specta-typescript = { path = "../specta/specta-typescript" }
87 changes: 45 additions & 42 deletions examples/app/src/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,59 +79,62 @@ export type Testing = { a: string }

/** tauri-specta globals **/

import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
import {
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
} from "@tauri-apps/api/core";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";

type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
listen: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
};

export type Result<T, E> =
| { status: "ok"; data: T }
| { status: "error"; error: E };
| { status: "ok"; data: T }
| { status: "error"; error: E };

function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>
mappings: Record<keyof T, string>,
) {
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];

return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
}
);
return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
},
);
}


55 changes: 29 additions & 26 deletions src/globals.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
import {
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
} from "@tauri-apps/api/core";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";

/** @typedef {typeof import("@tauri-apps/api/window").WebviewWindowHandle} __WebviewWindowHandle__ */
Expand Down Expand Up @@ -33,30 +36,30 @@ import * as TAURI_API_EVENT from "@tauri-apps/api/event";
* }}
*/
function __makeEvents__(mappings) {
return new Proxy(
{},
{
get: (_, event) => {
const name = mappings[event];
return new Proxy(
{},
{
get: (_, event) => {
const name = mappings[event];

new Proxy(() => {}, {
apply: (_, __, [window]) => ({
listen: (arg) => window.listen(name, arg),
once: (arg) => window.once(name, arg),
emit: (arg) => window.emit(name, arg),
}),
get: (_, command) => {
switch (command) {
case "listen":
return (arg) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
}
);
new Proxy(() => {}, {
apply: (_, __, [window]) => ({
listen: (arg) => window.listen(name, arg),
once: (arg) => window.once(name, arg),
emit: (arg) => window.emit(name, arg),
}),
get: (_, command) => {
switch (command) {
case "listen":
return (arg) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
},
);
}
87 changes: 45 additions & 42 deletions src/globals.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,57 @@
import { invoke as TAURI_INVOKE } from "@tauri-apps/api/core";
import {
invoke as TAURI_INVOKE,
Channel as TAURI_CHANNEL,
} from "@tauri-apps/api/core";
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";

type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
listen: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>,
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
};

export type Result<T, E> =
| { status: "ok"; data: T }
| { status: "error"; error: E };
| { status: "ok"; data: T }
| { status: "error"; error: E };

function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>
mappings: Record<keyof T, string>,
) {
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>;
};
},
{
get: (_, event) => {
const name = mappings[event as keyof T];

return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
}
);
return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg),
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case "listen":
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
case "once":
return (arg: any) => TAURI_API_EVENT.once(name, arg);
case "emit":
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
}
},
});
},
},
);
}
3 changes: 1 addition & 2 deletions src/js.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::*;
use heck::ToLowerCamelCase;
use indoc::formatdoc;
use js_ts::unraw;
use specta::{datatype, FunctionResultVariant};
use specta_typescript as ts;
use specta_typescript::js_doc;
Expand Down Expand Up @@ -57,7 +56,7 @@ impl ExportLanguage for Language {
type_map,
)
.map(|typ| {
let name = unraw(name).to_lower_camel_case();
let name = name.to_lower_camel_case();

format!("@param {{ {typ} }} {name}")
})
Expand Down
10 changes: 1 addition & 9 deletions src/js_ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,9 @@ pub fn render_all_parts<T: ExportLanguage<Config = specta_typescript::ExportConf
})
}

pub fn unraw(s: &str) -> &str {
if s.starts_with("r#") {
s.split_at(2).1
} else {
s.as_ref()
}
}

pub fn arg_names(args: &[(Cow<'static, str>, DataType)]) -> Vec<String> {
args.iter()
.map(|(name, _)| unraw(name).to_lower_camel_case())
.map(|(name, _)| name.to_lower_camel_case())
.collect::<Vec<_>>()
}

Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,10 @@ where
let commands = export_fn(&mut type_map);

types.collect(&mut type_map);
// TODO: This is required for channels to work correctly.
// This should be unfeature gated once the upstream fix is merged: https://github.com/tauri-apps/tauri/pull/10435
#[cfg(feature = "UNSTABLE_channels")]
type_map.remove(<tauri::ipc::Channel<()> as specta::NamedType>::sid());

let rendered = TLang::render(&commands, &events, &type_map, &statics, &config)?;

Expand Down
7 changes: 2 additions & 5 deletions src/ts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
js_ts::{self, unraw},
*,
};
use crate::{js_ts, *};
use heck::ToLowerCamelCase;
use indoc::formatdoc;
use specta::{datatype, FunctionResultVariant};
Expand Down Expand Up @@ -46,7 +43,7 @@ impl ExportLanguage for Language {
&FunctionResultVariant::Value(typ.clone()),
type_map,
)
.map(|ty| format!("{}: {}", unraw(name).to_lower_camel_case(), ty))
.map(|ty| format!("{}: {}", name.to_lower_camel_case(), ty))
})
.collect::<Result<Vec<_>, _>>()?;

Expand Down

0 comments on commit d511a29

Please sign in to comment.