@pi-in-go/pigpen-pi-typesafe 0.1.0

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.
Files changed (189) hide show
  1. package/CREDITS.md +14 -0
  2. package/LICENSE +22 -0
  3. package/README.md +45 -0
  4. package/extensions/pi-typesafe/branches_test.go +185 -0
  5. package/extensions/pi-typesafe/command.go +319 -0
  6. package/extensions/pi-typesafe/export_test.go +9 -0
  7. package/extensions/pi-typesafe/extension.go +188 -0
  8. package/extensions/pi-typesafe/extension_test.go +321 -0
  9. package/extensions/pi-typesafe/fakehost_test.go +548 -0
  10. package/extensions/pi-typesafe/format.go +191 -0
  11. package/extensions/pi-typesafe/format_test.go +75 -0
  12. package/extensions/pi-typesafe/go.mod +10 -0
  13. package/extensions/pi-typesafe/go.sum +2 -0
  14. package/extensions/pi-typesafe/go.work +11 -0
  15. package/extensions/pi-typesafe/harness_test.go +200 -0
  16. package/extensions/pi-typesafe/ownmodel_test.go +100 -0
  17. package/extensions/pi-typesafe/review_test.go +134 -0
  18. package/extensions/pi-typesafe/tool.go +193 -0
  19. package/extensions/pi-typesafe/twin_test.go +28 -0
  20. package/libs/pi-typesafe-api/CREDITS.md +14 -0
  21. package/libs/pi-typesafe-api/LICENSE +22 -0
  22. package/libs/pi-typesafe-api/README.md +30 -0
  23. package/libs/pi-typesafe-api/ask.go +62 -0
  24. package/libs/pi-typesafe-api/ask_test.go +76 -0
  25. package/libs/pi-typesafe-api/auth.go +249 -0
  26. package/libs/pi-typesafe-api/auth_test.go +131 -0
  27. package/libs/pi-typesafe-api/backends.go +336 -0
  28. package/libs/pi-typesafe-api/backends_test.go +404 -0
  29. package/libs/pi-typesafe-api/batch.go +202 -0
  30. package/libs/pi-typesafe-api/batch_test.go +202 -0
  31. package/libs/pi-typesafe-api/battery_test.go +41 -0
  32. package/libs/pi-typesafe-api/calibrate.go +354 -0
  33. package/libs/pi-typesafe-api/calibrate_test.go +186 -0
  34. package/libs/pi-typesafe-api/client.go +615 -0
  35. package/libs/pi-typesafe-api/client_test.go +490 -0
  36. package/libs/pi-typesafe-api/credentials.go +252 -0
  37. package/libs/pi-typesafe-api/credentials_test.go +216 -0
  38. package/libs/pi-typesafe-api/doc.go +14 -0
  39. package/libs/pi-typesafe-api/errors.go +143 -0
  40. package/libs/pi-typesafe-api/evaluation.go +86 -0
  41. package/libs/pi-typesafe-api/evaluation_schema.json +264 -0
  42. package/libs/pi-typesafe-api/gaps_test.go +77 -0
  43. package/libs/pi-typesafe-api/go.mod +9 -0
  44. package/libs/pi-typesafe-api/go.sum +2 -0
  45. package/libs/pi-typesafe-api/helpers_test.go +169 -0
  46. package/libs/pi-typesafe-api/hostmodel/hostmodel.go +87 -0
  47. package/libs/pi-typesafe-api/json.go +299 -0
  48. package/libs/pi-typesafe-api/json_test.go +92 -0
  49. package/libs/pi-typesafe-api/ownmodel_test.go +79 -0
  50. package/libs/pi-typesafe-api/package.json +40 -0
  51. package/libs/pi-typesafe-api/provenance.json +18 -0
  52. package/libs/pi-typesafe-api/review_test.go +23 -0
  53. package/libs/pi-typesafe-api/schema.go +473 -0
  54. package/libs/pi-typesafe-api/schema_test.go +262 -0
  55. package/libs/pi-typesafe-api/testdata/tools/typebox-messages.mts +5 -0
  56. package/libs/pi-typesafe-api/testdata/typebox-messages.json +285 -0
  57. package/libs/pi-typesafe-api/twin_test.go +28 -0
  58. package/libs/pi-typesafe-api/ui/fakehost_test.go +548 -0
  59. package/libs/pi-typesafe-api/ui/keyprompt.go +115 -0
  60. package/libs/pi-typesafe-api/ui/login.go +106 -0
  61. package/libs/pi-typesafe-api/ui/twin_test.go +28 -0
  62. package/libs/pi-typesafe-api/ui/ui_test.go +285 -0
  63. package/libs/pi-typesafe-api/usage.go +366 -0
  64. package/libs/pi-typesafe-api/usage_test.go +139 -0
  65. package/libs/typesafe/CONTRACT.md +125 -0
  66. package/libs/typesafe/CREDITS.md +37 -0
  67. package/libs/typesafe/LICENSE +23 -0
  68. package/libs/typesafe/README.md +19 -0
  69. package/libs/typesafe/go.mod +3 -0
  70. package/libs/typesafe/libraries/ownmodel/backend_test.go +496 -0
  71. package/libs/typesafe/libraries/ownmodel/canon.go +190 -0
  72. package/libs/typesafe/libraries/ownmodel/convert.go +199 -0
  73. package/libs/typesafe/libraries/ownmodel/doc.go +15 -0
  74. package/libs/typesafe/libraries/ownmodel/equivalence_test.go +199 -0
  75. package/libs/typesafe/libraries/ownmodel/helpers_test.go +155 -0
  76. package/libs/typesafe/libraries/ownmodel/mutation_test.go +31 -0
  77. package/libs/typesafe/libraries/ownmodel/ownmodel.go +225 -0
  78. package/libs/typesafe/libraries/ownmodel/plan.go +442 -0
  79. package/libs/typesafe/libraries/ownmodel/run.go +288 -0
  80. package/libs/typesafe/libraries/ownmodel/schema_test.go +254 -0
  81. package/libs/typesafe/libraries/ownmodel/twins_test.go +169 -0
  82. package/libs/typesafe/libraries/ownmodel/utils_test.go +125 -0
  83. package/libs/typesafe/libraries/pigmodel/pigmodel.go +264 -0
  84. package/libs/typesafe/libraries/pigmodel/pigmodel_test.go +410 -0
  85. package/libs/typesafe/libraries/typesafe/answers.go +268 -0
  86. package/libs/typesafe/libraries/typesafe/api_response_test.go +113 -0
  87. package/libs/typesafe/libraries/typesafe/batch.go +80 -0
  88. package/libs/typesafe/libraries/typesafe/batch_test.go +133 -0
  89. package/libs/typesafe/libraries/typesafe/bench_test.go +71 -0
  90. package/libs/typesafe/libraries/typesafe/client.go +561 -0
  91. package/libs/typesafe/libraries/typesafe/client_test.go +495 -0
  92. package/libs/typesafe/libraries/typesafe/crosscheck_test.go +464 -0
  93. package/libs/typesafe/libraries/typesafe/crosscheck_workflowevals_test.go +219 -0
  94. package/libs/typesafe/libraries/typesafe/doc.go +27 -0
  95. package/libs/typesafe/libraries/typesafe/entry.go +142 -0
  96. package/libs/typesafe/libraries/typesafe/env.go +11 -0
  97. package/libs/typesafe/libraries/typesafe/errors.go +310 -0
  98. package/libs/typesafe/libraries/typesafe/errors_test.go +175 -0
  99. package/libs/typesafe/libraries/typesafe/helpers_test.go +294 -0
  100. package/libs/typesafe/libraries/typesafe/live_test.go +96 -0
  101. package/libs/typesafe/libraries/typesafe/logging.go +160 -0
  102. package/libs/typesafe/libraries/typesafe/logging_test.go +259 -0
  103. package/libs/typesafe/libraries/typesafe/marshal_test.go +112 -0
  104. package/libs/typesafe/libraries/typesafe/mutation_test.go +39 -0
  105. package/libs/typesafe/libraries/typesafe/questions.go +490 -0
  106. package/libs/typesafe/libraries/typesafe/questions_test.go +166 -0
  107. package/libs/typesafe/libraries/typesafe/regressions_test.go +159 -0
  108. package/libs/typesafe/libraries/typesafe/reliability_test.go +649 -0
  109. package/libs/typesafe/libraries/typesafe/retry.go +350 -0
  110. package/libs/typesafe/libraries/typesafe/retry_test.go +297 -0
  111. package/libs/typesafe/libraries/typesafe/runtime_test.go +26 -0
  112. package/libs/typesafe/libraries/typesafe/transport_test.go +163 -0
  113. package/libs/typesafe/libraries/typesafe/twins_test.go +127 -0
  114. package/libs/typesafe/libraries/typesafe/types_test.go +165 -0
  115. package/libs/typesafe/libraries/typesafe/version.go +10 -0
  116. package/libs/typesafe/package.json +37 -0
  117. package/libs/typesafe/provenance.json +49 -0
  118. package/package.json +42 -0
  119. package/port/PORT.md +98 -0
  120. package/port/accepted-gaps.json +3 -0
  121. package/port/golden/enable-confirm.jsonl +11 -0
  122. package/port/golden/enable-decline.jsonl +20 -0
  123. package/port/golden/enable-missing-key.jsonl +4 -0
  124. package/port/golden/login-shadow.jsonl +4 -0
  125. package/port/golden/logout-env-key.jsonl +6 -0
  126. package/port/golden/playground-cancel.jsonl +4 -0
  127. package/port/golden/playground-invalid-json.jsonl +5 -0
  128. package/port/golden/playground-invalid-questions.jsonl +5 -0
  129. package/port/golden/status-env-key.jsonl +6 -0
  130. package/port/golden/status-no-key.jsonl +6 -0
  131. package/port/golden/tool-disabled.jsonl +18 -0
  132. package/port/golden/trailing-words.jsonl +10 -0
  133. package/port/library-mutations.py +44 -0
  134. package/port/mutations.json +302 -0
  135. package/port/oracle/.env.example +4 -0
  136. package/port/oracle/CHANGELOG.md +91 -0
  137. package/port/oracle/CONTRIBUTING.md +35 -0
  138. package/port/oracle/LICENSE +21 -0
  139. package/port/oracle/README.md +159 -0
  140. package/port/oracle/docs/api.md +143 -0
  141. package/port/oracle/docs/ci-cd.md +97 -0
  142. package/port/oracle/examples/decision-extension.ts +41 -0
  143. package/port/oracle/extensions/index.js +2 -0
  144. package/port/oracle/package.json +89 -0
  145. package/port/oracle/scripts/dev-pi.mjs +23 -0
  146. package/port/oracle/scripts/live-smoke.mjs +35 -0
  147. package/port/oracle/src/ask.ts +42 -0
  148. package/port/oracle/src/auth.ts +171 -0
  149. package/port/oracle/src/backends.ts +196 -0
  150. package/port/oracle/src/batch.ts +170 -0
  151. package/port/oracle/src/calibrate.ts +237 -0
  152. package/port/oracle/src/client.ts +310 -0
  153. package/port/oracle/src/credentials.ts +136 -0
  154. package/port/oracle/src/errors.ts +53 -0
  155. package/port/oracle/src/extension.ts +204 -0
  156. package/port/oracle/src/index.ts +31 -0
  157. package/port/oracle/src/key-prompt.ts +51 -0
  158. package/port/oracle/src/login.ts +60 -0
  159. package/port/oracle/src/schema.ts +158 -0
  160. package/port/oracle/src/ui.ts +4 -0
  161. package/port/oracle/src/usage.ts +258 -0
  162. package/port/oracle/tests/ask.test.ts +63 -0
  163. package/port/oracle/tests/auth.test.ts +141 -0
  164. package/port/oracle/tests/backends.test.ts +380 -0
  165. package/port/oracle/tests/batch.test.ts +156 -0
  166. package/port/oracle/tests/calibrate.test.ts +144 -0
  167. package/port/oracle/tests/client.test.ts +499 -0
  168. package/port/oracle/tests/credentials.test.ts +144 -0
  169. package/port/oracle/tests/extension.test.ts +276 -0
  170. package/port/oracle/tests/key-prompt.test.ts +47 -0
  171. package/port/oracle/tests/login.test.ts +101 -0
  172. package/port/oracle/tests/schema.test.ts +85 -0
  173. package/port/oracle/tests/usage.test.ts +106 -0
  174. package/port/oracle/tsconfig.build.json +10 -0
  175. package/port/oracle/tsconfig.json +14 -0
  176. package/port/scenarios/enable-confirm.json +5 -0
  177. package/port/scenarios/enable-decline.json +3 -0
  178. package/port/scenarios/enable-missing-key.json +2 -0
  179. package/port/scenarios/login-shadow.json +2 -0
  180. package/port/scenarios/logout-env-key.json +3 -0
  181. package/port/scenarios/playground-cancel.json +2 -0
  182. package/port/scenarios/playground-invalid-json.json +2 -0
  183. package/port/scenarios/playground-invalid-questions.json +2 -0
  184. package/port/scenarios/status-env-key.json +3 -0
  185. package/port/scenarios/status-no-key.json +3 -0
  186. package/port/scenarios/tool-disabled.json +2 -0
  187. package/port/scenarios/trailing-words.json +5 -0
  188. package/port/upstream-tests.json +160 -0
  189. package/provenance.json +18 -0
