Skip to content

Commit 6c49a64

Browse files
committed
Explore CI for TOML definitions
1 parent 3408690 commit 6c49a64

3 files changed

Lines changed: 156 additions & 1 deletion

File tree

.github/workflows/ci.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install dependencies
17+
run: yarn
18+
19+
- name: Expand liquid
20+
run: yarn expand-liquid
21+
22+
- name: Validate schemas
23+
run: yarn validate-schemas

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
"@graphql-codegen/cli": "^3.2.2",
1010
"@graphql-codegen/typescript": "^3.0.2",
1111
"@graphql-codegen/typescript-operations": "^3.0.2",
12-
"graphql": "^16.6.0"
12+
"graphql": "^16.6.0",
13+
"ajv": "8.17.1"
1314
},
1415
"scripts": {
1516
"expand-liquid": "node ./util/expand-liquid.js",
17+
"validate-schemas": "node ./util/validate-schemas.js",
1618
"typegen": "yarn workspaces run graphql-code-generator --config package.json",
1719
"test-js": "yarn expand-liquid vanilla-js && yarn && yarn typegen && yarn workspaces run test run",
1820
"test-ts": "yarn expand-liquid typescript && yarn && yarn typegen && yarn workspaces run test run"

util/validate-schemas.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import fs from 'node:fs/promises';
2+
import path from 'node:path';
3+
4+
import toml from '@iarna/toml';
5+
import Ajv from 'ajv';
6+
7+
const schema = {
8+
type: 'object',
9+
properties: {
10+
api_version: {
11+
type: 'string',
12+
pattern: '^(202\\d{1}-\\d{2}|unstable)$', // Matches "202X-XX" format
13+
},
14+
extensions: {
15+
type: 'array',
16+
items: {
17+
type: 'object',
18+
properties: {
19+
description: { type: 'string' },
20+
handle: { type: 'string' },
21+
name: { type: 'string' },
22+
type: { type: 'string' },
23+
// build: {
24+
// type: 'object',
25+
// properties: {
26+
// command: { type: 'string' },
27+
// path: { type: 'string' },
28+
// additionalProperties: true, // Allow other properties in build
29+
// },
30+
// required: ['command', 'path'],
31+
// },
32+
// ui: {
33+
// type: 'object',
34+
// properties: {
35+
// paths: {
36+
// type: 'object',
37+
// properties: {
38+
// create: { type: 'string' },
39+
// details: { type: 'string' },
40+
// additionalProperties: { type: 'string' }, // Allow other paths
41+
// },
42+
// additionalProperties: true, // Allow other keys in paths
43+
// },
44+
// additionalProperties: true, // Allow other properties in ui
45+
// },
46+
// additionalProperties: true, // Allow other keys in ui
47+
// },
48+
// targeting: {
49+
// type: 'array',
50+
// items: {
51+
// type: 'object',
52+
// properties: {
53+
// export: { type: 'string' },
54+
// input_query: { type: 'string' },
55+
// target: { type: 'string' },
56+
// additionalProperties: true, // Allow other properties in targeting item
57+
// },
58+
// required: ['export', 'input_query', 'target'],
59+
// additionalProperties: true, // Allow other keys in targeting item
60+
// },
61+
// },
62+
// additionalProperties: true, // Allow other properties in extension
63+
},
64+
required: ['description', 'handle', 'name', 'type', 'build'],
65+
additionalProperties: true, // Allow other keys in extension
66+
},
67+
},
68+
additionalProperties: true, // Allow other top-level properties
69+
},
70+
required: ['api_version'],
71+
// required: ['api_version', 'extensions'],
72+
additionalProperties: true, // Allow other top-level keys
73+
};
74+
75+
const ajv = new Ajv();
76+
const compiledAjv = ajv.compile(schema);
77+
78+
async function findExtensionTomlFiles(directory) {
79+
const files = await fs.readdir(directory);
80+
const matchingFiles = [];
81+
82+
for (const file of files) {
83+
if (file === 'node_modules') {
84+
continue;
85+
}
86+
87+
const fullPath = path.join(directory, file);
88+
const stats = await fs.stat(fullPath);
89+
90+
if (stats.isFile() && file === 'shopify.extension.toml') {
91+
matchingFiles.push(fullPath);
92+
} else if (stats.isDirectory()) {
93+
// Recursively search subdirectories
94+
const subDirectoryFiles = await findExtensionTomlFiles(fullPath);
95+
matchingFiles.push(...subDirectoryFiles);
96+
}
97+
}
98+
99+
return matchingFiles;
100+
}
101+
102+
async function testSchema(filename) {
103+
await fs.readFile(filename, 'utf8')
104+
.then(data => {
105+
const parsedData = toml.parse(data);
106+
const isValid = compiledAjv(parsedData);
107+
108+
if (isValid) {
109+
console.log(`Validation successful for ${filename}`);
110+
} else {
111+
console.error(`Validation failed for ${filename}:`);
112+
console.error(compiledAjv.errors);
113+
114+
process.exit(-1)
115+
}
116+
})
117+
.catch(_ => {
118+
throw new Error(`Error reading file ${filename}.`);
119+
});
120+
}
121+
122+
async function test() {
123+
const filenames = await findExtensionTomlFiles('./');
124+
125+
filenames.forEach(filename => {
126+
testSchema(filename);
127+
});
128+
}
129+
130+
await test();

0 commit comments

Comments
 (0)