Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Generalised Tooling Support #129

Merged
merged 11 commits into from
Aug 13, 2024
10 changes: 10 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ fn main() -> Result<()> {

std::fs::write(file_path, defs)?;
}

if let Some(tooling) = code.tooling {
let tooling_path = config_path.parent().unwrap().join(tooling.path);

if let Some(parent) = tooling_path.parent() {
std::fs::create_dir_all(parent)?;
}

std::fs::write(tooling_path, tooling.code)?;
}
}

if diagnostics.is_empty() {
Expand Down
15 changes: 10 additions & 5 deletions docs/.vitepress/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const beforeMount = (monaco: Monaco) => {

const Calls = ["SingleSync", "SingleAsync", "ManySync", "ManyAsync"] as const;

const Options = ["write_checks", "typescript", "typescript_max_tuple_length", "manual_event_loop", "remote_scope", "server_output", "client_output", "casing", "yield_type", "async_lib"] as const;
const Options = ["write_checks", "typescript", "typescript_max_tuple_length", "manual_event_loop", "remote_scope", "server_output", "client_output", "casing", "yield_type", "async_lib", "tooling", "tooling_output", "tooling_show_internal_data"] as const;

const Casing = ["PascalCase", "camelCase", "snake_case"].map((value) => `"${value}"`);
const YieldType = ["yield", "future", "promise"].map((value) => `"${value}"`);
Expand Down Expand Up @@ -153,17 +153,22 @@ const beforeMount = (monaco: Monaco) => {

opt: Options,

casing: Casing,
yield_type: YieldType,

typescript: Operators,
typescript_max_tuple_length: [],

tooling: Operators,
tooling_show_internal_data: Operators,

write_checks: Operators,
manual_event_loop: Operators,

remote_scope: [],

server_output: [],
client_output: [],
tooling_output: [],

casing: Casing,
yield_type: YieldType,
async_lib: [],
} as const;

Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const sidebar = [
items: [
{ text: 'Generate Code', link: '/usage/generation' },
{ text: 'Event Usage', link: '/usage/events' },
{ text: 'Tooling Intergration', link: '/usage/tooling' },
]
}
]
Expand Down
52 changes: 52 additions & 0 deletions docs/config/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ opt client_output = "src/client/zap.luau"`

const asyncLibExample = `opt yield_type = "promise"
opt async_lib = "require(game:GetService('ReplicatedStorage').Promise)"`

const toolingOutputExample = `opt tooling = true
opt tooling_output = "src/ReplicatedStorage/RemoteName.profiler.luau"`

const toolingOutputExample2 = `opt typescript = true
opt tooling = true
opt tooling_output = "src/include/RemoteName.profiler.lua"`

const toolingShowInternalDataExample = `opt tooling = true
opt tooling_show_internal_data = true`
</script>

# Options
Expand Down Expand Up @@ -227,3 +237,45 @@ The path is empty.
### Example

<CodeBlock :code="asyncLibExample" />

## `tooling`

This option determines if Zap should generate a file to allow it to inteface with other tooling. More information on this feature can be found on the [tooling intergration](../usage/tooling.md) page.

### Default

`false`

### Example

<CodeBlock code="opt tooling = true" />

## `tooling_output`

This options allows you to configure where Zap will output its generated [tooling code](../usage/tooling.md). If you're not using the CLI these options can be ignored.

The path is relative to the configuration file and should point to a lua(u) file.

### Default

<CodeBlock code='opt tooling_output = "./network/tooling.lua"' />

### Example

<CodeBlock :code="toolingOutputExample" />

or

<CodeBlock :code="toolingOutputExample2" />

## `tooling_show_internal_data`

This option will add an additional element to the start of the [arguments array](../usage/tooling.md#tooling-format-returns) returned by the [tooling intergration](../usage/tooling.md) function. More information on its structure can be found [here](../usage/tooling.md#tooling-format-returns).

### Default

`false`

### Example

<CodeBlock :code="toolingShowInternalDataExample" />
7 changes: 7 additions & 0 deletions docs/playground.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@
:isCodeBlock="false"
/>
</PluginTabsTab>
<PluginTabsTab label="Tooling" v-if="compiledResult.code && compiledResult.code.tooling">
<CodeBlock
:code="compiledResult.code.tooling.code"
lang="lua"
:isCodeBlock="false"
/>
</PluginTabsTab>
</PluginTabs>

</ClientOnly>
Expand Down
79 changes: 79 additions & 0 deletions docs/usage/tooling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Tooling Intergration

Zap supports the ability to output a lua file that can deseralise compressed data so that it can be read by plugins and/or scripts such as [PacketProfiler](https://github.com/Pyseph/PacketProfiler/).

Zap and PacketProfiler have created a common format for this interfacing as detailed below:

## Tooling Format - Parameters

To deseralise this data, the function generated by Zap has the following parameters:

- The remote instance itself (`RemoteEvent | UnreliableRemoteEvent`)
- ALL arguments sent through the remote

An example is below:

::: danger
It is not intended behavior for you to run side effects if you deserialise the data yourself.
:::


<CodeBlock lang="lua" :code="example1" />

## Tooling Format - Returns

The function then returns an array in this format:

Lua:
<CodeBlock lang="lua" :code="returnsLua" />

TS:
<CodeBlock lang="typescript" :code="returnsTS" />

If the [`tooling_show_internal_data`](../config/options.md#tooling-show-internal-data) argument is `true`, then the first argument is of the type (although this type will respect your casing option):

Lua:
<CodeBlock lang="lua" :code="internalDataLua" />

TS:
<CodeBlock lang="typescript" :code="internalDataTS" />

And then the next argument in the array is the data deserialised from the event itself (if it exists).

<script setup lang="ts">
const example1 = `local ReplicatedStorage = game:GetService("ReplicatedStorage")
local zap_deserialiser = require(path.to.deserialiser)

local reliable = ReplicatedStorage:WaitForChild("ZAP_RELIABLE")
local unreliable = ReplicatedStorage:WaitForChild("ZAP_UNRELIABLE")

reliable.OnClientEvent:Connect(function(...)
local data = zap_deserialiser(reliable, unpack(...))
print(data)
end)

unreliable.OnClientEvent:Connect(function(...)
local data = zap_deserialiser(unreliable, unpack(...))
print(data)
end)`

const returnsLua = `type DecompressedData = { {
Name: string,
Arguments: { any },
} }`

const returnsTS = `type DecompressedData = {
Name: string,
Arguments: unknown[],
}[]`

const internalDataLua = `type InternalData = {
EventId: number,
CallId: number?
}`

const internalDataTS = `interface InternalData {
EventId: number,
CallId?: number
}`
</script>
8 changes: 6 additions & 2 deletions zap/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ pub struct Config<'src> {
pub evdecls: Vec<EvDecl<'src>>,
pub fndecls: Vec<FnDecl<'src>>,

pub write_checks: bool,
pub typescript: bool,
pub typescript_max_tuple_length: f64,
pub manual_event_loop: bool,

pub tooling: bool,
pub tooling_show_internal_data: bool,

pub write_checks: bool,
pub manual_event_loop: bool,
pub remote_scope: &'src str,

pub server_output: &'src str,
pub client_output: &'src str,
pub tooling_output: &'src str,

pub casing: Casing,
pub yield_type: YieldType,
Expand Down
3 changes: 3 additions & 0 deletions zap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct Output {
pub struct Code {
pub server: Output,
pub client: Output,
pub tooling: Option<Output>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -72,6 +73,7 @@ pub fn run(input: &str) -> Return {
code: output::luau::client::code(&config),
defs: output::typescript::client::code(&config),
},
tooling: output::tooling::output(&config),
}),
diagnostics: reports.into_iter().map(|report| report.into()).collect(),
}
Expand Down Expand Up @@ -110,6 +112,7 @@ pub fn run(input: &str) -> Return {
code: output::luau::client::code(&config),
defs: output::typescript::client::code(&config),
},
tooling: output::tooling::output(&config),
}),
diagnostics,
}
Expand Down
1 change: 1 addition & 0 deletions zap/src/output/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod luau;
pub mod tooling;
pub mod typescript;
Loading
Loading