@swirls/sdk 0.0.1

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 ADDED
@@ -0,0 +1,35 @@
1
+ # @swirls/sdk
2
+
3
+ TypeScript SDK for building applications powered by Swirls.
4
+
5
+ ## Overview
6
+
7
+ The Swirls SDK provides utilities for integrating Swirls into your applications. It is designed to be type-safe, headless, and framework-agnostic.
8
+
9
+ ### Configuration
10
+
11
+ The [`@swirls/sdk/config`](src/config/README.md) subpackage provides configuration "glue" that connects your application to a Swirls project and powers code generation.
12
+
13
+ ```typescript
14
+ import { defineConfig } from '@swirls/sdk/config'
15
+ ```
16
+
17
+ ### Forms
18
+
19
+ The [`@swirls/sdk/form`](src/form/README.md) subpackage provides a form library for building, validating, and submitting forms.
20
+
21
+ ```typescript
22
+ import { useSwirlsFormAdapter, SwirlsForm } from '@swirls/sdk/form'
23
+ ```
24
+
25
+ ## Installation
26
+
27
+ ```sh
28
+ bun add @swirls/sdk react zod
29
+ ```
30
+
31
+ ## Learn More
32
+
33
+ - [Swirls Documentation](https://docs.swirls.dev): Full platform documentation
34
+ - [Config Documentation](src/config/README.md): Configuration reference
35
+ - [Form Documentation](src/form/README.md): Complete guide to forms
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const configFileName = "swirls.config.ts";
4
+ declare const configSchema: z.ZodObject<{
5
+ projectId: z.ZodUUID;
6
+ genPath: z.ZodString;
7
+ }, z.core.$strip>;
8
+ type Config = z.infer<typeof configSchema>;
9
+ type ConfigOptions = {
10
+ /**
11
+ * Identifier of the Swirls project to use.
12
+ */
13
+ projectId: string;
14
+ /**
15
+ * Path defining the location of the generated code.
16
+ * @default 'src/swirls.gen.ts'
17
+ */
18
+ genPath?: string;
19
+ };
20
+ /**
21
+ * Defines a Swirls configuration with optional defaults.
22
+ */
23
+ declare function defineConfig(config: ConfigOptions): Config;
24
+ /**
25
+ * Generates a Swirls configuration skeleton with default and empty values.
26
+ */
27
+ declare function generateConfig(projectId?: string): string;
28
+
29
+ export { configFileName, configSchema, defineConfig, generateConfig };
@@ -0,0 +1,39 @@
1
+ // src/config/config.ts
2
+ import path from "path";
3
+ import { z } from "zod";
4
+ var configFileName = "swirls.config.ts";
5
+ var configImportPath = "@swirls/sdk/config";
6
+ var generatedFileName = "swirls.gen.ts";
7
+ var configSchema = z.object({
8
+ projectId: z.uuid(),
9
+ genPath: z.string().min(1)
10
+ });
11
+ function defineConfig(config) {
12
+ const root = process.cwd();
13
+ const source = path.join(root, "src");
14
+ const output = path.join(source, generatedFileName);
15
+ return {
16
+ projectId: config.projectId,
17
+ genPath: config.genPath ?? output
18
+ };
19
+ }
20
+ function generateConfig(projectId) {
21
+ const lines = [
22
+ `import { defineConfig } from '${configImportPath}'`,
23
+ "",
24
+ "export default defineConfig({",
25
+ " // swirls project identifier",
26
+ ` projectId: '${projectId || ""}',`,
27
+ " // path to generated code",
28
+ ` genPath: 'src/${generatedFileName}',`,
29
+ "})",
30
+ ""
31
+ ];
32
+ return lines.join("\n");
33
+ }
34
+ export {
35
+ configFileName,
36
+ configSchema,
37
+ defineConfig,
38
+ generateConfig
39
+ };
@@ -0,0 +1,99 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { z } from 'zod';
4
+
5
+ type Schema = z.ZodTypeAny;
6
+ type Value<S extends Schema> = z.input<S>;
7
+
8
+ interface FormRegistry {
9
+ }
10
+ type RegistryFormName = Extract<keyof FormRegistry, string>;
11
+ type FormName = [RegistryFormName] extends [never] ? string : RegistryFormName;
12
+ type FormDefinition<K extends string = string, S extends Schema = Schema> = {
13
+ id: string;
14
+ name: K;
15
+ schema: S;
16
+ };
17
+ type FormEntry<K extends FormName> = K extends keyof FormRegistry ? FormRegistry[K] & FormDefinition : FormDefinition;
18
+ declare function registerForm<K extends FormName>(name: K, form: FormEntry<K>): void;
19
+ /**
20
+ * Hook that returns a form adapter for integrating Swirls forms with your form library.
21
+ *
22
+ * The adapter is a bridge object that provides validation, submission, and schema information
23
+ * for a specific Swirls form. It allows you to wire up Swirls forms with any form library
24
+ * (React Hook Form, TanStack Form, Formik, or plain React state).
25
+ *
26
+ * **Returns:** A form adapter object with:
27
+ * - `submit(value)` - Submits form data to the Swirls API and triggers the workflow
28
+ * - `schema` - The Zod schema for the form (useful for form library resolvers)
29
+ * - `defaultValues` - Typed default values for the form
30
+ *
31
+ * **Access:** The adapter is returned directly from the hook. Use it to wire up your form library.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * // TanStack Form
36
+ * import { useForm } from '@tanstack/react-form'
37
+ *
38
+ * // Swirls Form Adapter
39
+ * const adapter = useSwirlsFormAdapter('contact-form', { email: '' })
40
+ *
41
+ * const form = useForm({
42
+ * defaultValues: adapter.defaultValues,
43
+ * validators: {
44
+ * onChange: adapter.schema.parse,
45
+ * },
46
+ * onSubmit: ({ value }) => adapter.submit(value),
47
+ * })
48
+ * ```
49
+ *
50
+ * @param name - The name of the form (autocompleted from registered forms)
51
+ * @param defaultValues - Typed default values matching the form schema
52
+ * @returns Form adapter object for wiring up with your form library
53
+ */
54
+ declare function useSwirlsFormAdapter<K extends FormName>(name: K, defaultValues: Value<FormEntry<K>['schema']>): {
55
+ submit: (value: Value<FormEntry<K>["schema"]>) => Promise<{
56
+ executionIds: string[];
57
+ message: string;
58
+ pizza: boolean;
59
+ }>;
60
+ schema: Schema;
61
+ defaultValues: Value<FormEntry<K>["schema"]>;
62
+ };
63
+ /**
64
+ * Render props component that provides a form adapter for integrating Swirls forms.
65
+ *
66
+ * The adapter is a bridge object that provides validation, submission, and schema information
67
+ * for a specific Swirls form. This component wraps `useSwirlsFormAdapter` and provides the
68
+ * adapter via a render prop, making it convenient for simpler form implementations.
69
+ *
70
+ * **Returns:** Renders the children function with the adapter as an argument.
71
+ *
72
+ * **Access:** The adapter is passed to the `children` render function. Use it within your
73
+ * form JSX to access validation, submission, schema, and defaultValues.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * <SwirlsForm schemaName="contact-form" defaultValues={{ name: '', email: '' }}>
78
+ * {(adapter) => (
79
+ * <form onSubmit={async (e) => {
80
+ * e.preventDefault()
81
+ * await adapter.submit(formData)
82
+ * }}>
83
+ * {/* ... *\/}
84
+ * </form>
85
+ * )}
86
+ * </SwirlsForm>
87
+ * ```
88
+ *
89
+ * @param name - The name of the form (autocompleted from registered forms)
90
+ * @param defaultValues - Typed default values matching the form schema
91
+ * @param children - Render function that receives the adapter object
92
+ */
93
+ declare function SwirlsForm<K extends FormName>({ name, defaultValues, children, }: {
94
+ name: K;
95
+ defaultValues: Value<FormEntry<K>['schema']>;
96
+ children: (adapter: ReturnType<typeof useSwirlsFormAdapter<K>>) => React.ReactNode;
97
+ }): react_jsx_runtime.JSX.Element;
98
+
99
+ export { type FormRegistry, SwirlsForm, registerForm, useSwirlsFormAdapter };
@@ -0,0 +1,75 @@
1
+ // src/form/submit.ts
2
+ import { z } from "zod";
3
+ var API_URL = "https://api.swirls.ai";
4
+ async function submitForm(form, value) {
5
+ const submission = parseSubmission(form.schema, value);
6
+ const response = await fetch(`${API_URL}/forms/${form.id}`, {
7
+ method: "POST",
8
+ headers: {
9
+ "Content-Type": "application/json"
10
+ },
11
+ body: JSON.stringify(submission)
12
+ });
13
+ if (!response.ok) {
14
+ const { message } = await response.json();
15
+ throw new Error(message);
16
+ }
17
+ return parseResponse(response);
18
+ }
19
+ function parseSubmission(schema, value) {
20
+ const parse = schema.safeParse(value);
21
+ if (!parse.success) {
22
+ const message = z.prettifyError(parse.error);
23
+ throw new Error(`Invalid submission: ${message}`, {
24
+ cause: parse.error
25
+ });
26
+ }
27
+ return parse.data;
28
+ }
29
+ var responseSchema = z.object({
30
+ executionIds: z.array(z.string()),
31
+ message: z.string(),
32
+ pizza: z.boolean()
33
+ });
34
+ async function parseResponse(response) {
35
+ const result = await response.json();
36
+ return responseSchema.parse(result);
37
+ }
38
+
39
+ // src/form/form.tsx
40
+ import { Fragment, jsx } from "react/jsx-runtime";
41
+ var formRegistry = {};
42
+ function registerForm(name, form) {
43
+ formRegistry[name] = form;
44
+ }
45
+ function getForm(name) {
46
+ return formRegistry[name];
47
+ }
48
+ function useSwirlsFormAdapter(name, defaultValues) {
49
+ const form = getForm(name);
50
+ if (!form) {
51
+ throw new Error(
52
+ `Form "${name}" is not registered. Did you call registerForms()?`
53
+ );
54
+ }
55
+ return {
56
+ submit: (value) => {
57
+ return submitForm(form, value);
58
+ },
59
+ schema: form.schema,
60
+ defaultValues
61
+ };
62
+ }
63
+ function SwirlsForm({
64
+ name,
65
+ defaultValues,
66
+ children
67
+ }) {
68
+ const adapter = useSwirlsFormAdapter(name, defaultValues);
69
+ return /* @__PURE__ */ jsx(Fragment, { children: children(adapter) });
70
+ }
71
+ export {
72
+ SwirlsForm,
73
+ registerForm,
74
+ useSwirlsFormAdapter
75
+ };
@@ -0,0 +1,10 @@
1
+ import { JsonSchema } from '@swirls/core/schemas';
2
+
3
+ type Form = {
4
+ id: string;
5
+ name: string;
6
+ schema: JsonSchema;
7
+ };
8
+ declare function generateFormsCode(forms: Form[], header: string[]): string;
9
+
10
+ export { generateFormsCode };
@@ -0,0 +1,87 @@
1
+ // src/form/generate.ts
2
+ import { jsonSchemaToZod } from "json-schema-to-zod";
3
+ import { camelCase, pascalCase } from "text-case";
4
+ function generateFormsCode(forms, header) {
5
+ const imports = [
6
+ `import { registerForm } from '@swirls/sdk/form'`,
7
+ `import { z } from 'zod'`,
8
+ ""
9
+ ];
10
+ const schemas = forms.flatMap(
11
+ ({ name, schema }) => generateStandardSchema(name, schema)
12
+ );
13
+ return [
14
+ ...header,
15
+ ...imports,
16
+ ...schemas,
17
+ ...generateRegistry(forms),
18
+ ...generateRegisterFunction(forms),
19
+ ...generateModuleAugmentation(forms)
20
+ ].join("\n");
21
+ }
22
+ function generateStandardSchema(name, schema) {
23
+ const output = jsonSchemaToZod(schema, {
24
+ module: "esm",
25
+ name: schemaName(name).camel,
26
+ noImport: true,
27
+ type: true
28
+ });
29
+ const [object, type] = output.split("\n");
30
+ if (!object || !type) {
31
+ throw new Error("Failed to generate standard schema");
32
+ }
33
+ return [`// Form schema: ${name}`, object, "", type, ""];
34
+ }
35
+ function generateRegistry(forms) {
36
+ return [
37
+ "// Form registry",
38
+ "export const registry = {",
39
+ ...forms.flatMap(({ name, id }) => [
40
+ ` '${name}': {`,
41
+ ` id: '${id}',`,
42
+ ` name: '${name}',`,
43
+ ` schema: ${schemaName(name).camel},`,
44
+ " },"
45
+ ]),
46
+ "} as const",
47
+ ""
48
+ ];
49
+ }
50
+ function generateRegisterFunction(forms) {
51
+ return [
52
+ "// Form registration",
53
+ "export function registerForms() {",
54
+ ...forms.map(({ name }) => {
55
+ return ` registerForm('${name}', registry['${name}'])`;
56
+ }),
57
+ "}",
58
+ ""
59
+ ];
60
+ }
61
+ function generateModuleAugmentation(forms) {
62
+ const module = "@swirls/sdk/form";
63
+ return [
64
+ `// Module augmentation for ${module}`,
65
+ `declare module '${module}' {`,
66
+ " interface FormRegistry {",
67
+ ...forms.flatMap(({ name, id }) => [
68
+ ` '${name}': {`,
69
+ ` id: '${id}'`,
70
+ ` name: '${name}'`,
71
+ ` schema: typeof ${schemaName(name).camel}`,
72
+ " }"
73
+ ]),
74
+ " }",
75
+ "}",
76
+ ""
77
+ ];
78
+ }
79
+ function schemaName(name) {
80
+ return {
81
+ camel: `${camelCase(name)}Schema`,
82
+ pascal: `${pascalCase(name)}Schema`
83
+ };
84
+ }
85
+ export {
86
+ generateFormsCode
87
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@swirls/sdk",
3
+ "version": "0.0.1",
4
+ "description": "Swirls SDK",
5
+ "author": {
6
+ "name": "Swirls",
7
+ "url": "https://swirls.ai"
8
+ },
9
+ "type": "module",
10
+ "exports": {
11
+ "./form": "./dist/form/form.js",
12
+ "./form/generate": "./dist/form/generate.js",
13
+ "./config": "./dist/config/config.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "pkg:publish": "bun publish",
22
+ "prepublishOnly": "bun run build"
23
+ },
24
+ "dependencies": {
25
+ "@swirls/core": "0.0.1",
26
+ "json-schema-to-zod": "2.7.0",
27
+ "text-case": "1.2.9",
28
+ "zod": "4.3.5"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "24.10.0",
32
+ "@types/react": "19.2.6",
33
+ "react": "19.2.1",
34
+ "tsup": "8.5.1"
35
+ },
36
+ "peerDependencies": {
37
+ "react": "^18.0.0 || ^19.0.0",
38
+ "zod": "^4.0.0"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ }
43
+ }