@techflows/shared-core

v1.1.0

Published

Shared validation schemas, types, and utilities for TechFlow

Readme

@techflows/shared-core

npm version TypeScript Zod

Shared validation schemas, types, and utilities for TechFlow.

A strictly-typed, environment-agnostic core library built on top of Zod. Designed to be consumed by both frontend and backend codebases so validation logic and TypeScript definitions never go out of sync.


Table of Contents


Why?

In a full-stack TypeScript project, keeping request validation in sync with your UI forms is tedious and error-prone. @techflows/shared-core solves this by providing a single source of truth:

| Concern | Solution | |---------|----------| | Validation | Zod schemas with granular error messages | | Types | TypeScript types inferred from schemasβ€”never manually maintained | | Frontend helpers | Lightweight validateXxx() wrappers that return strings (perfect for form error states) | | Utilities | Pure, environment-agnostic helpers (work in Node.js, browsers, edge runtimes) |


Installation

npm install @techflows/shared-core

Peer dependency: zod ^3.24.1 (automatically installed if missing).


Quick Start

import { RegisterSchema, type RegisterInput, validateEmail } from '@techflows/shared-core';
import { z } from 'zod';

// 1. Validate on the backend
const body = RegisterSchema.parse(req.body);   // throws on failure
const safe = RegisterSchema.safeParse(req.body); // returns `{ success, data/error }`

// 2. Get fully typed input
function createUser(input: RegisterInput) {
  // input is statically typed: { username, email, password }
}

// 3. Lightweight frontend validation
const error = validateEmail('not-an-email');
// β†’ "Invalid email address"

Features

πŸ” Auth & User Management

  • RegisterSchema / RegisterInput
  • LoginSchema / LoginInput
  • UpdateProfileSchema / UpdateProfileInput
  • SelfUpdateUserSchema / AdminUpdateUserSchema
  • ChangePasswordSchema / ChangePasswordInput
  • UserSearchSchema / UserSearchInput

πŸ“ Content (Articles & Comments)

  • CreateArticleSchema / UpdateArticleSchema
  • ArticleQuerySchema (with pagination, sorting, filters)
  • CreateCommentSchema / UpdateCommentSchema
  • LikeSchema

🏷️ Taxonomy & Notifications

  • CreateCategorySchema / UpdateCategorySchema
  • CreateNotificationSchema

βš™οΈ System & Admin

  • CreateSettingSchema / UpdateSettingSchema / BatchUpdateSettingsSchema
  • VerificationSchema (author / company / KOL verification)
  • SearchSchema (global search with type filtering)

πŸ—„οΈ Infrastructure Configs

  • CreateDatabaseConfigSchema / UpdateDatabaseConfigSchema / TestDatabaseConnectionSchema
  • CreateCosConfigSchema / UpdateCosConfigSchema / TestCosConnectionSchema
  • CreateOAuthProviderSchema / UpdateOAuthProviderSchema / ToggleOAuthProviderSchema

πŸ› οΈ Primitives & Utilities

  • emailSchema, passwordSchema, usernameSchema
  • PaginationSchema
  • sanitizeInput, isValidUuid, slugify
  • validateEmail, validatePassword, validateUsername

API Reference

Schemas

All schemas are Zod objects exported from the root. You can use them directly for parsing or compose them further.

import {
  RegisterSchema,
  LoginSchema,
  CreateArticleSchema,
  ArticleQuerySchema,
  PaginationSchema,
  emailSchema,
  passwordSchema,
  usernameSchema,
  // … and 30+ more
} from '@techflows/shared-core';

Primitive Schemas

| Schema | Rules | |--------|-------| | emailSchema | Required, valid email format | | passwordSchema | 8–128 chars, upper + lower + number + special character, bans common passwords and sequential sequences | | usernameSchema | 3–30 chars, alphanumeric + underscore, bans reserved names (admin, root, etc.) |

Pagination

PaginationSchema.parse({ page: '2', limit: '20' });
// β†’ { page: 2, limit: 20 } (coerced)

Auth Schemas

| Schema | Fields | |--------|--------| | RegisterSchema | username, email, password | | LoginSchema | email, password, rememberMe? | | UpdateProfileSchema | username?, bio?, avatar?, github?, website?, location?, skills? | | ChangePasswordSchema | currentPassword, newPassword | | UserSearchSchema | page, limit, search?, role?, status? |

Article Schemas

| Schema | Fields | |--------|--------| | CreateArticleSchema | title, content, excerpt?, coverImage?, status?, categoryId?, tags?, editorType?, blockDoc? | | UpdateArticleSchema | Same as CreateArticleSchema but all fields optional (.partial()) | | ArticleQuerySchema | page, limit, search?, category?, tag?, status?, authorId?, sort? |

Admin & System Schemas

