Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.1.0-alpha.3"
".": "0.1.0-alpha.4"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 13
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-92d29637c0ceda06c752ad70b078ff8dad505843c16b923130774376890baaa5.yml
openapi_spec_hash: 1f20f7d76aa5575ee0601ece537af956
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-899f22ed979e4df6977752fc5de114b92954d5f7499c032fc6aaa58fabd49862.yml
openapi_spec_hash: 95300d446039582ec24c2997bf975ad2
config_hash: cf202573c712b5d91a4d496f35f0ff57
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## 0.1.0-alpha.4 (2025-11-07)

Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/sfcompute/nodes-go/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)

### Features

* **api:** api update ([1342c39](https://github.com/sfcompute/nodes-go/commit/1342c3989b487bd7725ab95ba720c7da200c6899))
* **api:** api update ([02e6349](https://github.com/sfcompute/nodes-go/commit/02e6349b1823ed96fecf3353231e32b00ef3989b))
* **api:** api update ([26ba165](https://github.com/sfcompute/nodes-go/commit/26ba165c4e22a00f69c89f53edf7b0445057594f))


### Chores

* **internal:** codegen related update ([766d0aa](https://github.com/sfcompute/nodes-go/commit/766d0aaf277f7c0733d15ba33111d5e9519660a8))
* **internal:** grammar fix (it's -> its) ([1a198ba](https://github.com/sfcompute/nodes-go/commit/1a198bad6aa4689cecfaccec1953310a60a1a47c))

## 0.1.0-alpha.3 (2025-10-13)

Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/sfcompute/nodes-go/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/sfcompute/[email protected].3'
go get -u 'github.com/sfcompute/[email protected].4'
```

<!-- x-release-please-end -->
Expand Down Expand Up @@ -125,7 +125,7 @@ custom := param.Override[sfcnodes.FooParams](12)

### Request unions

Unions are represented as a struct with fields prefixed by "Of" for each of it's variants,
Unions are represented as a struct with fields prefixed by "Of" for each of its variants,
only one field can be non-zero. The non-zero field will be serialized.

Sub-properties of the union can be accessed via methods on the union struct.
Expand Down
14 changes: 7 additions & 7 deletions internal/apijson/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import (

var encoders sync.Map // map[encoderEntry]encoderFunc

// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
// special characters that sjson interprets as a path.
var EscapeSJSONKey = strings.NewReplacer("\\", "\\\\", "|", "\\|", "#", "\\#", "@", "\\@", "*", "\\*", ".", "\\.", ":", "\\:", "?", "\\?").Replace

func Marshal(value any) ([]byte, error) {
e := &encoder{dateFormat: time.RFC3339}
return e.marshal(value)
Expand Down Expand Up @@ -270,7 +274,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
if encoded == nil {
continue
}
json, err = sjson.SetRawBytes(json, ef.tag.name, encoded)
json, err = sjson.SetRawBytes(json, EscapeSJSONKey(ef.tag.name), encoded)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -348,7 +352,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error)
}
encodedKeyString = string(encodedKeyBytes)
}
encodedKey := []byte(sjsonReplacer.Replace(encodedKeyString))
encodedKey := []byte(encodedKeyString)
pairs = append(pairs, mapPair{key: encodedKey, value: iter.Value()})
}

Expand All @@ -366,7 +370,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error)
if len(encodedValue) == 0 {
continue
}
json, err = sjson.SetRawBytes(json, string(p.key), encodedValue)
json, err = sjson.SetRawBytes(json, EscapeSJSONKey(string(p.key)), encodedValue)
if err != nil {
return nil, err
}
Expand All @@ -386,7 +390,3 @@ func (e *encoder) newMapEncoder(_ reflect.Type) encoderFunc {
return json, nil
}
}

// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
// special characters that sjson interprets as a path.
var sjsonReplacer *strings.Replacer = strings.NewReplacer(".", "\\.", ":", "\\:", "*", "\\*")
4 changes: 2 additions & 2 deletions internal/apijson/union.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (d *decoderBuilder) newStructUnionDecoder(t reflect.Type) decoderFunc {

return func(n gjson.Result, v reflect.Value, state *decoderState) error {
if discriminated && n.Type == gjson.JSON && len(unionEntry.discriminatorKey) != 0 {
discriminator := n.Get(unionEntry.discriminatorKey).Value()
discriminator := n.Get(EscapeSJSONKey(unionEntry.discriminatorKey)).Value()
for _, decoder := range discriminatedDecoders {
if discriminator == decoder.discriminator {
inner := v.FieldByIndex(decoder.field.Index)
Expand Down Expand Up @@ -162,7 +162,7 @@ func (d *decoderBuilder) newUnionDecoder(t reflect.Type) decoderFunc {
}

if len(unionEntry.discriminatorKey) != 0 {
discriminatorValue := n.Get(unionEntry.discriminatorKey).Value()
discriminatorValue := n.Get(EscapeSJSONKey(unionEntry.discriminatorKey)).Value()
if discriminatorValue == variant.DiscriminatorValue {
inner := reflect.New(variant.Type).Elem()
err := decoder(n, inner, state)
Expand Down
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package internal

const PackageVersion = "0.1.0-alpha.3" // x-release-please-version
const PackageVersion = "0.1.0-alpha.4" // x-release-please-version
8 changes: 5 additions & 3 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,12 @@ type CreateNodesRequestParam struct {
CloudInitUserData param.Opt[string] `json:"cloud_init_user_data,omitzero" format:"byte"`
// Custom image ID to use for the VM instances
ImageID param.Opt[string] `json:"image_id,omitzero"`
// Start time as Unix timestamp in seconds Required for reserved nodes
// Start time as Unix timestamp in seconds Optional for reserved nodes. If not
// provided, defaults to now
StartAt param.Opt[int64] `json:"start_at,omitzero"`
// Custom node names Names cannot follow the vm\_{alpha_numeric_chars} as this is
// reserved for system-generated IDs Names cannot be numeric strings
// Custom node names Names cannot begin with 'vm*' or 'n*' as this is reserved for
// system-generated IDs Names cannot be numeric strings Names cannot exceed 128
// characters
Names []string `json:"names,omitzero"`
// Any of "autoreserved", "reserved".
NodeType NodeType `json:"node_type,omitzero"`
Expand Down
7 changes: 6 additions & 1 deletion packages/param/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"strings"
"time"

shimjson "github.com/sfcompute/nodes-go/internal/encoding/json"
Expand All @@ -14,6 +15,10 @@ import (
// EncodedAsDate is not be stable and shouldn't be relied upon
type EncodedAsDate Opt[time.Time]

// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
// special characters that sjson interprets as a path.
var EscapeSJSONKey = strings.NewReplacer("\\", "\\\\", "|", "\\|", "#", "\\#", "@", "\\@", "*", "\\*", ".", "\\.", ":", "\\:", "?", "\\?").Replace

type forceOmit int

func (m EncodedAsDate) MarshalJSON() ([]byte, error) {
Expand Down Expand Up @@ -52,7 +57,7 @@ func MarshalWithExtras[T ParamStruct, R any](f T, underlying any, extras map[str
}
continue
}
bytes, err = sjson.SetBytes(bytes, k, v)
bytes, err = sjson.SetBytes(bytes, EscapeSJSONKey(k), v)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion packages/respjson/respjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package respjson
// Use [Field.Valid] to check if an optional value was null or omitted.
//
// A Field will always occur in the following structure, where it
// mirrors the original field in it's parent struct:
// mirrors the original field in its parent struct:
//
// type ExampleObject struct {
// Foo bool `json:"foo"`
Expand Down
24 changes: 15 additions & 9 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,22 @@ func (r *VMLogsResponseData) UnmarshalJSON(data []byte) error {
}

type VmsshResponse struct {
SSHHostname string `json:"ssh_hostname,required"`
SSHPort int64 `json:"ssh_port,required"`
SSHHostKeys []VmsshResponseSSHHostKey `json:"ssh_host_keys,nullable"`
SSHHostname string `json:"ssh_hostname,required"`
SSHPort int64 `json:"ssh_port,required"`
// Unix timestamp in seconds since epoch
LastAttemptedKeyUpdate int64 `json:"last_attempted_key_update,nullable"`
// Unix timestamp in seconds since epoch
LastSuccessfulKeyUpdate int64 `json:"last_successful_key_update,nullable"`
SSHHostKeys []VmsshResponseSSHHostKey `json:"ssh_host_keys,nullable"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
SSHHostname respjson.Field
SSHPort respjson.Field
SSHHostKeys respjson.Field
ExtraFields map[string]respjson.Field
raw string
SSHHostname respjson.Field
SSHPort respjson.Field
LastAttemptedKeyUpdate respjson.Field
LastSuccessfulKeyUpdate respjson.Field
SSHHostKeys respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

Expand All @@ -117,7 +123,7 @@ func (r *VmsshResponse) UnmarshalJSON(data []byte) error {
}

type VmsshResponseSSHHostKey struct {
Base64EncodedKey string `json:"base64_encoded_key,required"`
Base64EncodedKey string `json:"base64_encoded_key,required" format:"byte"`
KeyType string `json:"key_type,required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Expand Down
3 changes: 3 additions & 0 deletions vmimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ type VMImageGetResponse struct {
Name string `json:"name,required"`
// Any of "image".
Object VMImageGetResponseObject `json:"object,required"`
// Size of the image file in bytes
ObjectSize int64 `json:"object_size,required"`
// SHA256 hash of the image file for integrity verification
Sha256Hash string `json:"sha256_hash,required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
Expand All @@ -136,6 +138,7 @@ type VMImageGetResponse struct {
ImageID respjson.Field
Name respjson.Field
Object respjson.Field
ObjectSize respjson.Field
Sha256Hash respjson.Field
ExtraFields map[string]respjson.Field
raw string
Expand Down
Loading