ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

使用 @tinacms/graphql 将文件与文件夹构建为可查询的 GraphQL 内容数据库

使用 @tinacms/graphql 将文件与文件夹构建为可查询的 GraphQL 内容数据库 使用 tinacms/graphql 将文件与文件夹构建为可查询的 GraphQL 内容数据库【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacmsTinaCMS 是面向 Markdown、MDX、JSON、YAML 等文本格式的开源 headless CMS而本篇文章聚焦的tinacms/graphql正是其核心引擎它把仓库里的一堆文件夹和文件编译成一个可以用 GraphQL 查询的数据库并提供文档间引用、schema 预生成与索引加速等能力。读完本文你将掌握该包的完整使用流程——从安装、定义 schema、建立数据库索引到执行 GraphQL 查询并深入理解其 Bridge、Level 存储、索引与解析器的源码实现。包定位文件系统到 GraphQL 数据库的桥梁tinacms/graphql位于 packages/tinacms/graphql它解决的问题非常明确让静态内容Markdown、MDX、JSON、YAML 等具备数据库般可查询的能力。其核心思路是两阶段流水线建库阶段index把磁盘上的内容文件读取、解析连同生成的 GraphQL Schema 一起写入一个 LevelDB 兼容的索引存储中查询阶段resolve接收 GraphQL 查询字符串借助预生成的 schema 与索引数据完成字段解析、引用关联与列表过滤。包入口 src/index.ts 导出了这套流水线的全部关键 APIDatabase、createDatabase、createLocalDatabase、FilesystemBridge、buildSchema、resolve以及getChangedFiles、getSha、shaExists等 Git 辅助函数。三大核心特性用 GraphQL 查询多种内容格式Markdown、MDX、JSON、YAML 等文件都被统一建模为文档Document并以相同的方式暴露给查询层文档间引用references一个文档可以引用另一个文档查询时能按需展开被引用文档的字段预生成 schema 与查询数据在构建期生成_schema.json、_graphql.json、_lookup.json等产物加速网站编译期查询避免运行时再全量解析。安装方式最简单的接入方式是通过官方脚手架创建完整的 TinaCMS 站点在项目根目录执行npx create-tina-applatest如果只想在现有项目中单独使用本包则按如下步骤安装pnpm install pnpm add tinacms/graphql从仓库内的 package.json 可以看到包当前版本为2.4.11它依赖graphql15.8.0作为查询执行引擎并通过tinacms/schema-tools同仓库工作区包提供 schema 类型定义与校验能力。构建你的第一个查询程序README 提供了一个完整的端到端示例下面逐段展开并补充说明。1. 引入依赖import { MemoryLevel } from memory-level; import { Database, FilesystemBridge, buildSchema, resolve } from tinacms/graphql; import { Schema } from tinacms/schema-tools;FilesystemBridge负责从文件系统读写内容的桥接器对应源码 src/database/bridge/filesystem.tsMemoryLevel来自memory-level的内存版 LevelDB 实现作为索引数据的存储层buildSchema根据 Tina 配置生成 schema 产物_schema.json、_graphql.json、_lookup.jsonresolve执行 GraphQL 查询并返回结果对应源码 src/resolve.ts。2. 准备数据源与索引存储const dir content; // Where to source content from const bridge new FilesystemBridge(dir); // Where to store the index data const indexStorage new MemoryLevelstring, Recordstring, string();这里bridge告诉数据库内容从哪来indexStorage告诉数据库索引数据放哪。生产环境中索引存储通常换成持久化的 LevelDB如classic-level或由 Tina 提供的远程数据层。3. 定义 schema 结构// Create the schema/structure of the database const rawSchema: Schema { collections: [ { name: post, path: , // Dont require content to be placed within a subdirectory fields: [ { type: string, name: title, isTitle: true, required: true } ] } ] }; const schema await buildSchema({ schema: rawSchema, build: { publicFolder: , outputFolder: } });collections是 Tina schema 的核心每个 collection 定义一类内容文件如postpath指定内容存放的子目录设为空字符串表示允许内容直接放在content根目录下不需要额外子目录isTitle: true标记该字段作为文档标题用于_sys.title等系统字段buildSchema内部会调用createSchema源码 src/schema/createSchema.ts对配置做validateSchema校验并注入包版本号major/minor/patch到TinaSchema中。4. 创建数据库对象// Create the object for editing and querying your repository const database new Database({ bridge, level: indexStorage, tinaDirectory: tina });Database构造参数DatabaseArgs见 src/database/index.ts包括参数类型说明bridgeBridge内容 I/O 桥接器可从文件系统、GitHub 等数据源读写levelLevel索引存储需实现 abstract-level 的 Level 接口tinaDirectorystring生成产物目录名默认tina兼容旧版.tinaonPut/onDelete回调内容写入/删除时的钩子常用于同步 GitindexStatusCallback回调索引进行中/完成/失败的状态通知versionboolean是否启用多版本索引空间namespacestring命名空间多租户隔离用levelBatchSizenumber批量写入的批次大小默认 255. 生成索引数据// Generate the index data required to support querying await database.indexContent(schema)这一步是整条流水线的核心。indexContentsrc/database/index.ts会从桥接器读取预生成的_lookup.json将_graphql.json、_schema.json、_lookup.json写入索引存储调用_indexAllContent扫描全部内容文件为每个文档生成默认排序键__filepath__、字段索引与引用索引若启用了version还会把新版本写入_metadata子库实现无锁的版本切换旧版本在回调中清理。索引的底层写入逻辑在 src/database/datalayer.ts文档会为每个可索引字段生成形如字段值\u001D文件路径的排序键数字字段还会做零填充默认 4 位整数 3 位小数datetime 字段统一转为 UTC ISO 字符串从而保证 LevelDB 的字典序即字段的语义序查询时可直接用范围扫描完成过滤与排序。6. 执行 GraphQL 查询// Query the database and output the result // In this case, it will retrieve the title of the post in.md const graphQLQuery query { document(collection: post, relativePath: in.md) { ...on Document { _values, _sys { title } } } } const result await resolve({ database, query: graphQLQuery, variables: {} }); // Output the result console.log(JSON.stringify(result))resolve的执行路径src/resolve.ts清晰可循从数据库读取预生成的 GraphQL AST用buildASTSchema构建 schema读取 Tina schema 并创建 resolver调用graphql()执行查询其中fieldResolver依据_lookup.json中的resolveType分发到不同的解析策略例如document字段走multiCollectionDocument分支把relativePath交给resolver.getDocument完成取数收集所有字段解析 Promise 并Promise.allSettled防止解析器失控提前返回。7. 准备内容文件并验证输出为了程序能跑通还需要安装依赖包tinacms/schema-tools与memory-level在content目录下添加文件content/in.md--- title: Hello ---预期的输出结果为{data:{document:{_values:{_collection:post,_template:post,title:Hello},_sys:{title:Hello}}}}可以看到_values返回了文档的原始字段值附带_collection与_template系统字段而_sys.title由isTitle: true的字段派生而来。深入Bridge 与 Level 两层抽象tinacms/graphql之所以能同时支持本地开发与云端部署关键在于其双抽象设计。Bridge内容访问层定义于 src/database/bridge/index.tsFilesystemBridge是其文件系统实现get/put/delete/glob分别对应读、写、删与通配扫描。值得一提的细节是它对路径安全做了纵深防御filesystem.ts所有公开方法都会通过assertWithinBase校验路径是否逃逸出基准目录CWE-22 路径穿越防护同时解析符号链接CWE-59并对tina/__generated__/生成目录做二次约束。仓库中还提供了AuditFileSystemBridge它只允许写入_lookup.json、_schema.json、_graphql.json三个生成产物其余内容一律丢弃适合审计/预检场景。从源码注释可以推断GitHub 等远程桥接器也遵循同一Bridge接口。Level索引存储层定义于 src/database/level.ts它要求传入实现 abstract-level 接口的对象MemoryLevel只是其中一个实现。索引数据按子库sublevel组织~前缀存放内容本体collection 名 排序键存放各类索引。LevelProxy对get做了容错——当键不存在抛出LEVEL_NOT_FOUND时返回undefined而非抛错这让查不到成为正常流程而非异常。从最小示例走向生产createDatabase 与真实查询形态最小示例用new Database(...)直连而生产代码通常使用createDatabasesrc/database/index.ts它要求同时提供databaseAdapter索引存储与gitProvider写入回调并接受namespace实现多租户数据隔离若仍传入旧的level/onPut/onDelete会打印弃用警告并走兼容分支。此外createLocalDatabase则封装了TinaLevelClientFilesystemBridge的组合便于本地开发。仓库src/spec/movies目录下的 GraphQL 查询示例可以帮你理解真实查询形态。例如 getMovieDocument/_query.movies.gql 演示了通过movie(relativePath: star-wars.mdx)按相对路径取单个文档_sys系统字段携带filename、basename、breadcrumbs、path、relativePath、extension、template、collection等元信息director引用字段通过... on Director { name }内联片段展开被引用文档的字段这正是文档间引用特性的查询侧体现引用关系在索引期由makeRefOpsForDocument以__refs__伪索引写入存储。连接Connection形态的查询遵循 Relay 风格edges { node { ... } }分页结构配合first/last/after/before游标参数底层由Database.querysrc/database/index.ts基于索引键范围扫描实现游标即索引键的 base64 编码。过滤条件eq、gt、gte、lt、lte、startsWith、in会先被转换为索引扫描的上下界makeFilterSuffixes无法用索引表达的条件再由makeFilter基于jsonpath-plus逐条二次过滤兼顾性能与灵活性。源码级验证测试与规格文件仓库用一套请求-响应规格文件来验证查询行为位于 src/spec例如movies/requests/getMovieDocument/单个文档查询含引用展开movies/requests/getMovieList/连接查询与错误响应其_response.json展示了字段拼写错误时返回的标准 GraphQL 错误结构Cannot query field ... Did you mean ...movies-with-datalayer/数据层datalayer模式下文档的增改与列表查询forestry-sample/面向 Forestry 迁移场景的请求/变更规格。对应测试入口 requests.test.ts 把这些.gql查询与期望响应逐一比对是理解本包行为最直接的可执行文档。包内单元测试还包括database.test.ts、datalayer.test.ts、alias-utils.test.ts、filter-utils.test.ts等src/database 与 src/resolver覆盖索引、别名、过滤、媒体富文本等细节。小结tinacms/graphql把一堆 Markdown/MDX/JSON/YAML 文件变成可查询的 GraphQL 数据库其价值链条清晰FilesystemBridge负责内容 I/ObuildSchema/createSchema负责把 Tina 配置编译成 GraphQL schema 与查询查找表indexContent建立索引resolve在预生成 schema 之上执行查询并解析引用。无论是通过create-tina-app起步还是将本包嵌入自研内容管线理解 Bridge/Level 双抽象与索引期构建、查询期扫描的设计都能帮助你在 TinaCMS 之上构建出高性能、可扩展的内容查询层。【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表