Trading card city builder game?

made some parts work and then getting tired mid way so heres more broken stuff

+298 -12
+1
Justfile
··· 65 65 66 66 [group: "release"] 67 67 build: 68 + cd api && gleam build --target javascript 68 69 npx svelte-kit sync 69 70 npx vite build 70 71
+25
api/package.json
··· 1 + { 2 + "name": "cartography-api", 3 + "version": "0.0.1", 4 + "description": "Cartography API", 5 + "private": true, 6 + "directories": { 7 + "lib": "./build/dev/javascript" 8 + }, 9 + "exports": { 10 + "./coder": { 11 + "import": "./build/dev/javascript/cartography_api/coder.mjs", 12 + "types": "./build/dev/javascript/cartography_api/coder.d.ts" 13 + }, 14 + "./request": { 15 + "import": "./build/dev/javascript/cartography_api/request.mjs", 16 + "types": "./build/dev/javascript/cartography_api/request.d.ts" 17 + }, 18 + "./response": { 19 + "import": "./build/dev/javascript/cartography_api/response.mjs", 20 + "types": "./build/dev/javascript/cartography_api/response.d.ts" 21 + } 22 + }, 23 + "author": "Cameron Eldridge <cameldridge@gmail.com>", 24 + "license": "ISC" 25 + }
+6 -3
api/src/codec.gleam
··· 7 7 } 8 8 9 9 pub opaque type Codec(from, to, from_error, to_error) { 10 - Codec(from_coder: Coder(from, from_error), to_coder: Coder(to, to_error)) 10 + Codec( 11 + from_coder: Coder(from, from_error, from_error), 12 + to_coder: Coder(to, to_error, to_error), 13 + ) 11 14 } 12 15 13 16 pub fn codec( 14 - from from_coder: Coder(from, from_error), 15 - to to_coder: Coder(to, to_error), 17 + from from_coder: Coder(from, from_error, from_error), 18 + to to_coder: Coder(to, to_error, to_error), 16 19 ) -> Codec(from, to, from_error, to_error) { 17 20 Codec(from_coder:, to_coder:) 18 21 }
+174 -8
api/src/coder.gleam
··· 1 1 import codable.{type Codable} 2 2 import gleam/bit_array 3 - import gleam/dict 3 + import gleam/dict.{type Dict} 4 4 import gleam/dynamic/decode 5 5 import gleam/function 6 6 import gleam/json.{type Json} as gleam_json 7 7 import gleam/list 8 8 import gleam/option 9 9 import gleam/result 10 + @target(erlang) 10 11 import glepack/data as glepack_data 12 + @target(erlang) 11 13 import glepack/decode as glepack_decode 14 + @target(erlang) 12 15 import glepack/encode as glepack_encode 13 16 import glepack/error as glepack_error 14 17 15 - pub opaque type Coder(encoding, err) { 18 + pub opaque type Coder(encoding, encode_err, decode_err) { 16 19 Coder( 17 - encode: fn(Codable) -> Result(encoding, err), 18 - decode: fn(encoding) -> Result(Codable, err), 20 + encode: fn(Codable) -> Result(encoding, encode_err), 21 + decode: fn(encoding) -> Result(Codable, decode_err), 19 22 ) 20 23 } 21 24 22 25 pub fn encode( 23 26 data: Codable, 24 - codec: Coder(encoding, err), 25 - ) -> Result(encoding, err) { 27 + codec: Coder(encoding, encode_err, decode_err), 28 + ) -> Result(encoding, encode_err) { 26 29 codec.encode(data) 27 30 } 28 31 29 32 pub fn decode( 30 33 data: encoding, 31 - codec: Coder(encoding, err), 32 - ) -> Result(Codable, err) { 34 + codec: Coder(encoding, encode_err, decode_err), 35 + ) -> Result(Codable, decode_err) { 33 36 codec.decode(data) 34 37 } 35 38 39 + pub opaque type EnumEncoderBuilder(t, ee, de) { 40 + EnumEncoderBuilder(cases: List(VariantCoder(t, ee, de)), error: ee) 41 + } 42 + 43 + pub opaque type VariantCoder(t, ee, de) { 44 + VariantCoder(tag: String, coder: Coder(t, ee, de)) 45 + } 46 + 47 + pub type EncoderError(e) { 48 + ExpectedNil 49 + ExpectedBool 50 + ExpectedInt 51 + ExpectedFloat 52 + ExpectedString 53 + ExpectedBinary 54 + ExpectedList 55 + ExpectedStruct 56 + ListEncoderError(e) 57 + StructEncoderError(String, e) 58 + StructVariantError(e) 59 + } 60 + 61 + pub type Bijection(t, u) { 62 + Bijection(from: fn(t) -> u, to: fn(u) -> t) 63 + } 64 + 65 + pub fn map(coder: Coder(t, ee, de), bimap: Bijection(t, u)) -> Coder(u, ee, de) { 66 + Coder( 67 + encode: fn(codable) { 68 + use value <- result.map(coder.encode(codable)) 69 + bimap.from(value) 70 + }, 71 + decode: fn(value) { coder.decode(bimap.to(value)) }, 72 + ) 73 + } 74 + 75 + pub fn nil(codable: Codable) -> Result(Nil, EncoderError(e)) { 76 + case codable { 77 + codable.Nil -> Ok(Nil) 78 + _ -> Error(ExpectedNil) 79 + } 80 + } 81 + 82 + pub fn bool(codable: Codable) -> Result(Bool, EncoderError(e)) { 83 + case codable { 84 + codable.Bool(value) -> Ok(value) 85 + _ -> Error(ExpectedBool) 86 + } 87 + } 88 + 89 + pub fn int(codable: Codable) -> Result(Int, EncoderError(e)) { 90 + case codable { 91 + codable.Int(value) -> Ok(value) 92 + _ -> Error(ExpectedInt) 93 + } 94 + } 95 + 96 + pub fn float(codable: Codable) -> Result(Float, EncoderError(e)) { 97 + case codable { 98 + codable.Float(value) -> Ok(value) 99 + _ -> Error(ExpectedFloat) 100 + } 101 + } 102 + 103 + pub fn string(codable: Codable) -> Result(Float, EncoderError(e)) { 104 + case codable { 105 + codable.Float(value) -> Ok(value) 106 + _ -> Error(ExpectedString) 107 + } 108 + } 109 + 110 + pub fn binary(codable: Codable) -> Result(BitArray, EncoderError(e)) { 111 + case codable { 112 + codable.Binary(value) -> Ok(value) 113 + _ -> Error(ExpectedBinary) 114 + } 115 + } 116 + 117 + pub fn list(coder: Coder(t, ee, de)) { 118 + fn(codable: Codable) -> Result(List(t), EncoderError(ee)) { 119 + case codable { 120 + codable.List(value) -> 121 + list.map(value, coder.encode) 122 + |> result.all() 123 + |> result.map_error(ListEncoderError) 124 + _ -> Error(ExpectedList) 125 + } 126 + } 127 + } 128 + 129 + pub fn record(coder: Coder(t, ee, de)) { 130 + fn(codable: Codable) -> Result(Dict(String, t), EncoderError(ee)) { 131 + case codable { 132 + codable.Record(value) -> 133 + dict.to_list(value) 134 + |> list.map(fn(kv) { 135 + let #(k, v) = kv 136 + use v <- result.map(coder.encode(v)) 137 + #(k, v) 138 + }) 139 + |> result.all() 140 + |> result.map(dict.from_list) 141 + |> result.map_error(ListEncoderError) 142 + _ -> Error(ExpectedList) 143 + } 144 + } 145 + } 146 + 147 + pub fn enum(error: ee) -> EnumEncoderBuilder(t, ee, de) { 148 + EnumEncoderBuilder(cases: [], error:) 149 + } 150 + 151 + pub fn variant( 152 + enum_encoder: EnumEncoderBuilder(t, ee, de), 153 + tag: String, 154 + coder: Coder(t, ee, de), 155 + ) -> EnumEncoderBuilder(t, ee, de) { 156 + EnumEncoderBuilder(..enum_encoder, cases: [ 157 + VariantCoder(tag, coder), 158 + ..enum_encoder.cases 159 + ]) 160 + } 161 + 162 + fn encode_variant( 163 + tag: String, 164 + payload: Codable, 165 + cases: List(VariantCoder(t, ee, de)), 166 + error: ee, 167 + ) -> Result(t, EncoderError(ee)) { 168 + case cases { 169 + [] -> Error(StructVariantError(error)) 170 + [VariantCoder(case_tag, coder), ..cases] -> { 171 + case case_tag == tag { 172 + True -> 173 + coder.encode(payload) 174 + |> result.map_error(fn(error) { StructEncoderError(tag, error) }) 175 + False -> encode_variant(tag, payload, cases, error) 176 + } 177 + } 178 + } 179 + } 180 + 181 + pub fn encode_with( 182 + enum_encoder: EnumEncoderBuilder(t, ee, de), 183 + decoder: fn(t) -> Result(Codable, de), 184 + ) -> Coder(t, EncoderError(ee), de) { 185 + Coder( 186 + encode: fn(input) { 187 + case input { 188 + codable.Struct(tag, payload) -> 189 + encode_variant(tag, payload, enum_encoder.cases, enum_encoder.error) 190 + _ -> Error(ExpectedStruct) 191 + } 192 + }, 193 + decode: decoder, 194 + ) 195 + } 196 + 36 197 pub type JsonError { 37 198 JsonError(gleam_json.DecodeError) 38 199 } ··· 133 294 UnknownExtension(Int) 134 295 } 135 296 297 + @target(erlang) 136 298 pub const messagepack = Coder( 137 299 encode: encode_messagepack, 138 300 decode: decode_messagepack, 139 301 ) 140 302 303 + @target(erlang) 141 304 fn codable_to_messagepack(codable: Codable) -> glepack_data.Value { 142 305 case codable { 143 306 codable.Nil -> glepack_data.Nil ··· 165 328 } 166 329 } 167 330 331 + @target(erlang) 168 332 fn messagepack_to_codable( 169 333 value: glepack_data.Value, 170 334 ) -> Result(Codable, MessagePackError) { ··· 211 375 } 212 376 } 213 377 378 + @target(erlang) 214 379 fn encode_messagepack(codable: Codable) -> Result(BitArray, MessagePackError) { 215 380 let assert Ok(bits) = 216 381 codable_to_messagepack(codable) ··· 218 383 Ok(bits) 219 384 } 220 385 386 + @target(erlang) 221 387 fn decode_messagepack(bit_array: BitArray) -> Result(Codable, MessagePackError) { 222 388 use #(value, trailer) <- result.try( 223 389 glepack_decode.value(bit_array) |> result.map_error(MessagePackError),
+25
api/src/request.gleam
··· 1 + import codable 2 + import coder 3 + 1 4 pub opaque type Request { 2 5 Authenticate(auth_token: String) 3 6 DebugAddCard(card_id: String) 7 + } 8 + 9 + pub type Error { 10 + InvalidTag 11 + } 12 + 13 + fn authenticate_coder() -> coder.Coder(Request, Error) { 14 + coder.map(coder.string, coder.Bijection(from: Authenticate)) 15 + } 16 + 17 + pub fn coder() -> coder.Coder(Request, Error) { 18 + coder.enum(InvalidTag) 19 + |> coder.variant("Authenticate", authenticate_coder()) 20 + |> coder.variant("DebugAddCard", debug_add_card_coder()) 21 + |> coder.encode_with(fn(request) { 22 + Ok(case request { 23 + Authenticate(auth_token) -> 24 + codable.Struct("Authenticate", codable.String(auth_token)) 25 + DebugAddCard(card_id) -> 26 + codable.Struct("DebugAddCard", codable.String(card_id)) 27 + }) 28 + }) 4 29 } 5 30 6 31 pub fn authenticate(auth_token: String) -> Request {
+42
api/tsconfig.json
··· 1 + { 2 + // Visit https://aka.ms/tsconfig to read more about this file 3 + "compilerOptions": { 4 + "noEmit": true, 5 + "outDir": "./build/dev/javascript/", 6 + 7 + // Environment Settings 8 + // See also https://aka.ms/tsconfig/module 9 + "module": "nodenext", 10 + "target": "esnext", 11 + "types": [], 12 + // For nodejs: 13 + // "lib": ["esnext"], 14 + // "types": ["node"], 15 + // and npm install -D @types/node 16 + 17 + // Other Outputs 18 + "sourceMap": true, 19 + "declaration": true, 20 + "declarationMap": true, 21 + 22 + // Stricter Typechecking Options 23 + "noUncheckedIndexedAccess": true, 24 + "exactOptionalPropertyTypes": true, 25 + 26 + // Style Options 27 + // "noImplicitReturns": true, 28 + // "noImplicitOverride": true, 29 + // "noUnusedLocals": true, 30 + // "noUnusedParameters": true, 31 + // "noFallthroughCasesInSwitch": true, 32 + // "noPropertyAccessFromIndexSignature": true, 33 + 34 + // Recommended Options 35 + "strict": true, 36 + "verbatimModuleSyntax": true, 37 + "isolatedModules": true, 38 + "noUncheckedSideEffectImports": true, 39 + "moduleDetection": "force", 40 + "skipLibCheck": true, 41 + } 42 + }
+16
package-lock.json
··· 8 8 "name": "cartography", 9 9 "version": "0.1.0", 10 10 "dependencies": { 11 + "cartography-api": "file:./api", 11 12 "core-js": "^3.38.1", 12 13 "seedrandom": "^3.0.5" 13 14 }, ··· 40 41 "node": "22.21.1", 41 42 "npm": "10.9.4" 42 43 } 44 + }, 45 + "../../../../api": { 46 + "extraneous": true 47 + }, 48 + "../../../../api/package.json": { 49 + "extraneous": true 50 + }, 51 + "api": { 52 + "name": "cartography-api", 53 + "version": "0.0.1", 54 + "license": "ISC" 43 55 }, 44 56 "node_modules/@esbuild/aix-ppc64": { 45 57 "version": "0.27.2", ··· 1895 1907 "engines": { 1896 1908 "node": ">=0.10.0" 1897 1909 } 1910 + }, 1911 + "node_modules/cartography-api": { 1912 + "resolved": "api", 1913 + "link": true 1898 1914 }, 1899 1915 "node_modules/chalk": { 1900 1916 "version": "4.1.2",
+2 -1
package.json
··· 33 33 "type": "module", 34 34 "dependencies": { 35 35 "core-js": "^3.38.1", 36 - "seedrandom": "^3.0.5" 36 + "seedrandom": "^3.0.5", 37 + "cartography-api": "file:./api" 37 38 }, 38 39 "engines": { 39 40 "node": "22.21.1",
+4
src/lib/appserver/socket/Message.ts
··· 5 5 import type { FieldTile } from "../FieldTile"; 6 6 import type { Card } from "../Card"; 7 7 8 + import { type Request$ } from "cartography-api/request"; 9 + 10 + let t: Request$["constructor"]["name"]; 11 + 8 12 export interface MessageReplyMap { 9 13 auth: AccountMessage; 10 14 get_fields: FieldsMessage;
+1
src/lib/appserver/socket/SocketV1.ts
··· 5 5 import type { Message, MessageReplyMap } from "./Message"; 6 6 import { ReactiveEventTarget } from "$lib/ReactiveEventTarget.svelte"; 7 7 import type { FieldId } from "../Field"; 8 + import { type Request$ } from "cartography-api/request"; 8 9 9 10 interface SocketV1EventMap { 10 11 message: MessageEvent;
+2
tsconfig.json
··· 1 1 { 2 2 "extends": "./.svelte-kit/tsconfig.json", 3 + "references": [{ "path": "./api" }], 3 4 "compilerOptions": { 5 + "composite": true, 4 6 "allowJs": true, 5 7 "checkJs": true, 6 8 "esModuleInterop": true,