@crowdedkingdoms/ckx-kit 0.6.0-test.1 → 0.7.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ckx-sdk"
3
- version = "0.13.0-test.1"
3
+ version = "0.14.0-dev.1"
4
4
  edition = "2024"
5
5
  description = "Write ck-exec hubs, spokes and mods for Crowded Kingdoms in Rust, compiled to wasm32-unknown-unknown"
6
6
  license = "MIT OR Apache-2.0"
@@ -73,7 +73,7 @@ pub mod prelude {
73
73
  pub use crate::cron::Cron;
74
74
  pub use crate::emit::{Spatial, actor_id};
75
75
  pub use crate::model::{Model, PropKind, Schema, Viewer, Visibility};
76
- pub use crate::node::{AgeBracket, ChunkPos, GridPick, ReportReason, SafetyReport, VoxelWrite};
76
+ pub use crate::node::{AgeBracket, ChunkPos, ChunkVoxelState, GridPick, ReportReason, SafetyReport, VoxelWrite};
77
77
  pub use crate::{
78
78
  Call, CallError, Caller, Ctx, Error, Hub, Kind, Level, Presence, PresencePlayer, Result, Session, Spoke, Status, TopicMsg,
79
79
  WorldEvent, decode, encode,
@@ -1,7 +1,7 @@
1
1
  //! The platform's bounds on a node: what its sandbox and its checks hold every call, snapshot
2
2
  //! and module to. [`crate::testing`] applies the ones a native test can see.
3
3
 
4
- pub use crate::node::{MAX_CHUNK_STATE, MAX_VOXEL_STATE, MAX_VOXEL_WRITES};
4
+ pub use crate::node::{CHUNK_GRID_BYTES, MAX_CHUNK_STATE, MAX_CHUNK_STATES, MAX_VOXEL_STATE, MAX_VOXEL_WRITE_BYTES, MAX_VOXEL_WRITES};
5
5
  pub use crate::rt::{MAX_TIMERS, MAX_WATCHES, MIN_TIMER_MS};
6
6
 
7
7
  /// The largest payload a node may send in one message, and the largest reply it may return. A
@@ -53,3 +53,17 @@ pub mod mods {
53
53
  /// The node API scopes every mod holds, each confined to its grid.
54
54
  pub const SCOPES: [&str; 3] = ["grids.read", "world.read", "world.write"];
55
55
  }
56
+
57
+ /// What the game API's node API allows an app on each of its replicas. An app's own code and its
58
+ /// players' mods draw on separate buckets, so no player's mod can spend the app's. Past it a call
59
+ /// answers [`crate::Status::RateLimited`]; retry after a moment.
60
+ pub mod node {
61
+ /// Units per second; a bucket holds two seconds' worth for a burst.
62
+ pub const READ_UNITS_PER_SEC: u32 = 200;
63
+ pub const WRITE_UNITS_PER_SEC: u32 = 50;
64
+ pub const BURST_SECONDS: u32 = 2;
65
+ /// Voxels one write unit pays for: a `set_voxels` of 4,096 voxels costs 64 units, and a
66
+ /// `set_chunk` costs one unit plus one per started 64 states. A chunk state costs one unit per
67
+ /// started 4 KiB, and any other call one unit.
68
+ pub const VOXELS_PER_WRITE_UNIT: usize = 64;
69
+ }
@@ -27,10 +27,17 @@ use serde_json::{Value, json};
27
27
 
28
28
  use crate::{CallError, Ctx, Status};
29
29
 
30
- /// Voxel writes in one [`World::set_voxels`] call.
31
- pub const MAX_VOXEL_WRITES: usize = 16;
30
+ /// Voxel writes in one [`World::set_voxels`] call: a whole 16×16×16 chunk's worth.
31
+ pub const MAX_VOXEL_WRITES: usize = 4096;
32
+ /// The voxel states of one [`World::set_voxels`] or [`World::set_chunk`] call together, so the
33
+ /// call stays well under the platform's message limit once encoded.
34
+ pub const MAX_VOXEL_WRITE_BYTES: usize = 2 << 20;
32
35
  /// A voxel's state bytes.
33
36
  pub const MAX_VOXEL_STATE: usize = 1024;
37
+ /// A [`World::set_chunk`] grid: one type byte per voxel of the 16×16×16 chunk.
38
+ pub const CHUNK_GRID_BYTES: usize = 4096;
39
+ /// Voxel states stored with one [`World::set_chunk`].
40
+ pub const MAX_CHUNK_STATES: usize = 4096;
34
41
  /// A chunk's state bytes ([`World::set_chunk_state`]).
35
42
  pub const MAX_CHUNK_STATE: usize = 65_536;
36
43
  /// A safety report's details, in characters as the game API counts them (UTF-16 units).
@@ -92,6 +99,15 @@ pub struct VoxelWrite {
92
99
  pub state: Option<Vec<u8>>,
93
100
  }
94
101
 
102
+ /// One voxel's state stored with a [`World::set_chunk`]: the voxel, its type and its bytes.
103
+ #[derive(Debug, Clone, PartialEq)]
104
+ pub struct ChunkVoxelState {
105
+ /// `(x, y, z)` within the chunk.
106
+ pub voxel: (i16, i16, i16),
107
+ pub voxel_type: i16,
108
+ pub state: Option<Vec<u8>>,
109
+ }
110
+
95
111
  /// A player's actor in the world, from live presence.
96
112
  #[derive(Debug, Clone, PartialEq)]
97
113
  pub struct Actor {
@@ -270,6 +286,21 @@ fn bad_reply(op: &str, e: impl std::fmt::Display) -> CallError {
270
286
  CallError { status: Status::Internal, message: format!("unexpected {op} reply: {e}") }
271
287
  }
272
288
 
289
+ /// Refuses a voxel state over [`MAX_VOXEL_STATE`], or states over [`MAX_VOXEL_WRITE_BYTES`] together.
290
+ fn check_state_bytes<'a>(states: impl Iterator<Item = Option<&'a [u8]>>) -> Result<(), CallError> {
291
+ let mut total = 0usize;
292
+ for s in states.flatten() {
293
+ if s.len() > MAX_VOXEL_STATE {
294
+ return Err(bad_request(format!("a voxel's state is at most {MAX_VOXEL_STATE} bytes")));
295
+ }
296
+ total += s.len();
297
+ }
298
+ if total > MAX_VOXEL_WRITE_BYTES {
299
+ return Err(bad_request(format!("the voxel states of one call are at most {MAX_VOXEL_WRITE_BYTES} bytes together")));
300
+ }
301
+ Ok(())
302
+ }
303
+
273
304
  fn bad_request(message: impl Into<String>) -> CallError {
274
305
  CallError { status: Status::BadRequest, message: message.into() }
275
306
  }
@@ -481,17 +512,17 @@ impl World<'_> {
481
512
  Ok(r.voxels.into_iter().map(Voxel::from).collect())
482
513
  }
483
514
 
484
- /// Writes up to [`MAX_VOXEL_WRITES`] voxels in one transaction, as the app, and shows them
485
- /// to nearby players. Returns the voxel update ids. Scope `world.write`.
515
+ /// Writes up to [`MAX_VOXEL_WRITES`] voxels in one transaction, as the app, and shows each
516
+ /// to nearby players as a voxel update. Their states may hold [`MAX_VOXEL_WRITE_BYTES`]
517
+ /// together. Returns the voxel update ids. A call costs one write per started 64 voxels
518
+ /// ([`crate::limits::node`]). Scope `world.write`.
486
519
  pub fn set_voxels(&self, writes: &[VoxelWrite]) -> Result<Vec<u64>, CallError> {
487
520
  if writes.is_empty() || writes.len() > MAX_VOXEL_WRITES {
488
521
  return Err(bad_request(format!("write 1 to {MAX_VOXEL_WRITES} voxels per call")));
489
522
  }
523
+ check_state_bytes(writes.iter().map(|w| w.state.as_deref()))?;
490
524
  let mut list = Vec::with_capacity(writes.len());
491
525
  for w in writes {
492
- if w.state.as_ref().is_some_and(|s| s.len() > MAX_VOXEL_STATE) {
493
- return Err(bad_request(format!("a voxel's state is at most {MAX_VOXEL_STATE} bytes")));
494
- }
495
526
  list.push(json!({
496
527
  "chunk": w.chunk.json(),
497
528
  "voxel": { "x": w.voxel.0, "y": w.voxel.1, "z": w.voxel.2 },
@@ -508,6 +539,39 @@ impl World<'_> {
508
539
  r.voxel_update_ids.iter().map(|id| id.parse().map_err(|e| bad_reply("world.set_voxels", e))).collect()
509
540
  }
510
541
 
542
+ /// Replaces the chunk at `chunk` with `grid` (one type byte per voxel, index
543
+ /// `x + y*16 + z*256`) and `states`, and drops every voxel written into it before, so it
544
+ /// reads back exactly as written; its own state blob ([`World::set_chunk_state`]) is kept.
545
+ /// Nearby players are told once to read the chunk again rather than sent a voxel update per
546
+ /// voxel, so this is the cheap way to change most of a chunk; the grid's mods hear it as
547
+ /// `voxels`. A call costs one write plus one per started 64 states ([`crate::limits::node`]).
548
+ /// Scope `world.write`; a mod may set chunks only inside its grid, where its owner may edit.
549
+ pub fn set_chunk(&self, chunk: ChunkPos, grid: &[u8], states: &[ChunkVoxelState]) -> Result<(), CallError> {
550
+ if grid.len() != CHUNK_GRID_BYTES {
551
+ return Err(bad_request(format!("a chunk grid is {CHUNK_GRID_BYTES} bytes, one per voxel")));
552
+ }
553
+ if states.len() > MAX_CHUNK_STATES {
554
+ return Err(bad_request(format!("at most {MAX_CHUNK_STATES} voxel states per chunk")));
555
+ }
556
+ check_state_bytes(states.iter().map(|s| s.state.as_deref()))?;
557
+ let list: Vec<Value> = states
558
+ .iter()
559
+ .map(|s| {
560
+ json!({
561
+ "voxel": { "x": s.voxel.0, "y": s.voxel.1, "z": s.voxel.2 },
562
+ "voxelType": s.voxel_type,
563
+ "stateBase64": s.state.as_deref().map(b64),
564
+ })
565
+ })
566
+ .collect();
567
+ let mut body = json!({ "chunk": chunk.json(), "gridBase64": b64(grid) });
568
+ if !list.is_empty() {
569
+ body["states"] = Value::Array(list);
570
+ }
571
+ let _: Value = op(self.0, "world.set_chunk", body)?;
572
+ Ok(())
573
+ }
574
+
511
575
  /// Replaces the chunk's own state blob, the one [`Chunk::chunk_state`] reads (at most
512
576
  /// [`MAX_CHUNK_STATE`] bytes; `None` clears it). Scope `world.write`.
513
577
  pub fn set_chunk_state(&self, chunk: ChunkPos, state: Option<&[u8]>) -> Result<(), CallError> {
@@ -1042,6 +1106,50 @@ mod tests {
1042
1106
  assert_eq!(refused_here(|c| c.world().set_voxels(&[big])).status, Status::BadRequest);
1043
1107
  }
1044
1108
 
1109
+ #[test]
1110
+ fn a_whole_chunk_of_voxels_fits_one_set_voxels_and_the_states_share_a_cap() {
1111
+ let at = |i: usize| VoxelWrite {
1112
+ chunk: ChunkPos::new(0, 0, 0),
1113
+ voxel: ((i % 16) as i16, (i / 16 % 16) as i16, (i / 256) as i16),
1114
+ voxel_type: 1,
1115
+ state: None,
1116
+ };
1117
+ let all: Vec<VoxelWrite> = (0..MAX_VOXEL_WRITES).map(at).collect();
1118
+ let ids: Vec<String> = (0..MAX_VOXEL_WRITES).map(|i| i.to_string()).collect();
1119
+ let (got, _, _) = exchange(json!({ "voxelUpdateIds": ids }), |c| c.world().set_voxels(&all));
1120
+ assert_eq!(got.unwrap().len(), MAX_VOXEL_WRITES);
1121
+ let one_more: Vec<VoxelWrite> = (0..=MAX_VOXEL_WRITES).map(at).collect();
1122
+ assert_eq!(refused_here(|c| c.world().set_voxels(&one_more)).status, Status::BadRequest);
1123
+ // 2,049 states of 1,024 bytes pass the shared 2 MiB.
1124
+ let heavy: Vec<VoxelWrite> = (0..2049).map(|i| VoxelWrite { state: Some(vec![0; MAX_VOXEL_STATE]), ..at(i) }).collect();
1125
+ assert_eq!(refused_here(|c| c.world().set_voxels(&heavy)).status, Status::BadRequest);
1126
+ }
1127
+
1128
+ #[test]
1129
+ fn set_chunk_sends_the_grid_and_its_states() {
1130
+ let grid = vec![3u8; CHUNK_GRID_BYTES];
1131
+ let states = vec![ChunkVoxelState { voxel: (1, 2, 3), voxel_type: -4, state: Some(vec![9]) }];
1132
+ let (got, name, body) = exchange(json!({ "updatedAt": "t" }), |c| c.world().set_chunk(ChunkPos::new(7, 0, -2), &grid, &states));
1133
+ got.unwrap();
1134
+ assert_eq!(name, "world.set_chunk");
1135
+ assert_eq!(body["chunk"], pos(7, 0, -2));
1136
+ assert_eq!(B64.decode(body["gridBase64"].as_str().unwrap()).unwrap(), grid);
1137
+ assert_eq!(body["states"], json!([{ "voxel": { "x": 1, "y": 2, "z": 3 }, "voxelType": -4, "stateBase64": "CQ==" }]));
1138
+ let (_, _, bare) = exchange(json!({ "updatedAt": "t" }), |c| c.world().set_chunk(ChunkPos::default(), &grid, &[]));
1139
+ assert!(bare.get("states").is_none(), "no states, no list");
1140
+ }
1141
+
1142
+ #[test]
1143
+ fn set_chunk_refuses_a_wrong_grid_or_too_many_states_before_sending() {
1144
+ let short = vec![0u8; CHUNK_GRID_BYTES - 1];
1145
+ assert_eq!(refused_here(|c| c.world().set_chunk(ChunkPos::default(), &short, &[])).status, Status::BadRequest);
1146
+ let grid = vec![0u8; CHUNK_GRID_BYTES];
1147
+ let many = vec![ChunkVoxelState { voxel: (0, 0, 0), voxel_type: 1, state: None }; MAX_CHUNK_STATES + 1];
1148
+ assert_eq!(refused_here(|c| c.world().set_chunk(ChunkPos::default(), &grid, &many)).status, Status::BadRequest);
1149
+ let big = vec![ChunkVoxelState { voxel: (0, 0, 0), voxel_type: 1, state: Some(vec![0; MAX_VOXEL_STATE + 1]) }];
1150
+ assert_eq!(refused_here(|c| c.world().set_chunk(ChunkPos::default(), &grid, &big)).status, Status::BadRequest);
1151
+ }
1152
+
1045
1153
  #[test]
1046
1154
  fn a_chunk_state_is_set_or_cleared_within_its_cap() {
1047
1155
  let (got, name, body) = exchange(json!({ "updatedAt": "2026-10-09T12:00:00.000Z" }), |c| {
@@ -847,11 +847,19 @@ pub fn player_payload(player: u64) -> crate::Result<Vec<u8>> {
847
847
  // ---- the node API, as it serves a mod ----
848
848
 
849
849
  /// The node API operations a mod may call.
850
- const MOD_OPS: [&str; 7] =
851
- ["world.chunk", "world.voxels", "world.actors", "world.actors_radius", "world.set_voxels", "grids.get", "grids.check_permission"];
850
+ const MOD_OPS: [&str; 8] = [
851
+ "world.chunk",
852
+ "world.voxels",
853
+ "world.actors",
854
+ "world.actors_radius",
855
+ "world.set_voxels",
856
+ "world.set_chunk",
857
+ "grids.get",
858
+ "grids.check_permission",
859
+ ];
852
860
 
853
861
  /// Each node API operation and the scope it needs.
854
- const OP_SCOPES: [(&str, &str); 29] = [
862
+ const OP_SCOPES: [(&str, &str); 30] = [
855
863
  ("players.get", "players.read"),
856
864
  ("players.features", "players.read"),
857
865
  ("players.check_permission", "players.read"),
@@ -864,6 +872,7 @@ const OP_SCOPES: [(&str, &str); 29] = [
864
872
  ("world.actors", "world.read"),
865
873
  ("world.actors_radius", "world.read"),
866
874
  ("world.set_voxels", "world.write"),
875
+ ("world.set_chunk", "world.write"),
867
876
  ("world.set_chunk_state", "world.write"),
868
877
  ("grids.get", "grids.read"),
869
878
  ("grids.check_permission", "grids.read"),
@@ -998,10 +1007,11 @@ struct FakeChunk {
998
1007
 
999
1008
  /// A mod's grid as the node API serves it to the mod: the box, its owner, the chunks and
1000
1009
  /// voxels in it, the actors there and its permissions, under the node API's rules for mods.
1001
- /// A mod calls seven operations (`world.chunk`, `world.voxels`, `world.actors`,
1002
- /// `world.actors_radius`, `world.set_voxels`, `grids.get`, `grids.check_permission`), only
1003
- /// inside its grid; writes voxels only where its owner may edit them; and is refused
1004
- /// everything once its owner no longer owns the grid. A refusal reads as the game API's.
1010
+ /// A mod calls eight operations (`world.chunk`, `world.voxels`, `world.actors`,
1011
+ /// `world.actors_radius`, `world.set_voxels`, `world.set_chunk`, `grids.get`,
1012
+ /// `grids.check_permission`), only inside its grid; writes voxels and chunks only where its
1013
+ /// owner may edit them; and is refused everything once its owner no longer owns the grid. A
1014
+ /// refusal reads as the game API's.
1005
1015
  #[derive(Debug, Clone)]
1006
1016
  pub struct FakeGrid {
1007
1017
  id: u64,
@@ -1223,6 +1233,11 @@ impl FakeGrid {
1223
1233
  return Err(refusal(403, &format!("the capability lacks scope {scope}")));
1224
1234
  }
1225
1235
  let writes = if op == "world.set_voxels" { voxel_writes(body)? } else { Vec::new() };
1236
+ let (states, grid) = if op == "world.set_chunk" {
1237
+ (chunk_states(body)?, base64_bytes(body.get("gridBase64"), "gridBase64", crate::node::CHUNK_GRID_BYTES)?)
1238
+ } else {
1239
+ (Vec::new(), None)
1240
+ };
1226
1241
  if op == "world.set_chunk_state" {
1227
1242
  base64_bytes(body.get("stateBase64"), "stateBase64", crate::node::MAX_CHUNK_STATE)?;
1228
1243
  }
@@ -1289,6 +1304,49 @@ impl FakeGrid {
1289
1304
  }
1290
1305
  Ok(json!({ "voxelUpdateIds": ids }))
1291
1306
  }
1307
+ "world.set_chunk" => {
1308
+ let at = chunk_pos(body.get("chunk"), "chunk")?;
1309
+ self.inside(at, 0, 0)?;
1310
+ if self.closed.contains(&key(at)) {
1311
+ return Err(refusal(
1312
+ 403,
1313
+ &format!(
1314
+ "the mod's owner may not edit voxels at chunk ({}, {}, {}): the most specific grid there does not grant them 'update_voxel_data'",
1315
+ at.x, at.y, at.z
1316
+ ),
1317
+ ));
1318
+ }
1319
+ let grid = grid.ok_or_else(|| {
1320
+ refusal(400, &format!("gridBase64 must hold the chunk's {} voxel bytes", crate::node::CHUNK_GRID_BYTES))
1321
+ })?;
1322
+ if grid.len() != crate::node::CHUNK_GRID_BYTES {
1323
+ return Err(refusal(400, &format!("a chunk grid is {} bytes, one per voxel", crate::node::CHUNK_GRID_BYTES)));
1324
+ }
1325
+ let next_id = self.next_update;
1326
+ let chunk = self.chunks.entry(key(at)).or_default();
1327
+ let (id, chunk_state) = match &chunk.stored {
1328
+ Some(c) => (c.id, c.chunk_state.clone()),
1329
+ None => (next_id, None),
1330
+ };
1331
+ if chunk.stored.is_none() {
1332
+ self.next_update += 1;
1333
+ }
1334
+ chunk.stored = Some(Chunk { id, at, voxels: Some(grid), chunk_state });
1335
+ chunk.edits.clear();
1336
+ for s in states {
1337
+ let voxel = Voxel {
1338
+ x: s.voxel.0,
1339
+ y: s.voxel.1,
1340
+ z: s.voxel.2,
1341
+ voxel_type: s.voxel_type,
1342
+ state: s.state,
1343
+ created_by: Some("0".to_owned()),
1344
+ updated_at: Some(rfc3339(now)),
1345
+ };
1346
+ chunk.edits.insert((voxel.y, voxel.x, voxel.z), voxel);
1347
+ }
1348
+ Ok(json!({ "updatedAt": rfc3339(now) }))
1349
+ }
1292
1350
  "grids.get" => {
1293
1351
  self.own_grid(body)?;
1294
1352
  Ok(json!({ "grid": self.grid_json() }))
@@ -1331,6 +1389,32 @@ fn voxel_writes(body: &Value) -> Result<Vec<Write>, CallError> {
1331
1389
  .collect()
1332
1390
  }
1333
1391
 
1392
+ struct StateWrite {
1393
+ voxel: (i16, i16, i16),
1394
+ voxel_type: i16,
1395
+ state: Option<Vec<u8>>,
1396
+ }
1397
+
1398
+ fn chunk_states(body: &Value) -> Result<Vec<StateWrite>, CallError> {
1399
+ let max = crate::node::MAX_CHUNK_STATES;
1400
+ let list = match body.get("states") {
1401
+ None | Some(Value::Null) => return Ok(Vec::new()),
1402
+ Some(Value::Array(l)) if l.len() <= max => l,
1403
+ Some(_) => return Err(refusal(400, &format!("states must list at most {max} voxel states"))),
1404
+ };
1405
+ let axis = |v: &Value, i: usize, k: &str| int_in(v.get(k), &format!("states[{i}].voxel.{k}"), i16::MIN.into(), i16::MAX.into());
1406
+ list.iter()
1407
+ .enumerate()
1408
+ .map(|(i, s)| {
1409
+ let v = s.get("voxel").unwrap_or(&Value::Null);
1410
+ let voxel = (axis(v, i, "x")? as i16, axis(v, i, "y")? as i16, axis(v, i, "z")? as i16);
1411
+ let voxel_type = int_in(s.get("voxelType"), &format!("states[{i}].voxelType"), i16::MIN.into(), i16::MAX.into())? as i16;
1412
+ let state = base64_bytes(s.get("stateBase64"), &format!("states[{i}].stateBase64"), crate::node::MAX_VOXEL_STATE)?;
1413
+ Ok(StateWrite { voxel, voxel_type, state })
1414
+ })
1415
+ .collect()
1416
+ }
1417
+
1334
1418
  #[cfg(test)]
1335
1419
  mod tests {
1336
1420
  use super::*;
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "crowdy-client-sdk"
3
- version = "0.1.0-test.1"
3
+ version = "0.1.0-dev.1"
4
4
  edition = "2021"
5
5
  description = "Guest SDK for the CLIENT half of a ck-exec mod: browser WASM (ck ABI v0 + the client host calls)."
6
6
  license = "MIT OR Apache-2.0"
package/kit.pin CHANGED
@@ -1,9 +1,9 @@
1
1
  # The platform toolchain release this kit was copied from (sync-kit.sh in the platform's
2
2
  # repository). The paths in `copied` are byte-identical to it: change them there, never here.
3
- toolchain_version=v1.16.0
4
- toolchain_commit=9423aa5f66b5480f2aa19110b6888d3e04c4534d
5
- sdk_commit=27d5774d7b9d3b3c28928ad1a4d27902ac5130e1
6
- ckx_sdk_version=0.13.0
3
+ toolchain_version=v1.17.0
4
+ toolchain_commit=a3c5049209c6633e0f65480eafe3be4a40530a32
5
+ sdk_commit=cc5b85b2adfc1214bf8e61a24f3d0ac7e0cedc6d
6
+ ckx_sdk_version=0.14.0
7
7
  crowdy_client_sdk_version=0.1.0
8
8
  rust_version=1.97.1
9
9
  copied=crates/ckx-sdk/src crates/crowdy-client-sdk/src tools/instrument/Cargo.toml tools/instrument/Cargo.lock tools/instrument/src checks/src/build/exec-source.ts checks/src/build/exec-source.spec.ts checks/src/build/rust-source-guard.ts checks/src/build/rust-source-guard.spec.ts checks/src/build/wasm-inspect.ts checks/src/build/wasm-inspect.spec.ts checks/src/build/client-capabilities.ts checks/src/build/client-capabilities.spec.ts checks/src/test-support/wasm-module.ts checks/compute-toolchain/host-catalog.json starters rust-toolchain.toml vendor.lock
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdedkingdoms/ckx-kit",
3
- "version": "0.6.0-test.1",
3
+ "version": "0.7.0-dev.1",
4
4
  "description": "Build, check and test Crowded Kingdoms ck-exec mods, hubs and spokes on your machine, as the platform builds them",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "homepage": "https://docs.crowdedkingdoms.com/exec/intro",
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,5 +9,5 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,5 +9,5 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,5 +9,5 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"
@@ -9,6 +9,6 @@ publish = false
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- ckx-sdk = "0.13.0"
12
+ ckx-sdk = "0.14.0"
13
13
  serde = { version = "1", features = ["derive"] }
14
14
  serde_json = "1"