diff --git a/.vscode/settings.json b/.vscode/settings.json index a3b4dac3..66a6d6c0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,6 +37,7 @@ "listhen", "middlewares", "modii", + "modiimedia", "nitropack", "nocheck", "ofetch", diff --git a/go.mod b/go.mod index 91683ae0..3a0739ff 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module github.com/modiimedia/arri go 1.22.5 + +require github.com/iancoleman/strcase v0.3.0 + +require ( + github.com/tidwall/gjson v1.18.0 + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect +) diff --git a/languages/go/go-server/go.sum b/go.sum similarity index 90% rename from languages/go/go-server/go.sum rename to go.sum index 954b51b9..607dc4f2 100644 --- a/languages/go/go-server/go.sum +++ b/go.sum @@ -4,7 +4,6 @@ github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= diff --git a/go.work b/go.work index 88dc6ced..253e4226 100644 --- a/go.work +++ b/go.work @@ -1,5 +1,7 @@ go 1.22.5 -use ./languages/go/go-server -use ./playground/go -use ./tests/servers/go \ No newline at end of file +use ( + . + ./playground/go + ./tests/servers/go +) diff --git a/go.work.sum b/go.work.sum index 6bfd1357..e3a3f1a1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,11 +1,8 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/languages/go/go-server/README.md b/languages/go/go-server/README.md index f6f4b3f1..7203ce67 100644 --- a/languages/go/go-server/README.md +++ b/languages/go/go-server/README.md @@ -6,6 +6,7 @@ Go implementation of [Arri RPC](/README.md). It uses the `net/http` package from - [Quickstart](#quickstart) - [Basic Example](#basic-example) +- [Manual Setup](#manual-setup) - [Creating HTTP Procedures](#creating-http-procedures) - [Creating Event Stream Procedures](#creating-event-stream-procedures) - [Defining Messages](#defining-messages) @@ -21,6 +22,8 @@ Go implementation of [Arri RPC](/README.md). It uses the `net/http` package from ## Quickstart +The Arri CLI comes with an initialization script that will scaffold a basic go server for Arri RPC. + ```bash # npm npx arri init [project-name] @@ -35,6 +38,18 @@ pnpm install pnpm run dev ``` +Follow the prompts and be sure to select go as your language of choice: + +```terminal +What kind of project do you want to initialize? +-> application + generator plugin + +What language do you want to use? + typescript +-> go +``` + ## Basic Example ```go diff --git a/languages/go/go-server/decode_json_test.go b/languages/go/go-server/decode_json_test.go index d97ceda0..08593ffb 100644 --- a/languages/go/go-server/decode_json_test.go +++ b/languages/go/go-server/decode_json_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - arri "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) var _objectWithEveryTypeInput, _objectWithEveryTypeInputErr = os.ReadFile("../../../tests/test-files/ObjectWithEveryType.json") diff --git a/languages/go/go-server/decode_url_query_test.go b/languages/go/go-server/decode_url_query_test.go index a62f2b12..1280029d 100644 --- a/languages/go/go-server/decode_url_query_test.go +++ b/languages/go/go-server/decode_url_query_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - arri "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) type queryResultWithEveryType struct { diff --git a/languages/go/go-server/encode_json_new.go___ b/languages/go/go-server/encode_json_new.go___ index 4c53a6ff..e748d6b7 100644 --- a/languages/go/go-server/encode_json_new.go___ +++ b/languages/go/go-server/encode_json_new.go___ @@ -1,4 +1,4 @@ -package arri +package go_server import ( "encoding/json" diff --git a/languages/go/go-server/encode_json_test.go b/languages/go/go-server/encode_json_test.go index 5b6df60a..377636e3 100644 --- a/languages/go/go-server/encode_json_test.go +++ b/languages/go/go-server/encode_json_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - arri "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) var testDate = time.Date(2001, time.January, 01, 16, 0, 0, 0, time.UTC) diff --git a/languages/go/go-server/go.mod b/languages/go/go-server/go.mod deleted file mode 100644 index 7a305f37..00000000 --- a/languages/go/go-server/go.mod +++ /dev/null @@ -1,13 +0,0 @@ -module arri - -go 1.22.5 - -require ( - github.com/iancoleman/strcase v0.3.0 - github.com/tidwall/gjson v1.18.0 -) - -require ( - github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.1 // indirect -) diff --git a/languages/go/go-server/testing_utils_test.go b/languages/go/go-server/testing_utils_test.go index 68045d9c..ddbf522e 100644 --- a/languages/go/go-server/testing_utils_test.go +++ b/languages/go/go-server/testing_utils_test.go @@ -5,7 +5,7 @@ import ( "reflect" "time" - arri "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) type nestedObject struct { diff --git a/languages/go/go-server/type_def_test.go b/languages/go/go-server/type_def_test.go index f2c5cc16..ce949dd7 100644 --- a/languages/go/go-server/type_def_test.go +++ b/languages/go/go-server/type_def_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - arri "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) func TestStringToTypeDef(t *testing.T) { diff --git a/languages/rust/rust-client/src/lib.rs b/languages/rust/rust-client/src/lib.rs index e44290be..594b69f1 100644 --- a/languages/rust/rust-client/src/lib.rs +++ b/languages/rust/rust-client/src/lib.rs @@ -54,7 +54,7 @@ pub struct ArriParsedRequestOptions<'a> { } #[derive(Debug)] -pub struct ArriServerError { +pub struct arriError { pub code: u16, pub message: String, pub stack: Option, @@ -65,7 +65,7 @@ trait ArriRequestErrorMethods { fn from_response_data(status: u16, body: String) -> Self; } -impl ArriRequestErrorMethods for ArriServerError { +impl ArriRequestErrorMethods for arriError { fn from_response_data(status: u16, body: String) -> Self { let mut err = Self::from_json_string(body.to_owned()); if err.code == 0 { @@ -78,7 +78,7 @@ impl ArriRequestErrorMethods for ArriServerError { } } -impl ArriModel for ArriServerError { +impl ArriModel for arriError { fn new() -> Self { Self { code: 0, @@ -192,7 +192,7 @@ impl ArriModel for ArriServerError { pub async fn arri_request<'a>( opts: ArriRequestOptions<'a>, params: Option, -) -> Result { +) -> Result { let response: Result; let mut headers: HashMap<&str, String> = HashMap::new(); { @@ -302,7 +302,7 @@ pub async fn arri_request<'a>( match response { Ok(res) => return Ok(res), Err(err) => { - return Err(ArriServerError { + return Err(arriError { code: err.status().unwrap_or(StatusCode::default()).as_u16(), message: format!("Error requesting \"{}\"", opts.url), stack: None, @@ -357,7 +357,7 @@ pub async fn parsed_arri_request<'a, TResponse>( opts: ArriParsedRequestOptions<'a>, params: Option, parser: fn(body: String) -> TResponse, -) -> Result { +) -> Result { let result = arri_request( ArriRequestOptions { method: opts.method, @@ -376,7 +376,7 @@ pub async fn parsed_arri_request<'a, TResponse>( let status = response.status().as_u16(); let body: Result = response.text().await; if status >= 300 || status < 200 { - return Err(ArriServerError::from_response_data( + return Err(arriError::from_response_data( status, body.unwrap_or_default(), )); @@ -384,7 +384,7 @@ pub async fn parsed_arri_request<'a, TResponse>( match body { Ok(text) => return Ok(parser(text)), Err(err) => { - return Err(ArriServerError { + return Err(arriError { code: status, message: "Expected server to return plaintext".to_string(), stack: None, diff --git a/languages/rust/rust-client/src/sse.rs b/languages/rust/rust-client/src/sse.rs index 042fb05f..9fcfbfdc 100644 --- a/languages/rust/rust-client/src/sse.rs +++ b/languages/rust/rust-client/src/sse.rs @@ -5,7 +5,7 @@ use std::{ time::{Duration, Instant}, }; -use crate::{ArriModel, ArriRequestErrorMethods, ArriServerError}; +use crate::{ArriModel, ArriRequestErrorMethods, arriError}; pub struct ArriParsedSseRequestOptions<'a> { pub client: &'a reqwest::Client, @@ -21,7 +21,7 @@ pub struct ArriParsedSseRequestOptions<'a> { pub enum SseEvent { Message(T), - Error(ArriServerError), + Error(arriError), Open, Close, } @@ -204,7 +204,7 @@ impl<'a> EventSource<'a> { } if !response.is_ok() { - on_event(SseEvent::Error(ArriServerError::new()), &mut controller); + on_event(SseEvent::Error(arriError::new()), &mut controller); if controller.is_aborted { return SseAction::Abort; } @@ -219,7 +219,7 @@ impl<'a> EventSource<'a> { if status < 200 || status >= 300 { let body = ok_response.text().await.unwrap_or_default(); on_event( - SseEvent::Error(ArriServerError::from_response_data(status, body)), + SseEvent::Error(arriError::from_response_data(status, body)), &mut controller, ); if controller.is_aborted { diff --git a/languages/rust/rust-codegen-reference/src/example_client.rs b/languages/rust/rust-codegen-reference/src/example_client.rs index b68758b0..2bbf03bc 100644 --- a/languages/rust/rust-codegen-reference/src/example_client.rs +++ b/languages/rust/rust-codegen-reference/src/example_client.rs @@ -6,6 +6,7 @@ deprecated )] use arri_client::{ + arriError, chrono::{DateTime, FixedOffset}, parsed_arri_request, reqwest::{self, Request}, @@ -13,7 +14,7 @@ use arri_client::{ sse::{parsed_arri_sse_request, ArriParsedSseRequestOptions, SseController, SseEvent}, utils::{serialize_date_time, serialize_string}, ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions, - ArriServerError, EmptyArriModel, InternalArriClientConfig, + EmptyArriModel, InternalArriClientConfig, }; use std::collections::{BTreeMap, HashMap}; @@ -39,7 +40,7 @@ impl ArriClientService for ExampleClient { } impl ExampleClient { - pub async fn send_object(&self, params: NestedObject) -> Result { + pub async fn send_object(&self, params: NestedObject) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -75,7 +76,7 @@ impl ArriClientService for ExampleClientBooksService { impl ExampleClientBooksService { /// Get a book - pub async fn get_book(&self, params: BookParams) -> Result { + pub async fn get_book(&self, params: BookParams) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -92,7 +93,7 @@ impl ExampleClientBooksService { /// Create a book #[deprecated] - pub async fn create_book(&self, params: Book) -> Result { + pub async fn create_book(&self, params: Book) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, diff --git a/languages/rust/rust-codegen/src/_index.ts b/languages/rust/rust-codegen/src/_index.ts index b8b5d64c..9b608f43 100644 --- a/languages/rust/rust-codegen/src/_index.ts +++ b/languages/rust/rust-codegen/src/_index.ts @@ -172,7 +172,7 @@ use arri_client::{ sse::{parsed_arri_sse_request, ArriParsedSseRequestOptions, SseController, SseEvent}, utils::{serialize_date_time, serialize_string}, ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions, - ArriServerError, EmptyArriModel, InternalArriClientConfig, + arriError, EmptyArriModel, InternalArriClientConfig, }; use std::collections::{BTreeMap, HashMap}; diff --git a/languages/rust/rust-codegen/src/procedures.ts b/languages/rust/rust-codegen/src/procedures.ts index ab22a35b..21407517 100644 --- a/languages/rust/rust-codegen/src/procedures.ts +++ b/languages/rust/rust-codegen/src/procedures.ts @@ -78,7 +78,7 @@ export function rustHttpRpcFromSchema( return `${leading}pub async fn ${functionName}( &self, ${params ? `params: ${context.typeNamePrefix}${params},` : ""} - ) -> Result<${context.typeNamePrefix}${response ?? "()"}, ArriServerError> { + ) -> Result<${context.typeNamePrefix}${response ?? "()"}, arriError> { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, diff --git a/languages/ts/ts-server/src/app.ts b/languages/ts/ts-server/src/app.ts index 436dd7f7..9f61c7d9 100644 --- a/languages/ts/ts-server/src/app.ts +++ b/languages/ts/ts-server/src/app.ts @@ -20,7 +20,7 @@ import { } from "h3"; import { RequestHookContext } from "./context"; -import { type ArriServerError, defineError, handleH3Error } from "./errors"; +import { type arriError, defineError, handleH3Error } from "./errors"; import { isEventStreamRpc, registerEventStreamRpc } from "./eventStreamRpc"; import { type Middleware, MiddlewareEvent } from "./middleware"; import { type ArriRoute, registerRoute } from "./route"; @@ -284,7 +284,7 @@ export interface ArriOptions { onAfterResponse?: (event: RequestHookEvent) => void | Promise; onBeforeResponse?: (event: RequestHookEvent) => void | Promise; onError?: ( - error: ArriServerError, + error: arriError, event: RequestHookEvent, ) => void | Promise; } diff --git a/languages/ts/ts-server/src/errors.ts b/languages/ts/ts-server/src/errors.ts index 91985d21..65a31b8a 100644 --- a/languages/ts/ts-server/src/errors.ts +++ b/languages/ts/ts-server/src/errors.ts @@ -11,7 +11,7 @@ import { import { type ArriOptions } from "./app"; -export class ArriServerError extends Error { +export class arriError extends Error { code: number; data?: any; constructor(err: { @@ -29,7 +29,7 @@ export class ArriServerError extends Error { } } -export const ArriServerErrorResponse = a.object({ +export const arriErrorResponse = a.object({ code: a.int16(), message: a.string(), stack: a.optional(a.array(a.string())), @@ -41,14 +41,14 @@ export const ArriServerErrorResponse = a.object({ data?: any; }>; -export type ArriServerErrorResponse = a.infer; +export type arriErrorResponse = a.infer; export function defineError( statusCode: StatusCode, - input: Partial> = {}, -): ArriServerError { + input: Partial> = {}, +): arriError { const defaultVals = errorResponseDefaults[statusCode]; - return new ArriServerError({ + return new arriError({ code: statusCode, message: input.message ?? @@ -238,25 +238,25 @@ export async function handleH3Error( onError: ArriOptions["onError"], debug: boolean, ) { - let arriErr: ArriServerError | undefined; - if (err instanceof ArriServerError) { + let arriErr: arriError | undefined; + if (err instanceof arriError) { arriErr = err; } else if (isError(err)) { - arriErr = new ArriServerError({ + arriErr = new arriError({ code: err.statusCode, message: err.message, stack: err.stack, data: err.data, }); } else if (err instanceof Error) { - arriErr = new ArriServerError({ + arriErr = new arriError({ code: 500, message: err.message, data: err, stack: err.stack, }); } else { - arriErr = new ArriServerError({ + arriErr = new arriError({ code: 500, message: `An unknown error occurred`, data: err, @@ -275,12 +275,8 @@ export async function handleH3Error( return sendArriError(event, arriErr, debug); } -async function sendArriError( - event: H3Event, - error: ArriServerError, - debug: boolean, -) { - const payload: ArriServerErrorResponse = { +async function sendArriError(event: H3Event, error: arriError, debug: boolean) { + const payload: arriErrorResponse = { code: error.code, message: error.message, data: error.data, diff --git a/languages/ts/ts-server/src/websocketRpc.ts b/languages/ts/ts-server/src/websocketRpc.ts index 20605cf8..942bd174 100644 --- a/languages/ts/ts-server/src/websocketRpc.ts +++ b/languages/ts/ts-server/src/websocketRpc.ts @@ -7,7 +7,7 @@ import { import { type Peer, type WSError } from "crossws"; import { defineWebSocketHandler, type Router } from "h3"; -import { type ArriServerErrorResponse } from "./errors"; +import { type arriErrorResponse } from "./errors"; import { getRpcParamName, getRpcResponseName, @@ -83,7 +83,7 @@ export class WsPeer { return this._peer.send(`event: message\ndata: ${payload}`); } - sendError(err: ArriServerErrorResponse) { + sendError(err: arriErrorResponse) { return this._peer.send(`event: error\ndata: ${JSON.stringify(err)}`); } @@ -104,7 +104,7 @@ export class WsPeer { return; } if (!this._validator.validate(message)) { - const err: ArriServerErrorResponse = { + const err: arriErrorResponse = { code: 500, message: `Error serializing message on server. The payload doesn't match the specified schema.`, data: { @@ -196,7 +196,7 @@ export function registerWebsocketRpc( // } // const data = paramValidator.safeParse(message.text()); // if (!data.success) { - // const errorResponse: ArriServerErrorResponse = { + // const errorResponse: arriErrorResponse = { // code: 400, // message: data.error.message, // data: data.error.errors, diff --git a/playground/go/go.mod b/playground/go/go.mod index caea9021..89c7fd87 100644 --- a/playground/go/go.mod +++ b/playground/go/go.mod @@ -1,17 +1,3 @@ module arri-go-playground go 1.22.5 - -require github.com/shirou/gopsutil/v4 v4.24.9 - -require ( - github.com/ebitengine/purego v0.8.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/google/uuid v1.6.0 - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/sys v0.25.0 // indirect -) diff --git a/playground/go/go.sum b/playground/go/go.sum index f5d8e64d..e69de29b 100644 --- a/playground/go/go.sum +++ b/playground/go/go.sum @@ -1,26 +0,0 @@ -github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE= -github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= -github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/playground/go/main.go b/playground/go/main.go index 038067d3..c0632d76 100644 --- a/playground/go/main.go +++ b/playground/go/main.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" ) func main() { diff --git a/tests/clients/rust/src/test_client.g.rs b/tests/clients/rust/src/test_client.g.rs index 92b3b8c0..51d880b8 100644 --- a/tests/clients/rust/src/test_client.g.rs +++ b/tests/clients/rust/src/test_client.g.rs @@ -6,6 +6,7 @@ deprecated )] use arri_client::{ + arriError, chrono::{DateTime, FixedOffset}, parsed_arri_request, reqwest::{self, Request}, @@ -13,7 +14,7 @@ use arri_client::{ sse::{parsed_arri_sse_request, ArriParsedSseRequestOptions, SseController, SseEvent}, utils::{serialize_date_time, serialize_string}, ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions, - ArriServerError, EmptyArriModel, InternalArriClientConfig, + EmptyArriModel, InternalArriClientConfig, }; use std::collections::{BTreeMap, HashMap}; @@ -60,7 +61,7 @@ impl ArriClientService for TestClientTestsService { } impl TestClientTestsService { - pub async fn empty_params_get_request(&self) -> Result { + pub async fn empty_params_get_request(&self) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -77,7 +78,7 @@ impl TestClientTestsService { ) .await } - pub async fn empty_params_post_request(&self) -> Result { + pub async fn empty_params_post_request(&self) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -97,7 +98,7 @@ impl TestClientTestsService { pub async fn empty_response_get_request( &self, params: DefaultPayload, - ) -> Result<(), ArriServerError> { + ) -> Result<(), arriError> { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -117,7 +118,7 @@ impl TestClientTestsService { pub async fn empty_response_post_request( &self, params: DefaultPayload, - ) -> Result<(), ArriServerError> { + ) -> Result<(), arriError> { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -136,7 +137,7 @@ impl TestClientTestsService { } /// If the target language supports it. Generated code should mark this procedure as deprecated. #[deprecated] - pub async fn deprecated_rpc(&self, params: DeprecatedRpcParams) -> Result<(), ArriServerError> { + pub async fn deprecated_rpc(&self, params: DeprecatedRpcParams) -> Result<(), arriError> { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -150,7 +151,7 @@ impl TestClientTestsService { ) .await } - pub async fn send_error(&self, params: SendErrorParams) -> Result<(), ArriServerError> { + pub async fn send_error(&self, params: SendErrorParams) -> Result<(), arriError> { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -167,7 +168,7 @@ impl TestClientTestsService { pub async fn send_object( &self, params: ObjectWithEveryType, - ) -> Result { + ) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -184,7 +185,7 @@ impl TestClientTestsService { pub async fn send_object_with_nullable_fields( &self, params: ObjectWithEveryNullableType, - ) -> Result { + ) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -204,7 +205,7 @@ impl TestClientTestsService { pub async fn send_partial_object( &self, params: ObjectWithEveryOptionalType, - ) -> Result { + ) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -221,7 +222,7 @@ impl TestClientTestsService { pub async fn send_recursive_object( &self, params: RecursiveObject, - ) -> Result { + ) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, @@ -241,7 +242,7 @@ impl TestClientTestsService { pub async fn send_recursive_union( &self, params: RecursiveUnion, - ) -> Result { + ) -> Result { parsed_arri_request( ArriParsedRequestOptions { http_client: &self._config.http_client, diff --git a/tests/servers/go/go.mod b/tests/servers/go/go.mod index 2b616f1b..8b70d089 100644 --- a/tests/servers/go/go.mod +++ b/tests/servers/go/go.mod @@ -2,4 +2,9 @@ module github.com/modiimedia/arri-go-test-server go 1.22.5 -require gopkg.in/loremipsum.v1 v1.1.2 +require ( + github.com/google/uuid v1.6.0 + gopkg.in/loremipsum.v1 v1.1.2 +) + +require github.com/stretchr/testify v1.9.0 // indirect diff --git a/tests/servers/go/go.sum b/tests/servers/go/go.sum index ffc4430c..93ac7425 100644 --- a/tests/servers/go/go.sum +++ b/tests/servers/go/go.sum @@ -1,2 +1,7 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= gopkg.in/loremipsum.v1 v1.1.2 h1:12APklfJKuGszqZsrArW5QoQh03/W+qyCCjvnDuS6Tw= gopkg.in/loremipsum.v1 v1.1.2/go.mod h1:TuRvzFuzuejXj+odBU6Tubp/EPUyGb9wmSvHenyP2Ts= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/tests/servers/go/main.go b/tests/servers/go/main.go index 95e7861a..b6ec5327 100644 --- a/tests/servers/go/main.go +++ b/tests/servers/go/main.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "arri" + arri "github.com/modiimedia/arri/languages/go/go-server" "github.com/google/uuid" "gopkg.in/loremipsum.v1" diff --git a/tooling/cli/src/commands/init.ts b/tooling/cli/src/commands/init.ts index cb6d68a7..57ee4fc8 100644 --- a/tooling/cli/src/commands/init.ts +++ b/tooling/cli/src/commands/init.ts @@ -1,6 +1,7 @@ import fs, { readFileSync, rmSync, writeFileSync } from "node:fs"; import { kebabCase } from "@arrirpc/codegen-utils"; +import { a } from "@arrirpc/schema"; import { defineCommand } from "citty"; import Degit from "degit"; import enquirer from "enquirer"; @@ -9,6 +10,17 @@ import prettier from "prettier"; import { logger } from "../common"; +const Language = a.enumerator(["typescript", "go"]); +type Language = a.infer; + +const CliArgs = a.object({ + dir: a.string(), + force: a.optional(a.boolean()), + type: a.optional(a.enumerator(["app", "plugin"])), + language: a.optional(Language), +}); +type CliArgs = a.infer; + export default defineCommand({ meta: { name: "Init", @@ -31,20 +43,15 @@ export default defineCommand({ type: "string", description: `"app" | "plugin"`, }, + language: { + type: "string", + alias: ["lang", "l"], + default: `"typescript" | "go"`, + }, }, async run(context) { - let type: "app" | "plugin" | undefined; - switch (context.args.type?.toLowerCase()) { - case "app": - type = "app"; - break; - case "plugin": - type = "plugin"; - break; - default: - break; - } - if (!type) { + const args = a.parse(CliArgs, context.args); + if (!args.type) { const { projectType } = await enquirer.prompt<{ projectType: "application" | "generator plugin"; }>([ @@ -57,10 +64,10 @@ export default defineCommand({ ]); switch (projectType) { case "application": - type = "app"; + args.type = "app"; break; case "generator plugin": - type = "plugin"; + args.type = "plugin"; break; default: throw new Error( @@ -68,11 +75,23 @@ export default defineCommand({ ); } } + if (!args.language) { + const { language } = await enquirer.prompt<{ + language: "typescript" | "go"; + }>([ + { + type: "select", + name: "language", + message: "What language do you want to use?", + choices: ["typescript", "go"], + }, + ]); + args.language = language; + } const dir = path.resolve(context.args.dir); if (!fs.existsSync(dir)) { fs.mkdirSync(dir); } - const dirFiles = fs.readdirSync(dir); if (dirFiles.length && !context.args.force) { logger.error( @@ -80,22 +99,33 @@ export default defineCommand({ ); process.exit(1); } - switch (type) { + switch (args.type) { case "app": - await initApp(context.args.dir, context.args.force); + await initApp(args.dir, args.language, args.force ?? false); break; case "plugin": - await initPlugin(context.args.dir, context.args.force); + await initPlugin(args.dir, args.force ?? false); break; default: - logger.error(`Unknown app type: '${type as any}'"`); + logger.error(`Unknown app type: '${args.type as any}'"`); break; } process.exit(0); }, }); -async function initApp(dir: string, force: boolean) { +async function initApp(dir: string, language: Language, force: boolean) { + switch (language) { + case "typescript": + return initTypescriptApp(dir, force); + case "go": + return initGoApp(dir, force); + default: + language satisfies never; + } +} + +async function initTypescriptApp(dir: string, force: boolean) { const { eslint } = await enquirer.prompt<{ eslint: boolean }>([ { name: "eslint", @@ -116,6 +146,22 @@ async function initApp(dir: string, force: boolean) { force, }); await degit.clone(dir); + await cleanPackageJsonAndPnpmLockFiles(dir); + logger.success(`Project initialized in ${dir}!`); + logger.info(`To get started:\n- cd ${dir}\n- pnpm install\n- pnpm run dev`); +} + +async function initGoApp(dir: string, force: boolean) { + const degit = Degit("modiimedia/arri-starters/app-starter-go", { force }); + await degit.clone(dir); + await cleanPackageJsonAndPnpmLockFiles(dir); + logger.success(`Project created in ${dir}!`); + logger.info( + `To get started:\n- cd ${dir}\n- go mod tidy\n- pnpm install\n- pnpm run dev`, + ); +} + +async function cleanPackageJsonAndPnpmLockFiles(dir: string) { rmSync(path.resolve(dir, "pnpm-lock.yaml")); const packageJson = JSON.parse( readFileSync(path.resolve(dir, "package.json"), { @@ -140,8 +186,6 @@ async function initApp(dir: string, force: boolean) { trailingComma: "all", }), ); - logger.success(`Project initialized in ${dir}!`); - logger.info(`To get started:\n- cd ${dir}\n- pnpm install\n- pnpm run dev`); } async function initPlugin(dir: string, force: boolean) { diff --git a/vitest.workspace.js b/vitest.workspace.js index b62bb907..3eb2e856 100644 --- a/vitest.workspace.js +++ b/vitest.workspace.js @@ -13,5 +13,5 @@ export default defineWorkspace([ "./tooling/jtd-utils/vite.config.ts", "./tooling/schema/vite.config.ts", "./tooling/schema-typebox-adapter/vite.config.ts", - "./tests/clients/client-typescript/vite.config.ts", + "./tests/clients/ts/vite.config.ts", ]);