Skip to content

Instantly share code, notes, and snippets.

@jakobmeusburger
Created April 16, 2025 16:35
Show Gist options
  • Save jakobmeusburger/43f47da2c99c075bba90e8463c845069 to your computer and use it in GitHub Desktop.
Save jakobmeusburger/43f47da2c99c075bba90e8463c845069 to your computer and use it in GitHub Desktop.
TinaCMS GitLab + MongoDB
MONGODB_URI=[YOUR_MONGO_DB_URL]
GITLAB_HOST=[YOUR_GITLABHOST_URL]
GITLAB_PROJECT_ID=[YOUR_GITLAB_PROJECT_ID]
GITLAB_BRANCH=[YOUR_GITLAB_BRANCH]
GITLAB_PERSONAL_ACCESS_TOKEN=[YOUR_GITLAB_TOKEN]
import { createDatabase, createLocalDatabase } from '@tinacms/datalayer';
import { MongodbLevel } from 'mongodb-level';
import { GitLabProvider } from './GitLabProvider';
const branch = process.env.GITLAB_BRANCH || process.env.VERCEL_GIT_COMMIT_REF || process.env.HEAD || 'main';
const isLocal = process.env.TINA_PUBLIC_IS_LOCAL === 'true';
export default isLocal
? createLocalDatabase()
: createDatabase({
gitProvider: new GitLabProvider({
branch,
projectId: process.env.GITLAB_PROJECT_ID!,
token: process.env.GITLAB_PERSONAL_ACCESS_TOKEN!,
gitlabOptions: {
host: process.env.GITLAB_HOST,
},
}),
databaseAdapter: new MongodbLevel({
collectionName: `tinacms-${branch}`,
dbName: 'tinacms',
mongoUri: process.env.MONGODB_URI!,
}),
namespace: branch,
});
import { Gitlab } from '@gitbeaker/rest';
import { Base64 } from 'js-base64';
import type { GitProvider } from '@tinacms/graphql';
type GitlabOptions = ConstructorParameters<typeof Gitlab>[0];
export interface GitLabProviderOptions {
projectId: string;
token: string;
branch: string;
commitMessage?: string;
rootPath?: string;
gitlabOptions?: GitlabOptions;
}
export class GitLabProvider implements GitProvider {
gitlab: InstanceType<typeof Gitlab>;
projectId: string;
branch: string;
rootPath?: string;
commitMessage?: string;
constructor(args: GitLabProviderOptions) {
this.projectId = args.projectId;
this.branch = args.branch;
this.commitMessage = args.commitMessage;
this.rootPath = args.rootPath;
this.gitlab = new Gitlab({
token: args.token,
...(args.gitlabOptions || {}),
});
}
async onPut(key: string, value: string) {
const keyWithPath = this.rootPath ? `${this.rootPath}/${key}` : key;
let fileExists = false;
try {
await this.gitlab.RepositoryFiles.show(this.projectId, keyWithPath, this.branch);
fileExists = true;
} catch (e) {
/* empty */
}
await this.gitlab.Commits.create(this.projectId, this.branch, 'Tina CMS Commit', [
{
filePath: keyWithPath,
action: fileExists ? 'update' : 'create',
content: Base64.encode(value),
encoding: 'base64',
},
]);
}
async onDelete(key: string) {
const keyWithPath = this.rootPath ? `${this.rootPath}/${key}` : key;
let fileExists = false;
try {
await this.gitlab.RepositoryFiles.show(this.projectId, key, this.branch);
fileExists = true;
} catch (e) {
/* empty */
}
if (fileExists) {
await this.gitlab.Commits.create(this.projectId, this.branch, 'Tina CMS Commit', [
{
filePath: key,
action: 'delete',
},
]);
} else {
throw new Error(`Could not find file ${keyWithPath} in project ${this.projectId}`);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment