@qasshq/qass 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +40 -0
  2. package/README.md +163 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +117 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/config.d.ts +4 -0
  8. package/dist/core/config.d.ts.map +1 -0
  9. package/dist/core/config.js +128 -0
  10. package/dist/core/config.js.map +1 -0
  11. package/dist/core/diff-analyzer.d.ts +3 -0
  12. package/dist/core/diff-analyzer.d.ts.map +1 -0
  13. package/dist/core/diff-analyzer.js +194 -0
  14. package/dist/core/diff-analyzer.js.map +1 -0
  15. package/dist/core/discover.d.ts +3 -0
  16. package/dist/core/discover.d.ts.map +1 -0
  17. package/dist/core/discover.js +51 -0
  18. package/dist/core/discover.js.map +1 -0
  19. package/dist/core/license.d.ts +13 -0
  20. package/dist/core/license.d.ts.map +1 -0
  21. package/dist/core/license.js +132 -0
  22. package/dist/core/license.js.map +1 -0
  23. package/dist/core/report.d.ts +4 -0
  24. package/dist/core/report.d.ts.map +1 -0
  25. package/dist/core/report.js +95 -0
  26. package/dist/core/report.js.map +1 -0
  27. package/dist/core/runner.d.ts +3 -0
  28. package/dist/core/runner.d.ts.map +1 -0
  29. package/dist/core/runner.js +136 -0
  30. package/dist/core/runner.js.map +1 -0
  31. package/dist/core/test-planner.d.ts +3 -0
  32. package/dist/core/test-planner.d.ts.map +1 -0
  33. package/dist/core/test-planner.js +107 -0
  34. package/dist/core/test-planner.js.map +1 -0
  35. package/dist/integrations/cursor-rule.d.ts +2 -0
  36. package/dist/integrations/cursor-rule.d.ts.map +1 -0
  37. package/dist/integrations/cursor-rule.js +46 -0
  38. package/dist/integrations/cursor-rule.js.map +1 -0
  39. package/dist/integrations/mcp-server.d.ts +67 -0
  40. package/dist/integrations/mcp-server.d.ts.map +1 -0
  41. package/dist/integrations/mcp-server.js +61 -0
  42. package/dist/integrations/mcp-server.js.map +1 -0
  43. package/dist/runners/api/api-runner.d.ts +3 -0
  44. package/dist/runners/api/api-runner.d.ts.map +1 -0
  45. package/dist/runners/api/api-runner.js +258 -0
  46. package/dist/runners/api/api-runner.js.map +1 -0
  47. package/dist/runners/api/endpoint-discovery.d.ts +3 -0
  48. package/dist/runners/api/endpoint-discovery.d.ts.map +1 -0
  49. package/dist/runners/api/endpoint-discovery.js +106 -0
  50. package/dist/runners/api/endpoint-discovery.js.map +1 -0
  51. package/dist/runners/e2e/playwright-runner.d.ts +3 -0
  52. package/dist/runners/e2e/playwright-runner.d.ts.map +1 -0
  53. package/dist/runners/e2e/playwright-runner.js +309 -0
  54. package/dist/runners/e2e/playwright-runner.js.map +1 -0
  55. package/dist/runners/security/dynamic-checker.d.ts +3 -0
  56. package/dist/runners/security/dynamic-checker.d.ts.map +1 -0
  57. package/dist/runners/security/dynamic-checker.js +136 -0
  58. package/dist/runners/security/dynamic-checker.js.map +1 -0
  59. package/dist/runners/security/rules/auth-middleware.d.ts +13 -0
  60. package/dist/runners/security/rules/auth-middleware.d.ts.map +1 -0
  61. package/dist/runners/security/rules/auth-middleware.js +94 -0
  62. package/dist/runners/security/rules/auth-middleware.js.map +1 -0
  63. package/dist/runners/security/rules/config-audit.d.ts +14 -0
  64. package/dist/runners/security/rules/config-audit.d.ts.map +1 -0
  65. package/dist/runners/security/rules/config-audit.js +91 -0
  66. package/dist/runners/security/rules/config-audit.js.map +1 -0
  67. package/dist/runners/security/rules/dep-audit.d.ts +7 -0
  68. package/dist/runners/security/rules/dep-audit.d.ts.map +1 -0
  69. package/dist/runners/security/rules/dep-audit.js +82 -0
  70. package/dist/runners/security/rules/dep-audit.js.map +1 -0
  71. package/dist/runners/security/rules/input-sanitization.d.ts +12 -0
  72. package/dist/runners/security/rules/input-sanitization.d.ts.map +1 -0
  73. package/dist/runners/security/rules/input-sanitization.js +64 -0
  74. package/dist/runners/security/rules/input-sanitization.js.map +1 -0
  75. package/dist/runners/security/rules/rate-limit-audit.d.ts +11 -0
  76. package/dist/runners/security/rules/rate-limit-audit.d.ts.map +1 -0
  77. package/dist/runners/security/rules/rate-limit-audit.js +51 -0
  78. package/dist/runners/security/rules/rate-limit-audit.js.map +1 -0
  79. package/dist/runners/security/rules/secrets-scan.d.ts +4 -0
  80. package/dist/runners/security/rules/secrets-scan.d.ts.map +1 -0
  81. package/dist/runners/security/rules/secrets-scan.js +129 -0
  82. package/dist/runners/security/rules/secrets-scan.js.map +1 -0
  83. package/dist/runners/security/rules/xss-vectors.d.ts +13 -0
  84. package/dist/runners/security/rules/xss-vectors.d.ts.map +1 -0
  85. package/dist/runners/security/rules/xss-vectors.js +76 -0
  86. package/dist/runners/security/rules/xss-vectors.js.map +1 -0
  87. package/dist/runners/security/static-analyzer.d.ts +7 -0
  88. package/dist/runners/security/static-analyzer.d.ts.map +1 -0
  89. package/dist/runners/security/static-analyzer.js +87 -0
  90. package/dist/runners/security/static-analyzer.js.map +1 -0
  91. package/dist/runners/unit/unit-runner.d.ts +3 -0
  92. package/dist/runners/unit/unit-runner.d.ts.map +1 -0
  93. package/dist/runners/unit/unit-runner.js +157 -0
  94. package/dist/runners/unit/unit-runner.js.map +1 -0
  95. package/dist/types.d.ts +153 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +2 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/util/glob.d.ts +2 -0
  100. package/dist/util/glob.d.ts.map +1 -0
  101. package/dist/util/glob.js +32 -0
  102. package/dist/util/glob.js.map +1 -0
  103. package/package.json +68 -0