| Schema | Purpose | |--------|---------| | CreateDatabaseConfigSchema | MySQL / Postgres / SQLite / MongoDB / Redis connection config | | CreateCosConfigSchema | Object-storage config (AWS, Aliyun, Tencent, Qiniu, Huawei, MinIO, Cloudflare) | | CreateOAuthProviderSchema | OAuth 2.0 provider setup (clientId, authUrl, tokenUrl, etc.) | | BatchUpdateSettingsSchema | Batch update up to 50 settings at once | | VerificationSchema | KYC / author verification request |


Types

Every schema has a corresponding *Input type inferred automatically via z.infer. You never need to write these by hand.

import type {
  RegisterInput,
  LoginInput,
  CreateArticleInput,
  UpdateArticleInput,
  ArticleQueryInput,
  PaginationInput,
  // … and 30+ more
} from '@techflows/shared-core';

Example

async function registerUser(data: RegisterInput) {
  // data is fully typed
  const { username, email, password } = data;
}

Validators

For frontend forms where you want a quick string | null error message (instead of a Zod error object):

import { validateEmail, validatePassword, validateUsername } from '@techflows/shared-core';

const emailError    = validateEmail('bad');      // β†’ "Invalid email address"
const passwordError = validatePassword('123');   // β†’ "Password must be at least 8 characters"
const usernameError = validateUsername('ab');    // β†’ "Username must be at least 3 characters"

These helpers are thin wrappers around the same Zod schemas used on the backend, so frontend and backend validation rules are guaranteed to stay in sync.


Utilities

Pure functions that work in any JavaScript environment (Node.js, browser, edge workers).

import { sanitizeInput, isValidUuid, slugify } from '@techflows/shared-core';

sanitizeInput(input: string): string

Escapes HTML entities and trims whitespace.

sanitizeInput('<script>alert(1)</script>');
// β†’ "&lt;script&gt;alert(1)&lt;/script&gt;"

isValidUuid(str: string): boolean

Validates RFC-4122 UUID v1–v5 format.

isValidUuid('550e8400-e29b-41d4-a716-446655440000'); // β†’ true
isValidUuid('not-a-uuid');                            // β†’ false

slugify(text: string): string

Converts any string into a URL-friendly slug.

slugify('Hello World! δ½ ε₯½');
// β†’ "hello-world-ni-hao"

Rules:

  1. Decomposes Unicode accents (NFD normalization)
  2. Lowercases everything
  3. Replaces spaces with hyphens
  4. Strips non-word characters
  5. Collapses multiple hyphens

Constants

Shared enumerations used across the TechFlow platform:

import { Roles, Statuses, ArticleStatuses, NotificationTypes } from '@techflows/shared-core';

| Constant | Values | |----------|--------| | Roles | 'USER', 'AUTHOR', 'ADMIN' | | Statuses | 'ACTIVE', 'BANNED', 'PENDING_VERIFY' | | ArticleStatuses | 'DRAFT', 'PUBLISHED', 'ARCHIVED' | | NotificationTypes | 'SYSTEM', 'COMMENT', 'LIKE', 'FOLLOW' |


Usage Examples

Backend (Express / Next.js API)

import { Request, Response } from 'express';
import { RegisterSchema, type RegisterInput } from '@techflows/shared-core';

export async function registerHandler(req: Request, res: Response) {
  const parseResult = RegisterSchema.safeParse(req.body);

  if (!parseResult.success) {
    return res.status(400).json({
      message: 'Validation failed',
      errors: parseResult.error.flatten().fieldErrors,
    });
  }

  const data: RegisterInput = parseResult.data;
  // … proceed to create user
}

Frontend (React / Vue)

import { useState } from 'react';
import { validateEmail, validatePassword, validateUsername } from '@techflows/shared-core';

export function RegisterForm() {
  const [email, setEmail] = useState('');
  const [errors, setErrors] = useState<Record<string, string | null>>({});

  function handleBlur(field: 'email' | 'password' | 'username', value: string) {
    const validator =
      field === 'email'    ? validateEmail :
      field === 'password' ? validatePassword :
                             validateUsername;
    setErrors((prev) => ({ ...prev, [field]: validator(value) }));
  }

  return (
    <form>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        onBlur={(e) => handleBlur('email', e.target.value)}
      />
      {errors.email && <span className="error">{errors.email}</span>}
    </form>
  );
}

Development

# Install dependencies
npm install

# Build (TypeScript β†’ dist/)
npm run build

# Watch mode
npm run dev

# Lint
npm run lint

Project Structure

β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts       # Public API exports
β”‚   β”œβ”€β”€ schemas.ts     # Zod schemas (validation rules)
β”‚   β”œβ”€β”€ types.ts       # Inferred TypeScript types
β”‚   β”œβ”€β”€ validators.ts  # Lightweight frontend helpers
β”‚   └── utils.ts       # Environment-agnostic utilities
β”œβ”€β”€ dist/              # Compiled output (published)
β”œβ”€β”€ tsconfig.json      # Strict TypeScript config (ES2022 + bundler resolution)
└── package.json

License

MIT Β© TechFlow