@superblocksteam/sdk-api 2.0.178-next.2 → 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 +13 -8
- package/dist/readme.test.d.ts +2 -0
- package/dist/readme.test.d.ts.map +1 -0
- package/dist/readme.test.js +36 -0
- package/dist/readme.test.js.map +1 -0
- package/package.json +6 -2
- package/src/readme.test.ts +51 -0
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.
|
|
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 @@
|
|
|
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.
|
|
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.
|
|
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
|
+
});
|