
后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载本篇技术指南围绕 PostGraphile v4 中用于以代码方式批量应用 Smart Tags的三个插件生成器展开makePgSmartTagsFromFilePlugin、makeJSONPgSmartTagsPlugin与底层能力最强的makePgSmartTagsPlugin。文中不仅完整呈现三个 API 的类型签名、实体标识符规则与可复制示例还结合当前仓库中 makePgSmartTagsPlugin.ts 的实现源码与 pgSmartTags.test.ts 测试用例剖析其匹配、合并、watch 模式的底层原理。读完你将掌握如何用 JSON5 文件、代码内 JSON 对象或自定义规则精准地重命名、省略、补充描述 PostGraphile 生成的 GraphQL Schema 中的各类资源。背景Smart Tags 是什么为什么需要插件生成器Smart Tags 是 PostGraphile 提供的一套打标签机制你可以给表、视图、列、函数、约束等 PostgreSQL 实体打上omit从 Schema 中省略、name重命名、description覆盖描述等标签从而在不修改数据库结构的前提下定制生成的 GraphQL Schema。关于 Smart Tags 的完整概念、内置标签清单deprecated、hasDefault、name、fieldName、foreignFieldName、resultFieldName、omit、sortable、filterable、simpleCollections、arg0variant、notNull、primaryKey、foreignKey、unique等以及每种标签的适用实体与取值方式请先参阅 Smart Tags 文档。给实体打标签有多种途径postgraphile.tags.json5文件详见 smart-tags-file.md数据库中的 Smart Comments通过COMMENT ON ...书写一个makePgSmartTagsPlugin系列插件实例即本文主角自己编写的自定义 Graphile Engine 插件。对绝大多数用户官方推荐直接使用postgraphile.tags.json5文件而当你有更高级、更动态、或基于代码逻辑的需求时下面的插件生成器就是更合适的工具。它们构成一个从高封装到底层的递进序列函数封装层级输入方式适用场景makePgSmartTagsFromFilePlugin最高层JSON5 文件路径文件驱动的标签支持 watch 文件变更makeJSONPgSmartTagsPlugin中间层代码内 JSON 对象在代码中直接书写 JSON 配置makePgSmartTagsPlugin最底层规则字符串或匹配函数需要函数式匹配的复杂逻辑注意在当前仓库的新版源码中这三个函数已被重命名为pgSmartTagsFromFile、jsonPgSmartTags、pgSmartTags旧名保留为deprecated别名详见 makePgSmartTagsPlugin.ts 与 index.ts。本文按文档惯例使用旧名同时给出新名以便你在新版代码中无缝使用。makePgSmartTagsFromFilePlugin从 JSON5 文件加载标签这是三者中层级最高、最易用的入口。与大多数插件生成器不同它来自postgraphile/plugins而非graphile-utils——原因正如文档所述它需要访问文件系统。const { makePgSmartTagsFromFilePlugin } require(postgraphile/plugins);用法示例库模式const SmartTagsPlugin makePgSmartTagsFromFilePlugin( // JSON 和 JSONC 也是 JSON5 兼容的所以你也可以使用这些扩展名 /path/to/my/tags.file.json5, ); // ... app.use( postgraphile(process.env.DATABASE_URL, app_public, { //... appendPlugins: [SmartTagsPlugin], }), );这个插件正是 PostGraphile CLI 中自动加载postgraphile.tags.json5文件能力的实现基础CLI 会在当前目录自动查找该文件并处理其中的标签与描述详见 smart-tags-file.md库模式用户则可以按上面的方式显式挂载。你甚至可以多次调用它以合并来自多个文件的标签。从源码看pgSmartTagsFromFile的实现要点如下makePgSmartTagsPlugin.ts默认文件路径为process.cwd() /postgraphile.tags.json5未传参时即为 CLI 约定的默认文件传入路径则指向你的自定义文件它内部包装了jsonPgSmartTags通过readFile(tagsFile, utf8)读取文件、JSON5.parse解析内容支持 watch 模式使用 Node 的watchFile以507ms 的轮询间隔监控文件变化文件变更时重新解析并触发 Schema 刷新若文件被删除ENOENT则回调updateJSON(null)清空标签插件还导出了一个现成的TagsFilePlugin等价于pgSmartTagsFromFile(undefined, TagsFilePlugin)库模式可以直接require(postgraphile/plugins).TagsFilePlugin使用它会自动加载并监视默认的postgraphile.tags.json5文件见 makePgSmartTagsPlugin.ts。如果你希望避免依赖fs模块例如使用 webpack 打包时则应选用下面的makeJSONPgSmartTagsPlugin。makeJSONPgSmartTagsPlugin在代码中书写 JSON 配置该函数来自graphile-utilsconst { makeJSONPgSmartTagsPlugin } require(graphile-utils);完整类型签名function makeJSONPgSmartTagsPlugin( json: JSONPgSmartTags | null, subscribeToJSONUpdatesCallback?: SubscribeToJSONPgSmartTagsUpdatesCallback | null, ): Plugin; type JSONPgSmartTags { version: 1; config: { [kind in PgSmartTagSupportedKinds]?: { [identifier: string]: { tags?: PgSmartTagTags; description?: string; attribute?: { [attributeName: string]: { tags?: PgSmartTagTags; description?: string; }; }; constraint?: { [constraintName: string]: { tags?: PgSmartTagTags; description?: string; }; }; }; }; }; }; type SubscribeToJSONPgSmartTagsUpdatesCallback ( cb: UpdateJSONPgSmartTagsCallback | null, ) void | Promisevoid;它接收一个JSONPgSmartTags对象并把其中描述的标签/描述应用到对应的实体上——它就是makePgSmartTagsFromFilePlugin的底层实现但你可以在自己的 PostGraphile Schema 插件中直接使用它从而避开文件系统。一个空的JSONPgSmartTags对象长这样{ version: 1, config: { class: {}, attribute: {}, constraint: {}, procedure: {}, }, }带注释的、更完整的配置文件示例请见 postgraphile.tags.json5 文件文档。支持的实体 kind 与标识符格式在config对象内部我们可以为每种受支持的 PostgreSQL 实体kind添加条目。文档明确列出的四类为class—— 表、视图、物化视图、复合类型及其他类表实体即可以在 PostgreSQL 系统表pg_class中找到的东西attribute—— 某个class的列/属性即pg_attribute中的内容constraint—— 约束即pg_constraint中的内容procedure—— 函数与存储过程即pg_proc中的内容。源码补充在当前仓库的PgEntityByKind类型中受支持的 kind 实际扩展到了6 种额外包含type类型对应pg_type与namespace模式/Schema见 makePgSmartTagsPlugin.ts 及 L67-L76。测试用例 pgSmartTags.test.ts 也分别验证了type与namespace的匹配不会跨实体泄漏。每种 kind 的 value 是另一个以实体标识符为键的对象。各类实体的标识符格式不同kind标识符格式示例classschema_name.table_nameapp_public.usersattributeschema_name.table_name.column_nameapp_public.users.idconstraintschema_name.table_name.constraint_nameapp_public.users.users_pkeyprocedureschema_name.function_nameapp_public.authenticate注意由于 PostGraphile 不支持函数重载procedure的标识符不包含函数参数。标识符的从左省略规则与批量应用对于每个标识符你可以使用上述完整限定形式也可以省略最左侧的段。例如app_public.users.id列可以写作app_public.users.id、users.id或仅id。当使用的形式不是完全限定时配置将应用到所有匹配的实体上。例如若想在所有表的created_at/updated_at列上统一省略 create/update 操作配置可以写成{ version: 1, config: { attribute: { created_at: { tags: { omit: create,update } }, updated_at: { tags: { omit: create,update } }, }, }, }这种从左省略的匹配逻辑在源码中由parseIdentifierParts解析标识符、再由compileRule生成匹配函数实现解析得到的段会被右对齐缺失的左侧段补undefined然后逐段比较——只要指定了tableName就校验表名指定了schemaName就校验模式名未指定的段直接放行详见 makePgSmartTagsPlugin.ts。parseIdentifierParts还支持 SQL 风格的双引号转义表示一个字面双引号详见 parseIdentifierParts.ts。实体配置参数tags 与 description每个匹配实体的配置对象接受以下参数均可选tags—— 你要应用的所有标签的映射表它们会与通过其他途径Smart Comments、其他插件等应用的标签合并同名标签会被覆盖。具体可用的标签及其取值参见 Smart Tags 文档。description—— 应用于该资源的描述等价于在底层 PostgreSQL 实体上执行COMMENT ON但不会进行 Smart Comment 解析。class 上的便捷属性attribute 与 constraint对class实体还额外提供两个便捷属性以便在同一位置维护表、列与约束的配置attribute—— 用于配置列constraint—— 用于配置约束。使用时列/约束的标识符不能是完全限定的因为表标识符会自动前置。源码中这一逻辑由processEntity实现它会用config.class.table.key.name拼出完整标识符并生成相应规则同时它对嵌套名称做校验——嵌套的列/约束名中不允许出现句点.否则会抛出错误见 makePgSmartTagsPlugin.ts。一个综合示例{ version: 1, config: { class: { post: { description: A post within our forum., tags: { foreignKey: [ (default_user_id) references user (id)|fieldName defaultUser, (organization_id) references organization (id)|fieldName organization, ], }, attribute: { body: { description: The body of the post, tags: { omit: update, }, }, }, }, }, }, }makePgSmartTagsPlugin最底层的规则引擎当 JSON 结构无法表达你的需求例如需要基于实体属性的编程式匹配时makePgSmartTagsPlugin登场。它同样来自graphile-utilsconst { makePgSmartTagsPlugin } require(graphile-utils);完整类型签名function makePgSmartTagsPlugin( ruleOrRules: PgSmartTagRule | PgSmartTagRule[] | null, subscribeToUpdatesCallback?: SubscribeToPgSmartTagUpdatesCallback | null, ): Plugin; interface PgSmartTagRuleT extends PgEntity PgEntity { kind: PgEntityKind; match: string | PgSmartTagFilterFunctionT; tags?: PgSmartTagTags; description?: string; } type PgSmartTagFilterFunctionT (input: T, build: Build) boolean; type UpdatePgSmartTagRulesCallback ( ruleOrRules: PgSmartTagRule | PgSmartTagRule[] | null, ) void; type SubscribeToPgSmartTagUpdatesCallback ( cb: UpdatePgSmartTagRulesCallback | null, ) void | Promisevoid;它是更通用但需要更多投入的插件生成器为makeJSONPgSmartTagsPlugin提供底层能力。与传入配置对象不同这里传入的是规则列表或单条规则。每条规则必须指定kind——class、attribute、constraint或procedure源码中同样额外支持type与namespacematch—— 既可以是标识符字符串遵循与makeJSONPgSmartTagsPlugin相同的从左省略规则也可以是匹配函数tags可选—— 要合并的 Smart Tags 对象description可选—— 覆盖之前的描述。匹配函数规则引擎的真正威力匹配函数使这个插件生成器极其强大——例如它可以用来给所有符合某个与名称无关的条件的 PostgreSQL 实体打标签。匹配函数接收 Graphile Engine 对该实体类型的表示PgClass、PgAttribute、PgConstraint、PgProc等来自pg-introspection以及build对象并返回布尔值表示该实体是否匹配。从源码看compileRule对match的处理逻辑是makePgSmartTagsPlugin.ts若match是函数直接使用该函数若match是字符串先校验 kind 是否合法非法 kind 会抛出错误提示可用值再通过parseIdentifierParts解析为段按 kind 分别生成比较逻辑——例如class会比较rel.relname与可选的nsp.nspnameattribute会比较attname、relname与nspname若match是空字符串解析结果为 0 段则匹配所有该 kind 的实体若既不是函数也不是字符串抛出pgSmartTags rule match is neither a string nor a function错误。应用标签的时机与合并语义规则的实际应用发生在 Graphile Engine 的introspection内省阶段pgIntrospection_introspection钩子会在任何代码使用 tags 之前遍历对应 kind 的内省结果introspection.classes、introspection.attributes、introspection.constraints、introspection.procs、introspection.types、introspection.namespaces对每个匹配实体执行若规则带tagsObject.assign(obj.tags, rule.tags)——覆盖同名标签、保留其他标签若规则带description直接覆盖obj.description。见 makePgSmartTagsPlugin.ts。无匹配时的警告一个值得注意的源码细节如果某条规则没有任何实体命中插件会输出警告提示规则可能存在拼写错误WARNING: there were no matches for makePgSmartTagsPlugin rule {idx} - {rule}makePgSmartTagsPlugin.ts。这能帮你在配置了大量规则时快速定位拼写失误或标识符错误。Watch 模式Schema 热刷新makePgSmartTagsFromFilePlugin与makeJSONPgSmartTagsPlugin均支持在 watch 模式下让 Schema 随标签变更自动刷新。makeJSONPgSmartTagsPlugin的第二个参数是subscribeToJSONUpdatesCallback。当 Graphile Engine 进入 watch 模式例如 CLI 的postgraphile --watch时该回调会被调用并传入一个回调函数——当变更发生时你必须调用这个回调退出 watch 模式时该函数会再次被调用不传回调你需要释放此前建立的监视。makePgSmartTagsFromFilePlugin内部正是借助这一点监控 JSON5 文件变化并触发 Schema 刷新如前所述实现为 507ms 间隔的watchFile轮询。makePgSmartTagsPlugin同样支持subscribeToUpdatesCallback工作方式与subscribeToJSONUpdatesCallback一致。源码中watch 更新时新的规则会被resolveRules解析并写入info.cache.rulesPromise随后触发callback()让 Schema 重新构建若解析出错错误会被记录而不会中断进程见 makePgSmartTagsPlugin.ts。从源码看两个易踩的坑version必须为 1pgSmartTagRulesFromJSON会校验json.version ! 1否则抛出This version of graphile-utils only supports the version 1 smart tags JSON format错误makePgSmartTagsPlugin.ts。测试 pgSmartTags.test.ts 也专门验证了这一点。嵌套规则只支持tags与description在class的嵌套attribute/constraint或标识符规格中设置其他键会触发警告提示如jsonPgSmartTags identifier spec only supports tags, description, attribute and constraint提醒你也许忘了把它们包进tags里makePgSmartTagsPlugin.ts。测试验证行为即契约仓库中 pgSmartTags.test.ts 以真实的 PostgreSQL 测试库验证了上述行为可作为你理解各 API 语义的可靠参照pgSmartTags applies table descriptions通过kind: class、match: graphile_utils.users覆盖表的 GraphQL 描述多组does not leak matches across ...测试分别对class、attribute、constraint、procedure、type、namespace验证——一条规则的描述不会泄漏到名称相近的其他实体上例如graphile_utils.users.name不会影响graphile_utils.pets.namejsonPgSmartTags applies JSON-based rules验证 JSON 对象配置的端到端效果pgSmartTagRulesFromJSON validates version验证 version 校验逻辑。这些测试展示了三个插件生成器最核心的语义按标识符精确命中、描述覆盖、标签合并、且绝不跨实体泄漏。如何选择需要文件驱动、支持 CLI 约定或热加载 →makePgSmartTagsFromFilePlugin或直接使用TagsFilePlugin想要避开fs如 webpack 环境、在代码中集中管理配置 →makeJSONPgSmartTagsPlugin需要按列名以外的属性如实体类型、权限、命名空间等编程式匹配或希望以null关闭所有标签 →makePgSmartTagsPlugin的匹配函数。三者共享同一套合并语义tags与既有标签合并同名覆盖description直接覆盖。无论选择哪个都可以与 postgraphile.tags.json5 文件、数据库 Smart Comments 以及其他自定义插件叠加使用共同定制你的 PostGraphile GraphQL Schema。赞分享后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载相关推荐软件兄弟的AdminJS安装与配置完全指南软件兄弟的AdminJS安装与配置完全指南 项目基础介绍及主要编程语言 AdminJS是由软件兄弟SoftwareBrothers开发的一款专为Node.j后端低代码PostGraphile Smart Tags 完全指南用数据库注释与 JSON5 配置定制 GraphQL SchemaPostGraphile Smart Tags 完全指南用数据库注释与 JSON5 配置定制 GraphQL Schema 本文基于 PostGraphile后端API网关Flipper Zero 密码生成器插件PassGen完全指南从 FAP 构建到源码级原理Flipper Zero 密码生成器插件PassGen完全指南从 FAP 构建到源码级原理 导读 本文以 grnch/passgen https://li示例工程上一篇3分钟上手YAML驱动的工作流DolphinScheduler配置即流程实践下一篇7大核心模型揭秘Easy Dataset基于Prisma的LLM数据集高效管理方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考