gatsby-attainlabs-cms 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +29 -0
  2. package/gatsby-node.js +148 -0
  3. package/package.json +18 -0
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # gatsby-attain-labs-cms
2
+
3
+ A Gatsby plugin that downloads and syncs `index.tsx` components from the **Attain Labs CMS** hosted in Azure Repos into your Gatsby project at build time.
4
+
5
+ This is especially useful for keeping brand-specific and global CMS blocks up to date across Gatsby projects without manual copying.
6
+
7
+ ---
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install gatsby-attain-labs-cms
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Usage
18
+
19
+ In your gatsby-config.js, configure the plugin with the brand you want to sync:
20
+
21
+ ```javascript
22
+ {
23
+ resolve: "gatsby-attain-labs-cms",
24
+ options: {
25
+ // Select one: 'LendDirect', 'Cash Money', or 'Heights Finance'
26
+ brand: "LendDirect",
27
+ },
28
+ },
29
+ ```
package/gatsby-node.js ADDED
@@ -0,0 +1,148 @@
1
+ import fs from "fs";
2
+ import https from "https";
3
+ import path from "path";
4
+ import "dotenv/config";
5
+ // Load PAT from env instead of hardcoding (fallback to old const for now but warn)
6
+
7
+ export const onPreInit = async (_, pluginOptions) => {
8
+ const { brand, azureBranch } = pluginOptions;
9
+
10
+ const pat = process.env.GATSBY_PERSONAL_ACCESS_TOKEN;
11
+
12
+ const brands = {
13
+ LendDirect: "lenddirect",
14
+ "Cash Money": "cashmoney",
15
+ "Heights Finance": "heightsfinance",
16
+ };
17
+
18
+ const org = "CuroFinTech";
19
+ const project = "Marketing";
20
+ const repo = "Attain Labs";
21
+ const branch = azureBranch || "feature/adding-puck-for-visual-code-editing";
22
+
23
+ // List of folders to download from
24
+ const targets = [
25
+ {
26
+ repoPath: `/apps/cms/src/cms/components/editor/templates/visual-block-editor/components/brands/${brands[brand]}`,
27
+ localBasePath: path.resolve("./src/cms/components/brand"),
28
+ },
29
+ {
30
+ repoPath:
31
+ "/apps/cms/src/cms/components/editor/templates/visual-block-editor/components/global/blocks",
32
+ localBasePath: path.resolve("./src/cms/components/global"),
33
+ },
34
+ ];
35
+
36
+ const options = {
37
+ headers: {
38
+ Authorization: `Basic ${Buffer.from(`:${pat}`).toString("base64")}`,
39
+ "User-Agent": "component-transfer-script",
40
+ },
41
+ };
42
+
43
+ // Loop through targets
44
+ targets.forEach(({ repoPath, localBasePath }) => {
45
+ const listUrl = `https://dev.azure.com/${org}/${project}/_apis/git/repositories/${encodeURIComponent(
46
+ repo
47
+ )}/items?scopePath=${encodeURIComponent(
48
+ repoPath
49
+ )}&recursionLevel=full&includeContentMetadata=true&versionDescriptor.version=${encodeURIComponent(
50
+ branch
51
+ )}&versionDescriptor.versionType=branch&api-version=7.0`;
52
+
53
+ https
54
+ .get(listUrl, options, (res) => {
55
+ let data = "";
56
+ res.on("data", (chunk) => (data += chunk));
57
+ res.on("end", () => {
58
+ if (res.statusCode !== 200) {
59
+ console.error(
60
+ `Failed to list items for ${repoPath}: ${res.statusCode} ${res.statusMessage}`
61
+ );
62
+ console.error(data);
63
+ return;
64
+ }
65
+
66
+ const result = JSON.parse(data);
67
+ const posix = path.posix;
68
+
69
+ // Keep only index.tsx files
70
+ const items = (result.value || []).filter(
71
+ (i) =>
72
+ !i.isFolder &&
73
+ i.gitObjectType === "blob" &&
74
+ posix.basename(i.path) === "index.tsx"
75
+ );
76
+
77
+ console.log(`Found ${items.length} index.tsx files in ${repoPath}`);
78
+ items.forEach((item) =>
79
+ downloadFile(item.path, repoPath, localBasePath)
80
+ );
81
+ });
82
+ })
83
+ .on("error", (err) => {
84
+ console.error("Request error:", err.message);
85
+ });
86
+ });
87
+
88
+ // Download a single file preserving folder structure under localBasePath
89
+ function downloadFile(filePath, repoPath, localBasePath) {
90
+ const fileUrl = `https://dev.azure.com/${org}/${project}/_apis/git/repositories/${encodeURIComponent(
91
+ repo
92
+ )}/items?path=${encodeURIComponent(
93
+ filePath
94
+ )}&versionDescriptor.version=${encodeURIComponent(
95
+ branch
96
+ )}&versionDescriptor.versionType=branch&api-version=7.0&download=true`;
97
+
98
+ const posix = path.posix;
99
+ const relativePath = posix.relative(repoPath, filePath); // structure under repoPath
100
+ const destFile = path.join(localBasePath, ...relativePath.split("/"));
101
+ const destDir = path.dirname(destFile);
102
+
103
+ if (!fs.existsSync(destDir)) {
104
+ fs.mkdirSync(destDir, { recursive: true });
105
+ console.log(`📂 Created directory: ${destDir}`);
106
+ }
107
+
108
+ const doRequest = (url) => {
109
+ https
110
+ .get(url, options, (res) => {
111
+ if (
112
+ res.statusCode &&
113
+ res.statusCode >= 300 &&
114
+ res.statusCode < 400 &&
115
+ res.headers.location
116
+ ) {
117
+ return doRequest(res.headers.location);
118
+ }
119
+
120
+ if (res.statusCode !== 200) {
121
+ console.error(
122
+ `Failed to download ${filePath}: ${res.statusCode} ${res.statusMessage}`
123
+ );
124
+ res.resume();
125
+ return;
126
+ }
127
+
128
+ const tmpFile = destFile + ".part";
129
+ const fileStream = fs.createWriteStream(tmpFile);
130
+
131
+ res.pipe(fileStream);
132
+ fileStream.on("finish", () => {
133
+ fileStream.close(() => {
134
+ fs.renameSync(tmpFile, destFile);
135
+ console.log(`✅ Downloaded ${destFile}`);
136
+ });
137
+ });
138
+ })
139
+ .on("error", (err) => {
140
+ console.error("Request error:", err.message);
141
+ });
142
+ };
143
+
144
+ doRequest(fileUrl);
145
+ }
146
+ };
147
+
148
+ onPreInit({}, { brand: "LendDirect" }); // For testing purposes, remove when done
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "gatsby-attainlabs-cms",
3
+ "version": "1.0.0",
4
+ "main": "gatsby-node.js",
5
+ "type": "module",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "Anthony Barrera",
10
+ "license": "ISC",
11
+ "description": "A Gatsby plugin that downloads and syncs `index.tsx` components from the **Attain Labs CMS** hosted in Azure Repos into your Gatsby project at build time.",
12
+ "peerDependencies": {
13
+ "gatsby": "^5.0.0 || ^4.0.0"
14
+ },
15
+ "dependencies": {
16
+ "dotenv": "^17.2.1"
17
+ }
18
+ }