@apicrafthq/script-sdk 0.1.0-beta.5 → 0.1.0-beta.7

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
@@ -1,6 +1,6 @@
1
1
  # @apicrafthq/script-sdk
2
2
 
3
- TypeScript types for [API Craft](https://github.com/fvarrin/api-craft) middleware and custom-auth scripts. Use it to get autocomplete and type-checking for the `ctx` argument in your `before` / `after` request hooks and custom auth handlers.
3
+ TypeScript types for [API Craft](https://github.com/fvarrin/api-craft) scripts. Use it to get autocomplete and type-checking for the `ctx` argument in middleware, custom-auth handlers, and workflow script blocks.
4
4
 
5
5
  > **Beta.** API Craft is pre-1.0. Breaking changes may happen before the stable release. Pin to a specific `beta` version if you need stability.
6
6
 
@@ -14,18 +14,22 @@ pnpm add -D @apicrafthq/script-sdk
14
14
  npm i -D @apicrafthq/script-sdk
15
15
  ```
16
16
 
17
- ## Usage
17
+ The package is types-only: it has no runtime code and no dependencies.
18
+
19
+ ## Middleware and custom auth
20
+
21
+ Request middleware and custom-auth handlers receive a `BeforeRequestContext`. Mutate `ctx.request` in place:
18
22
 
19
23
  ```ts
20
24
  import type { BeforeRequestContext } from '@apicrafthq/script-sdk';
21
25
 
22
26
  export const addAuthHeader = async (ctx: BeforeRequestContext) => {
23
- const token = await ctx.var('AUTH_TOKEN');
27
+ const token = ctx.var('AUTH_TOKEN');
24
28
  ctx.request.headers['Authorization'] = `Bearer ${token}`;
25
29
  };
26
30
  ```
27
31
 
28
- Response middleware:
32
+ Response middleware receives an `AfterResponseContext`. `ctx.request` is read-only; mutate `ctx.response`:
29
33
 
30
34
  ```ts
31
35
  import type { AfterResponseContext } from '@apicrafthq/script-sdk';
@@ -35,16 +39,47 @@ export const logStatus = async (ctx: AfterResponseContext) => {
35
39
  };
36
40
  ```
37
41
 
38
- ## `expect` for assertions
42
+ Every context also provides `ctx.http` (an HTTP client for auxiliary requests such as login or token refresh) and `ctx.cache` (a persistent key/value store shared across the project's request scripts).
43
+
44
+ ### Options
45
+
46
+ A script file can export an `options` constant describing configurable options per exported function. API Craft renders them as a form when the function is attached, stores the chosen values on the attached ref, and passes them as `ctx.options`:
47
+
48
+ ```ts
49
+ import type { AfterResponseContext, InferOptions, OptionsMap } from '@apicrafthq/script-sdk';
50
+
51
+ export const options = {
52
+ byStatus: {
53
+ status: { type: 'integer', title: 'Expected status', enum: [200, 201, 204, 404], default: 200 },
54
+ onMismatch: { type: 'string', enum: ['fail', 'warn'], default: 'fail' },
55
+ },
56
+ } as const satisfies OptionsMap;
57
+
58
+ export const byStatus = async (ctx: AfterResponseContext<InferOptions<typeof options.byStatus>>) => {
59
+ if (ctx.response.status === ctx.options.status) return;
60
+ const message = `Expected ${ctx.options.status}, got ${ctx.response.status}`;
61
+ if (ctx.options.onMismatch === 'warn') return ctx.logger.warn(message);
62
+ throw new Error(message);
63
+ };
64
+ ```
65
+
66
+ Each option is a small JSON Schema: `type` (`string`, `integer`, `number`, `boolean`), optional `enum`, `default`, `title`, `description`, and `required: true`. `InferOptions` derives the `ctx.options` type: a key with `required: true` or a `default` is always present, the others are optional. Values are validated against the schema before the script runs.
39
67
 
40
- The `expect` helper is available via a separate subpath so the main entry stays dependency-free:
68
+ ## Workflow scripts
69
+
70
+ Workflow blocks have their own contexts: `AssertContext`, `ConditionContext`, `TransformContext`, and `ScriptContext`. They expose `ctx.blockResult(blockId)` to read previous block outputs and `ctx.env(apiSlug)` for the resolved environment of a bound API:
41
71
 
42
72
  ```ts
43
- import { expect } from '@apicrafthq/script-sdk/testing';
73
+ import type { TransformContext } from '@apicrafthq/script-sdk';
44
74
 
45
- expect(ctx.response.status).toBe(200);
75
+ export const extractUserId = async (ctx: TransformContext) => {
76
+ const { response } = ctx.blockResult('create-user');
77
+ return { userId: response.body.id };
78
+ };
46
79
  ```
47
80
 
81
+ An assert script fails by throwing; a condition script returns a boolean; a transform script returns an object whose keys become the block's outputs. Free-form `ScriptContext` blocks additionally get `ctx.sleep(milliseconds)` for polling.
82
+
48
83
  ## License
49
84
 
50
85
  MIT
package/dist/index.d.ts CHANGED
@@ -60,13 +60,17 @@ interface RequestScopedContext extends BaseContext {
60
60
  cache: ScriptCache;
61
61
  }
62
62
  /** Context for a before-middleware. Mutate `request` in place. */
63
- interface BeforeRequestContext extends RequestScopedContext {
63
+ interface BeforeRequestContext<O = Record<string, never>> extends RequestScopedContext {
64
64
  request: MutableResolvedRequest;
65
+ /** Options declared by the script's `options` export, as configured on the attached ref. */
66
+ readonly options: O;
65
67
  }
66
68
  /** Context for an after-middleware. `request` is read-only; mutate `response`. */
67
- interface AfterResponseContext extends RequestScopedContext {
69
+ interface AfterResponseContext<O = Record<string, never>> extends RequestScopedContext {
68
70
  readonly request: Readonly<ResolvedRequest>;
69
71
  response: HttpResponse;
72
+ /** Options declared by the script's `options` export, as configured on the attached ref. */
73
+ readonly options: O;
70
74
  }
71
75
  interface MutableResolvedRequest {
72
76
  method: string;
@@ -83,6 +87,57 @@ interface ResolvedRequest {
83
87
  body?: unknown;
84
88
  }
85
89
 
90
+ /** Declarable option, a subset of JSON Schema. Rendered as a form field by API Craft. */
91
+ type OptionSchema = {
92
+ type: 'string';
93
+ enum?: readonly string[];
94
+ default?: string;
95
+ title?: string;
96
+ description?: string;
97
+ required?: boolean;
98
+ } | {
99
+ type: 'integer' | 'number';
100
+ enum?: readonly number[];
101
+ default?: number;
102
+ title?: string;
103
+ description?: string;
104
+ required?: boolean;
105
+ } | {
106
+ type: 'boolean';
107
+ default?: boolean;
108
+ title?: string;
109
+ description?: string;
110
+ required?: boolean;
111
+ };
112
+ /** Options declared by a script file, keyed by exported function name. */
113
+ type OptionsMap = Record<string, Record<string, OptionSchema>>;
114
+ type OptionValue<S extends OptionSchema> = S extends {
115
+ enum: readonly (infer E)[];
116
+ } ? E : S extends {
117
+ type: 'string';
118
+ } ? string : S extends {
119
+ type: 'integer' | 'number';
120
+ } ? number : S extends {
121
+ type: 'boolean';
122
+ } ? boolean : never;
123
+ type IsProvidedKey<S extends OptionSchema> = S extends {
124
+ required: true;
125
+ } ? true : S extends {
126
+ default: string | number | boolean;
127
+ } ? true : false;
128
+ type ProvidedKeys<S extends Record<string, OptionSchema>> = {
129
+ [K in keyof S]: IsProvidedKey<S[K]> extends true ? K : never;
130
+ }[keyof S];
131
+ type Simplify<T> = {
132
+ [K in keyof T]: T[K];
133
+ } & {};
134
+ /** Derives the `ctx.options` type from one entry of an {@link OptionsMap}. */
135
+ type InferOptions<S extends Record<string, OptionSchema>> = Simplify<{
136
+ readonly [K in ProvidedKeys<S>]: OptionValue<S[K]>;
137
+ } & {
138
+ readonly [K in Exclude<keyof S, ProvidedKeys<S>>]?: OptionValue<S[K]>;
139
+ }>;
140
+
86
141
  /**
87
142
  * Known workflow block ids. Augmented per-API by the generated env.d.ts so
88
143
  * `blockResult(...)` autocompletes real block ids; falls back to `string`.
@@ -117,4 +172,4 @@ interface ScriptContext extends WorkflowScopedContext {
117
172
  sleep(milliseconds: number): Promise<void>;
118
173
  }
119
174
 
120
- export type { AfterResponseContext, AssertContext, BaseContext, BeforeRequestContext, BlockResult, BlockResultSchema, ConditionContext, EnvSchema, HttpClient, HttpRequestInit, HttpResponse, HttpResponseBody, MutableResolvedRequest, RequestScopedContext, ResolvedRequest, ScriptCache, ScriptContext, ScriptLogger, TransformContext, WorkflowScopedContext };
175
+ export type { AfterResponseContext, AssertContext, BaseContext, BeforeRequestContext, BlockResult, BlockResultSchema, ConditionContext, EnvSchema, HttpClient, HttpRequestInit, HttpResponse, HttpResponseBody, InferOptions, MutableResolvedRequest, OptionSchema, OptionsMap, RequestScopedContext, ResolvedRequest, ScriptCache, ScriptContext, ScriptLogger, TransformContext, WorkflowScopedContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apicrafthq/script-sdk",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.0-beta.7",
4
4
  "type": "module",
5
5
  "description": "TypeScript types for API Craft middleware and custom-auth scripts.",
6
6
  "license": "MIT",
@@ -24,8 +24,7 @@
24
24
  "LICENSE"
25
25
  ],
26
26
  "publishConfig": {
27
- "access": "public",
28
- "tag": "beta"
27
+ "access": "public"
29
28
  },
30
29
  "exports": {
31
30
  ".": {