Skip to content

Commit b17594b

Browse files
authored
Proposal for v2 of typeid (#502)
## Summary Implements a proposed version 2 of TypeID: + Removes all the generic stuff and simplifies the API considerably. + Improves the base32 encoder to allow for zero allocations and buffer reuse. + Improved error handling via CorruptInputError and ErrValidation. + Adds extensive benchmarks. Rewrote existing ones as well. All benchmarks now use the newer loop notation and use sinks (to prevent compiler optimizations from invalidating the benchmarks) + Rethinks the SQL integration to have a nullable version and a non-nullable version. + Changes the internal encoding of the TypeID struct to be more efficient by using a single string and an integer. Note that I tested a byte slice version as well, and it didn't perform as well as this one in the benchmarks. + Improved unit tests so that every single constructor is tested against the spec. + Rewrote constructors to minimize allocations as much as possible (some constructors are zero allocations, others are 1 or 2 at most) + Changed meaning of IsZero() (so that it makes sense to use with `omitzero`). Introduced HasSuffix() that addresses the same use case as the previous version of IsZero(). Rollout proposal: + Merge this PR + Update axiom to use it, see if we like it better. Maybe we tweak it a bit more. + Once happy with it, we release a new version under `v2` ## How was it tested? Ran all the tests ## Community Contribution License All community contributions in this pull request are licensed to the project maintainers under the terms of the [Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0). By creating this pull request I represent that I have the right to license the contributions to the project maintainers under the Apache 2 License as stated in the [Community Contribution License](https://github.com/jetify-com/opensource/blob/main/CONTRIBUTING.md#community-contribution-license).
1 parent f64960d commit b17594b

File tree

4 files changed

+29
-32
lines changed

4 files changed

+29
-32
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ require (
2222
github.com/samber/lo v1.49.1
2323
github.com/spf13/cobra v1.9.1
2424
go.jetify.com/pkg v0.0.0-20250529161140-389e29497c0d
25-
go.jetify.com/typeid v1.3.1-0.20250402201646-5c084b871320
2625
golang.org/x/text v0.23.0
2726
)
2827

@@ -63,6 +62,7 @@ require (
6362
github.com/russross/blackfriday/v2 v2.1.0 // indirect
6463
github.com/spf13/pflag v1.0.6 // indirect
6564
github.com/tailscale/hujson v0.0.0-20250226034555-ec1d1c113d33 // indirect
65+
go.jetify.com/typeid v1.3.1-0.20250402201646-5c084b871320 // indirect
6666
golang.org/x/crypto v0.36.0 // indirect
6767
golang.org/x/oauth2 v0.28.0 // indirect
6868
golang.org/x/sys v0.31.0 // indirect

internal/flow/init.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import (
1616
membersv1alpha1 "go.jetify.com/pkg/api/gen/priv/members/v1alpha1"
1717
projectsv1alpha1 "go.jetify.com/pkg/api/gen/priv/projects/v1alpha1"
1818
"go.jetify.com/pkg/auth/session"
19-
"go.jetify.com/pkg/id"
20-
"go.jetify.com/typeid"
19+
"go.jetify.com/pkg/ids"
2120
)
2221

2322
// flow:
@@ -33,35 +32,35 @@ type Init struct {
3332
WorkingDir string
3433
}
3534

36-
func (i *Init) Run(ctx context.Context) (id.ProjectID, error) {
35+
func (i *Init) Run(ctx context.Context) (ids.ProjectID, error) {
3736
createProject, err := i.confirmSetupProjectPrompt()
3837
if err != nil {
39-
return id.ProjectID{}, err
38+
return ids.ProjectID{}, err
4039
}
4140
if !createProject {
42-
return id.ProjectID{}, errors.New("aborted")
41+
return ids.ProjectID{}, errors.New("aborted")
4342
}
4443

4544
member, err := i.Client.GetMember(ctx, i.Token.IDClaims().Subject)
4645
if err != nil {
47-
return id.ProjectID{}, err
46+
return ids.ProjectID{}, err
4847
}
4948

5049
// TODO: printOrgNotice will be a team picker once that is implemented.
5150
i.printOrgNotice(member)
52-
orgID, err := typeid.Parse[id.OrgID](i.Token.IDClaims().OrgID)
51+
orgID, err := ids.ParseOrgID(i.Token.IDClaims().OrgID)
5352
if err != nil {
54-
return id.ProjectID{}, err
53+
return ids.ProjectID{}, err
5554
}
5655

5756
projects, err := i.Client.ListProjects(ctx, orgID)
5857
if err != nil {
59-
return id.ProjectID{}, err
58+
return ids.ProjectID{}, err
6059
}
6160
if len(projects) > 0 {
6261
linkToExisting, err := i.linkToExistingPrompt()
6362
if err != nil {
64-
return id.ProjectID{}, err
63+
return ids.ProjectID{}, err
6564
}
6665
if linkToExisting {
6766
return i.showExistingListPrompt(projects)
@@ -97,7 +96,7 @@ func (i *Init) linkToExistingPrompt() (bool, error) {
9796

9897
func (i *Init) showExistingListPrompt(
9998
projects []*projectsv1alpha1.Project,
100-
) (id.ProjectID, error) {
99+
) (ids.ProjectID, error) {
101100
// Ignore errors, it's fine if not in repo or git not installed.
102101
repo, _ := git.GitRepoURL(i.WorkingDir)
103102
directory, _ := git.GitSubdirectory(i.WorkingDir)
@@ -117,12 +116,12 @@ func (i *Init) showExistingListPrompt(
117116

118117
idx := 0
119118
if err := survey.AskOne(prompt, &idx); err != nil {
120-
return id.ProjectID{}, err
119+
return ids.ProjectID{}, err
121120
}
122121

123-
projectID, err := typeid.Parse[id.ProjectID](projects[idx].GetId())
122+
projectID, err := ids.ParseProjectID(projects[idx].GetId())
124123
if err != nil {
125-
return id.ProjectID{}, err
124+
return ids.ProjectID{}, err
126125
}
127126
name := projects[idx].GetName()
128127
if name == "" {
@@ -135,20 +134,20 @@ func (i *Init) showExistingListPrompt(
135134
func (i *Init) createNewPrompt(
136135
ctx context.Context,
137136
member *membersv1alpha1.Member,
138-
) (id.ProjectID, error) {
137+
) (ids.ProjectID, error) {
139138
prompt := &survey.Input{
140139
Message: "What’s the name of your new project?",
141140
Default: filepath.Base(i.WorkingDir),
142141
}
143142

144143
name := ""
145144
if err := survey.AskOne(prompt, &name); err != nil {
146-
return id.ProjectID{}, err
145+
return ids.ProjectID{}, err
147146
}
148147

149-
orgID, err := typeid.Parse[id.OrgID](i.Token.IDClaims().OrgID)
148+
orgID, err := ids.ParseOrgID(i.Token.IDClaims().OrgID)
150149
if err != nil {
151-
return id.ProjectID{}, err
150+
return ids.ProjectID{}, err
152151
}
153152

154153
// Ignore errors, it's fine if not in repo or git not installed.
@@ -163,12 +162,12 @@ func (i *Init) createNewPrompt(
163162
strings.TrimSpace(name),
164163
)
165164
if err != nil {
166-
return id.ProjectID{}, err
165+
return ids.ProjectID{}, err
167166
}
168167

169-
projectID, err := typeid.Parse[id.ProjectID](project.GetId())
168+
projectID, err := ids.ParseProjectID(project.GetId())
170169
if err != nil {
171-
return id.ProjectID{}, err
170+
return ids.ProjectID{}, err
172171
}
173172

174173
fmt.Fprintf(

pkg/envcli/flags.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import (
1414
"go.jetify.com/envsec/pkg/stores/jetstore"
1515
"go.jetify.com/envsec/pkg/stores/ssmstore"
1616
"go.jetify.com/pkg/envvar"
17-
"go.jetify.com/pkg/id"
18-
"go.jetify.com/typeid"
17+
"go.jetify.com/pkg/ids"
1918
)
2019

2120
// to be composed into xyzCmdFlags structs
@@ -48,7 +47,7 @@ func (f *configFlags) register(cmd *cobra.Command) {
4847
)
4948
}
5049

51-
func (f *configFlags) validateProjectID(orgID id.OrgID) (string, error) {
50+
func (f *configFlags) validateProjectID(orgID ids.OrgID) (string, error) {
5251
if f.projectID != "" {
5352
return f.projectID, nil
5453
}
@@ -111,7 +110,7 @@ func (f *configFlags) genConfig(cmd *cobra.Command) (*CmdConfig, error) {
111110
f.orgID = tok.IDClaims().OrgID
112111
}
113112

114-
orgID, err := typeid.Parse[id.OrgID](f.orgID)
113+
orgID, err := ids.ParseOrgID(f.orgID)
115114
if err != nil {
116115
return nil, errors.WithStack(err)
117116
}

pkg/envsec/init.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import (
1010
"go.jetify.com/envsec/internal/flow"
1111
"go.jetify.com/envsec/internal/git"
1212
"go.jetify.com/pkg/api"
13-
"go.jetify.com/pkg/id"
14-
"go.jetify.com/typeid"
13+
"go.jetify.com/pkg/ids"
1514
)
1615

1716
var (
@@ -26,8 +25,8 @@ const (
2625
)
2726

2827
type projectConfig struct {
29-
ProjectID id.ProjectID `json:"project_id"`
30-
OrgID id.OrgID `json:"org_id"`
28+
ProjectID ids.ProjectID `json:"project_id"`
29+
OrgID ids.OrgID `json:"org_id"`
3130
}
3231

3332
func (e *Envsec) NewProject(ctx context.Context, force bool) error {
@@ -62,7 +61,7 @@ func (e *Envsec) NewProject(ctx context.Context, force bool) error {
6261
return err
6362
}
6463

65-
orgID, err := typeid.Parse[id.OrgID](tok.IDClaims().OrgID)
64+
orgID, err := ids.ParseOrgID(tok.IDClaims().OrgID)
6665
if err != nil {
6766
return err
6867
}
@@ -94,7 +93,7 @@ func (e *Envsec) configName() string {
9493
return configName
9594
}
9695

97-
func (e *Envsec) saveConfig(projectID id.ProjectID, orgID id.OrgID) error {
96+
func (e *Envsec) saveConfig(projectID ids.ProjectID, orgID ids.OrgID) error {
9897
cfg := projectConfig{ProjectID: projectID, OrgID: orgID}
9998
data, err := json.MarshalIndent(cfg, "", " ")
10099
if err != nil {

0 commit comments

Comments
 (0)