@superblocksteam/sdk-api 2.0.178-next.3 → 2.0.179-next.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.
package/README.md CHANGED
@@ -62,6 +62,7 @@ import { api, z, postgres } from "@superblocksteam/sdk-api";
62
62
 
63
63
  const myApi = api({
64
64
  name: "GetUsers",
65
+ description: "Lists users from Postgres",
65
66
  integrations: { db: postgres("prod-postgres-id") },
66
67
  input: z.object({ limit: z.number() }),
67
68
  output: z.object({ users: z.array(z.object({ id: z.string() })) }),
@@ -243,6 +244,7 @@ const UserSchema = z.object({
243
244
 
244
245
  export default api({
245
246
  name: "GetUserById",
247
+ description: "Fetches one user by ID from Postgres",
246
248
 
247
249
  // Declare integrations upfront for type safety
248
250
  integrations: {
@@ -284,6 +286,7 @@ import { api, z } from "@superblocksteam/sdk-api";
284
286
 
285
287
  export const ListProfiles = api({
286
288
  name: "ListProfiles",
289
+ description: "Lists an organization's user profiles",
287
290
  input: z.object({ orgId: z.string() }),
288
291
  output: z.object({ profiles: z.array(z.object({ id: z.string() })) }),
289
292
  async run() {
@@ -293,6 +296,7 @@ export const ListProfiles = api({
293
296
 
294
297
  export const UpdateProfile = api({
295
298
  name: "UpdateProfile",
299
+ description: "Updates a user's profile",
296
300
  input: z.object({ userId: z.string() }),
297
301
  output: z.object({ ok: z.literal(true) }),
298
302
  async run() {
@@ -318,14 +322,14 @@ Defines a TypeScript-based API with input/output validation. Returns a complete
318
322
 
319
323
  #### Required Fields
320
324
 
321
- | Field | Type | Description |
322
- | -------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
323
- | `name` | `string` | **Required.** Unique identifier for the API |
324
- | `description` | `string` | Optional. Plain-language summary of what this API does and which integrations it uses. Auto-generated by the AI agent when creating or editing an API. |
325
- | `input` | `z.ZodType` | **Required.** Zod schema for input validation |
326
- | `output` | `z.ZodType` | **Required.** Zod schema for output validation |
327
- | `run` | `(ctx, input) => Promise<Output>` | **Required.** The implementation function |
328
- | `integrations` | `Record<string, IntegrationRef>` | Optional. Integration declarations for the API |
325
+ | Field | Type | Description |
326
+ | -------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
327
+ | `name` | `string` | **Required.** Unique identifier for the API |
328
+ | `description` | `string` | Optional in the type, but always set it when creating or editing an API. A short plain-language phrase (under 10 words) on what the API does and which integrations it uses, such as "Fetches active orders from Postgres". Place it right after `name`, and update it when the API's logic changes. |
329
+ | `input` | `z.ZodType` | **Required.** Zod schema for input validation |
330
+ | `output` | `z.ZodType` | **Required.** Zod schema for output validation |
331
+ | `run` | `(ctx, input) => Promise<Output>` | **Required.** The implementation function |
332
+ | `integrations` | `Record<string, IntegrationRef>` | Optional. Integration declarations for the API |
329
333
 
330
334
  ### Context (`ctx`) and Input
331
335
 
@@ -354,6 +358,7 @@ const OPS_SLACK = "b2c3d4e5-6789-01ab-cdef-ghijklmnopqr";
354
358
 
355
359
  export default api({
356
360
  name: "ProcessUserWorkflow",
361
+ description: "Looks up a user in Postgres and notifies Slack",
357
362
  integrations: {
358
363
  db: postgres(PROD_POSTGRES),
359
364
  notifier: slack(OPS_SLACK),
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=readme.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readme.test.d.ts","sourceRoot":"","sources":["../src/readme.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { describe, expect, it } from "vitest";
5
+ // getSdkApiDocs serves this README to the builder agent as its only guide to
6
+ // writing APIs, so the agent copies what its examples and rules show.
7
+ const README = readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), "../README.md"), "utf8");
8
+ /** The `api({ ... })` calls in the README's TypeScript code blocks. */
9
+ function apiExamples() {
10
+ const blocks = [...README.matchAll(/```typescript\n([\s\S]*?)```/g)].map((match) => match[1]);
11
+ const examples = [];
12
+ for (const block of blocks) {
13
+ for (const call of block.matchAll(/\bapi\(\{\n([\s\S]*?)\n\}\);/g)) {
14
+ const body = call[1];
15
+ const name = /^\s*name: "([^"]+)",/m.exec(body)?.[1] ?? "(unnamed)";
16
+ examples.push({ name, body });
17
+ }
18
+ }
19
+ return examples;
20
+ }
21
+ describe("SDK API README", () => {
22
+ it("has api() examples to check", () => {
23
+ expect(apiExamples().length).toBeGreaterThanOrEqual(5);
24
+ });
25
+ it.each(apiExamples())("$name example sets a description right after its name", ({ body }) => {
26
+ const lines = body.split("\n").filter((line) => line.trim() !== "");
27
+ const nameIndex = lines.findIndex((line) => /^\s*name: /.test(line));
28
+ expect(nameIndex).toBeGreaterThanOrEqual(0);
29
+ expect(lines[nameIndex + 1]).toMatch(/^\s*description:\s*(".+"|$)/);
30
+ });
31
+ it("tells the agent to always set a description", () => {
32
+ const row = README.split("\n").find((line) => line.startsWith("| `description`"));
33
+ expect(row).toMatch(/always set it when creating or editing an API/i);
34
+ });
35
+ });
36
+ //# sourceMappingURL=readme.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readme.test.js","sourceRoot":"","sources":["../src/readme.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,6EAA6E;AAC7E,sEAAsE;AACtE,MAAM,MAAM,GAAG,YAAY,CACzB,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,EAChE,MAAM,CACP,CAAC;AAEF,uEAAuE;AACvE,SAAS,WAAW;IAClB,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,CAAC,GAAG,CACtE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CACpB,CAAC;IACF,MAAM,QAAQ,GAAqC,EAAE,CAAC;IACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC;YACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CACpB,uDAAuD,EACvD,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACtE,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAC3C,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CACnC,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@superblocksteam/sdk-api",
3
- "version": "2.0.178-next.3",
3
+ "version": "2.0.179-next.0",
4
4
  "description": "Superblocks SDK for TypeScript-based API definitions",
5
5
  "license": "Superblocks Community Software License",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/superblocksteam/superblocks.git"
9
+ },
6
10
  "files": [
7
11
  "dist",
8
12
  "src",
@@ -22,7 +26,7 @@
22
26
  "devDependencies": {
23
27
  "@bufbuild/protobuf": "1.3.0",
24
28
  "@eslint/js": "^9.39.5",
25
- "@superblocksteam/shared": "0.9620.4",
29
+ "@superblocksteam/shared": "0.9622.0",
26
30
  "@types/node": "^20.19.43",
27
31
  "@typescript/native": "npm:typescript@^7.0.2",
28
32
  "dotenv": "^16.6.1",
@@ -0,0 +1,51 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import { describe, expect, it } from "vitest";
6
+
7
+ // getSdkApiDocs serves this README to the builder agent as its only guide to
8
+ // writing APIs, so the agent copies what its examples and rules show.
9
+ const README = readFileSync(
10
+ resolve(dirname(fileURLToPath(import.meta.url)), "../README.md"),
11
+ "utf8",
12
+ );
13
+
14
+ /** The `api({ ... })` calls in the README's TypeScript code blocks. */
15
+ function apiExamples(): { name: string; body: string }[] {
16
+ const blocks = [...README.matchAll(/```typescript\n([\s\S]*?)```/g)].map(
17
+ (match) => match[1],
18
+ );
19
+ const examples: { name: string; body: string }[] = [];
20
+ for (const block of blocks) {
21
+ for (const call of block.matchAll(/\bapi\(\{\n([\s\S]*?)\n\}\);/g)) {
22
+ const body = call[1];
23
+ const name = /^\s*name: "([^"]+)",/m.exec(body)?.[1] ?? "(unnamed)";
24
+ examples.push({ name, body });
25
+ }
26
+ }
27
+ return examples;
28
+ }
29
+
30
+ describe("SDK API README", () => {
31
+ it("has api() examples to check", () => {
32
+ expect(apiExamples().length).toBeGreaterThanOrEqual(5);
33
+ });
34
+
35
+ it.each(apiExamples())(
36
+ "$name example sets a description right after its name",
37
+ ({ body }) => {
38
+ const lines = body.split("\n").filter((line) => line.trim() !== "");
39
+ const nameIndex = lines.findIndex((line) => /^\s*name: /.test(line));
40
+ expect(nameIndex).toBeGreaterThanOrEqual(0);
41
+ expect(lines[nameIndex + 1]).toMatch(/^\s*description:\s*(".+"|$)/);
42
+ },
43
+ );
44
+
45
+ it("tells the agent to always set a description", () => {
46
+ const row = README.split("\n").find((line) =>
47
+ line.startsWith("| `description`"),
48
+ );
49
+ expect(row).toMatch(/always set it when creating or editing an API/i);
50
+ });
51
+ });