pdf-forge

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

pdf-forge

pdf-forge

Go module for multi-tenant document templates with PDF generation via Typst.
一个基于Typst的多租户文档模板PDF生成Go模块。

Installation

安装

bash
npx skills add https://github.com/rendis/pdf-forge --skill pdf-forge
bash
npx skills add https://github.com/rendis/pdf-forge --skill pdf-forge

How It Works

工作原理

plaintext
Tenant → Workspace → Template → Version (DRAFT→PUBLISHED)
                              Injectables (variables)
                              Render → PDF
plaintext
Tenant → Workspace → Template → Version (DRAFT→PUBLISHED)
                              Injectables (variables)
                              Render → PDF

Quick Start

快速开始

go
// core/extensions/register.go
func Register(engine *sdk.Engine) {
    engine.RegisterInjector(&CustomerNameInjector{})
    engine.SetMapper(&MyMapper{})
    engine.SetInitFunc(MyInit())
}

// core/cmd/api/main.go
func main() {
    engine := sdk.NewWithConfig("settings/app.yaml").
        SetI18nFilePath("settings/injectors.i18n.yaml")
    extensions.Register(engine)
    if err := engine.Run(); err != nil {
        slog.Error("failed to run engine", slog.String("error", err.Error()))
        os.Exit(1)
    }
}
go
// core/extensions/register.go
func Register(engine *sdk.Engine) {
    engine.RegisterInjector(&CustomerNameInjector{})
    engine.SetMapper(&MyMapper{})
    engine.SetInitFunc(MyInit())
}

// core/cmd/api/main.go
func main() {
    engine := sdk.NewWithConfig("settings/app.yaml").
        SetI18nFilePath("settings/injectors.i18n.yaml")
    extensions.Register(engine)
    if err := engine.Run(); err != nil {
        slog.Error("failed to run engine", slog.String("error", err.Error()))
        os.Exit(1)
    }
}

Creating an Injector

创建注入器

go
type CustomerNameInjector struct{}

func (i *CustomerNameInjector) Code() string { return "customer_name" }

func (i *CustomerNameInjector) Resolve() (sdk.ResolveFunc, []string) {
    return func(ctx context.Context, injCtx *sdk.InjectorContext) (*sdk.InjectorResult, error) {
        payload := injCtx.RequestPayload().(map[string]any)
        return &sdk.InjectorResult{Value: sdk.StringValue(payload["name"].(string))}, nil
    }, nil  // dependencies
}

func (i *CustomerNameInjector) IsCritical() bool              { return true }
func (i *CustomerNameInjector) Timeout() time.Duration        { return 5 * time.Second }
func (i *CustomerNameInjector) DataType() sdk.ValueType       { return sdk.ValueTypeString }
func (i *CustomerNameInjector) DefaultValue() *sdk.InjectableValue { return nil }
func (i *CustomerNameInjector) Formats() *sdk.FormatConfig    { return nil }
go
type CustomerNameInjector struct{}

func (i *CustomerNameInjector) Code() string { return "customer_name" }

func (i *CustomerNameInjector) Resolve() (sdk.ResolveFunc, []string) {
    return func(ctx context.Context, injCtx *sdk.InjectorContext) (*sdk.InjectorResult, error) {
        payload := injCtx.RequestPayload().(map[string]any)
        return &sdk.InjectorResult{Value: sdk.StringValue(payload["name"].(string))}, nil
    }, nil  // dependencies
}

func (i *CustomerNameInjector) IsCritical() bool              { return true }
func (i *CustomerNameInjector) Timeout() time.Duration        { return 5 * time.Second }
func (i *CustomerNameInjector) DataType() sdk.ValueType       { return sdk.ValueTypeString }
func (i *CustomerNameInjector) DefaultValue() *sdk.InjectableValue { return nil }
func (i *CustomerNameInjector) Formats() *sdk.FormatConfig    { return nil }

Value Types

数据类型

TypeConstructorConstant
Text
sdk.StringValue(s)
sdk.ValueTypeString
Number
sdk.NumberValue(n)
sdk.ValueTypeNumber
Boolean
sdk.BoolValue(b)
sdk.ValueTypeBool
Date/Time
sdk.TimeValue(t)
sdk.ValueTypeTime
Image
sdk.ImageValue(url)
sdk.ValueTypeImage
Table
sdk.TableValueData(t)
sdk.ValueTypeTable
List
sdk.ListValueData(l)
sdk.ValueTypeList
See types-reference.md for Tables, Lists, InjectorContext, FormatConfig.
类型构造函数常量
文本
sdk.StringValue(s)
sdk.ValueTypeString
数字
sdk.NumberValue(n)
sdk.ValueTypeNumber
布尔值
sdk.BoolValue(b)
sdk.ValueTypeBool
日期/时间
sdk.TimeValue(t)
sdk.ValueTypeTime
图片
sdk.ImageValue(url)
sdk.ValueTypeImage
表格
sdk.TableValueData(t)
sdk.ValueTypeTable
列表
sdk.ListValueData(l)
sdk.ValueTypeList
关于表格、列表、InjectorContext、FormatConfig的详细信息,请查看types-reference.md

Built-in Injectors

内置注入器

