yarn global add ruk-cuk
Generate Moleculer-compliant TypeScript typings from any 3.x OpenAPI document.
ruk-cuk generate [documents..]
generate Moleculer-compliant TypeScript signatures from 3.x OpenAPI documents
Positionals:
documents Location of 3.x OpenAPI documents. [array] [default: []]
Options:
--version Show version number [boolean]
--help Show help [boolean]
-o, --output The name of the file or full file path to store def
initions as [string] [default: "types.d.ts"]
--prettify Use Prettier to format the output code
[boolean] [default: true]
-q, --quiet Print nothing but errors [boolean] [default: false]
--ts-namespace-prefix Prefix used within the TypeScript declaration name
[string] [default: ""]
--ts-skip-events Exclude events definitions
[boolean] [default: false]
-w, --watch Watch document and rebuild on changes
[boolean] [default: false]
Given the following OpenAPI Document
openapi.v1.json
{
"openapi": "3.1.0",
"info": {
"title": "Activity",
"version": "1.0",
"description": "Operations for managing activity logs."
},
"paths": {
"/v1/workspaces/{workspace_id}/activity": {
"get": {
"summary": "List Workspace Activity",
"tags": [],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Activity"
}
}
}
},
"headers": {
"Link": {
"schema": {
"type": "string"
},
"description": "Provides links to the next and previous results per https://datatracker.ietf.org/doc/html/rfc5988"
}
}
},
"400": {
"$ref": "#/components/responses/BadRequestError"
},
"401": {
"$ref": "#/components/responses/UnauthorizedError"
},
"402": {
"$ref": "#/components/responses/PaymentRequired"
},
"403": {
"$ref": "#/components/responses/ForbiddenError"
},
"404": {
"$ref": "#/components/responses/NotFoundError"
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
},
"operationId": "v1.activity.byWorkspace",
"security": [
{
"Authorization": []
}
],
"parameters": [
{
"schema": {
"type": "string",
"example": "2021-08-02T14:59:01.433Z",
"format": "date-time"
},
"in": "query",
"name": "before",
"description": "Filter list before a specific created date. Useful for pagination."
},
{
"schema": {
"type": "string",
"format": "date-time",
"example": "2021-08-02T14:59:01.433Z"
},
"in": "query",
"name": "after",
"description": "Filter list after a specific created date. Useful for pagination."
},
{
"schema": {
"type": "number",
"default": 50,
"minimum": 1,
"maximum": 100
},
"in": "query",
"name": "limit",
"description": "Limit the size of the list returned"
},
{
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ActivityType"
}
},
"in": "query",
"name": "type",
"description": "Filter to a specific activity types"
},
{
"schema": {
"type": "string"
},
"in": "query",
"name": "group",
"description": "Filter to a specific group ID"
}
]
},
"parameters": [
{
"schema": {
"type": "string",
"example": "d2s6MQ"
},
"name": "workspace_id",
"in": "path",
"required": true,
"description": "Base64 encoded \"wk:\" + workspace ID"
}
]
},
"/v1/activity/hasura-event-handler": {
"post": {
"summary": "Hasura Activity Log Event Handler",
"operationId": "v1.activity.hasuraEventHandler",
"responses": {
"200": {
"description": "OK"
}
},
"x-internal": true,
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"event": {
"type": "object",
"required": ["session_variables", "op", "data"],
"properties": {
"session_variables": {
"type": ["object", "null"]
},
"op": {
"type": "string",
"enum": ["INSERT", "UPDATE", "DELETE", "MANUAL"]
},
"data": {
"type": "object",
"required": ["old", "new"],
"properties": {
"old": {
"type": ["object", "null"]
},
"new": {
"type": ["object", "null"]
}
}
}
}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"id": {
"type": "string"
},
"trigger": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
}
}
},
"table": {
"type": "object",
"required": ["schema", "name"],
"properties": {
"schema": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
},
"required": ["event", "created_at", "id", "trigger", "table"]
}
}
}
},
"description": ""
},
"parameters": []
}
},
"components": {
"schemas": {
"Activity": {
"title": "Activity",
"type": "object",
"examples": [],
"properties": {
"id": {
"type": "string"
},
"type": {
"$ref": "#/components/schemas/ActivityType"
},
"metadata": {
"type": "object",
"description": "Additional information specific to the activity type"
},
"created_at": {
"type": "string",
"description": "Timestamp when the activity was performed",
"format": "date-time"
},
"ip_address": {
"type": ["string", "null"],
"description": "IP address of client where the activity was performed",
"format": "ipv4"
},
"actor": {
"type": ["object", "null"],
"description": "User who performed the activity",
"required": ["name", "email"],
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
}
}
}
},
"required": [
"id",
"type",
"metadata",
"created_at",
"ip_address",
"actor"
]
},
"Error": {
"title": "Error",
"type": "object",
"description": "Represents generic error",
"examples": [
{
"message": "Name is required.",
"code": 400,
"type": "VALIDATION_ERROR"
}
],
"properties": {
"message": {
"type": "string",
"description": "Detailed error message"
},
"code": {
"type": "number",
"enum": [400, 401, 403, 404, 409, 500],
"description": "HTTP Status Code"
},
"type": {
"type": "string",
"description": "Error type"
}
},
"required": ["message", "code"]
},
"ActivityType": {
"type": "string",
"title": "ActivityType",
"enum": ["create", "move", "read", "delete", "update"]
}
},
"securitySchemes": {
"Authorization": {
"type": "http",
"scheme": "bearer"
}
},
"responses": {
"BadRequestError": {
"description": "The server could not understand the request due to invalid syntax.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"Missing required field": {
"value": {
"message": "Name is required.",
"code": 400,
"type": "VALIDATION_ERROR"
}
}
}
},
"application/xml": {
"schema": {
"type": "object",
"properties": {}
}
},
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"NotFoundError": {
"description": "The server can not find the requested resource.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"Entity not found": {
"value": {
"message": "Group is not found",
"code": 404,
"type": "GROUP_NOT_FOUND"
}
}
}
}
}
},
"UnauthorizedError": {
"description": "The client must authenticate itself to get the requested response.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"Missing authorization header": {
"value": {
"message": "Missing authorization",
"code": 401,
"type": "UNAUTHORIZED"
}
}
}
}
}
},
"PaymentRequired": {
"description": "The client must be on the correct billing plan to access the content.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"Payment Required": {
"value": {
"code": 402,
"type": "PAYMENT_REQUIRED",
"message": "This feature is not enabled for your workspace billing plan, or your workspace billing is out of standing."
}
}
}
}
}
},
"ForbiddenError": {
"description": "The client does not have permissions to access the content.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"No permissions": {
"value": {
"message": "You do not have permissions to delete this group.",
"code": 403,
"type": "FORBIDDEN"
}
}
}
}
}
},
"InternalServerError": {
"description": "The server has encountered a situation it doesn't know how to handle.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
},
"examples": {
"Transporter receives unknown data": {
"value": {
"message": "Internal Server Error",
"code": 500,
"type": "INVALID_PACKET_DATA"
}
}
}
}
}
}
},
"parameters": {}
}
}
Executing
ruk-cuk generate "openapi.v1.json"
would generate types.d.ts
file with the following content:
declare namespace Activity {
type Actions = {
'v1.activity': {
byWorkspace: (params: ByWorkspaceParams) => Promise<ByWorkspaceResponse>;
hasuraEventHandler: (params: HasuraEventHandlerParams) => Promise<void>;
};
};
type Events = never;
type ByWorkspaceParams = {
workspace_id: string;
before?: string;
after?: string;
/**
* @defaultValue `50`
*/
limit?: number;
type?: ActivityType[];
group?: string;
};
type ByWorkspaceResponse = Activity[];
type HasuraEventHandlerParams = {
event: {
session_variables: Record<string, unknown> | null;
op: 'INSERT' | 'UPDATE' | 'DELETE' | 'MANUAL';
data: {
old: Record<string, unknown> | null;
new: Record<string, unknown> | null;
[k: string]: unknown;
};
[k: string]: unknown;
};
created_at: string;
id: string;
trigger: {
name: string;
[k: string]: unknown;
};
table: {
schema: string;
name: string;
[k: string]: unknown;
};
[k: string]: unknown;
};
type Activity = {
id: string;
type: ActivityType;
/**
* Additional information specific to the activity type
*/
metadata: Record<string, unknown>;
/**
* Timestamp when the activity was performed
*/
created_at: string;
/**
* IP address of client where the activity was performed
*/
ip_address: string | null;
/**
* User who performed the activity
*/
actor: {
name: string;
email: string;
[k: string]: unknown;
} | null;
[k: string]: unknown;
};
type Error = {
/**
* Detailed error message
*/
message: string;
/**
* HTTP Status Code
*/
code: 400 | 401 | 403 | 404 | 409 | 500;
/**
* Error type
*/
type?: string;
[k: string]: unknown;
};
type ActivityType = 'create' | 'move' | 'read' | 'delete' | 'update';
type BadRequestError = Error | Record<string, unknown>;
type NotFoundError = Error;
type UnauthorizedError = Error;
type PaymentRequired = Error;
type ForbiddenError = Error;
type InternalServerError = Error;
}