@@ -0,0 +1,159 @@
1
+ package typesafe
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "errors"
7
+ "net/http"
8
+ "strings"
9
+ "testing"
10
+ "testing/synctest"
11
+ "time"
12
+ )
13
+
14
+ func TestReleaseRegressions_ReplacesMixedCaseDefaultsAndProtectsEverySDKHeaderOnEveryAttempt(t *testing.T) {
15
+ twin(t, "release-regressions.test.ts | release regressions replaces mixed-case defaults and protects every SDK header on every attempt")
16
+ calls := 0
17
+ m := newMock(func(*recordedRequest) (*http.Response, error) {
18
+ calls++
19
+ if calls == 1 {
20
+ return jsonResp(503, map[string]any{}), nil
21
+ }
22
+ return jsonResp(200, map[string]any{}), nil
23
+ })
24
+ c := newClient(t, m, func(cfg *Config) {
25
+ cfg.APIKey = "secret"
26
+ cfg.DefaultHeaders = map[string]string{"X-Team": "default", "authorization": "bad", "content-type": "text/plain", "x-typesafe-retry-count": "99"}
27
+ cfg.Retry = RetryOverrides{MaxRetries: Ptr(1), BackoffInitial: Ptr(time.Duration(0))}
28
+ })
29
+ _, err := c.SystemOne(ctxBG(), SystemOneRequest{State: Text("s"), Questions: Questions{Ask("q", Noul("?"))}}, &RequestOptions{Headers: map[string]string{
30
+ "x-team": "call", "AUTHORIZATION": "bad-again", "ACCEPT": "text/plain", "USER-AGENT": "bad", "X-TYPESAFE-SDK": "bad",
31
+ "X-TYPESAFE-RUNTIME": "bad", "CONTENT-TYPE": "text/html", "X-TYPESAFE-RETRY-COUNT": "88",
32
+ }})
33
+ noErr(t, err)
34
+ eq(t, m.count(), 2)
35
+ for i := 0; i < 2; i++ {
36
+ hd := m.req(i).Header
37
+ eq(t, hd.Get("authorization"), "Bearer secret")
38
+ eq(t, hd.Get("x-team"), "call")
39
+ eq(t, hd.Get("content-type"), "application/json")
40
+ eq(t, hd.Get("accept"), "application/json")
41
+ if !strings.HasPrefix(hd.Get("user-agent"), "typesafe-sdk") || !strings.HasPrefix(hd.Get("x-typesafe-sdk"), "typesafe-sdk") {
42
+ t.Fatalf("identity headers %v", hd)
43
+ }
44
+ if strings.Contains(hd.Get("x-typesafe-runtime"), "bad") {
45
+ t.Fatal("runtime header overridden")
46
+ }
47
+ want := ""
48
+ if i == 1 {
49
+ want = "1"
50
+ }
51
+ eq(t, hd.Get("x-typesafe-retry-count"), want)
52
+ eq(t, len(hd.Values("Authorization")), 1)
53
+ eq(t, len(hd.Values("X-Team")), 1)
54
+ }
55
+ }
56
+
57
+ func TestReleaseRegressions_DoesNotSendACallerSuppliedContentTypeOrRetryCountOnGET(t *testing.T) {
58
+ twin(t, "release-regressions.test.ts | release regressions does not send a caller-supplied content type or retry count on GET")
59
+ m := modelsOK()
60
+ c := newClient(t, m, func(cfg *Config) {
61
+ cfg.DefaultHeaders = map[string]string{"content-type": "bad", "x-typesafe-retry-count": "99"}
62
+ })
63
+ _, err := c.Models().List(ctxBG(), nil)
64
+ noErr(t, err)
65
+ hd := m.req(0).Header
66
+ if _, has := hd["Content-Type"]; has {
67
+ t.Fatal("content type on GET")
68
+ }
69
+ if _, has := hd["X-Typesafe-Retry-Count"]; has {
70
+ t.Fatal("retry count on the first attempt")
71
+ }
72
+ }
73
+
74
+ func TestReleaseRegressions_PreservesOwnProtoQuestionsWithoutMutation(t *testing.T) {
75
+ twin(t, "release-regressions.test.ts | release regressions preserves own __proto__ questions without mutation")
76
+ qs := Questions{Ask("__proto__", Noul("?")), Ask("score", Score("?", "no", "yes"))}
77
+ before, err := json.Marshal(qs)
78
+ noErr(t, err)
79
+ m := always(func() *http.Response { return jsonResp(200, map[string]any{}) })
80
+ _, err = newClient(t, m).SystemOne(ctxBG(), SystemOneRequest{State: Text("s"), Questions: qs}, nil)
81
+ noErr(t, err)
82
+ var body struct {
83
+ Questions map[string]json.RawMessage `json:"questions"`
84
+ }
85
+ noErr(t, json.Unmarshal(m.req(0).Raw, &body))
86
+ jsonEq(t, body.Questions["__proto__"], `{"type":"noul","instructions":"?"}`)
87
+ jsonEq(t, body.Questions["score"], `{"type":"score","instructions":"?","criteria":["no","yes"]}`)
88
+ after, err := json.Marshal(qs)
89
+ noErr(t, err)
90
+ eq(t, string(after), string(before))
91
+ }
92
+
93
+ func TestReleaseRegressions_TimesOutAStalledBodyEvenWithACustomFetchIgnoringSignals(t *testing.T) {
94
+ twin(t,
95
+ "release-regressions.test.ts | release regressions times out a stalled 200 body even with a custom fetch ignoring signals",
96
+ "release-regressions.test.ts | release regressions times out a stalled 503 body even with a custom fetch ignoring signals")
97
+ for _, status := range []int{200, 503} {
98
+ synctest.Test(t, func(t *testing.T) {
99
+ var bodies []*blockingBody
100
+ m := newMock(func(*recordedRequest) (*http.Response, error) {
101
+ b := newBlockingBody()
102
+ bodies = append(bodies, b)
103
+ return respWithBody(status, b), nil
104
+ })
105
+ c := newClient(t, m, func(cfg *Config) {
106
+ cfg.Timeout = 50 * time.Millisecond
107
+ cfg.Retry = RetryOverrides{MaxRetries: Ptr(1), BackoffInitial: Ptr(time.Duration(0))}
108
+ })
109
+ _, err := c.Models().List(ctxBG(), nil)
110
+ mustAs[*APITimeoutError](t, err)
111
+ eq(t, m.count(), 2)
112
+ eq(t, len(bodies), 2)
113
+ for _, b := range bodies {
114
+ eq(t, b.closeCount(), 1)
115
+ }
116
+ })
117
+ }
118
+ }
119
+
120
+ func TestReleaseRegressions_WrapsBodyFailuresWithTheirCauseAndHonorsDisabledConnectionRetries(t *testing.T) {
121
+ twin(t,
122
+ "release-regressions.test.ts | release regressions wraps 200 body failures with their cause and honors disabled connection retries",
123
+ "release-regressions.test.ts | release regressions wraps 503 body failures with their cause and honors disabled connection retries")
124
+ for _, status := range []int{200, 503} {
125
+ cause := errors.New("socket dropped")
126
+ m := newMock(func(*recordedRequest) (*http.Response, error) { return respWithBody(status, errBody{cause}), nil })
127
+ c := newClient(t, m, func(cfg *Config) { cfg.Retry = RetryOverrides{APIConnectionError: Ptr(false)} })
128
+ _, err := c.Models().List(ctxBG(), nil)
129
+ conn := mustAs[*APIConnectionError](t, err)
130
+ if !errors.Is(conn, cause) {
131
+ t.Fatalf("%d: cause lost: %v", status, err)
132
+ }
133
+ eq(t, m.count(), 1)
134
+ }
135
+ }
136
+
137
+ func TestReleaseRegressions_CancelsABodyWhenTheSignalWasAbortedJustBeforeFetchReturnedHeaders(t *testing.T) {
138
+ twin(t, "release-regressions.test.ts | release regressions cancels a body when the signal was aborted just before fetch returned headers")
139
+ synctest.Test(t, func(t *testing.T) {
140
+ ctx, cancel := context.WithCancel(context.Background())
141
+ body := newBlockingBody()
142
+ m := newMock(func(*recordedRequest) (*http.Response, error) { cancel(); return respWithBody(200, body), nil })
143
+ _, err := newClient(t, m).Models().List(ctx, nil)
144
+ mustAs[*APIUserAbortError](t, err)
145
+ eq(t, m.count(), 1)
146
+ eq(t, body.closeCount(), 1)
147
+ })
148
+ }
149
+
150
+ func TestReleaseRegressions_ReturnsANullBodyResponseWithoutTryingToReadAStream(t *testing.T) {
151
+ twin(t, "release-regressions.test.ts | release regressions returns a null-body response without trying to read a stream")
152
+ m := newMock(func(*recordedRequest) (*http.Response, error) {
153
+ return &http.Response{StatusCode: 204, Header: http.Header{}, Body: http.NoBody}, nil
154
+ })
155
+ raw, err := newClient(t, m).Models().ListRaw(ctxBG(), nil)
156
+ noErr(t, err)
157
+ eq(t, raw.Status, 204)
158
+ eq(t, len(raw.Body), 0)
159
+ }