CodeTypeFormats
date_now
TIMEDD/MM/YYYY, MM/DD/YYYY, YYYY-MM-DD
time_now
TIMEHH:mm, HH:mm:ss, hh:mm a
date_time_now
TIMECombined
year_now
NUMBER-
month_now
NUMBERnumber, name, short_name
day_now
NUMBER-
标识码类型格式
date_now
TIMEDD/MM/YYYY, MM/DD/YYYY, YYYY-MM-DD
time_now
TIMEHH:mm, HH:mm:ss, hh:mm a
date_time_now
TIME组合格式
year_now
NUMBER-
month_now
NUMBERnumber, name, short_name
day_now
NUMBER-

Error Handling

错误处理

IsCritical()
On Error
true
Aborts render
false
Uses
DefaultValue()
, continues
IsCritical()
错误时行为
true
终止渲染流程
false
使用
DefaultValue()
,继续渲染

Extension Points

扩展点

ExtensionPurposeRegister
InjectorData resolvers
RegisterInjector()
MapperRequest parsing
SetMapper()
InitFuncShared setup
SetInitFunc()
ProviderDynamic injectables
SetWorkspaceInjectableProvider()
AuthCustom render auth
SetRenderAuthenticator()
MiddlewareRequest handling
UseMiddleware()
,
UseAPIMiddleware()
FrontendEmbedded SPA
SetFrontendFS()
(nil to disable)
LifecycleStartup/shutdown
OnStart()
,
OnShutdown()
See extensions-reference.md for implementation examples.
扩展类型用途注册方式
Injector数据解析器
RegisterInjector()
Mapper请求解析器
SetMapper()
InitFunc全局初始化
SetInitFunc()
Provider动态注入项
SetWorkspaceInjectableProvider()
Auth自定义渲染认证
SetRenderAuthenticator()
Middleware请求处理中间件
UseMiddleware()
,
UseAPIMiddleware()
Frontend嵌入式SPA
SetFrontendFS()
(设为nil可禁用)
Lifecycle启动/关闭钩子
OnStart()
,
OnShutdown()
实现示例请参考extensions-reference.md

Configuration

配置

See config-reference.md for all YAML keys, env vars, and auth setup.
Dummy auth: Omit
auth
config entirely for development mode.
所有YAML配置项、环境变量和认证设置请参考config-reference.md
虚拟认证:开发模式下可完全省略
auth
配置。

CLI Commands

CLI命令

bash
make build      # Build frontend + embed + Go binary (single binary)
make embed-app  # Build frontend and copy to Go embed location
make run        # Run API server (with embedded frontend)
make dev        # Hot reload backend (air)
make migrate    # Apply database migrations
make test       # Run tests
make lint       # Run linter
make swagger    # Regenerate OpenAPI spec
make doctor     # Check system dependencies
bash
make build      # Build frontend + embed + Go binary (single binary)
make embed-app  # Build frontend and copy to Go embed location
make run        # Run API server (with embedded frontend)
make dev        # Hot reload backend (air)
make migrate    # Apply database migrations
make test       # Run tests
make lint       # Run linter
make swagger    # Regenerate OpenAPI spec
make doctor     # Check system dependencies

Common Mistakes

常见错误

WrongCorrect
sdk.NewTextValue()
sdk.StringValue()
sdk.ValueTypeText
sdk.ValueTypeString
Forgetting dependencies
return fn, []string{"dep1"}
IsCritical()=true
without handling
Provide
DefaultValue()
错误做法正确做法
sdk.NewTextValue()
sdk.StringValue()
sdk.ValueTypeText
sdk.ValueTypeString
忘记声明依赖项
return fn, []string{"dep1"}
IsCritical()=true
但未设置默认值
提供
DefaultValue()

API Headers

API请求头

HeaderPurposeUsed By
Authorization
Bearer <JWT>
(omit in dummy mode)
All auth routes
X-Tenant-ID
Tenant UUIDPanel routes
X-Workspace-ID
Workspace UUIDPanel routes
X-Tenant-Code
Tenant code (e.g.
CL
)
Render routes
X-Workspace-Code
Workspace code (e.g.
SYSTEM
)
Render routes
请求头用途适用场景
Authorization
Bearer <JWT>
(虚拟模式下可省略)
所有认证路由
X-Tenant-ID
租户UUID面板路由
X-Workspace-ID
工作区UUID面板路由
X-Tenant-Code
租户编码(例如
CL
渲染路由
X-Workspace-Code
工作区编码(例如
SYSTEM
渲染路由

References

参考文档

  • config-reference.md - YAML keys, env vars, auth, performance
  • types-reference.md - Tables, Lists, FormatConfig, InjectorContext
  • extensions-reference.md - Middleware, Lifecycle, Provider, Auth examples
  • patterns-reference.md - Logging, error handling, context, anti-patterns
  • enterprise-scenarios.md - CRM integration, Vault, validation patterns
  • domain-reference.md - Tenants, workspaces, roles, render flow
  • config-reference.md - YAML配置项、环境变量、认证、性能优化
  • types-reference.md - 表格、列表、FormatConfig、InjectorContext
  • extensions-reference.md - 中间件、生命周期、Provider、Auth实现示例
  • patterns-reference.md - 日志、错误处理、上下文、反模式
  • enterprise-scenarios.md - CRM集成、Vault、验证模式
  • domain-reference.md - 租户、工作区、角色、渲染流程