@@ -0,0 +1,87 @@
1
+ import { resolve } from "node:path";
2
+ import chalk from "chalk";
3
+ import { glob } from "../../util/glob.js";
4
+ import { runAuthMiddlewareRule } from "./rules/auth-middleware.js";
5
+ import { runInputSanitizationRule } from "./rules/input-sanitization.js";
6
+ import { runSecretsScanRule } from "./rules/secrets-scan.js";
7
+ import { runXssVectorsRule } from "./rules/xss-vectors.js";
8
+ import { runConfigAuditRule } from "./rules/config-audit.js";
9
+ import { runRateLimitAuditRule } from "./rules/rate-limit-audit.js";
10
+ import { runDepAuditRule } from "./rules/dep-audit.js";
11
+ const RULES = [
12
+ { name: "auth-middleware", run: runAuthMiddlewareRule },
13
+ { name: "input-sanitization", run: runInputSanitizationRule },
14
+ { name: "secrets-scan", run: runSecretsScanRule },
15
+ { name: "xss-vectors", run: runXssVectorsRule },
16
+ { name: "config-audit", run: runConfigAuditRule },
17
+ { name: "rate-limit-audit", run: runRateLimitAuditRule },
18
+ { name: "dep-audit", run: runDepAuditRule },
19
+ ];
20
+ export async function runStaticAnalysis(config, projectPath, diff) {
21
+ const enabledRules = config.security?.static_rules ?? RULES.map((r) => r.name);
22
+ const threshold = config.security?.severity_threshold ?? "LOW";
23
+ const defaultIgnore = [
24
+ "**/*.test.*",
25
+ "**/*.spec.*",
26
+ "**/node_modules/**",
27
+ "**/runners/security/rules/**",
28
+ "**/runners/security/dynamic-checker.*",
29
+ ];
30
+ const ignorePatterns = config.security?.ignore_paths
31
+ ? [...config.security.ignore_paths, ...defaultIgnore]
32
+ : defaultIgnore;
33
+ const filesToScan = await getFilesToScan(projectPath, config, diff, ignorePatterns);
34
+ if (filesToScan.length === 0) {
35
+ console.log(chalk.dim(" No files to scan"));
36
+ return [];
37
+ }
38
+ console.log(chalk.dim(` Scanning ${filesToScan.length} files...`));
39
+ const findings = [];
40
+ for (const rule of RULES) {
41
+ if (!enabledRules.includes(rule.name))
42
+ continue;
43
+ try {
44
+ const ruleFindings = await rule.run(filesToScan, config, projectPath);
45
+ findings.push(...ruleFindings);
46
+ }
47
+ catch (e) {
48
+ console.log(chalk.dim(` Rule ${rule.name} failed: ${e instanceof Error ? e.message : "unknown"}`));
49
+ }
50
+ }
51
+ return findings.filter((f) => severityRank(f.severity) >= severityRank(threshold));
52
+ }
53
+ async function getFilesToScan(projectPath, config, diff, ignorePatterns) {
54
+ const { readFile } = await import("node:fs/promises");
55
+ const { minimatch } = await import("minimatch");
56
+ let filePaths;
57
+ if (diff) {
58
+ filePaths = diff.changedFiles
59
+ .filter((f) => f.status !== "deleted")
60
+ .map((f) => f.path);
61
+ }
62
+ else {
63
+ filePaths = await glob("**/*.{ts,tsx,js,jsx,json,yaml,yml}", resolve(projectPath));
64
+ }
65
+ const filtered = filePaths.filter((f) => !ignorePatterns.some((pattern) => minimatch(f, pattern)));
66
+ const files = [];
67
+ for (const fp of filtered) {
68
+ try {
69
+ const content = await readFile(resolve(projectPath, fp), "utf-8");
70
+ files.push({ path: fp, content });
71
+ }
72
+ catch {
73
+ // skip unreadable files
74
+ }
75
+ }
76
+ return files;
77
+ }
78
+ function severityRank(s) {
79
+ const ranks = {
80
+ INFO: 0,
81
+ LOW: 1,
82
+ MEDIUM: 2,
83
+ HIGH: 3,
84
+ };
85
+ return ranks[s] ?? 0;
86
+ }
87
+ //# sourceMappingURL=static-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-analyzer.js","sourceRoot":"","sources":["../../../src/runners/security/static-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { QassConfig, DiffAnalysis, TestResult } from "../../types.js";
2
+ export declare function runUnitTests(config: QassConfig, projectPath: string, diff: DiffAnalysis): Promise<TestResult[]>;
3
+ //# sourceMappingURL=unit-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-runner.d.ts","sourceRoot":"","sources":["../../../src/runners/unit/unit-runner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI3E,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CAkGvB"}
@@ -0,0 +1,157 @@
1
+ import chalk from "chalk";
2
+ import { resolve, join, basename } from "node:path";
3
+ import { mkdir, writeFile, readFile } from "node:fs/promises";
4
+ import { execFile } from "node:child_process";
5
+ import { promisify } from "node:util";
6
+ const exec = promisify(execFile);
7
+ export async function runUnitTests(config, projectPath, diff) {
8
+ const results = [];
9
+ const testableFiles = diff.changedFiles.filter((f) => f.status !== "deleted" &&
10
+ /\.(ts|tsx|js|jsx)$/.test(f.path) &&
11
+ !f.path.includes(".test.") &&
12
+ !f.path.includes(".spec.") &&
13
+ !f.path.includes("node_modules"));
14
+ if (testableFiles.length === 0) {
15
+ console.log(chalk.dim(" No testable files changed"));
16
+ return results;
17
+ }
18
+ const testDir = resolve(projectPath, ".qass", "tests", "unit");
19
+ await mkdir(testDir, { recursive: true });
20
+ let generatedCount = 0;
21
+ for (const file of testableFiles) {
22
+ try {
23
+ const content = await readFile(resolve(projectPath, file.path), "utf-8");
24
+ const testCode = generateTestForFile(file.path, content);
25
+ if (testCode) {
26
+ const testFileName = basename(file.path).replace(/\.(ts|tsx|js|jsx)$/, ".test.ts");
27
+ await writeFile(join(testDir, testFileName), testCode, "utf-8");
28
+ generatedCount++;
29
+ }
30
+ }
31
+ catch {
32
+ // skip files we can't read/generate for
33
+ }
34
+ }
35
+ if (generatedCount === 0) {
36
+ console.log(chalk.dim(" No tests generated"));
37
+ return results;
38
+ }
39
+ console.log(chalk.dim(` Generated ${generatedCount} test file(s)`));
40
+ try {
41
+ const { stdout, stderr } = await exec("npx", ["vitest", "run", "--reporter=json", testDir], {
42
+ cwd: projectPath,
43
+ timeout: 60000,
44
+ env: { ...process.env, NODE_ENV: "test" },
45
+ });
46
+ const output = stdout || stderr;
47
+ try {
48
+ const vitestResult = JSON.parse(output);
49
+ if (vitestResult.testResults) {
50
+ for (const suite of vitestResult.testResults) {
51
+ for (const test of suite.assertionResults ?? []) {
52
+ results.push({
53
+ name: test.fullName ?? test.title ?? "unknown test",
54
+ type: "unit",
55
+ status: test.status === "passed" ? "passed" : "failed",
56
+ duration: test.duration,
57
+ error: test.failureMessages?.join("\n"),
58
+ file: suite.name,
59
+ });
60
+ }
61
+ }
62
+ }
63
+ }
64
+ catch {
65
+ results.push({
66
+ name: "Unit test suite",
67
+ type: "unit",
68
+ status: generatedCount > 0 ? "passed" : "skipped",
69
+ });
70
+ }
71
+ }
72
+ catch (e) {
73
+ const errMsg = e instanceof Error ? e.message : "unknown";
74
+ if (/vitest.*not found|Cannot find/i.test(errMsg)) {
75
+ console.log(chalk.yellow(" Vitest not installed. Run: npm i -D vitest"));
76
+ }
77
+ else {
78
+ results.push({
79
+ name: "Unit test suite",
80
+ type: "unit",
81
+ status: "failed",
82
+ error: errMsg,
83
+ fix: "Check the generated tests in .qass/tests/unit/ for issues.",
84
+ });
85
+ }
86
+ }
87
+ return results;
88
+ }
89
+ function generateTestForFile(filePath, content) {
90
+ const exports = extractExports(content);
91
+ if (exports.length === 0)
92
+ return null;
93
+ const isReactComponent = /\b(React|jsx|tsx)\b/.test(content) ||
94
+ /export\s+(?:default\s+)?function\s+\w+.*\(/.test(content) && /</.test(content);
95
+ const lines = [];
96
+ const modulePath = filePath.replace(/\.(ts|tsx|js|jsx)$/, "");
97
+ lines.push(`import { describe, it, expect } from "vitest";`);
98
+ if (isReactComponent) {
99
+ lines.push("");
100
+ lines.push(`describe("${basename(filePath)}", () => {`);
101
+ lines.push(` it("module is importable", async () => {`);
102
+ lines.push(` const mod = await import("${modulePath}").catch(e => e);`);
103
+ lines.push(` expect(mod).toBeDefined();`);
104
+ lines.push(` });`);
105
+ lines.push(`});`);
106
+ }
107
+ else {
108
+ lines.push("");
109
+ lines.push(`describe("${basename(filePath)}", () => {`);
110
+ for (const exp of exports) {
111
+ if (exp.type === "function") {
112
+ lines.push(` describe("${exp.name}", () => {`);
113
+ lines.push(` it("is a function", async () => {`);
114
+ lines.push(` const mod = await import("${modulePath}");`);
115
+ lines.push(` expect(typeof mod.${exp.name}).toBe("function");`);
116
+ lines.push(` });`);
117
+ if (exp.params.length === 0) {
118
+ lines.push(` it("runs without errors when called with no args", async () => {`);
119
+ lines.push(` const mod = await import("${modulePath}");`);
120
+ lines.push(` expect(() => mod.${exp.name}()).not.toThrow();`);
121
+ lines.push(` });`);
122
+ }
123
+ lines.push(` });`);
124
+ lines.push("");
125
+ }
126
+ else if (exp.type === "const") {
127
+ lines.push(` it("exports ${exp.name}", async () => {`);
128
+ lines.push(` const mod = await import("${modulePath}");`);
129
+ lines.push(` expect(mod.${exp.name}).toBeDefined();`);
130
+ lines.push(` });`);
131
+ lines.push("");
132
+ }
133
+ }
134
+ lines.push(`});`);
135
+ }
136
+ return lines.join("\n");
137
+ }
138
+ function extractExports(content) {
139
+ const exports = [];
140
+ const funcMatches = content.matchAll(/export\s+(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g);
141
+ for (const m of funcMatches) {
142
+ exports.push({
143
+ name: m[1],
144
+ type: "function",
145
+ params: m[2]
146
+ .split(",")
147
+ .map((p) => p.trim())
148
+ .filter(Boolean),
149
+ });
150
+ }
151
+ const constMatches = content.matchAll(/export\s+const\s+(\w+)\s*[=:]/g);
152
+ for (const m of constMatches) {
153
+ exports.push({ name: m[1], type: "const", params: [] });
154
+ }
155
+ return exports;
156
+ }
157
+ //# sourceMappingURL=unit-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-runner.js","sourceRoot":"","sources":["../../../src/runners/unit/unit-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ export interface QassConfig {
2
+ project: {
3
+ name: string;
4
+ root: string;
5
+ type?: "monorepo" | "standalone";
6
+ };
7
+ services?: Record<string, {
8
+ start: string;
9
+ port: number;
10
+ health?: string;
11
+ url?: string;
12
+ }>;
13
+ auth?: {
14
+ provider: "supabase";
15
+ supabase_url: string;
16
+ supabase_anon_key: string;
17
+ };
18
+ test_accounts?: TestAccount[];
19
+ paths?: Record<string, string>;
20
+ route_mounting?: Record<string, string>;
21
+ feature_matrix?: Record<string, string[]>;
22
+ plan_error_codes?: string[];
23
+ security?: SecurityConfig;
24
+ e2e?: E2EConfig;
25
+ flows?: Record<string, FlowDefinition>;
26
+ }
27
+ export interface TestAccount {
28
+ email: string;
29
+ password: string;
30
+ role: string;
31
+ }
32
+ export interface SecurityConfig {
33
+ enabled?: boolean;
34
+ severity_threshold?: Severity;
35
+ static_rules?: string[];
36
+ dynamic_checks?: boolean;
37
+ ignore_paths?: string[];
38
+ secrets_allowlist?: string[];
39
+ required_headers?: string[];
40
+ }
41
+ export interface E2EConfig {
42
+ viewports?: Viewport[];
43
+ smoke_crawl?: boolean;
44
+ visual_regression?: boolean;
45
+ visual_threshold?: number;
46
+ mask_selectors?: string[];
47
+ stuck_timeout?: number;
48
+ slow_response?: number;
49
+ }
50
+ export interface Viewport {
51
+ width: number;
52
+ height: number;
53
+ name: string;
54
+ }
55
+ export interface FlowDefinition {
56
+ as: string;
57
+ steps: FlowStep[];
58
+ }
59
+ export type FlowStep = {
60
+ goto: string;
61
+ } | {
62
+ fill: string;
63
+ } | {
64
+ click: string;
65
+ } | {
66
+ wait: string;
67
+ } | {
68
+ wait_url: string;
69
+ } | {
70
+ assert_visible: string;
71
+ } | {
72
+ assert_hidden: string;
73
+ } | {
74
+ assert_url: string;
75
+ };
76
+ export type Severity = "HIGH" | "MEDIUM" | "LOW" | "INFO";
77
+ export interface FileChange {
78
+ path: string;
79
+ status: "added" | "modified" | "deleted" | "renamed";
80
+ category: FileCategory;
81
+ diff?: string;
82
+ }
83
+ export type FileCategory = "api_route" | "middleware" | "frontend_page" | "component" | "shared_lib" | "migration" | "config" | "other";
84
+ export interface DiffAnalysis {
85
+ changedFiles: FileChange[];
86
+ affectedFeatures: string[];
87
+ affectedRoles: string[];
88
+ changeCategories: FileCategory[];
89
+ }
90
+ export interface Endpoint {
91
+ method: string;
92
+ path: string;
93
+ fullPath: string;
94
+ requiresAuth: boolean;
95
+ requiredRole?: string;
96
+ planGate?: string;
97
+ middlewareChain: string[];
98
+ routeFile: string;
99
+ }
100
+ export interface TestResult {
101
+ name: string;
102
+ type: "api" | "e2e" | "unit" | "security";
103
+ status: "passed" | "failed" | "skipped";
104
+ duration?: number;
105
+ error?: string;
106
+ file?: string;
107
+ line?: number;
108
+ screenshot?: string;
109
+ fix?: string;
110
+ }
111
+ export interface SecurityFinding {
112
+ rule: string;
113
+ severity: Severity;
114
+ file: string;
115
+ line?: number;
116
+ description: string;
117
+ fix: string;
118
+ }
119
+ export interface QassReport {
120
+ timestamp: string;
121
+ scope: {
122
+ filesChanged: number;
123
+ featuresAffected: string[];
124
+ };
125
+ summary: {
126
+ total: number;
127
+ passed: number;
128
+ failed: number;
129
+ skipped: number;
130
+ securityFindings: number;
131
+ };
132
+ results: TestResult[];
133
+ securityFindings: SecurityFinding[];
134
+ }
135
+ export interface TestPlan {
136
+ apiTests: {
137
+ endpoints: Endpoint[];
138
+ accounts: TestAccount[];
139
+ };
140
+ e2eTests: {
141
+ pages: string[];
142
+ accounts: TestAccount[];
143
+ flows: string[];
144
+ };
145
+ unitTests: {
146
+ files: string[];
147
+ };
148
+ securityScan: {
149
+ files: string[];
150
+ dynamicChecks: boolean;
151
+ };
152
+ }
153
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function glob(pattern: string, rootDir: string): Promise<string[]>;
2
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"AAIA,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAInB"}
@@ -0,0 +1,32 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { join, relative } from "node:path";
3
+ import { minimatch } from "minimatch";
4
+ export async function glob(pattern, rootDir) {
5
+ const matches = [];
6
+ await walkDir(rootDir, rootDir, pattern, matches);
7
+ return matches.sort();
8
+ }
9
+ async function walkDir(dir, rootDir, pattern, matches) {
10
+ try {
11
+ const entries = await readdir(dir, { withFileTypes: true });
12
+ for (const entry of entries) {
13
+ const fullPath = join(dir, entry.name);
14
+ if (entry.isDirectory()) {
15
+ if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist") {
16
+ continue;
17
+ }
18
+ await walkDir(fullPath, rootDir, pattern, matches);
19
+ }
20
+ else if (entry.isFile()) {
21
+ const relPath = relative(rootDir, fullPath).replace(/\\/g, "/");
22
+ if (minimatch(relPath, pattern)) {
23
+ matches.push(relPath);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ // skip inaccessible directories
30
+ }
31
+ }
32
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/util/glob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAe,EACf,OAAe;IAEf,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,GAAW,EACX,OAAe,EACf,OAAe,EACf,OAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpF,SAAS;gBACX,CAAC;gBACD,MAAM,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACrD,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAChE,IAAI,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;oBAChC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@qasshq/qass",
3
+ "version": "0.1.2",
4
+ "description": "QA + Security Scanner for vibe-coded applications. Your AI writes code. QASS catches what it got wrong.",
5
+ "type": "module",
6
+ "bin": {
7
+ "qass": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "dev": "tsx src/cli.ts",
16
+ "build": "tsc",
17
+ "start": "node dist/cli.js",
18
+ "test": "vitest run"
19
+ },
20
+ "keywords": [
21
+ "qa",
22
+ "security",
23
+ "scanner",
24
+ "testing",
25
+ "vibe-coding",
26
+ "ai",
27
+ "cursor",
28
+ "windsurf",
29
+ "copilot",
30
+ "playwright"
31
+ ],
32
+ "license": "SEE LICENSE IN LICENSE",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/Dujaun-Paul/QASS.git"
36
+ },
37
+ "homepage": "https://github.com/Dujaun-Paul/QASS",
38
+ "bugs": {
39
+ "url": "https://github.com/Dujaun-Paul/QASS/issues"
40
+ },
41
+ "engines": {
42
+ "node": ">=20.11.0"
43
+ },
44
+ "dependencies": {
45
+ "chalk": "^5.4.1",
46
+ "commander": "^13.1.0",
47
+ "minimatch": "^10.0.1",
48
+ "yaml": "^2.7.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.13.4",
52
+ "tsx": "^4.19.3",
53
+ "typescript": "^5.7.3",
54
+ "vitest": "^4.0.18"
55
+ },
56
+ "peerDependencies": {
57
+ "playwright": ">=1.40.0",
58
+ "vitest": ">=1.0.0"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "playwright": {
62
+ "optional": true
63
+ },
64
+ "vitest": {
65
+ "optional": true
66
+ }
67
+ }
68
+ }