@embrace-ai/infra-api-schema-sync 1.0.0 → 1.0.1
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.
- package/CHANGELOG.md +7 -0
- package/dist/src/dispatch-update.d.ts +34 -0
- package/dist/src/dispatch-update.d.ts.map +1 -0
- package/dist/src/dispatch-update.js +224 -0
- package/dist/src/dispatch-update.js.map +1 -0
- package/dist/src/fetch-schema.d.ts +6 -0
- package/dist/src/fetch-schema.d.ts.map +1 -0
- package/dist/src/fetch-schema.js +43 -0
- package/dist/src/fetch-schema.js.map +1 -0
- package/dist/src/generate-schema-url.d.ts +8 -0
- package/dist/src/generate-schema-url.d.ts.map +1 -0
- package/dist/src/generate-schema-url.js +91 -0
- package/dist/src/generate-schema-url.js.map +1 -0
- package/dist/src/generate-summary.d.ts +4 -0
- package/dist/src/generate-summary.d.ts.map +1 -0
- package/dist/src/generate-summary.js +47 -0
- package/dist/src/generate-summary.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +62 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/validate-schema.d.ts +7 -0
- package/dist/src/validate-schema.d.ts.map +1 -0
- package/dist/src/validate-schema.js +115 -0
- package/dist/src/validate-schema.js.map +1 -0
- package/dist/vitest.config.js +3 -5
- package/dist/vitest.config.js.map +1 -1
- package/package.json +3 -2
- package/templates/workflows/emit-schema-update.yml +9 -9
- package/templates/workflows/graphql-schema-validate.yml +8 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.1](https://github.com/Embrace-AI/infra-api-schema-sync/compare/v1.0.0...v1.0.1) (2025-06-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **workflows:** use pnpm exec in workflows, use correct build path in package.json for cli tool ([#8](https://github.com/Embrace-AI/infra-api-schema-sync/issues/8)) ([5b8daf3](https://github.com/Embrace-AI/infra-api-schema-sync/commit/5b8daf305dc8c868cf1766c1b4b4b5d86503b282))
|
|
9
|
+
|
|
3
10
|
## 1.0.0 (2025-06-19)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function dispatchUpdate(options: {
|
|
2
|
+
schemaUrl: string;
|
|
3
|
+
sourceRepo: string;
|
|
4
|
+
commit: string;
|
|
5
|
+
branch: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
token: string;
|
|
8
|
+
orgName: string;
|
|
9
|
+
repoFilter: string;
|
|
10
|
+
dryRun: boolean;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
success: number;
|
|
13
|
+
errors: number;
|
|
14
|
+
total: number;
|
|
15
|
+
dryRun?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
success: number;
|
|
18
|
+
errors: number;
|
|
19
|
+
total: number;
|
|
20
|
+
dryRun: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
export function dispatchUpdateCommand(opts: any): Promise<{
|
|
23
|
+
success: number;
|
|
24
|
+
errors: number;
|
|
25
|
+
total: number;
|
|
26
|
+
dryRun?: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
success: number;
|
|
29
|
+
errors: number;
|
|
30
|
+
total: number;
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
}>;
|
|
33
|
+
export default dispatchUpdateCommand;
|
|
34
|
+
//# sourceMappingURL=dispatch-update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-update.d.ts","sourceRoot":"","sources":["../../src/dispatch-update.js"],"names":[],"mappings":"AAeO,wCAVJ;IAAwB,SAAS,EAAzB,MAAM;IACU,UAAU,EAA1B,MAAM;IACU,MAAM,EAAtB,MAAM;IACU,MAAM,EAAtB,MAAM;IACU,SAAS,EAAzB,MAAM;IACU,KAAK,EAArB,MAAM;IACU,OAAO,EAAvB,MAAM;IACU,UAAU,EAA1B,MAAM;IACW,MAAM,EAAvB,OAAO;CACjB;;;;;;;;;;GA4LA;AA2DM;;;;;;;;;;GAyDN"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
export const dispatchUpdate = async (options) => {
|
|
3
|
+
try {
|
|
4
|
+
const { schemaUrl, sourceRepo, commit, branch, timestamp, token, orgName, repoFilter = ".*", dryRun = false, } = options;
|
|
5
|
+
console.log("📡 Starting schema update dispatch...");
|
|
6
|
+
console.log(`🌐 Schema URL: ${schemaUrl}`);
|
|
7
|
+
console.log(`📁 Source Repository: ${sourceRepo}`);
|
|
8
|
+
console.log(`🔍 Organization: ${orgName}`);
|
|
9
|
+
console.log(`🎯 Repository Filter: ${repoFilter}`);
|
|
10
|
+
if (dryRun) {
|
|
11
|
+
console.log("DRY RUN MODE - No actual dispatches will be sent");
|
|
12
|
+
}
|
|
13
|
+
const fetchAllRepos = async () => {
|
|
14
|
+
let page = 1;
|
|
15
|
+
const perPage = 100;
|
|
16
|
+
let allRepos = "";
|
|
17
|
+
while (true) {
|
|
18
|
+
console.log(`Fetching repos page ${page}...`);
|
|
19
|
+
const response = await fetch(`https://api.github.com/orgs/${orgName}/repos?page=${page}&per_page=${perPage}&type=all`, {
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${token}`,
|
|
22
|
+
Accept: "application/vnd.github.v3+json",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
const errorData = await response.json();
|
|
27
|
+
throw new Error(`GitHub API error: ${errorData.message || response.statusText}`);
|
|
28
|
+
}
|
|
29
|
+
const repos = await response.json();
|
|
30
|
+
if (!repos || repos.length === 0) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
const repoNames = repos.map((repo) => repo.full_name).join("\n");
|
|
34
|
+
allRepos += `${repoNames}\n`;
|
|
35
|
+
if (repos.length < perPage) {
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
page++;
|
|
39
|
+
}
|
|
40
|
+
return allRepos;
|
|
41
|
+
};
|
|
42
|
+
console.log("🔍 Fetching all organization repositories...");
|
|
43
|
+
let allRepos;
|
|
44
|
+
if (dryRun && (token === "fake-token" || token.startsWith("fake"))) {
|
|
45
|
+
console.log("DRY RUN: Using simulated repositories");
|
|
46
|
+
allRepos = `${orgName}/repo1\n${orgName}/repo2\n${orgName}/frontend\n${sourceRepo}\n`;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
allRepos = await fetchAllRepos();
|
|
50
|
+
}
|
|
51
|
+
let filteredRepos;
|
|
52
|
+
if (repoFilter !== ".*") {
|
|
53
|
+
console.log(`🔍 Filtering repositories with pattern: ${repoFilter}`);
|
|
54
|
+
const repoList = allRepos.split("\n").filter((repo) => repo.trim());
|
|
55
|
+
const regex = new RegExp(repoFilter);
|
|
56
|
+
filteredRepos = repoList.filter((repo) => regex.test(repo)).join("\n");
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
filteredRepos = allRepos;
|
|
60
|
+
}
|
|
61
|
+
const targetRepos = filteredRepos
|
|
62
|
+
.split("\n")
|
|
63
|
+
.filter((repo) => repo.trim() && repo !== sourceRepo)
|
|
64
|
+
.filter((repo) => repo.length > 0);
|
|
65
|
+
if (targetRepos.length === 0) {
|
|
66
|
+
console.log("⚠️ No target repositories found to notify");
|
|
67
|
+
return { success: 0, errors: 0, total: 0 };
|
|
68
|
+
}
|
|
69
|
+
console.log(`Found ${targetRepos.length} repositories to notify:`);
|
|
70
|
+
targetRepos.forEach((repo) => console.log(` - ${repo}`));
|
|
71
|
+
console.log("");
|
|
72
|
+
if (dryRun) {
|
|
73
|
+
console.log("DRY RUN: Would dispatch to the above repositories");
|
|
74
|
+
return {
|
|
75
|
+
success: targetRepos.length,
|
|
76
|
+
errors: 0,
|
|
77
|
+
total: targetRepos.length,
|
|
78
|
+
dryRun: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
let successCount = 0;
|
|
82
|
+
let errorCount = 0;
|
|
83
|
+
for (const repo of targetRepos) {
|
|
84
|
+
if (repo.trim()) {
|
|
85
|
+
console.log(`📡 Dispatching to repository: ${repo}`);
|
|
86
|
+
try {
|
|
87
|
+
const dispatchResponse = await fetch(`https://api.github.com/repos/${repo}/dispatches`, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Bearer ${token}`,
|
|
91
|
+
Accept: "application/vnd.github.v3+json",
|
|
92
|
+
"Content-Type": "application/json",
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify({
|
|
95
|
+
event_type: "graphql-schema-updated",
|
|
96
|
+
client_payload: {
|
|
97
|
+
schemaUrl,
|
|
98
|
+
sourceRepo,
|
|
99
|
+
commit,
|
|
100
|
+
branch,
|
|
101
|
+
timestamp,
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
if (dispatchResponse.status === 204) {
|
|
106
|
+
console.log(" ✅ Success");
|
|
107
|
+
successCount++;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.log(` ❌ Failed (HTTP ${dispatchResponse.status})`);
|
|
111
|
+
errorCount++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.log(` ❌ Failed: ${error.message}`);
|
|
116
|
+
errorCount++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
console.log("");
|
|
121
|
+
console.log("📊 Dispatch Summary:");
|
|
122
|
+
console.log(` ✅ Successful: ${successCount}`);
|
|
123
|
+
console.log(` ❌ Failed: ${errorCount}`);
|
|
124
|
+
console.log(` 📋 Total: ${successCount + errorCount}`);
|
|
125
|
+
if (errorCount > 0) {
|
|
126
|
+
console.log("⚠️ Some dispatches failed. Check repository permissions and workflow file presence.");
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
success: successCount,
|
|
130
|
+
errors: errorCount,
|
|
131
|
+
total: successCount + errorCount,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error(`❌ Failed to dispatch schema updates: ${error.message}`);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const detectValues = () => {
|
|
140
|
+
const sourceRepo = process.env.GITHUB_REPOSITORY || detectRepositoryFromGit();
|
|
141
|
+
const commit = process.env.GITHUB_SHA || detectCommitFromGit();
|
|
142
|
+
const branch = process.env.GITHUB_REF_NAME || detectBranchFromGit();
|
|
143
|
+
const orgName = process.env.GITHUB_REPOSITORY_OWNER || sourceRepo?.split("/")[0];
|
|
144
|
+
const timestamp = new Date().toISOString();
|
|
145
|
+
return { sourceRepo, commit, branch, orgName, timestamp };
|
|
146
|
+
};
|
|
147
|
+
const detectRepositoryFromGit = () => {
|
|
148
|
+
try {
|
|
149
|
+
const remoteUrl = execSync("git config --get remote.origin.url", {
|
|
150
|
+
encoding: "utf8",
|
|
151
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
152
|
+
}).trim();
|
|
153
|
+
const match = remoteUrl.match(/github\.com[:/]([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
154
|
+
return match ? match[1] : null;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.warn("Failed to detect repository from git:", error.message);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const detectCommitFromGit = () => {
|
|
162
|
+
try {
|
|
163
|
+
return execSync("git rev-parse HEAD", {
|
|
164
|
+
encoding: "utf8",
|
|
165
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
166
|
+
}).trim();
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.warn("Failed to detect commit from git:", error.message);
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const detectBranchFromGit = () => {
|
|
174
|
+
try {
|
|
175
|
+
return execSync("git rev-parse --abbrev-ref HEAD", {
|
|
176
|
+
encoding: "utf8",
|
|
177
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
178
|
+
}).trim();
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.warn("Failed to detect branch from git:", error.message);
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
export const dispatchUpdateCommand = async (opts) => {
|
|
186
|
+
const { schemaUrl, sourceRepo: providedSourceRepo, commit: providedCommit, branch: providedBranch, token, orgName: providedOrgName, repoFilter, dryRun, } = opts;
|
|
187
|
+
const detected = detectValues();
|
|
188
|
+
const sourceRepo = providedSourceRepo || detected.sourceRepo;
|
|
189
|
+
const commit = providedCommit || detected.commit;
|
|
190
|
+
const branch = providedBranch || detected.branch;
|
|
191
|
+
const orgName = providedOrgName || detected.orgName;
|
|
192
|
+
const timestamp = detected.timestamp;
|
|
193
|
+
if (!schemaUrl) {
|
|
194
|
+
throw new Error("Schema URL is required (--schema-url)");
|
|
195
|
+
}
|
|
196
|
+
if (!token) {
|
|
197
|
+
throw new Error("GitHub token is required (--token)");
|
|
198
|
+
}
|
|
199
|
+
if (!sourceRepo) {
|
|
200
|
+
throw new Error("Source repository could not be detected. Please provide --source-repo");
|
|
201
|
+
}
|
|
202
|
+
if (!orgName) {
|
|
203
|
+
throw new Error("Organization name could not be detected. Please provide --org-name");
|
|
204
|
+
}
|
|
205
|
+
console.log("🔧 Preparing schema update dispatch...");
|
|
206
|
+
console.log(`📁 Source Repository: ${sourceRepo}`);
|
|
207
|
+
console.log(`🏷️ Commit: ${commit || "not detected"}`);
|
|
208
|
+
console.log(`🌿 Branch: ${branch || "not detected"}`);
|
|
209
|
+
console.log(`🏢 Organization: ${orgName}`);
|
|
210
|
+
console.log(`⏰ Timestamp: ${timestamp}`);
|
|
211
|
+
return dispatchUpdate({
|
|
212
|
+
schemaUrl,
|
|
213
|
+
sourceRepo,
|
|
214
|
+
commit,
|
|
215
|
+
branch,
|
|
216
|
+
timestamp,
|
|
217
|
+
token,
|
|
218
|
+
orgName,
|
|
219
|
+
repoFilter,
|
|
220
|
+
dryRun,
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
export default dispatchUpdateCommand;
|
|
224
|
+
//# sourceMappingURL=dispatch-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-update.js","sourceRoot":"","sources":["../../src/dispatch-update.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-schema.d.ts","sourceRoot":"","sources":["../../src/fetch-schema.js"],"names":[],"mappings":"AAKO;;;kBAwDN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import fse from "fs-extra";
|
|
3
|
+
import { buildClientSchema, getIntrospectionQuery, printSchema } from "graphql";
|
|
4
|
+
import path from "path";
|
|
5
|
+
export const fetchSchema = async ({ url, output }) => {
|
|
6
|
+
try {
|
|
7
|
+
console.log(`🔄 Fetching GraphQL schema from ${url}...`);
|
|
8
|
+
const introspectionQuery = getIntrospectionQuery();
|
|
9
|
+
const response = await fetch(url, {
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
Accept: "application/json",
|
|
14
|
+
},
|
|
15
|
+
body: JSON.stringify({
|
|
16
|
+
query: introspectionQuery,
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
21
|
+
}
|
|
22
|
+
const result = await response.json();
|
|
23
|
+
if (result.errors) {
|
|
24
|
+
throw new Error(`GraphQL errors: ${result.errors.map((e) => e.message).join(", ")}`);
|
|
25
|
+
}
|
|
26
|
+
if (!result.data) {
|
|
27
|
+
throw new Error("No data returned from introspection query");
|
|
28
|
+
}
|
|
29
|
+
const schema = buildClientSchema(result.data);
|
|
30
|
+
const schemaSDL = printSchema(schema);
|
|
31
|
+
const outputDir = path.dirname(output);
|
|
32
|
+
fse.ensureDirSync(outputDir);
|
|
33
|
+
fs.writeFileSync(output, schemaSDL, "utf8");
|
|
34
|
+
console.log(`✅ Schema successfully saved to ${output}`);
|
|
35
|
+
console.log(`📊 Schema contains ${Object.keys(schema.getTypeMap()).length} types`);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(`❌ Failed to fetch schema: ${error.message}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export default fetchSchema;
|
|
43
|
+
//# sourceMappingURL=fetch-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-schema.js","sourceRoot":"","sources":["../../src/fetch-schema.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;IACnD,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,mCAAmC,GAAG,KAAK,CAAC,CAAC;QAGzD,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAC;QAGnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,kBAAkB;aAC3B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,kBAAkB;aAC1B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,mBAAmB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAGD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAG9C,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAGtC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvC,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAG7B,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CACT,sBAAsB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,QAAQ,CACtE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAGF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function buildSchemaUrl({ stage, service, repo }: {
|
|
2
|
+
stage: string;
|
|
3
|
+
service: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
}): string;
|
|
6
|
+
export function generateSchemaUrl(opts: any): string;
|
|
7
|
+
export default generateSchemaUrl;
|
|
8
|
+
//# sourceMappingURL=generate-schema-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-schema-url.d.ts","sourceRoot":"","sources":["../../src/generate-schema-url.js"],"names":[],"mappings":"AAWO,yDALJ;IAAwB,KAAK,EAArB,MAAM;IACU,OAAO,EAAvB,MAAM;IACU,IAAI,EAApB,MAAM;CACd,GAAU,MAAM,CAwBlB;AAkGM,qDA8BN"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export const buildSchemaUrl = ({ stage = "dev", service, repo }) => {
|
|
4
|
+
if (!repo) {
|
|
5
|
+
repo = detectRepositoryName();
|
|
6
|
+
}
|
|
7
|
+
if (!service) {
|
|
8
|
+
service = extractServiceName(repo);
|
|
9
|
+
}
|
|
10
|
+
if (service === "embrace" ||
|
|
11
|
+
repo === "embrace" ||
|
|
12
|
+
repo.endsWith("/embrace")) {
|
|
13
|
+
return buildEmbraceUrl(stage);
|
|
14
|
+
}
|
|
15
|
+
return buildServiceUrl(service, stage);
|
|
16
|
+
};
|
|
17
|
+
const buildEmbraceUrl = (stage) => {
|
|
18
|
+
switch (stage) {
|
|
19
|
+
case "dev":
|
|
20
|
+
return "https://api.dev.embrace.ai/v2/graphql/schema";
|
|
21
|
+
default:
|
|
22
|
+
if (stage.startsWith("pr-")) {
|
|
23
|
+
return `https://api.${stage}.dev.embrace.ai/v2/graphql/schema`;
|
|
24
|
+
}
|
|
25
|
+
return "https://api.dev.embrace.ai/v2/graphql/schema";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const buildServiceUrl = (service, stage) => {
|
|
29
|
+
switch (stage) {
|
|
30
|
+
case "prod":
|
|
31
|
+
return `https://api.${service}.services.embrace.ai/graphql/schema`;
|
|
32
|
+
case "dev":
|
|
33
|
+
return `https://api.${service}.services.dev.embrace.ai/graphql/schema`;
|
|
34
|
+
default:
|
|
35
|
+
if (stage.startsWith("pr-")) {
|
|
36
|
+
return `https://api.${service}.${stage}.services.dev.embrace.ai/graphql/schema`;
|
|
37
|
+
}
|
|
38
|
+
return `https://api.${service}.services.dev.embrace.ai/graphql/schema`;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const detectRepositoryName = () => {
|
|
42
|
+
try {
|
|
43
|
+
const remoteUrl = execSync("git config --get remote.origin.url", {
|
|
44
|
+
encoding: "utf8",
|
|
45
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
46
|
+
}).trim();
|
|
47
|
+
const match = remoteUrl.match(/[/:]([^/]+?)(?:\.git)?$/);
|
|
48
|
+
if (match) {
|
|
49
|
+
return match[1];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.warn("⚠️ Could not detect repository from git, using directory name: ", error.message);
|
|
54
|
+
}
|
|
55
|
+
return path.basename(process.cwd());
|
|
56
|
+
};
|
|
57
|
+
const extractServiceName = (repo) => {
|
|
58
|
+
let serviceName = repo
|
|
59
|
+
.replace(/^(api-|service-|microservice-|ms-)/, "")
|
|
60
|
+
.replace(/(-api|-service|-microservice|-ms)$/, "")
|
|
61
|
+
.replace(/^embrace-/, "");
|
|
62
|
+
if (serviceName === "embrace" || serviceName === "") {
|
|
63
|
+
return "embrace";
|
|
64
|
+
}
|
|
65
|
+
return serviceName;
|
|
66
|
+
};
|
|
67
|
+
export const generateSchemaUrl = (opts) => {
|
|
68
|
+
try {
|
|
69
|
+
const { stage, service, repo } = opts;
|
|
70
|
+
console.log("🔧 Generating schema URL...");
|
|
71
|
+
const detectedRepo = repo || detectRepositoryName();
|
|
72
|
+
const detectedService = service || extractServiceName(detectedRepo);
|
|
73
|
+
console.log(`📁 Repository: ${detectedRepo}`);
|
|
74
|
+
console.log(`🏷️ Service: ${detectedService}`);
|
|
75
|
+
console.log(`🚀 Stage: ${stage}`);
|
|
76
|
+
const url = buildSchemaUrl({
|
|
77
|
+
stage,
|
|
78
|
+
service: detectedService,
|
|
79
|
+
repo: detectedRepo,
|
|
80
|
+
});
|
|
81
|
+
console.log(`🌐 Generated URL: ${url}`);
|
|
82
|
+
process.stdout.write(url);
|
|
83
|
+
return url;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error(`❌ Failed to generate schema URL: ${error.message}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
export default generateSchemaUrl;
|
|
91
|
+
//# sourceMappingURL=generate-schema-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-schema-url.js","sourceRoot":"","sources":["../../src/generate-schema-url.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-summary.d.ts","sourceRoot":"","sources":["../../src/generate-summary.js"],"names":[],"mappings":"AAEO,+DA2BN;AAGM,iDAeN"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
export const generateSummaryFromReport = (report) => {
|
|
3
|
+
if (!report || report.length === 0) {
|
|
4
|
+
return "No GraphQL validation errors found.";
|
|
5
|
+
}
|
|
6
|
+
let output = "## 🚨 GraphQL Schema Validation Issues\n\n";
|
|
7
|
+
const grouped = report.reduce((acc, issue) => {
|
|
8
|
+
const file = issue.location?.file || "Unknown file";
|
|
9
|
+
if (!acc[file]) {
|
|
10
|
+
acc[file] = [];
|
|
11
|
+
}
|
|
12
|
+
acc[file].push(issue);
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
for (const [file, issues] of Object.entries(grouped)) {
|
|
16
|
+
output += `### \`${file}\`\n`;
|
|
17
|
+
issues.forEach(({ message, location, operation }) => {
|
|
18
|
+
const line = location?.line || "?";
|
|
19
|
+
output += `- ❌ \`${operation || "Unknown Operation"}\`: ${message} (line ${line})\n`;
|
|
20
|
+
});
|
|
21
|
+
output += "\n";
|
|
22
|
+
}
|
|
23
|
+
return output;
|
|
24
|
+
};
|
|
25
|
+
export const generateSummary = (opts) => {
|
|
26
|
+
const reportPath = opts.report;
|
|
27
|
+
const outputPath = opts.output;
|
|
28
|
+
const raw = fs.readFileSync(reportPath, "utf-8");
|
|
29
|
+
const report = JSON.parse(raw);
|
|
30
|
+
const summary = generateSummaryFromReport(report);
|
|
31
|
+
if (outputPath) {
|
|
32
|
+
fs.writeFileSync(outputPath, summary, "utf-8");
|
|
33
|
+
console.log(`✅ Summary written to ${outputPath}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(summary);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
if (process.argv[1] && process.argv[1].endsWith("generate-summary.js")) {
|
|
40
|
+
const reportPath = process.argv[2] || "report.json";
|
|
41
|
+
const raw = fs.readFileSync(reportPath, "utf-8");
|
|
42
|
+
const report = JSON.parse(raw);
|
|
43
|
+
const summary = generateSummaryFromReport(report);
|
|
44
|
+
console.log(summary);
|
|
45
|
+
}
|
|
46
|
+
export default generateSummary;
|
|
47
|
+
//# sourceMappingURL=generate-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-summary.js","sourceRoot":"","sources":["../../src/generate-summary.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,EAAE;IAClD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,qCAAqC,CAAC;IAC/C,CAAC;IAED,IAAI,MAAM,GAAG,4CAA4C,CAAC;IAG1D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,cAAc,CAAC;QACpD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACjB,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,SAAS,IAAI,MAAM,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;YAClD,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,GAAG,CAAC;YACnC,MAAM,IAAI,SAAS,SAAS,IAAI,mBAAmB,OAAO,OAAO,UAAU,IAAI,KAAK,CAAC;QACvF,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,IAAI,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,EAAE;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAE/B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElD,IAAI,UAAU,EAAE,CAAC;QACf,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC;AAGF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC;IACpD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAGD,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
const program = new Command();
|
|
4
|
+
program
|
|
5
|
+
.name("api-tool")
|
|
6
|
+
.description("CLI for API schema management")
|
|
7
|
+
.version("0.1.0");
|
|
8
|
+
program
|
|
9
|
+
.command("fetch")
|
|
10
|
+
.description("Fetch GraphQL schema from a URL")
|
|
11
|
+
.requiredOption("--url <url>", "Schema URL")
|
|
12
|
+
.requiredOption("--output <file>", "Output file path")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const { default: fetchSchema } = await import("./fetch-schema.js");
|
|
15
|
+
return fetchSchema(opts);
|
|
16
|
+
});
|
|
17
|
+
program
|
|
18
|
+
.command("validate")
|
|
19
|
+
.description("Validate queries against schema")
|
|
20
|
+
.requiredOption("--schema <file>", "Schema file path")
|
|
21
|
+
.requiredOption("--queries <glob>", "Glob pattern to GraphQL query files")
|
|
22
|
+
.requiredOption("--output <file>", "JSON report output")
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
const { default: validateSchema } = await import("./validate-schema.js");
|
|
25
|
+
return validateSchema(opts);
|
|
26
|
+
});
|
|
27
|
+
program
|
|
28
|
+
.command("summarize")
|
|
29
|
+
.description("Generate markdown from a validation report")
|
|
30
|
+
.requiredOption("--report <file>", "Validation JSON report")
|
|
31
|
+
.requiredOption("--output <file>", "Markdown file path")
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
const { default: generateSummary } = await import("./generate-summary.js");
|
|
34
|
+
return generateSummary(opts);
|
|
35
|
+
});
|
|
36
|
+
program
|
|
37
|
+
.command("generate-schema-url")
|
|
38
|
+
.description("Generate dynamic schema URL based on repository and stage")
|
|
39
|
+
.option("--stage <stage>", "Deployment stage (dev, prod, pr-*)", "dev")
|
|
40
|
+
.option("--service <service>", "Service name (auto-detected from repo if not provided)")
|
|
41
|
+
.option("--repo <repo>", "Repository name (auto-detected from git if not provided)")
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
const { default: generateSchemaUrl } = await import("./generate-schema-url.js");
|
|
44
|
+
return generateSchemaUrl(opts);
|
|
45
|
+
});
|
|
46
|
+
program
|
|
47
|
+
.command("dispatch-update")
|
|
48
|
+
.description("Dispatch schema update events to organization repositories")
|
|
49
|
+
.requiredOption("--schema-url <url>", "Schema URL to dispatch")
|
|
50
|
+
.requiredOption("--token <token>", "GitHub token for API access")
|
|
51
|
+
.option("--source-repo <repo>", "Source repository (auto-detected if not provided)")
|
|
52
|
+
.option("--commit <sha>", "Git commit SHA (auto-detected if not provided)")
|
|
53
|
+
.option("--branch <branch>", "Git branch name (auto-detected if not provided)")
|
|
54
|
+
.option("--org-name <org>", "GitHub organization name (auto-detected if not provided)")
|
|
55
|
+
.option("--repo-filter <pattern>", "Regex pattern to filter repositories", ".*")
|
|
56
|
+
.option("--dry-run", "Show what would be dispatched without sending", false)
|
|
57
|
+
.action(async (opts) => {
|
|
58
|
+
const { default: dispatchUpdate } = await import("./dispatch-update.js");
|
|
59
|
+
return dispatchUpdate(opts);
|
|
60
|
+
});
|
|
61
|
+
program.parse();
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-schema.d.ts","sourceRoot":"","sources":["../../src/validate-schema.js"],"names":[],"mappings":"AAMO;;;;kBAuGN"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { validate } from "@graphql-inspector/core";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import fse from "fs-extra";
|
|
4
|
+
import { buildSchema } from "graphql";
|
|
5
|
+
import path from "path";
|
|
6
|
+
export const validateSchema = async ({ schema, queries, output }) => {
|
|
7
|
+
try {
|
|
8
|
+
console.log(`🔄 Validating GraphQL queries against schema...`);
|
|
9
|
+
console.log(`📄 Schema: ${schema}`);
|
|
10
|
+
console.log(`🔍 Queries: ${queries}`);
|
|
11
|
+
if (!fs.existsSync(schema)) {
|
|
12
|
+
throw new Error(`Schema file not found: ${schema}`);
|
|
13
|
+
}
|
|
14
|
+
const outputDir = path.dirname(output);
|
|
15
|
+
fse.ensureDirSync(outputDir);
|
|
16
|
+
const schemaContent = fs.readFileSync(schema, "utf8");
|
|
17
|
+
const graphqlSchema = buildSchema(schemaContent);
|
|
18
|
+
const queryFiles = findFiles(queries);
|
|
19
|
+
if (queryFiles.length === 0) {
|
|
20
|
+
console.log(`⚠️ No query files found matching pattern: ${queries}`);
|
|
21
|
+
}
|
|
22
|
+
const sources = queryFiles.map((filePath) => ({
|
|
23
|
+
name: filePath,
|
|
24
|
+
body: fs.readFileSync(filePath, "utf8"),
|
|
25
|
+
location: filePath,
|
|
26
|
+
}));
|
|
27
|
+
console.log(`🚀 Validating ${sources.length} query file(s) against schema...`);
|
|
28
|
+
const invalidDocuments = validate(graphqlSchema, sources, {
|
|
29
|
+
strictDeprecated: false,
|
|
30
|
+
strictFragments: true,
|
|
31
|
+
apollo: false,
|
|
32
|
+
});
|
|
33
|
+
const validationReport = [];
|
|
34
|
+
for (const doc of invalidDocuments) {
|
|
35
|
+
for (const error of doc.errors) {
|
|
36
|
+
validationReport.push({
|
|
37
|
+
message: error.message,
|
|
38
|
+
location: {
|
|
39
|
+
file: doc.source.name,
|
|
40
|
+
line: error.locations?.[0]?.line || 1,
|
|
41
|
+
column: error.locations?.[0]?.column || 1,
|
|
42
|
+
},
|
|
43
|
+
operation: "validation",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
for (const deprecated of doc.deprecated) {
|
|
47
|
+
validationReport.push({
|
|
48
|
+
message: `Deprecated: ${deprecated.message}`,
|
|
49
|
+
location: {
|
|
50
|
+
file: doc.source.name,
|
|
51
|
+
line: deprecated.locations?.[0]?.line || 1,
|
|
52
|
+
column: deprecated.locations?.[0]?.column || 1,
|
|
53
|
+
},
|
|
54
|
+
operation: "deprecated",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
fs.writeFileSync(output, JSON.stringify(validationReport, null, 2), "utf8");
|
|
59
|
+
const errorCount = validationReport.length;
|
|
60
|
+
if (errorCount === 0) {
|
|
61
|
+
console.log(`✅ Validation completed successfully - no issues found`);
|
|
62
|
+
console.log(`📊 Report saved to ${output}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(`⚠️ Validation completed with ${errorCount} issue(s) found`);
|
|
66
|
+
console.log(`📊 Report saved to ${output}`);
|
|
67
|
+
const fileGroups = validationReport.reduce((acc, issue) => {
|
|
68
|
+
const file = issue.location?.file || "Unknown file";
|
|
69
|
+
acc[file] = (acc[file] || 0) + 1;
|
|
70
|
+
return acc;
|
|
71
|
+
}, {});
|
|
72
|
+
console.log(`📋 Issues by file:`);
|
|
73
|
+
Object.entries(fileGroups).forEach(([file, count]) => {
|
|
74
|
+
console.log(` ${file}: ${count} issue(s)`);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error(`❌ Validation failed: ${error.message}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const findFiles = (pattern) => {
|
|
84
|
+
if (fs.existsSync(pattern) && fs.statSync(pattern).isFile()) {
|
|
85
|
+
return [pattern];
|
|
86
|
+
}
|
|
87
|
+
const files = [];
|
|
88
|
+
if (pattern.includes("*")) {
|
|
89
|
+
const dir = pattern.includes("/") ? path.dirname(pattern) : ".";
|
|
90
|
+
const searchDir = fs.existsSync(dir) ? dir : ".";
|
|
91
|
+
const searchDirectory = (dirPath, recursive = false) => {
|
|
92
|
+
const entries = fs.readdirSync(dirPath);
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
const fullPath = path.join(dirPath, entry);
|
|
95
|
+
const stat = fs.statSync(fullPath);
|
|
96
|
+
if (stat.isDirectory() && recursive) {
|
|
97
|
+
searchDirectory(fullPath, true);
|
|
98
|
+
}
|
|
99
|
+
else if (stat.isFile() && entry.endsWith(".graphql")) {
|
|
100
|
+
files.push(fullPath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const recursive = pattern.includes("**");
|
|
105
|
+
searchDirectory(searchDir, recursive);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
if (fs.existsSync(pattern)) {
|
|
109
|
+
files.push(pattern);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return files;
|
|
113
|
+
};
|
|
114
|
+
export default validateSchema;
|
|
115
|
+
//# sourceMappingURL=validate-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-schema.js","sourceRoot":"","sources":["../../src/validate-schema.js"],"names":[],"mappings":"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"}
|
package/dist/vitest.config.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const config_1 = require("vitest/config");
|
|
4
|
-
exports.default = (0, config_1.defineConfig)({
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
export default defineConfig({
|
|
5
3
|
test: {
|
|
6
4
|
exclude: [
|
|
7
5
|
"**/node_modules/**",
|
|
@@ -11,7 +9,7 @@ exports.default = (0, config_1.defineConfig)({
|
|
|
11
9
|
],
|
|
12
10
|
chaiConfig: { truncateThreshold: 200 },
|
|
13
11
|
maxConcurrency: 20,
|
|
14
|
-
testTimeout: 20 * 1000,
|
|
12
|
+
testTimeout: 20 * 1000,
|
|
15
13
|
coverage: {
|
|
16
14
|
enabled: false,
|
|
17
15
|
exclude: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.config.js","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vitest.config.js","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,oBAAoB;YACpB,YAAY;YACZ,qCAAqC;YACrC,sFAAsF;SACvF;QACD,UAAU,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE;QACtC,cAAc,EAAE,EAAE;QAClB,WAAW,EAAE,EAAE,GAAG,IAAI;QACtB,QAAQ,EAAE;YACR,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACP,aAAa;gBACb,YAAY;gBACZ,oBAAoB;gBACpB,oBAAoB;aACrB;YACD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;SAC3B;KACF;IACD,OAAO,EAAE;QACP,gBAAgB,EAAE,IAAI;KACvB;CACF,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ on:
|
|
|
7
7
|
- main
|
|
8
8
|
paths:
|
|
9
9
|
- '**/*schema.ts'
|
|
10
|
+
workflow_dispatch: {}
|
|
10
11
|
|
|
11
12
|
env:
|
|
12
13
|
# Configure these environment variables for your setup
|
|
@@ -45,20 +46,21 @@ jobs:
|
|
|
45
46
|
env:
|
|
46
47
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
47
48
|
run: pnpm config set //registry.npmjs.org/:_authToken "${NPM_TOKEN}"
|
|
48
|
-
- name: Install dependencies
|
|
49
|
-
run: pnpm i --frozen-lockfile
|
|
50
49
|
|
|
51
50
|
- name: Install GraphQL schema sync tool
|
|
52
|
-
|
|
51
|
+
# Update below to use the version you want
|
|
52
|
+
run: pnpm install -w @embrace-ai/infra-api-schema-sync@1.1.0
|
|
53
|
+
|
|
53
54
|
# Generate dynamic schema URL based on repository and stage
|
|
54
55
|
- name: Generate schema URL
|
|
55
56
|
id: schema-url
|
|
57
|
+
if: ${{ env.SCHEMA_URL == '' || env.SCHEMA_URL == null }}
|
|
56
58
|
run: |
|
|
57
59
|
# Generate URL using the CLI tool
|
|
58
60
|
if [ -n "$SERVICE_NAME" ]; then
|
|
59
|
-
SCHEMA_URL=$(
|
|
61
|
+
SCHEMA_URL=$(pnpm exec api-tool generate-schema-url --stage "$DEPLOYMENT_STAGE" --service "$SERVICE_NAME")
|
|
60
62
|
else
|
|
61
|
-
SCHEMA_URL=$(
|
|
63
|
+
SCHEMA_URL=$(pnpm exec api-tool generate-schema-url --stage "$DEPLOYMENT_STAGE")
|
|
62
64
|
fi
|
|
63
65
|
|
|
64
66
|
# Set as output for use in later steps
|
|
@@ -69,11 +71,9 @@ jobs:
|
|
|
69
71
|
# Fetch all organization repositories and dispatch to each
|
|
70
72
|
- name: Dispatch schema update events to all org repositories
|
|
71
73
|
env:
|
|
72
|
-
|
|
73
|
-
# Use the dynamically generated schema URL
|
|
74
|
-
SCHEMA_URL: ${{ steps.schema-url.outputs.url }}
|
|
74
|
+
SCHEMA_URL: ${{ env.SCHEMA_URL || steps.schema-url.outputs.url }}
|
|
75
75
|
run: |
|
|
76
|
-
|
|
76
|
+
pnpm exec api-tool dispatch-update \
|
|
77
77
|
--schema-url "$SCHEMA_URL" \
|
|
78
78
|
--token "${{ secrets.GITHUB_TOKEN }}" \
|
|
79
79
|
--source-repo "${{ github.repository }}" \
|
|
@@ -4,7 +4,7 @@ name: Validate GraphQL Schema Updates
|
|
|
4
4
|
on:
|
|
5
5
|
repository_dispatch:
|
|
6
6
|
types: [graphql-schema-updated]
|
|
7
|
-
|
|
7
|
+
workflow_dispatch: {}
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
validate-schema:
|
|
@@ -27,11 +27,9 @@ jobs:
|
|
|
27
27
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
28
28
|
run: pnpm config set //registry.npmjs.org/:_authToken "${NPM_TOKEN}"
|
|
29
29
|
|
|
30
|
-
- name: Install dependencies
|
|
31
|
-
run: pnpm i --frozen-lockfile
|
|
32
|
-
|
|
33
30
|
- name: Install GraphQL schema sync tool
|
|
34
|
-
|
|
31
|
+
# Update line below to use the version you want
|
|
32
|
+
run: pnpm install -w @embrace-ai/infra-api-schema-sync@1.1.0
|
|
35
33
|
|
|
36
34
|
- name: Configure aws credentials
|
|
37
35
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
|
@@ -48,11 +46,11 @@ jobs:
|
|
|
48
46
|
echo "Timestamp: ${{ github.event.client_payload.timestamp }}"
|
|
49
47
|
|
|
50
48
|
- name: Fetch updated schema
|
|
51
|
-
run:
|
|
49
|
+
run: pnpm exec api-tool fetch --url ${{ github.event.client_payload.schemaUrl }} --output new-schema.graphql
|
|
52
50
|
|
|
53
51
|
- name: Validate queries against new schema
|
|
54
52
|
id: validate
|
|
55
|
-
run:
|
|
53
|
+
run: pnpm exec api-tool validate --schema new-schema.graphql --queries 'src/**/*.graphql' --output report.json
|
|
56
54
|
|
|
57
55
|
- name: Check for issues
|
|
58
56
|
id: check-issues
|
|
@@ -68,7 +66,7 @@ jobs:
|
|
|
68
66
|
- name: Generate summary
|
|
69
67
|
id: gen-summary
|
|
70
68
|
if: steps.check-issues.outputs.has_issues == 'true'
|
|
71
|
-
run:
|
|
69
|
+
run: pnpm exec api-tool summarize --report report.json --output GRAPHQL_ISSUES.md && echo "summary=$(cat GRAPHQL_ISSUES.md)" >> $GITHUB_OUTPUT
|
|
72
70
|
|
|
73
71
|
- name: Commit and create PR with issues
|
|
74
72
|
uses: peter-evans/create-pull-request@v6
|
|
@@ -87,14 +85,10 @@ jobs:
|
|
|
87
85
|
|
|
88
86
|
---
|
|
89
87
|
## ${{ steps.check-issues.outputs.has_issues == 'true' && 'Detected Issues' || '🎉 No Issues Found' }}
|
|
90
|
-
${{
|
|
91
|
-
steps.check-issues.outputs.has_issues == 'true'
|
|
92
|
-
? steps.gen-summary.outputs.summary
|
|
93
|
-
: 'The updated schema is compatible with your existing GraphQL queries. No changes are required.'
|
|
94
|
-
}}
|
|
88
|
+
${{ steps.check-issues.outputs.has_issues == 'true' && steps.gen-summary.outputs.summary || 'The updated schema is compatible with your existing GraphQL queries' }}
|
|
95
89
|
|
|
96
90
|
## Next Steps
|
|
97
|
-
1. Review
|
|
91
|
+
1. Review any compatibility issues above
|
|
98
92
|
2. Update your GraphQL queries to match the new schema
|
|
99
93
|
3. Test your changes thoroughly
|
|
100
94
|
4. Merge this PR once all issues are resolved
|