Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@stackaid/stackaid-json-generator

Package Overview
Dependencies
Maintainers
2
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stackaid/stackaid-json-generator - npm Package Compare versions

Comparing version
1.9.0-9
to
1.9.0-10
+5
dist/cjs/constants.d.ts
export declare const GITHUB_DOMAIN = "github.com";
export declare type Ecosystem = 'go' | 'java' | 'javascript' | 'php' | 'python' | 'ruby' | 'rust';
export declare const FileTypes: Record<Ecosystem, string[]>;
export declare const SUMMARY_FILE_TYPES: string[];
export declare const DEPENDENCY_FILE_TYPES: string[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEPENDENCY_FILE_TYPES = exports.SUMMARY_FILE_TYPES = exports.FileTypes = exports.GITHUB_DOMAIN = void 0;
exports.GITHUB_DOMAIN = 'github.com';
exports.FileTypes = {
go: ['go.mod'],
java: ['pom.xml'],
javascript: ['package.json'],
php: ['composer.json'],
python: ['pipfile', 'pyproject.toml', 'setup.py'],
ruby: ['gemfile'],
rust: ['cargo.toml'],
};
exports.SUMMARY_FILE_TYPES = Object.values(exports.FileTypes).flat();
exports.DEPENDENCY_FILE_TYPES = [
exports.FileTypes.java,
exports.FileTypes.php,
exports.FileTypes.python,
exports.FileTypes.ruby,
exports.FileTypes.rust,
].flat();
import { DependencyConfig, GraphConfig, PackageJson, StackAidDependency } from './types/index.js';
export declare const generators: {
go: ({ owner, repo, filename, sourceDir, }: DependencyConfig) => Promise<StackAidDependency[]>;
javascript: ({ octokit, owner, repo, filename, }: DependencyConfig) => Promise<PackageJson>;
graph: ({ octokit, owner, repo, after, }: GraphConfig) => Promise<StackAidDependency[]>;
};
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generators = void 0;
const go = __importStar(require("./go.js"));
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_js_1 = require("./constants.js");
const queries_js_1 = require("./queries.js");
const { uniqBy } = lodash_1.default;
const getJavaScriptDependencies = ({ octokit, owner, repo, filename, }) => __awaiter(void 0, void 0, void 0, function* () {
const content = yield (0, queries_js_1.getClient)(octokit).getFileContents(owner, repo, filename);
const { dependencies, devDependencies } = JSON.parse(content);
return { filename, dependencies, devDependencies };
});
const getGoDependencies = ({ owner, repo, filename, sourceDir, }) => __awaiter(void 0, void 0, void 0, function* () {
const parent = `https://${constants_js_1.GITHUB_DOMAIN}/${owner}/${repo}`;
const deps = go
.getDependencies(path_1.default.dirname(filename), sourceDir)
.filter(({ source }) => source !== parent);
return deps;
});
const getDependencyGraph = ({ octokit, owner, repo, after, }) => __awaiter(void 0, void 0, void 0, function* () {
const client = (0, queries_js_1.getClient)(octokit);
const dependencies = [];
const results = yield client.getRepositoryDependencies(owner, repo, 1, after);
const direct = uniqBy(results, (d) => d.repository.url);
for (const dep of direct) {
const { url: source, name, owner: { login: owner }, } = dep.repository;
const summary = yield client.getRepositorySummary(owner, name);
console.log(`${owner}/${name}: ${summary.map((s) => s.node.filename)}`);
let indirect = [];
for (const { after } of summary) {
const deps = yield client.getRepositoryDependencies(owner, name, 1, after);
indirect.push(...deps.map((d) => ({ source: d.repository.url })));
}
// Dependencies shouldn't be funding themselves.
indirect = indirect.filter((d) => d.source !== source);
dependencies.push({ source, dependencies: uniqBy(indirect, 'source') });
}
return dependencies;
});
exports.generators = {
go: getGoDependencies,
javascript: getJavaScriptDependencies,
graph: getDependencyGraph,
};
import { StackAidDependency } from './types/index.js';
export declare const listDirectDeps: (dir: string, sourceDir: string) => {
module: string;
version: string;
}[];
export declare const getModuleGraph: (dir: string, sourceDir: string) => Record<string, {
module: string;
version: string;
}[]>;
export declare const getDependencies: (dir?: string, sourceDir?: string) => StackAidDependency[];
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependencies = exports.getModuleGraph = exports.listDirectDeps = void 0;
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_js_1 = require("./constants.js");
const child_process_1 = require("child_process");
const { uniqBy } = lodash_1.default;
const filterDependency = (line) => line.startsWith(constants_js_1.GITHUB_DOMAIN);
const parseDependency = (line) => {
switch (true) {
case line.startsWith(constants_js_1.GITHUB_DOMAIN):
const [domain, owner, repo] = line.split('/');
return `https://${domain}/${owner}/${repo}`;
default:
return;
}
};
const parseModuleUrl = (m) => {
const [url, version = ''] = m.split('@');
const [domain, owner, repo] = url.split('/');
return { module: [domain, owner, repo].join('/'), version };
};
const listDirectDeps = (dir, sourceDir) => {
let output = (0, child_process_1.execSync)(`go list -f '{{if not .Indirect}}{{.}}{{end}}' -m all`, { cwd: path_1.default.resolve(sourceDir, dir) }).toString();
return output
.split('\n')
.map((d) => {
const [module, version = ''] = d.split(' ');
return { module, version };
})
.filter((entry) => filterDependency(entry.module));
};
exports.listDirectDeps = listDirectDeps;
const getModuleGraph = (dir, sourceDir) => {
const output = (0, child_process_1.execSync)(`go mod graph`, {
cwd: path_1.default.resolve(sourceDir, dir),
}).toString();
const graph = {};
output.split('\n').forEach((line) => {
if (!line) {
return;
}
const [parent, child] = line.split(' ');
const mod = parseModuleUrl(parent);
const childMod = parseModuleUrl(child);
const key = `${mod.module}@${mod.version}`;
graph[key] = graph[key] || [];
if (childMod.module !== key) {
graph[key].push(childMod);
}
});
Object.entries(graph).forEach(([key, deps]) => {
graph[key] = uniqBy(deps, 'module');
});
return graph;
};
exports.getModuleGraph = getModuleGraph;
const getDependencies = (dir = '', sourceDir = process.cwd()) => {
const graph = (0, exports.getModuleGraph)(dir, sourceDir);
const direct = (0, exports.listDirectDeps)(dir, sourceDir);
let dependencies = direct
.filter((d) => filterDependency(d.module))
.map((d) => {
const url = parseModuleUrl(d.module).module;
const deps = graph[`${url}@${d.version}`] || [];
return {
source: parseDependency(d.module),
dependencies: deps
.filter((d) => filterDependency(d.module))
.map((d) => ({
source: parseDependency(d.module),
})),
};
});
return dependencies;
};
exports.getDependencies = getDependencies;
import { DependencyConfig, PackageJson, StackAidJson } from './types/index.js';
import { generators } from './generate.js';
export { generators } from './generate.js';
export declare const getDependencies: (config: DependencyConfig, generatorTypes?: Partial<typeof generators>) => Promise<{
stackAidJson: StackAidJson;
packageJson: PackageJson[];
} | {
packageJson: PackageJson[];
stackAidJson?: undefined;
}>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependencies = exports.generators = void 0;
const core = __importStar(require("@actions/core"));
const constants_js_1 = require("./constants.js");
const generate_js_1 = require("./generate.js");
const queries_js_1 = require("./queries.js");
const utils_js_1 = require("./utils.js");
var generate_js_2 = require("./generate.js");
Object.defineProperty(exports, "generators", { enumerable: true, get: function () { return generate_js_2.generators; } });
const getDependencies = (config, generatorTypes) => __awaiter(void 0, void 0, void 0, function* () {
const { owner, repo, octokit } = config;
const packageJson = [];
const stackAidJson = { version: 1, dependencies: [] };
const client = (0, queries_js_1.getClient)(octokit);
const summary = yield client.getRepositorySummary(owner, repo, '**/');
const generate = Object.assign(Object.assign({}, generate_js_1.generators), generatorTypes);
for (const { after, node: { filename }, } of summary) {
switch (true) {
case (0, utils_js_1.isFileType)(filename, constants_js_1.FileTypes.go): {
core.info(`Found ${filename}, getting Go dependencies`);
const deps = yield generate.go(Object.assign(Object.assign({}, config), { filename }));
stackAidJson.dependencies.push(...deps);
break;
}
case (0, utils_js_1.isFileType)(filename, constants_js_1.FileTypes.javascript): {
core.info(`Found ${filename}, copying dependencies`);
const deps = yield generate.javascript(Object.assign(Object.assign({}, config), { filename }));
packageJson.push(deps);
break;
}
default:
const deps = yield generate.graph(Object.assign(Object.assign({}, config), { after }));
stackAidJson.dependencies.push(...deps);
break;
}
}
return stackAidJson.dependencies.length
? { stackAidJson, packageJson }
: { packageJson };
});
exports.getDependencies = getDependencies;
import { CreateCommitOnBranchInput } from './types/graphql.js';
import { Octokit } from 'octokit';
export declare const summaryFragment: import("graphql").DocumentNode;
export declare const repositoryFragment: import("graphql").DocumentNode;
export declare const getClient: (octokit: Octokit) => {
graphql(query: string, variables?: Record<string, any>): Promise<any>;
getFileContents(owner: string, repo: string, path: string): Promise<string | null>;
getRepositorySummaryPage(owner: string, repo: string, cursor?: string): Promise<{
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositorySummary(owner: string, repo: string, glob?: string): Promise<{
after: string | undefined;
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositoryDependencies(owner: string, repo: string, first?: number, after?: string): Promise<{
packageManager: string;
requirements: string;
packageName: string;
hasDependencies: boolean;
repository: {
name: string;
url: any;
owner: {
login: string;
} | {
login: string;
};
};
}[]>;
getHeadOid(owner: string, repo: string): Promise<{
name: string;
oid: any;
}>;
createCommit(owner: string, repo: string, input: Partial<CreateCommitOnBranchInput>): Promise<{
commit: {
url: any;
};
}>;
};
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClient = exports.repositoryFragment = exports.summaryFragment = void 0;
const lodash_1 = __importDefault(require("lodash"));
const constants_js_1 = require("./constants.js");
const graphql_tag_1 = require("graphql-tag");
const utils_js_1 = require("./utils.js");
const graphql_1 = require("graphql");
const { uniqBy } = lodash_1.default;
exports.summaryFragment = (0, graphql_tag_1.gql)(`
fragment summaryFragment on DependencyGraphManifestConnection {
edges {
cursor
node {
id
filename
}
}
}
`);
exports.repositoryFragment = (0, graphql_tag_1.gql)(`
fragment repositoryFragment on DependencyGraphManifestConnection {
nodes {
filename
dependencies {
nodes {
repository {
name
owner {
login
}
url
}
packageManager
requirements
packageName
hasDependencies
}
}
}
}
`);
const getClient = (octokit) => {
return {
graphql(query, variables) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield octokit.graphql(Object.assign(Object.assign({}, variables), { query, headers: {
// Required for dependency graph queries, see:
// https://docs.github.com/en/graphql/overview/schema-previews#access-to-a-repositories-dependency-graph-preview
Accept: 'application/vnd.github.hawkgirl-preview+json',
}, request: { timeout: 60 * 1000 } }));
return result;
});
},
getFileContents(owner, repo, path) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield octokit.rest.repos.getContent({
owner,
repo,
path,
});
if ((res === null || res === void 0 ? void 0 : res.status) !== 200) {
return null;
}
const encodedContent = res.data.content;
return Buffer.from(encodedContent, 'base64').toString();
});
},
getRepositorySummaryPage(owner, repo, cursor = '') {
return __awaiter(this, void 0, void 0, function* () {
const result = (yield this.graphql(`
query getRepositorySummary(
$owner: String!
$repo: String!
$cursor: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: 100
after: $cursor
) {
...summaryFragment
}
}
}
${(0, graphql_1.print)(exports.summaryFragment)}
`, { repo, owner, cursor }));
const { dependencyGraphManifests: { edges }, } = result.repository;
return edges;
});
},
getRepositorySummary(owner, repo, glob = '') {
return __awaiter(this, void 0, void 0, function* () {
let edges = yield this.getRepositorySummaryPage(owner, repo);
if (!edges.length) {
return [];
}
let { cursor } = edges[edges.length - 1];
while (cursor) {
edges = [
...edges,
...(yield this.getRepositorySummaryPage(owner, repo, cursor)),
];
const next = edges[edges.length - 1].cursor;
cursor = next !== cursor ? next : '';
}
const relevant = edges
.map((edge, i) => (Object.assign(Object.assign({}, edge), { after: i > 0 ? edges[i - 1].cursor : undefined })))
.filter((edge) => (0, utils_js_1.matches)(edge.node.filename, constants_js_1.SUMMARY_FILE_TYPES, glob));
return relevant;
});
},
getRepositoryDependencies(owner, repo, first, after) {
return __awaiter(this, void 0, void 0, function* () {
const result = (yield this.graphql(`
query getRepositoryDependencies(
$owner: String!
$repo: String!
$first: Int
$after: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: $first
after: $after
) {
...repositoryFragment
}
}
}
${(0, graphql_1.print)(exports.repositoryFragment)}
`, { repo, owner, first, after }));
const { dependencyGraphManifests: { nodes }, } = result.repository;
const dependencies = uniqBy(nodes
.filter((n) => (0, utils_js_1.matches)(n.filename, constants_js_1.DEPENDENCY_FILE_TYPES))
.flatMap((n) => n.dependencies.nodes)
.filter((d) => { var _a; return (_a = d.repository) === null || _a === void 0 ? void 0 : _a.url; }), (d) => d.repository.url);
return dependencies;
});
},
getHeadOid(owner, repo) {
return __awaiter(this, void 0, void 0, function* () {
const result = (yield this.graphql(`
query getHeadOid($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
defaultBranchRef {
name
target {
... on Commit {
history(first: 1) {
nodes {
oid
}
}
}
}
}
}
}
`, { owner, repo }));
const { name, target } = result.repository.defaultBranchRef;
return { name, oid: target.history.nodes[0].oid };
});
},
createCommit(owner, repo, input) {
return __awaiter(this, void 0, void 0, function* () {
const { name: branchName, oid } = yield this.getHeadOid(owner, repo);
const result = (yield this.graphql(`
mutation createCommit($input: CreateCommitOnBranchInput!) {
createCommitOnBranch(input: $input) {
commit {
url
}
}
}
`, {
input: Object.assign({ branch: {
repositoryNameWithOwner: `${owner}/${repo}`,
branchName,
}, expectedHeadOid: oid }, input),
}));
return result.createCommitOnBranch;
});
},
};
};
exports.getClient = getClient;

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import { Octokit } from 'octokit';
export interface DependencyConfig {
octokit: Octokit;
owner: string;
repo: string;
filename?: string;
sourceDir?: string;
}
export interface GraphConfig {
octokit: Octokit;
owner: string;
repo: string;
after?: string;
}
export interface PackageJson {
filename: string;
dependencies: Record<string, string>;
devDependencies: Record<string, string>;
}
export interface StackAidDependency {
source: string;
dependencies?: StackAidDependency[];
}
export interface StackAidJson {
version: 1;
dependencies: StackAidDependency[];
}
export interface GoModule {
Path: string;
Dir: string;
Version: string;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
import { Ecosystem, FileTypes } from './constants.js';
export declare const matches: (file: string, fileTypes: string[], glob?: string) => boolean;
export declare const isFileType: (filename: string, fileType: (typeof FileTypes)[Ecosystem]) => boolean;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFileType = exports.matches = void 0;
const minimatch_1 = __importDefault(require("minimatch"));
const matches = (file, fileTypes, glob = '') => (0, minimatch_1.default)(file.toLowerCase(), `${glob}*(${fileTypes.join('|')})`);
exports.matches = matches;
const isFileType = (filename, fileType) => (0, exports.matches)(filename, fileType, '**/');
exports.isFileType = isFileType;
export declare const GITHUB_DOMAIN = "github.com";
export declare type Ecosystem = 'go' | 'java' | 'javascript' | 'php' | 'python' | 'ruby' | 'rust';
export declare const FileTypes: Record<Ecosystem, string[]>;
export declare const SUMMARY_FILE_TYPES: string[];
export declare const DEPENDENCY_FILE_TYPES: string[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEPENDENCY_FILE_TYPES = exports.SUMMARY_FILE_TYPES = exports.FileTypes = exports.GITHUB_DOMAIN = void 0;
exports.GITHUB_DOMAIN = 'github.com';
exports.FileTypes = {
go: ['go.mod'],
java: ['pom.xml'],
javascript: ['package.json'],
php: ['composer.json'],
python: ['pipfile', 'pyproject.toml', 'setup.py'],
ruby: ['gemfile'],
rust: ['cargo.toml'],
};
exports.SUMMARY_FILE_TYPES = Object.values(exports.FileTypes).flat();
exports.DEPENDENCY_FILE_TYPES = [
exports.FileTypes.java,
exports.FileTypes.php,
exports.FileTypes.python,
exports.FileTypes.ruby,
exports.FileTypes.rust,
].flat();
import { DependencyConfig, GraphConfig, PackageJson, StackAidDependency } from './types/index.js';
export declare const generators: {
go: ({ owner, repo, filename, sourceDir, }: DependencyConfig) => Promise<StackAidDependency[]>;
javascript: ({ octokit, owner, repo, filename, }: DependencyConfig) => Promise<PackageJson>;
graph: ({ octokit, owner, repo, after, }: GraphConfig) => Promise<StackAidDependency[]>;
};
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generators = void 0;
const go = __importStar(require("./go.js"));
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_js_1 = require("./constants.js");
const queries_js_1 = require("./queries.js");
const { uniqBy } = lodash_1.default;
const getJavaScriptDependencies = async ({ octokit, owner, repo, filename, }) => {
const content = await (0, queries_js_1.getClient)(octokit).getFileContents(owner, repo, filename);
const { dependencies, devDependencies } = JSON.parse(content);
return { filename, dependencies, devDependencies };
};
const getGoDependencies = async ({ owner, repo, filename, sourceDir, }) => {
const parent = `https://${constants_js_1.GITHUB_DOMAIN}/${owner}/${repo}`;
const deps = go
.getDependencies(path_1.default.dirname(filename), sourceDir)
.filter(({ source }) => source !== parent);
return deps;
};
const getDependencyGraph = async ({ octokit, owner, repo, after, }) => {
const client = (0, queries_js_1.getClient)(octokit);
const dependencies = [];
const results = await client.getRepositoryDependencies(owner, repo, 1, after);
const direct = uniqBy(results, (d) => d.repository.url);
for (const dep of direct) {
const { url: source, name, owner: { login: owner }, } = dep.repository;
const summary = await client.getRepositorySummary(owner, name);
console.log(`${owner}/${name}: ${summary.map((s) => s.node.filename)}`);
let indirect = [];
for (const { after } of summary) {
const deps = await client.getRepositoryDependencies(owner, name, 1, after);
indirect.push(...deps.map((d) => ({ source: d.repository.url })));
}
// Dependencies shouldn't be funding themselves.
indirect = indirect.filter((d) => d.source !== source);
dependencies.push({ source, dependencies: uniqBy(indirect, 'source') });
}
return dependencies;
};
exports.generators = {
go: getGoDependencies,
javascript: getJavaScriptDependencies,
graph: getDependencyGraph,
};
import { StackAidDependency } from './types/index.js';
export declare const listDirectDeps: (dir: string, sourceDir: string) => {
module: string;
version: string;
}[];
export declare const getModuleGraph: (dir: string, sourceDir: string) => Record<string, {
module: string;
version: string;
}[]>;
export declare const getDependencies: (dir?: string, sourceDir?: string) => StackAidDependency[];
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependencies = exports.getModuleGraph = exports.listDirectDeps = void 0;
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const constants_js_1 = require("./constants.js");
const child_process_1 = require("child_process");
const { uniqBy } = lodash_1.default;
const filterDependency = (line) => line.startsWith(constants_js_1.GITHUB_DOMAIN);
const parseDependency = (line) => {
switch (true) {
case line.startsWith(constants_js_1.GITHUB_DOMAIN):
const [domain, owner, repo] = line.split('/');
return `https://${domain}/${owner}/${repo}`;
default:
return;
}
};
const parseModuleUrl = (m) => {
const [url, version = ''] = m.split('@');
const [domain, owner, repo] = url.split('/');
return { module: [domain, owner, repo].join('/'), version };
};
const listDirectDeps = (dir, sourceDir) => {
let output = (0, child_process_1.execSync)(`go list -f '{{if not .Indirect}}{{.}}{{end}}' -m all`, { cwd: path_1.default.resolve(sourceDir, dir) }).toString();
return output
.split('\n')
.map((d) => {
const [module, version = ''] = d.split(' ');
return { module, version };
})
.filter((entry) => filterDependency(entry.module));
};
exports.listDirectDeps = listDirectDeps;
const getModuleGraph = (dir, sourceDir) => {
const output = (0, child_process_1.execSync)(`go mod graph`, {
cwd: path_1.default.resolve(sourceDir, dir),
}).toString();
const graph = {};
output.split('\n').forEach((line) => {
if (!line) {
return;
}
const [parent, child] = line.split(' ');
const mod = parseModuleUrl(parent);
const childMod = parseModuleUrl(child);
const key = `${mod.module}@${mod.version}`;
graph[key] = graph[key] || [];
if (childMod.module !== key) {
graph[key].push(childMod);
}
});
Object.entries(graph).forEach(([key, deps]) => {
graph[key] = uniqBy(deps, 'module');
});
return graph;
};
exports.getModuleGraph = getModuleGraph;
const getDependencies = (dir = '', sourceDir = process.cwd()) => {
const graph = (0, exports.getModuleGraph)(dir, sourceDir);
const direct = (0, exports.listDirectDeps)(dir, sourceDir);
let dependencies = direct
.filter((d) => filterDependency(d.module))
.map((d) => {
const url = parseModuleUrl(d.module).module;
const deps = graph[`${url}@${d.version}`] || [];
return {
source: parseDependency(d.module),
dependencies: deps
.filter((d) => filterDependency(d.module))
.map((d) => ({
source: parseDependency(d.module),
})),
};
});
return dependencies;
};
exports.getDependencies = getDependencies;
import { DependencyConfig, PackageJson, StackAidJson } from './types/index.js';
import { generators } from './generate.js';
export { generators } from './generate.js';
export declare const getDependencies: (config: DependencyConfig, generatorTypes?: Partial<typeof generators>) => Promise<{
stackAidJson: StackAidJson;
packageJson: PackageJson[];
} | {
packageJson: PackageJson[];
stackAidJson?: undefined;
}>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependencies = exports.generators = void 0;
const core = __importStar(require("@actions/core"));
const constants_js_1 = require("./constants.js");
const generate_js_1 = require("./generate.js");
const queries_js_1 = require("./queries.js");
const utils_js_1 = require("./utils.js");
var generate_js_2 = require("./generate.js");
Object.defineProperty(exports, "generators", { enumerable: true, get: function () { return generate_js_2.generators; } });
const getDependencies = async (config, generatorTypes) => {
const { owner, repo, octokit } = config;
const packageJson = [];
const stackAidJson = { version: 1, dependencies: [] };
const client = (0, queries_js_1.getClient)(octokit);
const summary = await client.getRepositorySummary(owner, repo, '**/');
const generate = { ...generate_js_1.generators, ...generatorTypes };
for (const { after, node: { filename }, } of summary) {
switch (true) {
case (0, utils_js_1.isFileType)(filename, constants_js_1.FileTypes.go): {
core.info(`Found ${filename}, getting Go dependencies`);
const deps = await generate.go({ ...config, filename });
stackAidJson.dependencies.push(...deps);
break;
}
case (0, utils_js_1.isFileType)(filename, constants_js_1.FileTypes.javascript): {
core.info(`Found ${filename}, copying dependencies`);
const deps = await generate.javascript({ ...config, filename });
packageJson.push(deps);
break;
}
default:
const deps = await generate.graph({ ...config, after });
stackAidJson.dependencies.push(...deps);
break;
}
}
return stackAidJson.dependencies.length
? { stackAidJson, packageJson }
: { packageJson };
};
exports.getDependencies = getDependencies;
import { CreateCommitOnBranchInput } from './types/graphql.js';
import { Octokit } from 'octokit';
export declare const summaryFragment: import("graphql").DocumentNode;
export declare const repositoryFragment: import("graphql").DocumentNode;
export declare const getClient: (octokit: Octokit) => {
graphql(query: string, variables?: Record<string, any>): Promise<any>;
getFileContents(owner: string, repo: string, path: string): Promise<string | null>;
getRepositorySummaryPage(owner: string, repo: string, cursor?: string): Promise<{
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositorySummary(owner: string, repo: string, glob?: string): Promise<{
after: string | undefined;
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositoryDependencies(owner: string, repo: string, first?: number, after?: string): Promise<{
packageManager: string;
requirements: string;
packageName: string;
hasDependencies: boolean;
repository: {
name: string;
url: any;
owner: {
login: string;
} | {
login: string;
};
};
}[]>;
getHeadOid(owner: string, repo: string): Promise<{
name: string;
oid: any;
}>;
createCommit(owner: string, repo: string, input: Partial<CreateCommitOnBranchInput>): Promise<{
commit: {
url: any;
};
}>;
};
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClient = exports.repositoryFragment = exports.summaryFragment = void 0;
const lodash_1 = __importDefault(require("lodash"));
const constants_js_1 = require("./constants.js");
const graphql_tag_1 = require("graphql-tag");
const utils_js_1 = require("./utils.js");
const graphql_1 = require("graphql");
const { uniqBy } = lodash_1.default;
exports.summaryFragment = (0, graphql_tag_1.gql)(`
fragment summaryFragment on DependencyGraphManifestConnection {
edges {
cursor
node {
id
filename
}
}
}
`);
exports.repositoryFragment = (0, graphql_tag_1.gql)(`
fragment repositoryFragment on DependencyGraphManifestConnection {
nodes {
filename
dependencies {
nodes {
repository {
name
owner {
login
}
url
}
packageManager
requirements
packageName
hasDependencies
}
}
}
}
`);
const getClient = (octokit) => {
return {
async graphql(query, variables) {
const result = await octokit.graphql({
...variables,
query,
headers: {
// Required for dependency graph queries, see:
// https://docs.github.com/en/graphql/overview/schema-previews#access-to-a-repositories-dependency-graph-preview
Accept: 'application/vnd.github.hawkgirl-preview+json',
},
request: { timeout: 60 * 1000 },
});
return result;
},
async getFileContents(owner, repo, path) {
const res = await octokit.rest.repos.getContent({
owner,
repo,
path,
});
if (res?.status !== 200) {
return null;
}
const encodedContent = res.data.content;
return Buffer.from(encodedContent, 'base64').toString();
},
async getRepositorySummaryPage(owner, repo, cursor = '') {
const result = (await this.graphql(`
query getRepositorySummary(
$owner: String!
$repo: String!
$cursor: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: 100
after: $cursor
) {
...summaryFragment
}
}
}
${(0, graphql_1.print)(exports.summaryFragment)}
`, { repo, owner, cursor }));
const { dependencyGraphManifests: { edges }, } = result.repository;
return edges;
},
async getRepositorySummary(owner, repo, glob = '') {
let edges = await this.getRepositorySummaryPage(owner, repo);
if (!edges.length) {
return [];
}
let { cursor } = edges[edges.length - 1];
while (cursor) {
edges = [
...edges,
...(await this.getRepositorySummaryPage(owner, repo, cursor)),
];
const next = edges[edges.length - 1].cursor;
cursor = next !== cursor ? next : '';
}
const relevant = edges
.map((edge, i) => ({
...edge,
after: i > 0 ? edges[i - 1].cursor : undefined,
}))
.filter((edge) => (0, utils_js_1.matches)(edge.node.filename, constants_js_1.SUMMARY_FILE_TYPES, glob));
return relevant;
},
async getRepositoryDependencies(owner, repo, first, after) {
const result = (await this.graphql(`
query getRepositoryDependencies(
$owner: String!
$repo: String!
$first: Int
$after: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: $first
after: $after
) {
...repositoryFragment
}
}
}
${(0, graphql_1.print)(exports.repositoryFragment)}
`, { repo, owner, first, after }));
const { dependencyGraphManifests: { nodes }, } = result.repository;
const dependencies = uniqBy(nodes
.filter((n) => (0, utils_js_1.matches)(n.filename, constants_js_1.DEPENDENCY_FILE_TYPES))
.flatMap((n) => n.dependencies.nodes)
.filter((d) => d.repository?.url), (d) => d.repository.url);
return dependencies;
},
async getHeadOid(owner, repo) {
const result = (await this.graphql(`
query getHeadOid($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
defaultBranchRef {
name
target {
... on Commit {
history(first: 1) {
nodes {
oid
}
}
}
}
}
}
}
`, { owner, repo }));
const { name, target } = result.repository.defaultBranchRef;
return { name, oid: target.history.nodes[0].oid };
},
async createCommit(owner, repo, input) {
const { name: branchName, oid } = await this.getHeadOid(owner, repo);
const result = (await this.graphql(`
mutation createCommit($input: CreateCommitOnBranchInput!) {
createCommitOnBranch(input: $input) {
commit {
url
}
}
}
`, {
input: {
branch: {
repositoryNameWithOwner: `${owner}/${repo}`,
branchName,
},
expectedHeadOid: oid,
...input,
},
}));
return result.createCommitOnBranch;
},
};
};
exports.getClient = getClient;

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import { Octokit } from 'octokit';
export interface DependencyConfig {
octokit: Octokit;
owner: string;
repo: string;
filename?: string;
sourceDir?: string;
}
export interface GraphConfig {
octokit: Octokit;
owner: string;
repo: string;
after?: string;
}
export interface PackageJson {
filename: string;
dependencies: Record<string, string>;
devDependencies: Record<string, string>;
}
export interface StackAidDependency {
source: string;
dependencies?: StackAidDependency[];
}
export interface StackAidJson {
version: 1;
dependencies: StackAidDependency[];
}
export interface GoModule {
Path: string;
Dir: string;
Version: string;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
import { Ecosystem, FileTypes } from './constants.js';
export declare const matches: (file: string, fileTypes: string[], glob?: string) => boolean;
export declare const isFileType: (filename: string, fileType: (typeof FileTypes)[Ecosystem]) => boolean;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFileType = exports.matches = void 0;
const minimatch_1 = __importDefault(require("minimatch"));
const matches = (file, fileTypes, glob = '') => (0, minimatch_1.default)(file.toLowerCase(), `${glob}*(${fileTypes.join('|')})`);
exports.matches = matches;
const isFileType = (filename, fileType) => (0, exports.matches)(filename, fileType, '**/');
exports.isFileType = isFileType;
+17
-12
{
"name": "@stackaid/stackaid-json-generator",
"version": "1.9.0-9",
"version": "1.9.0-10",
"private": false,
"description": "Generate a stackaid.json file based on your repository's dependency graph",
"exports": "./dist/index.js",
"type": "module",
"engines": {
"node": ">=14.16"
},
"scripts": {
"build": "tsc",
"build": "npm run build:esm && npm run build:cjs",
"build:esm": "tsc",
"build:cjs": "tsc -p tsconfig-cjs.json",
"build:action": "ncc build ./src/action.ts -o dist/action --target es2020",

@@ -28,7 +25,14 @@ "release": "np",

"license": "ISC",
"types": "./dist/types/index.d.ts",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"exports": {
"node": {
"import": "./dist/ems/index.js",
"require": "./dist/cjs/index.js"
},
"default": "./dist/cjs/index.js"
},
"files": [
"dist/*.js",
"dist/*.d.ts",
"dist/types/index.*"
"dist/esm/*",
"dist/cjs/*"
],

@@ -41,3 +45,4 @@ "dependencies": {

"lodash": "^4.17.21",
"minimatch": "^3.1.2"
"minimatch": "^3.1.2",
"octokit": "^2.0.10"
},

@@ -44,0 +49,0 @@ "devDependencies": {

export declare const GITHUB_DOMAIN = "github.com";
export declare type Ecosystem = 'go' | 'java' | 'javascript' | 'php' | 'python' | 'ruby' | 'rust';
export declare const FileTypes: Record<Ecosystem, string[]>;
export declare const SUMMARY_FILE_TYPES: string[];
export declare const DEPENDENCY_FILE_TYPES: string[];
export const GITHUB_DOMAIN = 'github.com';
export const FileTypes = {
go: ['go.mod'],
java: ['pom.xml'],
javascript: ['package.json'],
php: ['composer.json'],
python: ['pipfile', 'pyproject.toml', 'setup.py'],
ruby: ['gemfile'],
rust: ['cargo.toml'],
};
export const SUMMARY_FILE_TYPES = Object.values(FileTypes).flat();
export const DEPENDENCY_FILE_TYPES = [
FileTypes.java,
FileTypes.php,
FileTypes.python,
FileTypes.ruby,
FileTypes.rust,
].flat();
import { DependencyConfig, GraphConfig, PackageJson, StackAidDependency } from './types/index.js';
export declare const generators: {
go: ({ owner, repo, filename, sourceDir, }: DependencyConfig) => Promise<StackAidDependency[]>;
javascript: ({ octokit, owner, repo, filename, }: DependencyConfig) => Promise<PackageJson>;
graph: ({ octokit, owner, repo, after, }: GraphConfig) => Promise<StackAidDependency[]>;
};
import * as go from './go.js';
import lodash from 'lodash';
import path from 'path';
import { GITHUB_DOMAIN } from './constants.js';
import { getClient } from './queries.js';
const { uniqBy } = lodash;
const getJavaScriptDependencies = async ({ octokit, owner, repo, filename, }) => {
const content = await getClient(octokit).getFileContents(owner, repo, filename);
const { dependencies, devDependencies } = JSON.parse(content);
return { filename, dependencies, devDependencies };
};
const getGoDependencies = async ({ owner, repo, filename, sourceDir, }) => {
const parent = `https://${GITHUB_DOMAIN}/${owner}/${repo}`;
const deps = go
.getDependencies(path.dirname(filename), sourceDir)
.filter(({ source }) => source !== parent);
return deps;
};
const getDependencyGraph = async ({ octokit, owner, repo, after, }) => {
const client = getClient(octokit);
const dependencies = [];
const results = await client.getRepositoryDependencies(owner, repo, 1, after);
const direct = uniqBy(results, (d) => d.repository.url);
for (const dep of direct) {
const { url: source, name, owner: { login: owner }, } = dep.repository;
const summary = await client.getRepositorySummary(owner, name);
console.log(`${owner}/${name}: ${summary.map((s) => s.node.filename)}`);
let indirect = [];
for (const { after } of summary) {
const deps = await client.getRepositoryDependencies(owner, name, 1, after);
indirect.push(...deps.map((d) => ({ source: d.repository.url })));
}
// Dependencies shouldn't be funding themselves.
indirect = indirect.filter((d) => d.source !== source);
dependencies.push({ source, dependencies: uniqBy(indirect, 'source') });
}
return dependencies;
};
export const generators = {
go: getGoDependencies,
javascript: getJavaScriptDependencies,
graph: getDependencyGraph,
};
import { StackAidDependency } from './types/index.js';
export declare const listDirectDeps: (dir: string, sourceDir: string) => {
module: string;
version: string;
}[];
export declare const getModuleGraph: (dir: string, sourceDir: string) => Record<string, {
module: string;
version: string;
}[]>;
export declare const getDependencies: (dir?: string, sourceDir?: string) => StackAidDependency[];
import lodash from 'lodash';
import path from 'path';
import { GITHUB_DOMAIN } from './constants.js';
import { execSync } from 'child_process';
const { uniqBy } = lodash;
const filterDependency = (line) => line.startsWith(GITHUB_DOMAIN);
const parseDependency = (line) => {
switch (true) {
case line.startsWith(GITHUB_DOMAIN):
const [domain, owner, repo] = line.split('/');
return `https://${domain}/${owner}/${repo}`;
default:
return;
}
};
const parseModuleUrl = (m) => {
const [url, version = ''] = m.split('@');
const [domain, owner, repo] = url.split('/');
return { module: [domain, owner, repo].join('/'), version };
};
export const listDirectDeps = (dir, sourceDir) => {
let output = execSync(`go list -f '{{if not .Indirect}}{{.}}{{end}}' -m all`, { cwd: path.resolve(sourceDir, dir) }).toString();
return output
.split('\n')
.map((d) => {
const [module, version = ''] = d.split(' ');
return { module, version };
})
.filter((entry) => filterDependency(entry.module));
};
export const getModuleGraph = (dir, sourceDir) => {
const output = execSync(`go mod graph`, {
cwd: path.resolve(sourceDir, dir),
}).toString();
const graph = {};
output.split('\n').forEach((line) => {
if (!line) {
return;
}
const [parent, child] = line.split(' ');
const mod = parseModuleUrl(parent);
const childMod = parseModuleUrl(child);
const key = `${mod.module}@${mod.version}`;
graph[key] = graph[key] || [];
if (childMod.module !== key) {
graph[key].push(childMod);
}
});
Object.entries(graph).forEach(([key, deps]) => {
graph[key] = uniqBy(deps, 'module');
});
return graph;
};
export const getDependencies = (dir = '', sourceDir = process.cwd()) => {
const graph = getModuleGraph(dir, sourceDir);
const direct = listDirectDeps(dir, sourceDir);
let dependencies = direct
.filter((d) => filterDependency(d.module))
.map((d) => {
const url = parseModuleUrl(d.module).module;
const deps = graph[`${url}@${d.version}`] || [];
return {
source: parseDependency(d.module),
dependencies: deps
.filter((d) => filterDependency(d.module))
.map((d) => ({
source: parseDependency(d.module),
})),
};
});
return dependencies;
};
import { DependencyConfig, PackageJson, StackAidJson } from './types/index.js';
import { generators } from './generate.js';
export { generators } from './generate.js';
export declare const getDependencies: (config: DependencyConfig, generatorTypes?: Partial<typeof generators>) => Promise<{
stackAidJson: StackAidJson;
packageJson: PackageJson[];
} | {
packageJson: PackageJson[];
stackAidJson?: undefined;
}>;
import * as core from '@actions/core';
import { FileTypes } from './constants.js';
import { generators } from './generate.js';
import { getClient } from './queries.js';
import { isFileType } from './utils.js';
export { generators } from './generate.js';
export const getDependencies = async (config, generatorTypes) => {
const { owner, repo, octokit } = config;
const packageJson = [];
const stackAidJson = { version: 1, dependencies: [] };
const client = getClient(octokit);
const summary = await client.getRepositorySummary(owner, repo, '**/');
const generate = { ...generators, ...generatorTypes };
for (const { after, node: { filename }, } of summary) {
switch (true) {
case isFileType(filename, FileTypes.go): {
core.info(`Found ${filename}, getting Go dependencies`);
const deps = await generate.go({ ...config, filename });
stackAidJson.dependencies.push(...deps);
break;
}
case isFileType(filename, FileTypes.javascript): {
core.info(`Found ${filename}, copying dependencies`);
const deps = await generate.javascript({ ...config, filename });
packageJson.push(deps);
break;
}
default:
const deps = await generate.graph({ ...config, after });
stackAidJson.dependencies.push(...deps);
break;
}
}
return stackAidJson.dependencies.length
? { stackAidJson, packageJson }
: { packageJson };
};
import { CreateCommitOnBranchInput } from './types/graphql.js';
import { Octokit } from './types/index.js';
export declare const summaryFragment: import("graphql").DocumentNode;
export declare const repositoryFragment: import("graphql").DocumentNode;
export declare const getClient: (octokit: Octokit) => {
octokit: import("@octokit/core").Octokit & import("@octokit/plugin-rest-endpoint-methods/dist-types/types.js").Api & {
paginate: import("@octokit/plugin-paginate-rest").PaginateInterface;
};
graphql(query: string, variables?: Record<string, any>): Promise<any>;
getFileContents(owner: string, repo: string, path: string): Promise<string | null>;
getRepositorySummaryPage(owner: string, repo: string, cursor?: string): Promise<{
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositorySummary(owner: string, repo: string, glob?: string): Promise<{
after: string | undefined;
cursor: string;
node: {
id: string;
filename: string;
};
}[]>;
getRepositoryDependencies(owner: string, repo: string, first?: number, after?: string): Promise<{
packageManager: string;
requirements: string;
packageName: string;
hasDependencies: boolean;
repository: {
name: string;
url: any;
owner: {
login: string;
} | {
login: string;
};
};
}[]>;
getHeadOid(owner: string, repo: string): Promise<{
name: string;
oid: any;
}>;
createCommit(owner: string, repo: string, input: Partial<CreateCommitOnBranchInput>): Promise<{
commit: {
url: any;
};
}>;
};
import lodash from 'lodash';
import { DEPENDENCY_FILE_TYPES, SUMMARY_FILE_TYPES } from './constants.js';
import { gql } from 'graphql-tag';
import { matches } from './utils.js';
import { print } from 'graphql';
const { uniqBy } = lodash;
export const summaryFragment = gql(`
fragment summaryFragment on DependencyGraphManifestConnection {
edges {
cursor
node {
id
filename
}
}
}
`);
export const repositoryFragment = gql(`
fragment repositoryFragment on DependencyGraphManifestConnection {
nodes {
filename
dependencies {
nodes {
repository {
name
owner {
login
}
url
}
packageManager
requirements
packageName
hasDependencies
}
}
}
}
`);
export const getClient = (octokit) => {
return {
octokit,
async graphql(query, variables) {
const result = await this.octokit.graphql({
...variables,
query,
headers: {
// Required for dependency graph queries, see:
// https://docs.github.com/en/graphql/overview/schema-previews#access-to-a-repositories-dependency-graph-preview
Accept: 'application/vnd.github.hawkgirl-preview+json',
},
request: { timeout: 60 * 1000 },
});
return result;
},
async getFileContents(owner, repo, path) {
const res = await this.octokit.rest.repos.getContent({
owner,
repo,
path,
});
if (res?.status !== 200) {
return null;
}
const encodedContent = res.data.content;
return Buffer.from(encodedContent, 'base64').toString();
},
async getRepositorySummaryPage(owner, repo, cursor = '') {
const result = (await this.graphql(`
query getRepositorySummary(
$owner: String!
$repo: String!
$cursor: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: 100
after: $cursor
) {
...summaryFragment
}
}
}
${print(summaryFragment)}
`, { repo, owner, cursor }));
const { dependencyGraphManifests: { edges }, } = result.repository;
return edges;
},
async getRepositorySummary(owner, repo, glob = '') {
let edges = await this.getRepositorySummaryPage(owner, repo);
if (!edges.length) {
return [];
}
let { cursor } = edges[edges.length - 1];
while (cursor) {
edges = [
...edges,
...(await this.getRepositorySummaryPage(owner, repo, cursor)),
];
const next = edges[edges.length - 1].cursor;
cursor = next !== cursor ? next : '';
}
const relevant = edges
.map((edge, i) => ({
...edge,
after: i > 0 ? edges[i - 1].cursor : undefined,
}))
.filter((edge) => matches(edge.node.filename, SUMMARY_FILE_TYPES, glob));
return relevant;
},
async getRepositoryDependencies(owner, repo, first, after) {
const result = (await this.graphql(`
query getRepositoryDependencies(
$owner: String!
$repo: String!
$first: Int
$after: String
) {
repository(owner: $owner, name: $repo) {
dependencyGraphManifests(
dependenciesFirst: 1
withDependencies: true
first: $first
after: $after
) {
...repositoryFragment
}
}
}
${print(repositoryFragment)}
`, { repo, owner, first, after }));
const { dependencyGraphManifests: { nodes }, } = result.repository;
const dependencies = uniqBy(nodes
.filter((n) => matches(n.filename, DEPENDENCY_FILE_TYPES))
.flatMap((n) => n.dependencies.nodes)
.filter((d) => d.repository?.url), (d) => d.repository.url);
return dependencies;
},
async getHeadOid(owner, repo) {
const result = (await this.graphql(`
query getHeadOid($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
defaultBranchRef {
name
target {
... on Commit {
history(first: 1) {
nodes {
oid
}
}
}
}
}
}
}
`, { owner, repo }));
const { name, target } = result.repository.defaultBranchRef;
return { name, oid: target.history.nodes[0].oid };
},
async createCommit(owner, repo, input) {
const { name: branchName, oid } = await this.getHeadOid(owner, repo);
const result = (await this.graphql(`
mutation createCommit($input: CreateCommitOnBranchInput!) {
createCommitOnBranch(input: $input) {
commit {
url
}
}
}
`, {
input: {
branch: {
repositoryNameWithOwner: `${owner}/${repo}`,
branchName,
},
expectedHeadOid: oid,
...input,
},
}));
return result.createCommitOnBranch;
},
};
};
import * as github from '@actions/github';
export declare type Octokit = ReturnType<typeof github.getOctokit>;
export interface DependencyConfig {
octokit: Octokit;
owner: string;
repo: string;
filename?: string;
sourceDir?: string;
}
export interface GraphConfig {
octokit: Octokit;
owner: string;
repo: string;
after?: string;
}
export interface PackageJson {
filename: string;
dependencies: Record<string, string>;
devDependencies: Record<string, string>;
}
export interface StackAidDependency {
source: string;
dependencies?: StackAidDependency[];
}
export interface StackAidJson {
version: 1;
dependencies: StackAidDependency[];
}
export interface GoModule {
Path: string;
Dir: string;
Version: string;
}
import { Ecosystem, FileTypes } from './constants.js';
export declare const matches: (file: string, fileTypes: string[], glob?: string) => boolean;
export declare const isFileType: (filename: string, fileType: (typeof FileTypes)[Ecosystem]) => boolean;
import minimatch from 'minimatch';
export const matches = (file, fileTypes, glob = '') => minimatch(file.toLowerCase(), `${glob}*(${fileTypes.join('|')})`);
export const isFileType = (filename, fileType) => matches(filename, fileType, '**/');