@utilix-tech/sdk 0.83.0 → 0.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
4
4
 
5
+ ## 0.84.0
6
+ - Add `findCronOverlaps` (cron-overlap-detector): walk minute-by-minute over a window of days and flag every minute where two or more cron schedules fire at once, listing which expressions collided.
7
+ - Add `lintDockerfile` (dockerfile-linter): lint a Dockerfile for an unpinned or `:latest` base image, a final stage missing WORKDIR or USER, and ADD used on a plain local file where COPY would do.
8
+
5
9
  ## 0.83.0
6
10
  - Add `extractMarkdownLinkReferences` (markdown-link-reference-extractor): extract reference-style Markdown links (`[text][ref]`, the `[text][]` shortcut, and `![alt][ref]` image references) and match them against their `[ref]: url` definitions, flagging unresolved references and unused definitions.
7
11
  - Add `extractPromptTemplateVariables` (prompt-template-variable-extractor): extract `{{variable}}`-style placeholders from a prompt template, report occurrence counts, flag duplicates, and optionally cross-check against a list of provided variable names.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @utilix-tech/sdk
2
2
 
3
- **718 developer utility functions for Node.js: runs locally, no API key required.**
3
+ **721 developer utility functions for Node.js: runs locally, no API key required.**
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@utilix-tech/sdk?style=flat-square&color=cb3837)](https://www.npmjs.com/package/@utilix-tech/sdk)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@utilix-tech/sdk?style=flat-square)](https://www.npmjs.com/package/@utilix-tech/sdk)
@@ -8,6 +8,7 @@ __export(time_exports, {
8
8
  TIMEZONES: () => TIMEZONES,
9
9
  convertTime: () => convertTime,
10
10
  diffDates: () => diffDates,
11
+ findCronOverlaps: () => findCronOverlaps,
11
12
  formatInTimezone: () => formatInTimezone,
12
13
  formatIso8601Duration: () => formatIso8601Duration,
13
14
  formatRelative: () => formatRelative,
@@ -683,6 +684,42 @@ function getRunInterval(dates) {
683
684
  const days = Math.round(diffMins / 1440);
684
685
  return `Every ${days} days`;
685
686
  }
687
+ var MAX_CRON_OVERLAPS = 200;
688
+ function findCronOverlaps(expressions, windowDays = 30, fromDate) {
689
+ if (expressions.length < 2) return { error: "Provide at least two cron expressions to check for overlaps" };
690
+ if (expressions.length > 10) return { error: "Provide 10 or fewer cron expressions" };
691
+ if (windowDays < 1 || windowDays > 365) return { error: "windowDays must be between 1 and 365" };
692
+ const parsedList = [];
693
+ for (let i = 0; i < expressions.length; i++) {
694
+ const parsed = parseCronExpression(expressions[i]);
695
+ if (typeof parsed === "object" && "error" in parsed) {
696
+ return { error: `Expression ${i + 1} ("${expressions[i]}"): ${parsed.error}` };
697
+ }
698
+ parsedList.push(parsed);
699
+ }
700
+ const start = fromDate ? new Date(fromDate) : /* @__PURE__ */ new Date();
701
+ const cursor = new Date(start);
702
+ cursor.setSeconds(0, 0);
703
+ cursor.setMinutes(cursor.getMinutes() + 1);
704
+ const endTime = cursor.getTime() + windowDays * 24 * 60 * 60 * 1e3;
705
+ const overlaps = [];
706
+ let truncated = false;
707
+ while (cursor.getTime() < endTime) {
708
+ const matched = [];
709
+ for (let i = 0; i < parsedList.length; i++) {
710
+ if (matchesCron(cursor, parsedList[i])) matched.push(i);
711
+ }
712
+ if (matched.length >= 2) {
713
+ if (overlaps.length >= MAX_CRON_OVERLAPS) {
714
+ truncated = true;
715
+ break;
716
+ }
717
+ overlaps.push({ date: new Date(cursor), expressionIndexes: matched });
718
+ }
719
+ cursor.setMinutes(cursor.getMinutes() + 1);
720
+ }
721
+ return { overlaps, windowDays, truncated };
722
+ }
686
723
  var DURATION_SECONDS_PER_YEAR = 365 * 86400;
687
724
  var DURATION_SECONDS_PER_MONTH = 30 * 86400;
688
725
  function humanizeDurationParts(parts) {
@@ -775,4 +812,4 @@ function formatIso8601Duration(seconds) {
775
812
  };
776
813
  }
777
814
 
778
- export { COMMON_CRONS, COMMON_DATE_PRESETS, TIMEZONES, convertTime, diffDates, formatInTimezone, formatIso8601Duration, formatRelative, formatRunDate, fromIsoString, fromUnix, getAllZonesForTime, getNextRuns, getNow, getRunInterval, getTimezoneOffset, humanizeDiff, parseCron, parseCronExpression, parseDate, parseIso8601Duration, time_exports };
815
+ export { COMMON_CRONS, COMMON_DATE_PRESETS, TIMEZONES, convertTime, diffDates, findCronOverlaps, formatInTimezone, formatIso8601Duration, formatRelative, formatRunDate, fromIsoString, fromUnix, getAllZonesForTime, getNextRuns, getNow, getRunInterval, getTimezoneOffset, humanizeDiff, parseCron, parseCronExpression, parseDate, parseIso8601Duration, time_exports };
@@ -39,6 +39,7 @@ __export(code_exports, {
39
39
  getMethodColor: () => getMethodColor,
40
40
  isValidTag: () => isValidTag,
41
41
  lintConventionalCommit: () => lintConventionalCommit,
42
+ lintDockerfile: () => lintDockerfile,
42
43
  lookupMime: () => lookupMime,
43
44
  minifyCss: () => minifyCss,
44
45
  minifyGql: () => minifyGql,
@@ -1869,6 +1870,111 @@ function normalizeRef(ref) {
1869
1870
  const tagPart = parsed.digest ? `@${parsed.digest}` : parsed.tag ? `:${parsed.tag}` : "";
1870
1871
  return `${parsed.registry}/${ns}${parsed.repository}${tagPart}`;
1871
1872
  }
1873
+ function _parseDockerfileInstructions(content) {
1874
+ const rawLines = content.replace(/\r\n/g, "\n").split("\n");
1875
+ const instructions = [];
1876
+ let buffer = "";
1877
+ let bufferStartLine = 0;
1878
+ for (let i = 0; i < rawLines.length; i++) {
1879
+ const lineNo = i + 1;
1880
+ const line = rawLines[i];
1881
+ const trimmed = line.trim();
1882
+ if (buffer === "") {
1883
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
1884
+ bufferStartLine = lineNo;
1885
+ buffer = line.trimEnd();
1886
+ } else {
1887
+ buffer += "\n" + line.trimEnd();
1888
+ }
1889
+ if (buffer.endsWith("\\")) {
1890
+ buffer = buffer.slice(0, -1);
1891
+ continue;
1892
+ }
1893
+ const match = buffer.trim().match(/^([A-Za-z]+)\s*([\s\S]*)$/);
1894
+ if (match) {
1895
+ instructions.push({ instruction: match[1].toUpperCase(), args: match[2].trim(), line: bufferStartLine });
1896
+ }
1897
+ buffer = "";
1898
+ }
1899
+ return instructions;
1900
+ }
1901
+ var _DOCKERFILE_TAR_RE = /\.(tar(\.(gz|bz2|xz))?|tgz|tbz2|txz)$/i;
1902
+ function lintDockerfile(content) {
1903
+ if (!content || !content.trim()) return { error: "Dockerfile content is required" };
1904
+ const instructions = _parseDockerfileInstructions(content);
1905
+ if (instructions.length === 0) return { error: "No Dockerfile instructions found" };
1906
+ const fromInstructions = instructions.filter((i) => i.instruction === "FROM");
1907
+ if (fromInstructions.length === 0) return { error: "No FROM instruction found; this does not look like a valid Dockerfile" };
1908
+ const stageNames = /* @__PURE__ */ new Set();
1909
+ const stages = fromInstructions.map((inst, idx) => {
1910
+ const asMatch = inst.args.match(/^(\S+)(?:\s+AS\s+(\S+))?/i);
1911
+ const baseImage = asMatch ? asMatch[1] : inst.args.split(/\s+/)[0];
1912
+ const name = asMatch && asMatch[2] ? asMatch[2] : null;
1913
+ if (name) stageNames.add(name.toLowerCase());
1914
+ return { index: idx, name, baseImage, fromLine: inst.line };
1915
+ });
1916
+ const findings = [];
1917
+ for (const stage of stages) {
1918
+ const base = stage.baseImage;
1919
+ if (base.toLowerCase() === "scratch") continue;
1920
+ if (stageNames.has(base.toLowerCase())) continue;
1921
+ const withoutDigest = base.split("@")[0];
1922
+ const hasTag = withoutDigest.includes(":");
1923
+ const tag = hasTag ? withoutDigest.split(":").pop() : null;
1924
+ if (!hasTag) {
1925
+ findings.push({
1926
+ rule: "unpinned-base-image",
1927
+ severity: "warning",
1928
+ line: stage.fromLine,
1929
+ message: `FROM ${base} has no tag, so it resolves to ":latest", which can silently change what gets built on a future run. Pin an explicit version tag instead.`
1930
+ });
1931
+ } else if (tag === "latest") {
1932
+ findings.push({
1933
+ rule: "unpinned-base-image",
1934
+ severity: "warning",
1935
+ line: stage.fromLine,
1936
+ message: `FROM ${base} is explicitly pinned to the "latest" tag, which is a moving target rather than a fixed version. Pin an explicit version tag instead.`
1937
+ });
1938
+ }
1939
+ }
1940
+ const finalStage = stages[stages.length - 1];
1941
+ const finalStageInstructions = instructions.filter((i) => i.line >= finalStage.fromLine);
1942
+ if (!finalStageInstructions.some((i) => i.instruction === "WORKDIR")) {
1943
+ findings.push({
1944
+ rule: "missing-workdir",
1945
+ severity: "warning",
1946
+ line: finalStage.fromLine,
1947
+ message: 'No WORKDIR instruction in the final stage, so RUN/CMD/ENTRYPOINT execute from "/" by default. Set an explicit WORKDIR.'
1948
+ });
1949
+ }
1950
+ if (!finalStageInstructions.some((i) => i.instruction === "USER")) {
1951
+ findings.push({
1952
+ rule: "running-as-root",
1953
+ severity: "warning",
1954
+ line: finalStage.fromLine,
1955
+ message: "No USER instruction in the final stage, so the container runs as root by default. Add a non-root USER unless root is genuinely required."
1956
+ });
1957
+ }
1958
+ for (const inst of instructions) {
1959
+ if (inst.instruction !== "ADD") continue;
1960
+ const parts = inst.args.split(/\s+/).filter(Boolean).filter((p) => !p.startsWith("--"));
1961
+ if (parts.length < 2) continue;
1962
+ const sources = parts.slice(0, -1);
1963
+ for (const src of sources) {
1964
+ const isUrl = /^https?:\/\//i.test(src);
1965
+ const isTar = _DOCKERFILE_TAR_RE.test(src);
1966
+ if (!isUrl && !isTar) {
1967
+ findings.push({
1968
+ rule: "add-vs-copy",
1969
+ severity: "info",
1970
+ line: inst.line,
1971
+ message: `ADD ${src} copies a local file/directory, not a URL or an auto-extracting archive. Use COPY instead, since ADD's extra behavior (remote fetch, tar auto-extract) doesn't apply here.`
1972
+ });
1973
+ }
1974
+ }
1975
+ }
1976
+ return { findings, stages };
1977
+ }
1872
1978
  function removeJsComments(code) {
1873
1979
  let result = "";
1874
1980
  let i = 0;
@@ -4328,4 +4434,4 @@ function extractMarkdownLinkReferences(markdown) {
4328
4434
  };
4329
4435
  }
4330
4436
 
4331
- export { ALL_FLAGS, CHEATSHEET, DEFAULT_COMMIT_TYPES, KNOWN_LANGUAGE_TAGS, MIME_TABLE, OPERATIONS, SQL_DEFAULT_OPTIONS, analyzeRegexGroups, auditDependencyRanges, buildDockerPull, buildDockerRun, buildGitCommand, code_exports, collapseHtmlWhitespace, collapseJsWhitespace, countProperties, countRules, countSqlPlaceholders, detectDialect, detectOperationType, detectRedos, envToExport, envToJson, extractMarkdownFootnotes, extractMarkdownLinkReferences, extractSvgSpriteSymbols, formatCss, formatGql, formatHtml, formatSql, getEndpointsByTag, getHtmlStats, getJsStats, getMethodColor, isValidTag, lintConventionalCommit, lookupMime, minifyCss, minifyGql, minifyHtml, minifyJs, minifySql, normalizeRef, parseCommitTrailers, parseConnectionString, parseDockerImage, parseEnv, parseGitCommand, parseGithubUrl, parseSpec, removeConsoleCalls, removeEmptyAttributes, removeHtmlComments, removeJsComments, removeRedundantAttributes, searchCheatsheet, searchEndpoints, splitStatements, testGitignorePatterns, testPattern, testRegex, validateAria, validateEditorConfig, validateEnvKey, validateFenceLanguageTags, validatePackageExports, validateTsconfig };
4437
+ export { ALL_FLAGS, CHEATSHEET, DEFAULT_COMMIT_TYPES, KNOWN_LANGUAGE_TAGS, MIME_TABLE, OPERATIONS, SQL_DEFAULT_OPTIONS, analyzeRegexGroups, auditDependencyRanges, buildDockerPull, buildDockerRun, buildGitCommand, code_exports, collapseHtmlWhitespace, collapseJsWhitespace, countProperties, countRules, countSqlPlaceholders, detectDialect, detectOperationType, detectRedos, envToExport, envToJson, extractMarkdownFootnotes, extractMarkdownLinkReferences, extractSvgSpriteSymbols, formatCss, formatGql, formatHtml, formatSql, getEndpointsByTag, getHtmlStats, getJsStats, getMethodColor, isValidTag, lintConventionalCommit, lintDockerfile, lookupMime, minifyCss, minifyGql, minifyHtml, minifyJs, minifySql, normalizeRef, parseCommitTrailers, parseConnectionString, parseDockerImage, parseEnv, parseGitCommand, parseGithubUrl, parseSpec, removeConsoleCalls, removeEmptyAttributes, removeHtmlComments, removeJsComments, removeRedundantAttributes, searchCheatsheet, searchEndpoints, splitStatements, testGitignorePatterns, testPattern, testRegex, validateAria, validateEditorConfig, validateEnvKey, validateFenceLanguageTags, validatePackageExports, validateTsconfig };
@@ -12,6 +12,7 @@
12
12
  * - git-builder (buildGitCommand, parseGitCommand, OPERATIONS)
13
13
  * - docker-image-parser (parseDockerImage, buildDockerPull, buildDockerRun,
14
14
  * isValidTag, normalizeRef)
15
+ * - dockerfile-linter (lintDockerfile)
15
16
  * - js-minifier (minifyJs, removeJsComments, collapseJsWhitespace,
16
17
  * removeConsoleCalls, getJsStats)
17
18
  * - openapi-viewer (parseSpec, getEndpointsByTag, searchEndpoints, getMethodColor)
@@ -175,6 +176,32 @@ declare function buildDockerPull(parsed: DockerImageRef): string;
175
176
  declare function buildDockerRun(parsed: DockerImageRef, containerName?: string): string;
176
177
  declare function isValidTag(tag: string): boolean;
177
178
  declare function normalizeRef(ref: string): string;
179
+ interface DockerfileLintFinding {
180
+ rule: 'unpinned-base-image' | 'missing-workdir' | 'running-as-root' | 'add-vs-copy';
181
+ severity: 'warning' | 'info';
182
+ line: number;
183
+ message: string;
184
+ }
185
+ interface DockerfileStage {
186
+ index: number;
187
+ name: string | null;
188
+ baseImage: string;
189
+ fromLine: number;
190
+ }
191
+ interface DockerfileLintResult {
192
+ findings: DockerfileLintFinding[];
193
+ stages: DockerfileStage[];
194
+ }
195
+ /**
196
+ * Lint a Dockerfile for 4 common mistakes: a base image with no tag or
197
+ * pinned to `:latest`, a final stage with no WORKDIR, a final stage with no
198
+ * USER (so it runs as root), and ADD used on a plain local file/directory
199
+ * where COPY would do (ADD's extra behavior only makes sense for a remote
200
+ * URL or an auto-extracting archive).
201
+ */
202
+ declare function lintDockerfile(content: string): DockerfileLintResult | {
203
+ error: string;
204
+ };
178
205
  interface JsMinifyOptions {
179
206
  removeComments?: boolean;
180
207
  collapseWhitespace?: boolean;
@@ -780,6 +807,9 @@ type code_DependencyAuditResult = DependencyAuditResult;
780
807
  type code_DependencyRangeType = DependencyRangeType;
781
808
  type code_DependencySection = DependencySection;
782
809
  type code_DockerImageRef = DockerImageRef;
810
+ type code_DockerfileLintFinding = DockerfileLintFinding;
811
+ type code_DockerfileLintResult = DockerfileLintResult;
812
+ type code_DockerfileStage = DockerfileStage;
783
813
  type code_EditorConfigIssue = EditorConfigIssue;
784
814
  type code_EditorConfigProperty = EditorConfigProperty;
785
815
  type code_EditorConfigSection = EditorConfigSection;
@@ -871,6 +901,7 @@ declare const code_getJsStats: typeof getJsStats;
871
901
  declare const code_getMethodColor: typeof getMethodColor;
872
902
  declare const code_isValidTag: typeof isValidTag;
873
903
  declare const code_lintConventionalCommit: typeof lintConventionalCommit;
904
+ declare const code_lintDockerfile: typeof lintDockerfile;
874
905
  declare const code_lookupMime: typeof lookupMime;
875
906
  declare const code_minifyCss: typeof minifyCss;
876
907
  declare const code_minifyGql: typeof minifyGql;
@@ -903,7 +934,7 @@ declare const code_validateFenceLanguageTags: typeof validateFenceLanguageTags;
903
934
  declare const code_validatePackageExports: typeof validatePackageExports;
904
935
  declare const code_validateTsconfig: typeof validateTsconfig;
905
936
  declare namespace code {
906
- export { code_ALL_FLAGS as ALL_FLAGS, type code_ApiEndpoint as ApiEndpoint, type code_ApiInfo as ApiInfo, type code_AriaIssue as AriaIssue, type code_AriaValidationResult as AriaValidationResult, code_CHEATSHEET as CHEATSHEET, type code_CheatsheetEntry as CheatsheetEntry, type code_CommitTrailer as CommitTrailer, type code_CommitTrailerResult as CommitTrailerResult, type code_ConnectionStringHost as ConnectionStringHost, type code_ConnectionStringResult as ConnectionStringResult, type code_ConventionalCommitFinding as ConventionalCommitFinding, type code_ConventionalCommitFooter as ConventionalCommitFooter, type code_ConventionalCommitOptions as ConventionalCommitOptions, type code_ConventionalCommitParsed as ConventionalCommitParsed, type code_ConventionalCommitResult as ConventionalCommitResult, type code_ConventionalCommitSeverity as ConventionalCommitSeverity, type code_CssResult as CssResult, code_DEFAULT_COMMIT_TYPES as DEFAULT_COMMIT_TYPES, type code_DependencyAuditDuplicate as DependencyAuditDuplicate, type code_DependencyAuditEntry as DependencyAuditEntry, type code_DependencyAuditIssue as DependencyAuditIssue, type code_DependencyAuditResult as DependencyAuditResult, type code_DependencyRangeType as DependencyRangeType, type code_DependencySection as DependencySection, type code_DockerImageRef as DockerImageRef, type code_EditorConfigIssue as EditorConfigIssue, type code_EditorConfigProperty as EditorConfigProperty, type code_EditorConfigSection as EditorConfigSection, type code_EditorConfigValidationResult as EditorConfigValidationResult, type code_EnvEntry as EnvEntry, type code_EnvParseResult as EnvParseResult, type code_ExportsIssue as ExportsIssue, type code_ExportsShape as ExportsShape, type code_ExportsValidationResult as ExportsValidationResult, type code_FenceTagIssue as FenceTagIssue, type code_FenceTagIssueType as FenceTagIssueType, type code_FenceValidationResult as FenceValidationResult, type code_GitCommandConfig as GitCommandConfig, type code_GitCommandResult as GitCommandResult, type code_GitOperation as GitOperation, type code_GithubUrlInfo as GithubUrlInfo, type code_GithubUrlType as GithubUrlType, type code_GitignoreTestResult as GitignoreTestResult, type code_GqlFormatResult as GqlFormatResult, type code_HtmlFormatResult as HtmlFormatResult, type code_HtmlMinifyOptions as HtmlMinifyOptions, type code_HtmlMinifyResult as HtmlMinifyResult, type code_JsMinifyOptions as JsMinifyOptions, type code_JsMinifyResult as JsMinifyResult, code_KNOWN_LANGUAGE_TAGS as KNOWN_LANGUAGE_TAGS, type code_LinkReferenceDefinition as LinkReferenceDefinition, type code_LinkReferenceUsage as LinkReferenceUsage, code_MIME_TABLE as MIME_TABLE, type code_MarkdownFootnoteDefinition as MarkdownFootnoteDefinition, type code_MarkdownFootnoteReference as MarkdownFootnoteReference, type code_MarkdownFootnoteResult as MarkdownFootnoteResult, type code_MarkdownLinkReferenceResult as MarkdownLinkReferenceResult, type code_MatchResult as MatchResult, type code_MimeEntry as MimeEntry, type code_MimeLookupResult as MimeLookupResult, code_OPERATIONS as OPERATIONS, type code_ParsedSpec as ParsedSpec, type code_PlaceholderStyle as PlaceholderStyle, type code_RedosFinding as RedosFinding, type code_RedosResult as RedosResult, type code_RedosSeverity as RedosSeverity, type code_RegexBackreferenceInfo as RegexBackreferenceInfo, type code_RegexError as RegexError, type code_RegexFlag as RegexFlag, type code_RegexGroupAnalysis as RegexGroupAnalysis, type code_RegexGroupInfo as RegexGroupInfo, type code_RegexGroupIssue as RegexGroupIssue, type code_RegexMatch as RegexMatch, type code_RegexResult as RegexResult, type code_RegexSuccess as RegexSuccess, type code_ResolvedLinkReference as ResolvedLinkReference, code_SQL_DEFAULT_OPTIONS as SQL_DEFAULT_OPTIONS, type code_Segment as Segment, type code_SpecVersion as SpecVersion, type code_SqlDialect as SqlDialect, type code_SqlFormatOptions as SqlFormatOptions, type code_SqlPlaceholder as SqlPlaceholder, type code_SqlPlaceholderResult as SqlPlaceholderResult, type code_SvgSpriteResult as SvgSpriteResult, type code_SvgSpriteSymbol as SvgSpriteSymbol, type code_TestPatternResult as TestPatternResult, type code_TsconfigIssue as TsconfigIssue, type code_TsconfigValidationResult as TsconfigValidationResult, code_analyzeRegexGroups as analyzeRegexGroups, code_auditDependencyRanges as auditDependencyRanges, code_buildDockerPull as buildDockerPull, code_buildDockerRun as buildDockerRun, code_buildGitCommand as buildGitCommand, code_collapseHtmlWhitespace as collapseHtmlWhitespace, code_collapseJsWhitespace as collapseJsWhitespace, code_countProperties as countProperties, code_countRules as countRules, code_countSqlPlaceholders as countSqlPlaceholders, code_detectDialect as detectDialect, code_detectOperationType as detectOperationType, code_detectRedos as detectRedos, code_envToExport as envToExport, code_envToJson as envToJson, code_extractMarkdownFootnotes as extractMarkdownFootnotes, code_extractMarkdownLinkReferences as extractMarkdownLinkReferences, code_extractSvgSpriteSymbols as extractSvgSpriteSymbols, code_formatCss as formatCss, code_formatGql as formatGql, code_formatHtml as formatHtml, code_formatSql as formatSql, code_getEndpointsByTag as getEndpointsByTag, code_getHtmlStats as getHtmlStats, code_getJsStats as getJsStats, code_getMethodColor as getMethodColor, code_isValidTag as isValidTag, code_lintConventionalCommit as lintConventionalCommit, code_lookupMime as lookupMime, code_minifyCss as minifyCss, code_minifyGql as minifyGql, code_minifyHtml as minifyHtml, code_minifyJs as minifyJs, code_minifySql as minifySql, code_normalizeRef as normalizeRef, code_parseCommitTrailers as parseCommitTrailers, code_parseConnectionString as parseConnectionString, code_parseDockerImage as parseDockerImage, code_parseEnv as parseEnv, code_parseGitCommand as parseGitCommand, code_parseGithubUrl as parseGithubUrl, code_parseSpec as parseSpec, code_removeConsoleCalls as removeConsoleCalls, code_removeEmptyAttributes as removeEmptyAttributes, code_removeHtmlComments as removeHtmlComments, code_removeJsComments as removeJsComments, code_removeRedundantAttributes as removeRedundantAttributes, code_searchCheatsheet as searchCheatsheet, code_searchEndpoints as searchEndpoints, code_splitStatements as splitStatements, code_testGitignorePatterns as testGitignorePatterns, code_testPattern as testPattern, code_testRegex as testRegex, code_validateAria as validateAria, code_validateEditorConfig as validateEditorConfig, code_validateEnvKey as validateEnvKey, code_validateFenceLanguageTags as validateFenceLanguageTags, code_validatePackageExports as validatePackageExports, code_validateTsconfig as validateTsconfig };
937
+ export { code_ALL_FLAGS as ALL_FLAGS, type code_ApiEndpoint as ApiEndpoint, type code_ApiInfo as ApiInfo, type code_AriaIssue as AriaIssue, type code_AriaValidationResult as AriaValidationResult, code_CHEATSHEET as CHEATSHEET, type code_CheatsheetEntry as CheatsheetEntry, type code_CommitTrailer as CommitTrailer, type code_CommitTrailerResult as CommitTrailerResult, type code_ConnectionStringHost as ConnectionStringHost, type code_ConnectionStringResult as ConnectionStringResult, type code_ConventionalCommitFinding as ConventionalCommitFinding, type code_ConventionalCommitFooter as ConventionalCommitFooter, type code_ConventionalCommitOptions as ConventionalCommitOptions, type code_ConventionalCommitParsed as ConventionalCommitParsed, type code_ConventionalCommitResult as ConventionalCommitResult, type code_ConventionalCommitSeverity as ConventionalCommitSeverity, type code_CssResult as CssResult, code_DEFAULT_COMMIT_TYPES as DEFAULT_COMMIT_TYPES, type code_DependencyAuditDuplicate as DependencyAuditDuplicate, type code_DependencyAuditEntry as DependencyAuditEntry, type code_DependencyAuditIssue as DependencyAuditIssue, type code_DependencyAuditResult as DependencyAuditResult, type code_DependencyRangeType as DependencyRangeType, type code_DependencySection as DependencySection, type code_DockerImageRef as DockerImageRef, type code_DockerfileLintFinding as DockerfileLintFinding, type code_DockerfileLintResult as DockerfileLintResult, type code_DockerfileStage as DockerfileStage, type code_EditorConfigIssue as EditorConfigIssue, type code_EditorConfigProperty as EditorConfigProperty, type code_EditorConfigSection as EditorConfigSection, type code_EditorConfigValidationResult as EditorConfigValidationResult, type code_EnvEntry as EnvEntry, type code_EnvParseResult as EnvParseResult, type code_ExportsIssue as ExportsIssue, type code_ExportsShape as ExportsShape, type code_ExportsValidationResult as ExportsValidationResult, type code_FenceTagIssue as FenceTagIssue, type code_FenceTagIssueType as FenceTagIssueType, type code_FenceValidationResult as FenceValidationResult, type code_GitCommandConfig as GitCommandConfig, type code_GitCommandResult as GitCommandResult, type code_GitOperation as GitOperation, type code_GithubUrlInfo as GithubUrlInfo, type code_GithubUrlType as GithubUrlType, type code_GitignoreTestResult as GitignoreTestResult, type code_GqlFormatResult as GqlFormatResult, type code_HtmlFormatResult as HtmlFormatResult, type code_HtmlMinifyOptions as HtmlMinifyOptions, type code_HtmlMinifyResult as HtmlMinifyResult, type code_JsMinifyOptions as JsMinifyOptions, type code_JsMinifyResult as JsMinifyResult, code_KNOWN_LANGUAGE_TAGS as KNOWN_LANGUAGE_TAGS, type code_LinkReferenceDefinition as LinkReferenceDefinition, type code_LinkReferenceUsage as LinkReferenceUsage, code_MIME_TABLE as MIME_TABLE, type code_MarkdownFootnoteDefinition as MarkdownFootnoteDefinition, type code_MarkdownFootnoteReference as MarkdownFootnoteReference, type code_MarkdownFootnoteResult as MarkdownFootnoteResult, type code_MarkdownLinkReferenceResult as MarkdownLinkReferenceResult, type code_MatchResult as MatchResult, type code_MimeEntry as MimeEntry, type code_MimeLookupResult as MimeLookupResult, code_OPERATIONS as OPERATIONS, type code_ParsedSpec as ParsedSpec, type code_PlaceholderStyle as PlaceholderStyle, type code_RedosFinding as RedosFinding, type code_RedosResult as RedosResult, type code_RedosSeverity as RedosSeverity, type code_RegexBackreferenceInfo as RegexBackreferenceInfo, type code_RegexError as RegexError, type code_RegexFlag as RegexFlag, type code_RegexGroupAnalysis as RegexGroupAnalysis, type code_RegexGroupInfo as RegexGroupInfo, type code_RegexGroupIssue as RegexGroupIssue, type code_RegexMatch as RegexMatch, type code_RegexResult as RegexResult, type code_RegexSuccess as RegexSuccess, type code_ResolvedLinkReference as ResolvedLinkReference, code_SQL_DEFAULT_OPTIONS as SQL_DEFAULT_OPTIONS, type code_Segment as Segment, type code_SpecVersion as SpecVersion, type code_SqlDialect as SqlDialect, type code_SqlFormatOptions as SqlFormatOptions, type code_SqlPlaceholder as SqlPlaceholder, type code_SqlPlaceholderResult as SqlPlaceholderResult, type code_SvgSpriteResult as SvgSpriteResult, type code_SvgSpriteSymbol as SvgSpriteSymbol, type code_TestPatternResult as TestPatternResult, type code_TsconfigIssue as TsconfigIssue, type code_TsconfigValidationResult as TsconfigValidationResult, code_analyzeRegexGroups as analyzeRegexGroups, code_auditDependencyRanges as auditDependencyRanges, code_buildDockerPull as buildDockerPull, code_buildDockerRun as buildDockerRun, code_buildGitCommand as buildGitCommand, code_collapseHtmlWhitespace as collapseHtmlWhitespace, code_collapseJsWhitespace as collapseJsWhitespace, code_countProperties as countProperties, code_countRules as countRules, code_countSqlPlaceholders as countSqlPlaceholders, code_detectDialect as detectDialect, code_detectOperationType as detectOperationType, code_detectRedos as detectRedos, code_envToExport as envToExport, code_envToJson as envToJson, code_extractMarkdownFootnotes as extractMarkdownFootnotes, code_extractMarkdownLinkReferences as extractMarkdownLinkReferences, code_extractSvgSpriteSymbols as extractSvgSpriteSymbols, code_formatCss as formatCss, code_formatGql as formatGql, code_formatHtml as formatHtml, code_formatSql as formatSql, code_getEndpointsByTag as getEndpointsByTag, code_getHtmlStats as getHtmlStats, code_getJsStats as getJsStats, code_getMethodColor as getMethodColor, code_isValidTag as isValidTag, code_lintConventionalCommit as lintConventionalCommit, code_lintDockerfile as lintDockerfile, code_lookupMime as lookupMime, code_minifyCss as minifyCss, code_minifyGql as minifyGql, code_minifyHtml as minifyHtml, code_minifyJs as minifyJs, code_minifySql as minifySql, code_normalizeRef as normalizeRef, code_parseCommitTrailers as parseCommitTrailers, code_parseConnectionString as parseConnectionString, code_parseDockerImage as parseDockerImage, code_parseEnv as parseEnv, code_parseGitCommand as parseGitCommand, code_parseGithubUrl as parseGithubUrl, code_parseSpec as parseSpec, code_removeConsoleCalls as removeConsoleCalls, code_removeEmptyAttributes as removeEmptyAttributes, code_removeHtmlComments as removeHtmlComments, code_removeJsComments as removeJsComments, code_removeRedundantAttributes as removeRedundantAttributes, code_searchCheatsheet as searchCheatsheet, code_searchEndpoints as searchEndpoints, code_splitStatements as splitStatements, code_testGitignorePatterns as testGitignorePatterns, code_testPattern as testPattern, code_testRegex as testRegex, code_validateAria as validateAria, code_validateEditorConfig as validateEditorConfig, code_validateEnvKey as validateEnvKey, code_validateFenceLanguageTags as validateFenceLanguageTags, code_validatePackageExports as validatePackageExports, code_validateTsconfig as validateTsconfig };
907
938
  }
908
939
 
909
- export { type LinkReferenceUsage as $, ALL_FLAGS as A, type EditorConfigValidationResult as B, CHEATSHEET as C, DEFAULT_COMMIT_TYPES as D, type EditorConfigIssue as E, type EnvEntry as F, type EnvParseResult as G, type ExportsIssue as H, type ExportsShape as I, type ExportsValidationResult as J, type FenceTagIssue as K, type FenceTagIssueType as L, type FenceValidationResult as M, type GitCommandConfig as N, type GitCommandResult as O, type GitOperation as P, type GithubUrlInfo as Q, type GithubUrlType as R, type GitignoreTestResult as S, type GqlFormatResult as T, type HtmlFormatResult as U, type HtmlMinifyOptions as V, type HtmlMinifyResult as W, type JsMinifyOptions as X, type JsMinifyResult as Y, KNOWN_LANGUAGE_TAGS as Z, type LinkReferenceDefinition as _, type ApiEndpoint as a, lintConventionalCommit as a$, MIME_TABLE as a0, type MarkdownFootnoteDefinition as a1, type MarkdownFootnoteReference as a2, type MarkdownFootnoteResult as a3, type MarkdownLinkReferenceResult as a4, type MatchResult as a5, type MimeEntry as a6, type MimeLookupResult as a7, OPERATIONS as a8, type ParsedSpec as a9, analyzeRegexGroups as aA, auditDependencyRanges as aB, buildDockerPull as aC, buildDockerRun as aD, buildGitCommand as aE, collapseHtmlWhitespace as aF, collapseJsWhitespace as aG, countProperties as aH, countRules as aI, countSqlPlaceholders as aJ, detectDialect as aK, detectOperationType as aL, detectRedos as aM, envToExport as aN, envToJson as aO, extractMarkdownFootnotes as aP, extractMarkdownLinkReferences as aQ, extractSvgSpriteSymbols as aR, formatCss as aS, formatGql as aT, formatHtml as aU, formatSql as aV, getEndpointsByTag as aW, getHtmlStats as aX, getJsStats as aY, getMethodColor as aZ, isValidTag as a_, type PlaceholderStyle as aa, type RedosFinding as ab, type RedosResult as ac, type RedosSeverity as ad, type RegexBackreferenceInfo as ae, type RegexError as af, type RegexFlag as ag, type RegexGroupAnalysis as ah, type RegexGroupInfo as ai, type RegexGroupIssue as aj, type RegexMatch as ak, type RegexResult as al, type RegexSuccess as am, type ResolvedLinkReference as an, SQL_DEFAULT_OPTIONS as ao, type Segment as ap, type SpecVersion as aq, type SqlDialect as ar, type SqlFormatOptions as as, type SqlPlaceholder as at, type SqlPlaceholderResult as au, type SvgSpriteResult as av, type SvgSpriteSymbol as aw, type TestPatternResult as ax, type TsconfigIssue as ay, type TsconfigValidationResult as az, type ApiInfo as b, lookupMime as b0, minifyCss as b1, minifyGql as b2, minifyHtml as b3, minifyJs as b4, minifySql as b5, normalizeRef as b6, parseCommitTrailers as b7, parseConnectionString as b8, parseDockerImage as b9, parseEnv as ba, parseGitCommand as bb, parseGithubUrl as bc, parseSpec as bd, removeConsoleCalls as be, removeEmptyAttributes as bf, removeHtmlComments as bg, removeJsComments as bh, removeRedundantAttributes as bi, searchCheatsheet as bj, searchEndpoints as bk, splitStatements as bl, testGitignorePatterns as bm, testPattern as bn, testRegex as bo, validateAria as bp, validateEditorConfig as bq, validateEnvKey as br, validateFenceLanguageTags as bs, validatePackageExports as bt, validateTsconfig as bu, code as c, type AriaIssue as d, type AriaValidationResult as e, type CheatsheetEntry as f, type CommitTrailer as g, type CommitTrailerResult as h, type ConnectionStringHost as i, type ConnectionStringResult as j, type ConventionalCommitFinding as k, type ConventionalCommitFooter as l, type ConventionalCommitOptions as m, type ConventionalCommitParsed as n, type ConventionalCommitResult as o, type ConventionalCommitSeverity as p, type CssResult as q, type DependencyAuditDuplicate as r, type DependencyAuditEntry as s, type DependencyAuditIssue as t, type DependencyAuditResult as u, type DependencyRangeType as v, type DependencySection as w, type DockerImageRef as x, type EditorConfigProperty as y, type EditorConfigSection as z };
940
+ export { type JsMinifyResult as $, ALL_FLAGS as A, type DockerfileStage as B, CHEATSHEET as C, DEFAULT_COMMIT_TYPES as D, type EditorConfigIssue as E, type EditorConfigProperty as F, type EditorConfigSection as G, type EditorConfigValidationResult as H, type EnvEntry as I, type EnvParseResult as J, type ExportsIssue as K, type ExportsShape as L, type ExportsValidationResult as M, type FenceTagIssue as N, type FenceTagIssueType as O, type FenceValidationResult as P, type GitCommandConfig as Q, type GitCommandResult as R, type GitOperation as S, type GithubUrlInfo as T, type GithubUrlType as U, type GitignoreTestResult as V, type GqlFormatResult as W, type HtmlFormatResult as X, type HtmlMinifyOptions as Y, type HtmlMinifyResult as Z, type JsMinifyOptions as _, type ApiEndpoint as a, getJsStats as a$, KNOWN_LANGUAGE_TAGS as a0, type LinkReferenceDefinition as a1, type LinkReferenceUsage as a2, MIME_TABLE as a3, type MarkdownFootnoteDefinition as a4, type MarkdownFootnoteReference as a5, type MarkdownFootnoteResult as a6, type MarkdownLinkReferenceResult as a7, type MatchResult as a8, type MimeEntry as a9, type TestPatternResult as aA, type TsconfigIssue as aB, type TsconfigValidationResult as aC, analyzeRegexGroups as aD, auditDependencyRanges as aE, buildDockerPull as aF, buildDockerRun as aG, buildGitCommand as aH, collapseHtmlWhitespace as aI, collapseJsWhitespace as aJ, countProperties as aK, countRules as aL, countSqlPlaceholders as aM, detectDialect as aN, detectOperationType as aO, detectRedos as aP, envToExport as aQ, envToJson as aR, extractMarkdownFootnotes as aS, extractMarkdownLinkReferences as aT, extractSvgSpriteSymbols as aU, formatCss as aV, formatGql as aW, formatHtml as aX, formatSql as aY, getEndpointsByTag as aZ, getHtmlStats as a_, type MimeLookupResult as aa, OPERATIONS as ab, type ParsedSpec as ac, type PlaceholderStyle as ad, type RedosFinding as ae, type RedosResult as af, type RedosSeverity as ag, type RegexBackreferenceInfo as ah, type RegexError as ai, type RegexFlag as aj, type RegexGroupAnalysis as ak, type RegexGroupInfo as al, type RegexGroupIssue as am, type RegexMatch as an, type RegexResult as ao, type RegexSuccess as ap, type ResolvedLinkReference as aq, SQL_DEFAULT_OPTIONS as ar, type Segment as as, type SpecVersion as at, type SqlDialect as au, type SqlFormatOptions as av, type SqlPlaceholder as aw, type SqlPlaceholderResult as ax, type SvgSpriteResult as ay, type SvgSpriteSymbol as az, type ApiInfo as b, getMethodColor as b0, isValidTag as b1, lintConventionalCommit as b2, lintDockerfile as b3, lookupMime as b4, minifyCss as b5, minifyGql as b6, minifyHtml as b7, minifyJs as b8, minifySql as b9, normalizeRef as ba, parseCommitTrailers as bb, parseConnectionString as bc, parseDockerImage as bd, parseEnv as be, parseGitCommand as bf, parseGithubUrl as bg, parseSpec as bh, removeConsoleCalls as bi, removeEmptyAttributes as bj, removeHtmlComments as bk, removeJsComments as bl, removeRedundantAttributes as bm, searchCheatsheet as bn, searchEndpoints as bo, splitStatements as bp, testGitignorePatterns as bq, testPattern as br, testRegex as bs, validateAria as bt, validateEditorConfig as bu, validateEnvKey as bv, validateFenceLanguageTags as bw, validatePackageExports as bx, validateTsconfig as by, code as c, type AriaIssue as d, type AriaValidationResult as e, type CheatsheetEntry as f, type CommitTrailer as g, type CommitTrailerResult as h, type ConnectionStringHost as i, type ConnectionStringResult as j, type ConventionalCommitFinding as k, type ConventionalCommitFooter as l, type ConventionalCommitOptions as m, type ConventionalCommitParsed as n, type ConventionalCommitResult as o, type ConventionalCommitSeverity as p, type CssResult as q, type DependencyAuditDuplicate as r, type DependencyAuditEntry as s, type DependencyAuditIssue as t, type DependencyAuditResult as u, type DependencyRangeType as v, type DependencySection as w, type DockerImageRef as x, type DockerfileLintFinding as y, type DockerfileLintResult as z };
@@ -12,6 +12,7 @@
12
12
  * - git-builder (buildGitCommand, parseGitCommand, OPERATIONS)
13
13
  * - docker-image-parser (parseDockerImage, buildDockerPull, buildDockerRun,
14
14
  * isValidTag, normalizeRef)
15
+ * - dockerfile-linter (lintDockerfile)
15
16
  * - js-minifier (minifyJs, removeJsComments, collapseJsWhitespace,
16
17
  * removeConsoleCalls, getJsStats)
17
18
  * - openapi-viewer (parseSpec, getEndpointsByTag, searchEndpoints, getMethodColor)
@@ -175,6 +176,32 @@ declare function buildDockerPull(parsed: DockerImageRef): string;
175
176
  declare function buildDockerRun(parsed: DockerImageRef, containerName?: string): string;
176
177
  declare function isValidTag(tag: string): boolean;
177
178
  declare function normalizeRef(ref: string): string;
179
+ interface DockerfileLintFinding {
180
+ rule: 'unpinned-base-image' | 'missing-workdir' | 'running-as-root' | 'add-vs-copy';
181
+ severity: 'warning' | 'info';
182
+ line: number;
183
+ message: string;
184
+ }
185
+ interface DockerfileStage {
186
+ index: number;
187
+ name: string | null;
188
+ baseImage: string;
189
+ fromLine: number;
190
+ }
191
+ interface DockerfileLintResult {
192
+ findings: DockerfileLintFinding[];
193
+ stages: DockerfileStage[];
194
+ }
195
+ /**
196
+ * Lint a Dockerfile for 4 common mistakes: a base image with no tag or
197
+ * pinned to `:latest`, a final stage with no WORKDIR, a final stage with no
198
+ * USER (so it runs as root), and ADD used on a plain local file/directory
199
+ * where COPY would do (ADD's extra behavior only makes sense for a remote
200
+ * URL or an auto-extracting archive).
201
+ */
202
+ declare function lintDockerfile(content: string): DockerfileLintResult | {
203
+ error: string;
204
+ };
178
205
  interface JsMinifyOptions {
179
206
  removeComments?: boolean;
180
207
  collapseWhitespace?: boolean;
@@ -780,6 +807,9 @@ type code_DependencyAuditResult = DependencyAuditResult;
780
807
  type code_DependencyRangeType = DependencyRangeType;
781
808
  type code_DependencySection = DependencySection;
782
809
  type code_DockerImageRef = DockerImageRef;
810
+ type code_DockerfileLintFinding = DockerfileLintFinding;
811
+ type code_DockerfileLintResult = DockerfileLintResult;
812
+ type code_DockerfileStage = DockerfileStage;
783
813
  type code_EditorConfigIssue = EditorConfigIssue;
784
814
  type code_EditorConfigProperty = EditorConfigProperty;
785
815
  type code_EditorConfigSection = EditorConfigSection;
@@ -871,6 +901,7 @@ declare const code_getJsStats: typeof getJsStats;
871
901
  declare const code_getMethodColor: typeof getMethodColor;
872
902
  declare const code_isValidTag: typeof isValidTag;
873
903
  declare const code_lintConventionalCommit: typeof lintConventionalCommit;
904
+ declare const code_lintDockerfile: typeof lintDockerfile;
874
905
  declare const code_lookupMime: typeof lookupMime;
875
906
  declare const code_minifyCss: typeof minifyCss;
876
907
  declare const code_minifyGql: typeof minifyGql;
@@ -903,7 +934,7 @@ declare const code_validateFenceLanguageTags: typeof validateFenceLanguageTags;
903
934
  declare const code_validatePackageExports: typeof validatePackageExports;
904
935
  declare const code_validateTsconfig: typeof validateTsconfig;
905
936
  declare namespace code {
906
- export { code_ALL_FLAGS as ALL_FLAGS, type code_ApiEndpoint as ApiEndpoint, type code_ApiInfo as ApiInfo, type code_AriaIssue as AriaIssue, type code_AriaValidationResult as AriaValidationResult, code_CHEATSHEET as CHEATSHEET, type code_CheatsheetEntry as CheatsheetEntry, type code_CommitTrailer as CommitTrailer, type code_CommitTrailerResult as CommitTrailerResult, type code_ConnectionStringHost as ConnectionStringHost, type code_ConnectionStringResult as ConnectionStringResult, type code_ConventionalCommitFinding as ConventionalCommitFinding, type code_ConventionalCommitFooter as ConventionalCommitFooter, type code_ConventionalCommitOptions as ConventionalCommitOptions, type code_ConventionalCommitParsed as ConventionalCommitParsed, type code_ConventionalCommitResult as ConventionalCommitResult, type code_ConventionalCommitSeverity as ConventionalCommitSeverity, type code_CssResult as CssResult, code_DEFAULT_COMMIT_TYPES as DEFAULT_COMMIT_TYPES, type code_DependencyAuditDuplicate as DependencyAuditDuplicate, type code_DependencyAuditEntry as DependencyAuditEntry, type code_DependencyAuditIssue as DependencyAuditIssue, type code_DependencyAuditResult as DependencyAuditResult, type code_DependencyRangeType as DependencyRangeType, type code_DependencySection as DependencySection, type code_DockerImageRef as DockerImageRef, type code_EditorConfigIssue as EditorConfigIssue, type code_EditorConfigProperty as EditorConfigProperty, type code_EditorConfigSection as EditorConfigSection, type code_EditorConfigValidationResult as EditorConfigValidationResult, type code_EnvEntry as EnvEntry, type code_EnvParseResult as EnvParseResult, type code_ExportsIssue as ExportsIssue, type code_ExportsShape as ExportsShape, type code_ExportsValidationResult as ExportsValidationResult, type code_FenceTagIssue as FenceTagIssue, type code_FenceTagIssueType as FenceTagIssueType, type code_FenceValidationResult as FenceValidationResult, type code_GitCommandConfig as GitCommandConfig, type code_GitCommandResult as GitCommandResult, type code_GitOperation as GitOperation, type code_GithubUrlInfo as GithubUrlInfo, type code_GithubUrlType as GithubUrlType, type code_GitignoreTestResult as GitignoreTestResult, type code_GqlFormatResult as GqlFormatResult, type code_HtmlFormatResult as HtmlFormatResult, type code_HtmlMinifyOptions as HtmlMinifyOptions, type code_HtmlMinifyResult as HtmlMinifyResult, type code_JsMinifyOptions as JsMinifyOptions, type code_JsMinifyResult as JsMinifyResult, code_KNOWN_LANGUAGE_TAGS as KNOWN_LANGUAGE_TAGS, type code_LinkReferenceDefinition as LinkReferenceDefinition, type code_LinkReferenceUsage as LinkReferenceUsage, code_MIME_TABLE as MIME_TABLE, type code_MarkdownFootnoteDefinition as MarkdownFootnoteDefinition, type code_MarkdownFootnoteReference as MarkdownFootnoteReference, type code_MarkdownFootnoteResult as MarkdownFootnoteResult, type code_MarkdownLinkReferenceResult as MarkdownLinkReferenceResult, type code_MatchResult as MatchResult, type code_MimeEntry as MimeEntry, type code_MimeLookupResult as MimeLookupResult, code_OPERATIONS as OPERATIONS, type code_ParsedSpec as ParsedSpec, type code_PlaceholderStyle as PlaceholderStyle, type code_RedosFinding as RedosFinding, type code_RedosResult as RedosResult, type code_RedosSeverity as RedosSeverity, type code_RegexBackreferenceInfo as RegexBackreferenceInfo, type code_RegexError as RegexError, type code_RegexFlag as RegexFlag, type code_RegexGroupAnalysis as RegexGroupAnalysis, type code_RegexGroupInfo as RegexGroupInfo, type code_RegexGroupIssue as RegexGroupIssue, type code_RegexMatch as RegexMatch, type code_RegexResult as RegexResult, type code_RegexSuccess as RegexSuccess, type code_ResolvedLinkReference as ResolvedLinkReference, code_SQL_DEFAULT_OPTIONS as SQL_DEFAULT_OPTIONS, type code_Segment as Segment, type code_SpecVersion as SpecVersion, type code_SqlDialect as SqlDialect, type code_SqlFormatOptions as SqlFormatOptions, type code_SqlPlaceholder as SqlPlaceholder, type code_SqlPlaceholderResult as SqlPlaceholderResult, type code_SvgSpriteResult as SvgSpriteResult, type code_SvgSpriteSymbol as SvgSpriteSymbol, type code_TestPatternResult as TestPatternResult, type code_TsconfigIssue as TsconfigIssue, type code_TsconfigValidationResult as TsconfigValidationResult, code_analyzeRegexGroups as analyzeRegexGroups, code_auditDependencyRanges as auditDependencyRanges, code_buildDockerPull as buildDockerPull, code_buildDockerRun as buildDockerRun, code_buildGitCommand as buildGitCommand, code_collapseHtmlWhitespace as collapseHtmlWhitespace, code_collapseJsWhitespace as collapseJsWhitespace, code_countProperties as countProperties, code_countRules as countRules, code_countSqlPlaceholders as countSqlPlaceholders, code_detectDialect as detectDialect, code_detectOperationType as detectOperationType, code_detectRedos as detectRedos, code_envToExport as envToExport, code_envToJson as envToJson, code_extractMarkdownFootnotes as extractMarkdownFootnotes, code_extractMarkdownLinkReferences as extractMarkdownLinkReferences, code_extractSvgSpriteSymbols as extractSvgSpriteSymbols, code_formatCss as formatCss, code_formatGql as formatGql, code_formatHtml as formatHtml, code_formatSql as formatSql, code_getEndpointsByTag as getEndpointsByTag, code_getHtmlStats as getHtmlStats, code_getJsStats as getJsStats, code_getMethodColor as getMethodColor, code_isValidTag as isValidTag, code_lintConventionalCommit as lintConventionalCommit, code_lookupMime as lookupMime, code_minifyCss as minifyCss, code_minifyGql as minifyGql, code_minifyHtml as minifyHtml, code_minifyJs as minifyJs, code_minifySql as minifySql, code_normalizeRef as normalizeRef, code_parseCommitTrailers as parseCommitTrailers, code_parseConnectionString as parseConnectionString, code_parseDockerImage as parseDockerImage, code_parseEnv as parseEnv, code_parseGitCommand as parseGitCommand, code_parseGithubUrl as parseGithubUrl, code_parseSpec as parseSpec, code_removeConsoleCalls as removeConsoleCalls, code_removeEmptyAttributes as removeEmptyAttributes, code_removeHtmlComments as removeHtmlComments, code_removeJsComments as removeJsComments, code_removeRedundantAttributes as removeRedundantAttributes, code_searchCheatsheet as searchCheatsheet, code_searchEndpoints as searchEndpoints, code_splitStatements as splitStatements, code_testGitignorePatterns as testGitignorePatterns, code_testPattern as testPattern, code_testRegex as testRegex, code_validateAria as validateAria, code_validateEditorConfig as validateEditorConfig, code_validateEnvKey as validateEnvKey, code_validateFenceLanguageTags as validateFenceLanguageTags, code_validatePackageExports as validatePackageExports, code_validateTsconfig as validateTsconfig };
937
+ export { code_ALL_FLAGS as ALL_FLAGS, type code_ApiEndpoint as ApiEndpoint, type code_ApiInfo as ApiInfo, type code_AriaIssue as AriaIssue, type code_AriaValidationResult as AriaValidationResult, code_CHEATSHEET as CHEATSHEET, type code_CheatsheetEntry as CheatsheetEntry, type code_CommitTrailer as CommitTrailer, type code_CommitTrailerResult as CommitTrailerResult, type code_ConnectionStringHost as ConnectionStringHost, type code_ConnectionStringResult as ConnectionStringResult, type code_ConventionalCommitFinding as ConventionalCommitFinding, type code_ConventionalCommitFooter as ConventionalCommitFooter, type code_ConventionalCommitOptions as ConventionalCommitOptions, type code_ConventionalCommitParsed as ConventionalCommitParsed, type code_ConventionalCommitResult as ConventionalCommitResult, type code_ConventionalCommitSeverity as ConventionalCommitSeverity, type code_CssResult as CssResult, code_DEFAULT_COMMIT_TYPES as DEFAULT_COMMIT_TYPES, type code_DependencyAuditDuplicate as DependencyAuditDuplicate, type code_DependencyAuditEntry as DependencyAuditEntry, type code_DependencyAuditIssue as DependencyAuditIssue, type code_DependencyAuditResult as DependencyAuditResult, type code_DependencyRangeType as DependencyRangeType, type code_DependencySection as DependencySection, type code_DockerImageRef as DockerImageRef, type code_DockerfileLintFinding as DockerfileLintFinding, type code_DockerfileLintResult as DockerfileLintResult, type code_DockerfileStage as DockerfileStage, type code_EditorConfigIssue as EditorConfigIssue, type code_EditorConfigProperty as EditorConfigProperty, type code_EditorConfigSection as EditorConfigSection, type code_EditorConfigValidationResult as EditorConfigValidationResult, type code_EnvEntry as EnvEntry, type code_EnvParseResult as EnvParseResult, type code_ExportsIssue as ExportsIssue, type code_ExportsShape as ExportsShape, type code_ExportsValidationResult as ExportsValidationResult, type code_FenceTagIssue as FenceTagIssue, type code_FenceTagIssueType as FenceTagIssueType, type code_FenceValidationResult as FenceValidationResult, type code_GitCommandConfig as GitCommandConfig, type code_GitCommandResult as GitCommandResult, type code_GitOperation as GitOperation, type code_GithubUrlInfo as GithubUrlInfo, type code_GithubUrlType as GithubUrlType, type code_GitignoreTestResult as GitignoreTestResult, type code_GqlFormatResult as GqlFormatResult, type code_HtmlFormatResult as HtmlFormatResult, type code_HtmlMinifyOptions as HtmlMinifyOptions, type code_HtmlMinifyResult as HtmlMinifyResult, type code_JsMinifyOptions as JsMinifyOptions, type code_JsMinifyResult as JsMinifyResult, code_KNOWN_LANGUAGE_TAGS as KNOWN_LANGUAGE_TAGS, type code_LinkReferenceDefinition as LinkReferenceDefinition, type code_LinkReferenceUsage as LinkReferenceUsage, code_MIME_TABLE as MIME_TABLE, type code_MarkdownFootnoteDefinition as MarkdownFootnoteDefinition, type code_MarkdownFootnoteReference as MarkdownFootnoteReference, type code_MarkdownFootnoteResult as MarkdownFootnoteResult, type code_MarkdownLinkReferenceResult as MarkdownLinkReferenceResult, type code_MatchResult as MatchResult, type code_MimeEntry as MimeEntry, type code_MimeLookupResult as MimeLookupResult, code_OPERATIONS as OPERATIONS, type code_ParsedSpec as ParsedSpec, type code_PlaceholderStyle as PlaceholderStyle, type code_RedosFinding as RedosFinding, type code_RedosResult as RedosResult, type code_RedosSeverity as RedosSeverity, type code_RegexBackreferenceInfo as RegexBackreferenceInfo, type code_RegexError as RegexError, type code_RegexFlag as RegexFlag, type code_RegexGroupAnalysis as RegexGroupAnalysis, type code_RegexGroupInfo as RegexGroupInfo, type code_RegexGroupIssue as RegexGroupIssue, type code_RegexMatch as RegexMatch, type code_RegexResult as RegexResult, type code_RegexSuccess as RegexSuccess, type code_ResolvedLinkReference as ResolvedLinkReference, code_SQL_DEFAULT_OPTIONS as SQL_DEFAULT_OPTIONS, type code_Segment as Segment, type code_SpecVersion as SpecVersion, type code_SqlDialect as SqlDialect, type code_SqlFormatOptions as SqlFormatOptions, type code_SqlPlaceholder as SqlPlaceholder, type code_SqlPlaceholderResult as SqlPlaceholderResult, type code_SvgSpriteResult as SvgSpriteResult, type code_SvgSpriteSymbol as SvgSpriteSymbol, type code_TestPatternResult as TestPatternResult, type code_TsconfigIssue as TsconfigIssue, type code_TsconfigValidationResult as TsconfigValidationResult, code_analyzeRegexGroups as analyzeRegexGroups, code_auditDependencyRanges as auditDependencyRanges, code_buildDockerPull as buildDockerPull, code_buildDockerRun as buildDockerRun, code_buildGitCommand as buildGitCommand, code_collapseHtmlWhitespace as collapseHtmlWhitespace, code_collapseJsWhitespace as collapseJsWhitespace, code_countProperties as countProperties, code_countRules as countRules, code_countSqlPlaceholders as countSqlPlaceholders, code_detectDialect as detectDialect, code_detectOperationType as detectOperationType, code_detectRedos as detectRedos, code_envToExport as envToExport, code_envToJson as envToJson, code_extractMarkdownFootnotes as extractMarkdownFootnotes, code_extractMarkdownLinkReferences as extractMarkdownLinkReferences, code_extractSvgSpriteSymbols as extractSvgSpriteSymbols, code_formatCss as formatCss, code_formatGql as formatGql, code_formatHtml as formatHtml, code_formatSql as formatSql, code_getEndpointsByTag as getEndpointsByTag, code_getHtmlStats as getHtmlStats, code_getJsStats as getJsStats, code_getMethodColor as getMethodColor, code_isValidTag as isValidTag, code_lintConventionalCommit as lintConventionalCommit, code_lintDockerfile as lintDockerfile, code_lookupMime as lookupMime, code_minifyCss as minifyCss, code_minifyGql as minifyGql, code_minifyHtml as minifyHtml, code_minifyJs as minifyJs, code_minifySql as minifySql, code_normalizeRef as normalizeRef, code_parseCommitTrailers as parseCommitTrailers, code_parseConnectionString as parseConnectionString, code_parseDockerImage as parseDockerImage, code_parseEnv as parseEnv, code_parseGitCommand as parseGitCommand, code_parseGithubUrl as parseGithubUrl, code_parseSpec as parseSpec, code_removeConsoleCalls as removeConsoleCalls, code_removeEmptyAttributes as removeEmptyAttributes, code_removeHtmlComments as removeHtmlComments, code_removeJsComments as removeJsComments, code_removeRedundantAttributes as removeRedundantAttributes, code_searchCheatsheet as searchCheatsheet, code_searchEndpoints as searchEndpoints, code_splitStatements as splitStatements, code_testGitignorePatterns as testGitignorePatterns, code_testPattern as testPattern, code_testRegex as testRegex, code_validateAria as validateAria, code_validateEditorConfig as validateEditorConfig, code_validateEnvKey as validateEnvKey, code_validateFenceLanguageTags as validateFenceLanguageTags, code_validatePackageExports as validatePackageExports, code_validateTsconfig as validateTsconfig };
907
938
  }
908
939
 
909
- export { type LinkReferenceUsage as $, ALL_FLAGS as A, type EditorConfigValidationResult as B, CHEATSHEET as C, DEFAULT_COMMIT_TYPES as D, type EditorConfigIssue as E, type EnvEntry as F, type EnvParseResult as G, type ExportsIssue as H, type ExportsShape as I, type ExportsValidationResult as J, type FenceTagIssue as K, type FenceTagIssueType as L, type FenceValidationResult as M, type GitCommandConfig as N, type GitCommandResult as O, type GitOperation as P, type GithubUrlInfo as Q, type GithubUrlType as R, type GitignoreTestResult as S, type GqlFormatResult as T, type HtmlFormatResult as U, type HtmlMinifyOptions as V, type HtmlMinifyResult as W, type JsMinifyOptions as X, type JsMinifyResult as Y, KNOWN_LANGUAGE_TAGS as Z, type LinkReferenceDefinition as _, type ApiEndpoint as a, lintConventionalCommit as a$, MIME_TABLE as a0, type MarkdownFootnoteDefinition as a1, type MarkdownFootnoteReference as a2, type MarkdownFootnoteResult as a3, type MarkdownLinkReferenceResult as a4, type MatchResult as a5, type MimeEntry as a6, type MimeLookupResult as a7, OPERATIONS as a8, type ParsedSpec as a9, analyzeRegexGroups as aA, auditDependencyRanges as aB, buildDockerPull as aC, buildDockerRun as aD, buildGitCommand as aE, collapseHtmlWhitespace as aF, collapseJsWhitespace as aG, countProperties as aH, countRules as aI, countSqlPlaceholders as aJ, detectDialect as aK, detectOperationType as aL, detectRedos as aM, envToExport as aN, envToJson as aO, extractMarkdownFootnotes as aP, extractMarkdownLinkReferences as aQ, extractSvgSpriteSymbols as aR, formatCss as aS, formatGql as aT, formatHtml as aU, formatSql as aV, getEndpointsByTag as aW, getHtmlStats as aX, getJsStats as aY, getMethodColor as aZ, isValidTag as a_, type PlaceholderStyle as aa, type RedosFinding as ab, type RedosResult as ac, type RedosSeverity as ad, type RegexBackreferenceInfo as ae, type RegexError as af, type RegexFlag as ag, type RegexGroupAnalysis as ah, type RegexGroupInfo as ai, type RegexGroupIssue as aj, type RegexMatch as ak, type RegexResult as al, type RegexSuccess as am, type ResolvedLinkReference as an, SQL_DEFAULT_OPTIONS as ao, type Segment as ap, type SpecVersion as aq, type SqlDialect as ar, type SqlFormatOptions as as, type SqlPlaceholder as at, type SqlPlaceholderResult as au, type SvgSpriteResult as av, type SvgSpriteSymbol as aw, type TestPatternResult as ax, type TsconfigIssue as ay, type TsconfigValidationResult as az, type ApiInfo as b, lookupMime as b0, minifyCss as b1, minifyGql as b2, minifyHtml as b3, minifyJs as b4, minifySql as b5, normalizeRef as b6, parseCommitTrailers as b7, parseConnectionString as b8, parseDockerImage as b9, parseEnv as ba, parseGitCommand as bb, parseGithubUrl as bc, parseSpec as bd, removeConsoleCalls as be, removeEmptyAttributes as bf, removeHtmlComments as bg, removeJsComments as bh, removeRedundantAttributes as bi, searchCheatsheet as bj, searchEndpoints as bk, splitStatements as bl, testGitignorePatterns as bm, testPattern as bn, testRegex as bo, validateAria as bp, validateEditorConfig as bq, validateEnvKey as br, validateFenceLanguageTags as bs, validatePackageExports as bt, validateTsconfig as bu, code as c, type AriaIssue as d, type AriaValidationResult as e, type CheatsheetEntry as f, type CommitTrailer as g, type CommitTrailerResult as h, type ConnectionStringHost as i, type ConnectionStringResult as j, type ConventionalCommitFinding as k, type ConventionalCommitFooter as l, type ConventionalCommitOptions as m, type ConventionalCommitParsed as n, type ConventionalCommitResult as o, type ConventionalCommitSeverity as p, type CssResult as q, type DependencyAuditDuplicate as r, type DependencyAuditEntry as s, type DependencyAuditIssue as t, type DependencyAuditResult as u, type DependencyRangeType as v, type DependencySection as w, type DockerImageRef as x, type EditorConfigProperty as y, type EditorConfigSection as z };
940
+ export { type JsMinifyResult as $, ALL_FLAGS as A, type DockerfileStage as B, CHEATSHEET as C, DEFAULT_COMMIT_TYPES as D, type EditorConfigIssue as E, type EditorConfigProperty as F, type EditorConfigSection as G, type EditorConfigValidationResult as H, type EnvEntry as I, type EnvParseResult as J, type ExportsIssue as K, type ExportsShape as L, type ExportsValidationResult as M, type FenceTagIssue as N, type FenceTagIssueType as O, type FenceValidationResult as P, type GitCommandConfig as Q, type GitCommandResult as R, type GitOperation as S, type GithubUrlInfo as T, type GithubUrlType as U, type GitignoreTestResult as V, type GqlFormatResult as W, type HtmlFormatResult as X, type HtmlMinifyOptions as Y, type HtmlMinifyResult as Z, type JsMinifyOptions as _, type ApiEndpoint as a, getJsStats as a$, KNOWN_LANGUAGE_TAGS as a0, type LinkReferenceDefinition as a1, type LinkReferenceUsage as a2, MIME_TABLE as a3, type MarkdownFootnoteDefinition as a4, type MarkdownFootnoteReference as a5, type MarkdownFootnoteResult as a6, type MarkdownLinkReferenceResult as a7, type MatchResult as a8, type MimeEntry as a9, type TestPatternResult as aA, type TsconfigIssue as aB, type TsconfigValidationResult as aC, analyzeRegexGroups as aD, auditDependencyRanges as aE, buildDockerPull as aF, buildDockerRun as aG, buildGitCommand as aH, collapseHtmlWhitespace as aI, collapseJsWhitespace as aJ, countProperties as aK, countRules as aL, countSqlPlaceholders as aM, detectDialect as aN, detectOperationType as aO, detectRedos as aP, envToExport as aQ, envToJson as aR, extractMarkdownFootnotes as aS, extractMarkdownLinkReferences as aT, extractSvgSpriteSymbols as aU, formatCss as aV, formatGql as aW, formatHtml as aX, formatSql as aY, getEndpointsByTag as aZ, getHtmlStats as a_, type MimeLookupResult as aa, OPERATIONS as ab, type ParsedSpec as ac, type PlaceholderStyle as ad, type RedosFinding as ae, type RedosResult as af, type RedosSeverity as ag, type RegexBackreferenceInfo as ah, type RegexError as ai, type RegexFlag as aj, type RegexGroupAnalysis as ak, type RegexGroupInfo as al, type RegexGroupIssue as am, type RegexMatch as an, type RegexResult as ao, type RegexSuccess as ap, type ResolvedLinkReference as aq, SQL_DEFAULT_OPTIONS as ar, type Segment as as, type SpecVersion as at, type SqlDialect as au, type SqlFormatOptions as av, type SqlPlaceholder as aw, type SqlPlaceholderResult as ax, type SvgSpriteResult as ay, type SvgSpriteSymbol as az, type ApiInfo as b, getMethodColor as b0, isValidTag as b1, lintConventionalCommit as b2, lintDockerfile as b3, lookupMime as b4, minifyCss as b5, minifyGql as b6, minifyHtml as b7, minifyJs as b8, minifySql as b9, normalizeRef as ba, parseCommitTrailers as bb, parseConnectionString as bc, parseDockerImage as bd, parseEnv as be, parseGitCommand as bf, parseGithubUrl as bg, parseSpec as bh, removeConsoleCalls as bi, removeEmptyAttributes as bj, removeHtmlComments as bk, removeJsComments as bl, removeRedundantAttributes as bm, searchCheatsheet as bn, searchEndpoints as bo, splitStatements as bp, testGitignorePatterns as bq, testPattern as br, testRegex as bs, validateAria as bt, validateEditorConfig as bu, validateEnvKey as bv, validateFenceLanguageTags as bw, validatePackageExports as bx, validateTsconfig as by, code as c, type AriaIssue as d, type AriaValidationResult as e, type CheatsheetEntry as f, type CommitTrailer as g, type CommitTrailerResult as h, type ConnectionStringHost as i, type ConnectionStringResult as j, type ConventionalCommitFinding as k, type ConventionalCommitFooter as l, type ConventionalCommitOptions as m, type ConventionalCommitParsed as n, type ConventionalCommitResult as o, type ConventionalCommitSeverity as p, type CssResult as q, type DependencyAuditDuplicate as r, type DependencyAuditEntry as s, type DependencyAuditIssue as t, type DependencyAuditResult as u, type DependencyRangeType as v, type DependencySection as w, type DockerImageRef as x, type DockerfileLintFinding as y, type DockerfileLintResult as z };
package/dist/index.cjs CHANGED
@@ -8111,6 +8111,7 @@ __export(time_exports, {
8111
8111
  TIMEZONES: () => TIMEZONES,
8112
8112
  convertTime: () => convertTime,
8113
8113
  diffDates: () => diffDates,
8114
+ findCronOverlaps: () => findCronOverlaps,
8114
8115
  formatInTimezone: () => formatInTimezone,
8115
8116
  formatIso8601Duration: () => formatIso8601Duration,
8116
8117
  formatRelative: () => formatRelative,
@@ -8786,6 +8787,42 @@ function getRunInterval(dates) {
8786
8787
  const days = Math.round(diffMins / 1440);
8787
8788
  return `Every ${days} days`;
8788
8789
  }
8790
+ var MAX_CRON_OVERLAPS = 200;
8791
+ function findCronOverlaps(expressions, windowDays = 30, fromDate) {
8792
+ if (expressions.length < 2) return { error: "Provide at least two cron expressions to check for overlaps" };
8793
+ if (expressions.length > 10) return { error: "Provide 10 or fewer cron expressions" };
8794
+ if (windowDays < 1 || windowDays > 365) return { error: "windowDays must be between 1 and 365" };
8795
+ const parsedList = [];
8796
+ for (let i = 0; i < expressions.length; i++) {
8797
+ const parsed = parseCronExpression(expressions[i]);
8798
+ if (typeof parsed === "object" && "error" in parsed) {
8799
+ return { error: `Expression ${i + 1} ("${expressions[i]}"): ${parsed.error}` };
8800
+ }
8801
+ parsedList.push(parsed);
8802
+ }
8803
+ const start = fromDate ? new Date(fromDate) : /* @__PURE__ */ new Date();
8804
+ const cursor = new Date(start);
8805
+ cursor.setSeconds(0, 0);
8806
+ cursor.setMinutes(cursor.getMinutes() + 1);
8807
+ const endTime = cursor.getTime() + windowDays * 24 * 60 * 60 * 1e3;
8808
+ const overlaps = [];
8809
+ let truncated = false;
8810
+ while (cursor.getTime() < endTime) {
8811
+ const matched = [];
8812
+ for (let i = 0; i < parsedList.length; i++) {
8813
+ if (matchesCron(cursor, parsedList[i])) matched.push(i);
8814
+ }
8815
+ if (matched.length >= 2) {
8816
+ if (overlaps.length >= MAX_CRON_OVERLAPS) {
8817
+ truncated = true;
8818
+ break;
8819
+ }
8820
+ overlaps.push({ date: new Date(cursor), expressionIndexes: matched });
8821
+ }
8822
+ cursor.setMinutes(cursor.getMinutes() + 1);
8823
+ }
8824
+ return { overlaps, windowDays, truncated };
8825
+ }
8789
8826
  var DURATION_SECONDS_PER_YEAR = 365 * 86400;
8790
8827
  var DURATION_SECONDS_PER_MONTH = 30 * 86400;
8791
8828
  function humanizeDurationParts(parts) {
@@ -16803,6 +16840,7 @@ __export(code_exports, {
16803
16840
  getMethodColor: () => getMethodColor,
16804
16841
  isValidTag: () => isValidTag,
16805
16842
  lintConventionalCommit: () => lintConventionalCommit,
16843
+ lintDockerfile: () => lintDockerfile,
16806
16844
  lookupMime: () => lookupMime,
16807
16845
  minifyCss: () => minifyCss,
16808
16846
  minifyGql: () => minifyGql,
@@ -18633,6 +18671,111 @@ function normalizeRef(ref) {
18633
18671
  const tagPart = parsed.digest ? `@${parsed.digest}` : parsed.tag ? `:${parsed.tag}` : "";
18634
18672
  return `${parsed.registry}/${ns}${parsed.repository}${tagPart}`;
18635
18673
  }
18674
+ function _parseDockerfileInstructions(content) {
18675
+ const rawLines = content.replace(/\r\n/g, "\n").split("\n");
18676
+ const instructions = [];
18677
+ let buffer = "";
18678
+ let bufferStartLine = 0;
18679
+ for (let i = 0; i < rawLines.length; i++) {
18680
+ const lineNo = i + 1;
18681
+ const line = rawLines[i];
18682
+ const trimmed = line.trim();
18683
+ if (buffer === "") {
18684
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
18685
+ bufferStartLine = lineNo;
18686
+ buffer = line.trimEnd();
18687
+ } else {
18688
+ buffer += "\n" + line.trimEnd();
18689
+ }
18690
+ if (buffer.endsWith("\\")) {
18691
+ buffer = buffer.slice(0, -1);
18692
+ continue;
18693
+ }
18694
+ const match = buffer.trim().match(/^([A-Za-z]+)\s*([\s\S]*)$/);
18695
+ if (match) {
18696
+ instructions.push({ instruction: match[1].toUpperCase(), args: match[2].trim(), line: bufferStartLine });
18697
+ }
18698
+ buffer = "";
18699
+ }
18700
+ return instructions;
18701
+ }
18702
+ var _DOCKERFILE_TAR_RE = /\.(tar(\.(gz|bz2|xz))?|tgz|tbz2|txz)$/i;
18703
+ function lintDockerfile(content) {
18704
+ if (!content || !content.trim()) return { error: "Dockerfile content is required" };
18705
+ const instructions = _parseDockerfileInstructions(content);
18706
+ if (instructions.length === 0) return { error: "No Dockerfile instructions found" };
18707
+ const fromInstructions = instructions.filter((i) => i.instruction === "FROM");
18708
+ if (fromInstructions.length === 0) return { error: "No FROM instruction found; this does not look like a valid Dockerfile" };
18709
+ const stageNames = /* @__PURE__ */ new Set();
18710
+ const stages = fromInstructions.map((inst, idx) => {
18711
+ const asMatch = inst.args.match(/^(\S+)(?:\s+AS\s+(\S+))?/i);
18712
+ const baseImage = asMatch ? asMatch[1] : inst.args.split(/\s+/)[0];
18713
+ const name = asMatch && asMatch[2] ? asMatch[2] : null;
18714
+ if (name) stageNames.add(name.toLowerCase());
18715
+ return { index: idx, name, baseImage, fromLine: inst.line };
18716
+ });
18717
+ const findings = [];
18718
+ for (const stage of stages) {
18719
+ const base = stage.baseImage;
18720
+ if (base.toLowerCase() === "scratch") continue;
18721
+ if (stageNames.has(base.toLowerCase())) continue;
18722
+ const withoutDigest = base.split("@")[0];
18723
+ const hasTag = withoutDigest.includes(":");
18724
+ const tag = hasTag ? withoutDigest.split(":").pop() : null;
18725
+ if (!hasTag) {
18726
+ findings.push({
18727
+ rule: "unpinned-base-image",
18728
+ severity: "warning",
18729
+ line: stage.fromLine,
18730
+ message: `FROM ${base} has no tag, so it resolves to ":latest", which can silently change what gets built on a future run. Pin an explicit version tag instead.`
18731
+ });
18732
+ } else if (tag === "latest") {
18733
+ findings.push({
18734
+ rule: "unpinned-base-image",
18735
+ severity: "warning",
18736
+ line: stage.fromLine,
18737
+ message: `FROM ${base} is explicitly pinned to the "latest" tag, which is a moving target rather than a fixed version. Pin an explicit version tag instead.`
18738
+ });
18739
+ }
18740
+ }
18741
+ const finalStage = stages[stages.length - 1];
18742
+ const finalStageInstructions = instructions.filter((i) => i.line >= finalStage.fromLine);
18743
+ if (!finalStageInstructions.some((i) => i.instruction === "WORKDIR")) {
18744
+ findings.push({
18745
+ rule: "missing-workdir",
18746
+ severity: "warning",
18747
+ line: finalStage.fromLine,
18748
+ message: 'No WORKDIR instruction in the final stage, so RUN/CMD/ENTRYPOINT execute from "/" by default. Set an explicit WORKDIR.'
18749
+ });
18750
+ }
18751
+ if (!finalStageInstructions.some((i) => i.instruction === "USER")) {
18752
+ findings.push({
18753
+ rule: "running-as-root",
18754
+ severity: "warning",
18755
+ line: finalStage.fromLine,
18756
+ message: "No USER instruction in the final stage, so the container runs as root by default. Add a non-root USER unless root is genuinely required."
18757
+ });
18758
+ }
18759
+ for (const inst of instructions) {
18760
+ if (inst.instruction !== "ADD") continue;
18761
+ const parts = inst.args.split(/\s+/).filter(Boolean).filter((p) => !p.startsWith("--"));
18762
+ if (parts.length < 2) continue;
18763
+ const sources = parts.slice(0, -1);
18764
+ for (const src of sources) {
18765
+ const isUrl = /^https?:\/\//i.test(src);
18766
+ const isTar = _DOCKERFILE_TAR_RE.test(src);
18767
+ if (!isUrl && !isTar) {
18768
+ findings.push({
18769
+ rule: "add-vs-copy",
18770
+ severity: "info",
18771
+ line: inst.line,
18772
+ message: `ADD ${src} copies a local file/directory, not a URL or an auto-extracting archive. Use COPY instead, since ADD's extra behavior (remote fetch, tar auto-extract) doesn't apply here.`
18773
+ });
18774
+ }
18775
+ }
18776
+ }
18777
+ return { findings, stages };
18778
+ }
18636
18779
  function removeJsComments(code) {
18637
18780
  let result = "";
18638
18781
  let i = 0;
package/dist/index.d.cts CHANGED
@@ -4,11 +4,11 @@ export { h as hashing } from './hashing-CJjlvqS_.cjs';
4
4
  export { t as text } from './text-CNn3whZA.cjs';
5
5
  export { d as data } from './data-DIyBrJ6l.cjs';
6
6
  export { g as generators } from './generators-DAXXrMvG.cjs';
7
- export { t as time } from './time-KqJjdqII.cjs';
7
+ export { t as time } from './time-VMAy_SrV.cjs';
8
8
  export { u as units } from './units-D7YRRwei.cjs';
9
9
  export { n as network } from './network-ylRtLPEs.cjs';
10
10
  export { a as api } from './api-CQnIUrVB.cjs';
11
- export { c as code } from './code-COUhffgE.cjs';
11
+ export { c as code } from './code-mkKV7BQ4.cjs';
12
12
  export { c as color } from './color-tPwZCr9H.cjs';
13
13
  export { c as css } from './css-Cf7AMGM-.cjs';
14
14
  export { m as misc } from './misc-CA3N198T.cjs';
package/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ export { h as hashing } from './hashing-CJjlvqS_.js';
4
4
  export { t as text } from './text-CNn3whZA.js';
5
5
  export { d as data } from './data-DIyBrJ6l.js';
6
6
  export { g as generators } from './generators-DAXXrMvG.js';
7
- export { t as time } from './time-KqJjdqII.js';
7
+ export { t as time } from './time-VMAy_SrV.js';
8
8
  export { u as units } from './units-D7YRRwei.js';
9
9
  export { n as network } from './network-ylRtLPEs.js';
10
10
  export { a as api } from './api-CQnIUrVB.js';
11
- export { c as code } from './code-COUhffgE.js';
11
+ export { c as code } from './code-mkKV7BQ4.js';
12
12
  export { c as color } from './color-tPwZCr9H.js';
13
13
  export { c as css } from './css-Cf7AMGM-.js';
14
14
  export { m as misc } from './misc-CA3N198T.js';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ export { media_exports as media } from './chunk-ZWFZRDQ4.js';
2
2
  export { units_exports as units } from './chunk-OFLNVDNX.js';
3
3
  export { network_exports as network } from './chunk-SW3J5CAI.js';
4
4
  export { api_exports as api } from './chunk-U2HREMZU.js';
5
- export { code_exports as code } from './chunk-KXUHXQFO.js';
5
+ export { code_exports as code } from './chunk-RMXZMYSG.js';
6
6
  export { color_exports as color } from './chunk-BPVAB4P2.js';
7
7
  export { css_exports as css } from './chunk-6YPV2AB5.js';
8
8
  export { misc_exports as misc } from './chunk-GX7H6TAX.js';
@@ -13,7 +13,7 @@ export { hashing_exports as hashing } from './chunk-PET2CGTH.js';
13
13
  export { text_exports as text } from './chunk-QVOK3BXM.js';
14
14
  export { data_exports as data } from './chunk-XOUS3M5Z.js';
15
15
  export { generators_exports as generators } from './chunk-422ICOZX.js';
16
- export { time_exports as time } from './chunk-IEPWZERQ.js';
16
+ export { time_exports as time } from './chunk-6EJVNQSY.js';
17
17
  import './chunk-MLKGABMK.js';
18
18
 
19
19
  // src/index.ts
@@ -6,6 +6,7 @@
6
6
  * - date-diff : parseDate, humanizeDiff, diffDates, COMMON_DATE_PRESETS
7
7
  * - timezone : TIMEZONES, getTimezoneOffset, convertTime, formatInTimezone, getAllZonesForTime
8
8
  * - cron-next : parseCronExpression, getNextRuns, formatRunDate, getRunInterval
9
+ * - cron-overlap-detector : findCronOverlaps
9
10
  * - iso8601-duration : parseIso8601Duration, formatIso8601Duration
10
11
  */
11
12
  interface TimestampResult {
@@ -112,6 +113,22 @@ declare function getNextRuns(expr: string, count?: number, fromDate?: Date): Dat
112
113
  };
113
114
  declare function formatRunDate(date: Date, timezone?: string): string;
114
115
  declare function getRunInterval(dates: Date[]): string;
116
+ interface CronOverlap {
117
+ date: Date;
118
+ expressionIndexes: number[];
119
+ }
120
+ interface CronOverlapResult {
121
+ overlaps: CronOverlap[];
122
+ windowDays: number;
123
+ truncated: boolean;
124
+ }
125
+ /**
126
+ * Walk minute-by-minute over `windowDays` and flag every minute where two or
127
+ * more of the given 5-field cron expressions fire at once.
128
+ */
129
+ declare function findCronOverlaps(expressions: string[], windowDays?: number, fromDate?: Date): CronOverlapResult | {
130
+ error: string;
131
+ };
115
132
  interface DurationParseResult {
116
133
  input: string;
117
134
  years: number;
@@ -158,6 +175,8 @@ declare const time_COMMON_CRONS: typeof COMMON_CRONS;
158
175
  declare const time_COMMON_DATE_PRESETS: typeof COMMON_DATE_PRESETS;
159
176
  type time_CronField = CronField;
160
177
  type time_CronNextField = CronNextField;
178
+ type time_CronOverlap = CronOverlap;
179
+ type time_CronOverlapResult = CronOverlapResult;
161
180
  type time_CronResult = CronResult;
162
181
  type time_DateDiffResult = DateDiffResult;
163
182
  type time_DurationFormatResult = DurationFormatResult;
@@ -168,6 +187,7 @@ type time_TimestampResult = TimestampResult;
168
187
  type time_TimezoneEntry = TimezoneEntry;
169
188
  declare const time_convertTime: typeof convertTime;
170
189
  declare const time_diffDates: typeof diffDates;
190
+ declare const time_findCronOverlaps: typeof findCronOverlaps;
171
191
  declare const time_formatInTimezone: typeof formatInTimezone;
172
192
  declare const time_formatIso8601Duration: typeof formatIso8601Duration;
173
193
  declare const time_formatRelative: typeof formatRelative;
@@ -185,7 +205,7 @@ declare const time_parseCronExpression: typeof parseCronExpression;
185
205
  declare const time_parseDate: typeof parseDate;
186
206
  declare const time_parseIso8601Duration: typeof parseIso8601Duration;
187
207
  declare namespace time {
188
- export { time_COMMON_CRONS as COMMON_CRONS, time_COMMON_DATE_PRESETS as COMMON_DATE_PRESETS, type time_CronField as CronField, type time_CronNextField as CronNextField, type time_CronResult as CronResult, type time_DateDiffResult as DateDiffResult, type time_DurationFormatResult as DurationFormatResult, type time_DurationParseResult as DurationParseResult, type time_ParsedCron as ParsedCron, time_TIMEZONES as TIMEZONES, type time_TimestampResult as TimestampResult, type time_TimezoneEntry as TimezoneEntry, time_convertTime as convertTime, time_diffDates as diffDates, time_formatInTimezone as formatInTimezone, time_formatIso8601Duration as formatIso8601Duration, time_formatRelative as formatRelative, time_formatRunDate as formatRunDate, time_fromIsoString as fromIsoString, time_fromUnix as fromUnix, time_getAllZonesForTime as getAllZonesForTime, time_getNextRuns as getNextRuns, time_getNow as getNow, time_getRunInterval as getRunInterval, time_getTimezoneOffset as getTimezoneOffset, time_humanizeDiff as humanizeDiff, time_parseCron as parseCron, time_parseCronExpression as parseCronExpression, time_parseDate as parseDate, time_parseIso8601Duration as parseIso8601Duration };
208
+ export { time_COMMON_CRONS as COMMON_CRONS, time_COMMON_DATE_PRESETS as COMMON_DATE_PRESETS, type time_CronField as CronField, type time_CronNextField as CronNextField, type time_CronOverlap as CronOverlap, type time_CronOverlapResult as CronOverlapResult, type time_CronResult as CronResult, type time_DateDiffResult as DateDiffResult, type time_DurationFormatResult as DurationFormatResult, type time_DurationParseResult as DurationParseResult, type time_ParsedCron as ParsedCron, time_TIMEZONES as TIMEZONES, type time_TimestampResult as TimestampResult, type time_TimezoneEntry as TimezoneEntry, time_convertTime as convertTime, time_diffDates as diffDates, time_findCronOverlaps as findCronOverlaps, time_formatInTimezone as formatInTimezone, time_formatIso8601Duration as formatIso8601Duration, time_formatRelative as formatRelative, time_formatRunDate as formatRunDate, time_fromIsoString as fromIsoString, time_fromUnix as fromUnix, time_getAllZonesForTime as getAllZonesForTime, time_getNextRuns as getNextRuns, time_getNow as getNow, time_getRunInterval as getRunInterval, time_getTimezoneOffset as getTimezoneOffset, time_humanizeDiff as humanizeDiff, time_parseCron as parseCron, time_parseCronExpression as parseCronExpression, time_parseDate as parseDate, time_parseIso8601Duration as parseIso8601Duration };
189
209
  }
190
210
 
191
- export { parseIso8601Duration as A, COMMON_CRONS as C, type DateDiffResult as D, type ParsedCron as P, TIMEZONES as T, COMMON_DATE_PRESETS as a, type CronField as b, type CronNextField as c, type CronResult as d, type DurationFormatResult as e, type DurationParseResult as f, type TimestampResult as g, type TimezoneEntry as h, convertTime as i, diffDates as j, formatInTimezone as k, formatIso8601Duration as l, formatRelative as m, formatRunDate as n, fromIsoString as o, fromUnix as p, getAllZonesForTime as q, getNextRuns as r, getNow as s, time as t, getRunInterval as u, getTimezoneOffset as v, humanizeDiff as w, parseCron as x, parseCronExpression as y, parseDate as z };
211
+ export { parseCron as A, parseCronExpression as B, COMMON_CRONS as C, type DateDiffResult as D, parseDate as E, parseIso8601Duration as F, type ParsedCron as P, TIMEZONES as T, COMMON_DATE_PRESETS as a, type CronField as b, type CronNextField as c, type CronOverlap as d, type CronOverlapResult as e, type CronResult as f, type DurationFormatResult as g, type DurationParseResult as h, type TimestampResult as i, type TimezoneEntry as j, convertTime as k, diffDates as l, findCronOverlaps as m, formatInTimezone as n, formatIso8601Duration as o, formatRelative as p, formatRunDate as q, fromIsoString as r, fromUnix as s, time as t, getAllZonesForTime as u, getNextRuns as v, getNow as w, getRunInterval as x, getTimezoneOffset as y, humanizeDiff as z };
@@ -6,6 +6,7 @@
6
6
  * - date-diff : parseDate, humanizeDiff, diffDates, COMMON_DATE_PRESETS
7
7
  * - timezone : TIMEZONES, getTimezoneOffset, convertTime, formatInTimezone, getAllZonesForTime
8
8
  * - cron-next : parseCronExpression, getNextRuns, formatRunDate, getRunInterval
9
+ * - cron-overlap-detector : findCronOverlaps
9
10
  * - iso8601-duration : parseIso8601Duration, formatIso8601Duration
10
11
  */
11
12
  interface TimestampResult {
@@ -112,6 +113,22 @@ declare function getNextRuns(expr: string, count?: number, fromDate?: Date): Dat
112
113
  };
113
114
  declare function formatRunDate(date: Date, timezone?: string): string;
114
115
  declare function getRunInterval(dates: Date[]): string;
116
+ interface CronOverlap {
117
+ date: Date;
118
+ expressionIndexes: number[];
119
+ }
120
+ interface CronOverlapResult {
121
+ overlaps: CronOverlap[];
122
+ windowDays: number;
123
+ truncated: boolean;
124
+ }
125
+ /**
126
+ * Walk minute-by-minute over `windowDays` and flag every minute where two or
127
+ * more of the given 5-field cron expressions fire at once.
128
+ */
129
+ declare function findCronOverlaps(expressions: string[], windowDays?: number, fromDate?: Date): CronOverlapResult | {
130
+ error: string;
131
+ };
115
132
  interface DurationParseResult {
116
133
  input: string;
117
134
  years: number;
@@ -158,6 +175,8 @@ declare const time_COMMON_CRONS: typeof COMMON_CRONS;
158
175
  declare const time_COMMON_DATE_PRESETS: typeof COMMON_DATE_PRESETS;
159
176
  type time_CronField = CronField;
160
177
  type time_CronNextField = CronNextField;
178
+ type time_CronOverlap = CronOverlap;
179
+ type time_CronOverlapResult = CronOverlapResult;
161
180
  type time_CronResult = CronResult;
162
181
  type time_DateDiffResult = DateDiffResult;
163
182
  type time_DurationFormatResult = DurationFormatResult;
@@ -168,6 +187,7 @@ type time_TimestampResult = TimestampResult;
168
187
  type time_TimezoneEntry = TimezoneEntry;
169
188
  declare const time_convertTime: typeof convertTime;
170
189
  declare const time_diffDates: typeof diffDates;
190
+ declare const time_findCronOverlaps: typeof findCronOverlaps;
171
191
  declare const time_formatInTimezone: typeof formatInTimezone;
172
192
  declare const time_formatIso8601Duration: typeof formatIso8601Duration;
173
193
  declare const time_formatRelative: typeof formatRelative;
@@ -185,7 +205,7 @@ declare const time_parseCronExpression: typeof parseCronExpression;
185
205
  declare const time_parseDate: typeof parseDate;
186
206
  declare const time_parseIso8601Duration: typeof parseIso8601Duration;
187
207
  declare namespace time {
188
- export { time_COMMON_CRONS as COMMON_CRONS, time_COMMON_DATE_PRESETS as COMMON_DATE_PRESETS, type time_CronField as CronField, type time_CronNextField as CronNextField, type time_CronResult as CronResult, type time_DateDiffResult as DateDiffResult, type time_DurationFormatResult as DurationFormatResult, type time_DurationParseResult as DurationParseResult, type time_ParsedCron as ParsedCron, time_TIMEZONES as TIMEZONES, type time_TimestampResult as TimestampResult, type time_TimezoneEntry as TimezoneEntry, time_convertTime as convertTime, time_diffDates as diffDates, time_formatInTimezone as formatInTimezone, time_formatIso8601Duration as formatIso8601Duration, time_formatRelative as formatRelative, time_formatRunDate as formatRunDate, time_fromIsoString as fromIsoString, time_fromUnix as fromUnix, time_getAllZonesForTime as getAllZonesForTime, time_getNextRuns as getNextRuns, time_getNow as getNow, time_getRunInterval as getRunInterval, time_getTimezoneOffset as getTimezoneOffset, time_humanizeDiff as humanizeDiff, time_parseCron as parseCron, time_parseCronExpression as parseCronExpression, time_parseDate as parseDate, time_parseIso8601Duration as parseIso8601Duration };
208
+ export { time_COMMON_CRONS as COMMON_CRONS, time_COMMON_DATE_PRESETS as COMMON_DATE_PRESETS, type time_CronField as CronField, type time_CronNextField as CronNextField, type time_CronOverlap as CronOverlap, type time_CronOverlapResult as CronOverlapResult, type time_CronResult as CronResult, type time_DateDiffResult as DateDiffResult, type time_DurationFormatResult as DurationFormatResult, type time_DurationParseResult as DurationParseResult, type time_ParsedCron as ParsedCron, time_TIMEZONES as TIMEZONES, type time_TimestampResult as TimestampResult, type time_TimezoneEntry as TimezoneEntry, time_convertTime as convertTime, time_diffDates as diffDates, time_findCronOverlaps as findCronOverlaps, time_formatInTimezone as formatInTimezone, time_formatIso8601Duration as formatIso8601Duration, time_formatRelative as formatRelative, time_formatRunDate as formatRunDate, time_fromIsoString as fromIsoString, time_fromUnix as fromUnix, time_getAllZonesForTime as getAllZonesForTime, time_getNextRuns as getNextRuns, time_getNow as getNow, time_getRunInterval as getRunInterval, time_getTimezoneOffset as getTimezoneOffset, time_humanizeDiff as humanizeDiff, time_parseCron as parseCron, time_parseCronExpression as parseCronExpression, time_parseDate as parseDate, time_parseIso8601Duration as parseIso8601Duration };
189
209
  }
190
210
 
191
- export { parseIso8601Duration as A, COMMON_CRONS as C, type DateDiffResult as D, type ParsedCron as P, TIMEZONES as T, COMMON_DATE_PRESETS as a, type CronField as b, type CronNextField as c, type CronResult as d, type DurationFormatResult as e, type DurationParseResult as f, type TimestampResult as g, type TimezoneEntry as h, convertTime as i, diffDates as j, formatInTimezone as k, formatIso8601Duration as l, formatRelative as m, formatRunDate as n, fromIsoString as o, fromUnix as p, getAllZonesForTime as q, getNextRuns as r, getNow as s, time as t, getRunInterval as u, getTimezoneOffset as v, humanizeDiff as w, parseCron as x, parseCronExpression as y, parseDate as z };
211
+ export { parseCron as A, parseCronExpression as B, COMMON_CRONS as C, type DateDiffResult as D, parseDate as E, parseIso8601Duration as F, type ParsedCron as P, TIMEZONES as T, COMMON_DATE_PRESETS as a, type CronField as b, type CronNextField as c, type CronOverlap as d, type CronOverlapResult as e, type CronResult as f, type DurationFormatResult as g, type DurationParseResult as h, type TimestampResult as i, type TimezoneEntry as j, convertTime as k, diffDates as l, findCronOverlaps as m, formatInTimezone as n, formatIso8601Duration as o, formatRelative as p, formatRunDate as q, fromIsoString as r, fromUnix as s, time as t, getAllZonesForTime as u, getNextRuns as v, getNow as w, getRunInterval as x, getTimezoneOffset as y, humanizeDiff as z };
@@ -1801,6 +1801,111 @@ function normalizeRef(ref) {
1801
1801
  const tagPart = parsed.digest ? `@${parsed.digest}` : parsed.tag ? `:${parsed.tag}` : "";
1802
1802
  return `${parsed.registry}/${ns}${parsed.repository}${tagPart}`;
1803
1803
  }
1804
+ function _parseDockerfileInstructions(content) {
1805
+ const rawLines = content.replace(/\r\n/g, "\n").split("\n");
1806
+ const instructions = [];
1807
+ let buffer = "";
1808
+ let bufferStartLine = 0;
1809
+ for (let i = 0; i < rawLines.length; i++) {
1810
+ const lineNo = i + 1;
1811
+ const line = rawLines[i];
1812
+ const trimmed = line.trim();
1813
+ if (buffer === "") {
1814
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
1815
+ bufferStartLine = lineNo;
1816
+ buffer = line.trimEnd();
1817
+ } else {
1818
+ buffer += "\n" + line.trimEnd();
1819
+ }
1820
+ if (buffer.endsWith("\\")) {
1821
+ buffer = buffer.slice(0, -1);
1822
+ continue;
1823
+ }
1824
+ const match = buffer.trim().match(/^([A-Za-z]+)\s*([\s\S]*)$/);
1825
+ if (match) {
1826
+ instructions.push({ instruction: match[1].toUpperCase(), args: match[2].trim(), line: bufferStartLine });
1827
+ }
1828
+ buffer = "";
1829
+ }
1830
+ return instructions;
1831
+ }
1832
+ var _DOCKERFILE_TAR_RE = /\.(tar(\.(gz|bz2|xz))?|tgz|tbz2|txz)$/i;
1833
+ function lintDockerfile(content) {
1834
+ if (!content || !content.trim()) return { error: "Dockerfile content is required" };
1835
+ const instructions = _parseDockerfileInstructions(content);
1836
+ if (instructions.length === 0) return { error: "No Dockerfile instructions found" };
1837
+ const fromInstructions = instructions.filter((i) => i.instruction === "FROM");
1838
+ if (fromInstructions.length === 0) return { error: "No FROM instruction found; this does not look like a valid Dockerfile" };
1839
+ const stageNames = /* @__PURE__ */ new Set();
1840
+ const stages = fromInstructions.map((inst, idx) => {
1841
+ const asMatch = inst.args.match(/^(\S+)(?:\s+AS\s+(\S+))?/i);
1842
+ const baseImage = asMatch ? asMatch[1] : inst.args.split(/\s+/)[0];
1843
+ const name = asMatch && asMatch[2] ? asMatch[2] : null;
1844
+ if (name) stageNames.add(name.toLowerCase());
1845
+ return { index: idx, name, baseImage, fromLine: inst.line };
1846
+ });
1847
+ const findings = [];
1848
+ for (const stage of stages) {
1849
+ const base = stage.baseImage;
1850
+ if (base.toLowerCase() === "scratch") continue;
1851
+ if (stageNames.has(base.toLowerCase())) continue;
1852
+ const withoutDigest = base.split("@")[0];
1853
+ const hasTag = withoutDigest.includes(":");
1854
+ const tag = hasTag ? withoutDigest.split(":").pop() : null;
1855
+ if (!hasTag) {
1856
+ findings.push({
1857
+ rule: "unpinned-base-image",
1858
+ severity: "warning",
1859
+ line: stage.fromLine,
1860
+ message: `FROM ${base} has no tag, so it resolves to ":latest", which can silently change what gets built on a future run. Pin an explicit version tag instead.`
1861
+ });
1862
+ } else if (tag === "latest") {
1863
+ findings.push({
1864
+ rule: "unpinned-base-image",
1865
+ severity: "warning",
1866
+ line: stage.fromLine,
1867
+ message: `FROM ${base} is explicitly pinned to the "latest" tag, which is a moving target rather than a fixed version. Pin an explicit version tag instead.`
1868
+ });
1869
+ }
1870
+ }
1871
+ const finalStage = stages[stages.length - 1];
1872
+ const finalStageInstructions = instructions.filter((i) => i.line >= finalStage.fromLine);
1873
+ if (!finalStageInstructions.some((i) => i.instruction === "WORKDIR")) {
1874
+ findings.push({
1875
+ rule: "missing-workdir",
1876
+ severity: "warning",
1877
+ line: finalStage.fromLine,
1878
+ message: 'No WORKDIR instruction in the final stage, so RUN/CMD/ENTRYPOINT execute from "/" by default. Set an explicit WORKDIR.'
1879
+ });
1880
+ }
1881
+ if (!finalStageInstructions.some((i) => i.instruction === "USER")) {
1882
+ findings.push({
1883
+ rule: "running-as-root",
1884
+ severity: "warning",
1885
+ line: finalStage.fromLine,
1886
+ message: "No USER instruction in the final stage, so the container runs as root by default. Add a non-root USER unless root is genuinely required."
1887
+ });
1888
+ }
1889
+ for (const inst of instructions) {
1890
+ if (inst.instruction !== "ADD") continue;
1891
+ const parts = inst.args.split(/\s+/).filter(Boolean).filter((p) => !p.startsWith("--"));
1892
+ if (parts.length < 2) continue;
1893
+ const sources = parts.slice(0, -1);
1894
+ for (const src of sources) {
1895
+ const isUrl = /^https?:\/\//i.test(src);
1896
+ const isTar = _DOCKERFILE_TAR_RE.test(src);
1897
+ if (!isUrl && !isTar) {
1898
+ findings.push({
1899
+ rule: "add-vs-copy",
1900
+ severity: "info",
1901
+ line: inst.line,
1902
+ message: `ADD ${src} copies a local file/directory, not a URL or an auto-extracting archive. Use COPY instead, since ADD's extra behavior (remote fetch, tar auto-extract) doesn't apply here.`
1903
+ });
1904
+ }
1905
+ }
1906
+ }
1907
+ return { findings, stages };
1908
+ }
1804
1909
  function removeJsComments(code) {
1805
1910
  let result = "";
1806
1911
  let i = 0;
@@ -4295,6 +4400,7 @@ exports.getJsStats = getJsStats;
4295
4400
  exports.getMethodColor = getMethodColor;
4296
4401
  exports.isValidTag = isValidTag;
4297
4402
  exports.lintConventionalCommit = lintConventionalCommit;
4403
+ exports.lintDockerfile = lintDockerfile;
4298
4404
  exports.lookupMime = lookupMime;
4299
4405
  exports.minifyCss = minifyCss;
4300
4406
  exports.minifyGql = minifyGql;
@@ -1 +1 @@
1
- export { A as ALL_FLAGS, a as ApiEndpoint, b as ApiInfo, d as AriaIssue, e as AriaValidationResult, C as CHEATSHEET, f as CheatsheetEntry, g as CommitTrailer, h as CommitTrailerResult, i as ConnectionStringHost, j as ConnectionStringResult, k as ConventionalCommitFinding, l as ConventionalCommitFooter, m as ConventionalCommitOptions, n as ConventionalCommitParsed, o as ConventionalCommitResult, p as ConventionalCommitSeverity, q as CssResult, D as DEFAULT_COMMIT_TYPES, r as DependencyAuditDuplicate, s as DependencyAuditEntry, t as DependencyAuditIssue, u as DependencyAuditResult, v as DependencyRangeType, w as DependencySection, x as DockerImageRef, E as EditorConfigIssue, y as EditorConfigProperty, z as EditorConfigSection, B as EditorConfigValidationResult, F as EnvEntry, G as EnvParseResult, H as ExportsIssue, I as ExportsShape, J as ExportsValidationResult, K as FenceTagIssue, L as FenceTagIssueType, M as FenceValidationResult, N as GitCommandConfig, O as GitCommandResult, P as GitOperation, Q as GithubUrlInfo, R as GithubUrlType, S as GitignoreTestResult, T as GqlFormatResult, U as HtmlFormatResult, V as HtmlMinifyOptions, W as HtmlMinifyResult, X as JsMinifyOptions, Y as JsMinifyResult, Z as KNOWN_LANGUAGE_TAGS, _ as LinkReferenceDefinition, $ as LinkReferenceUsage, a0 as MIME_TABLE, a1 as MarkdownFootnoteDefinition, a2 as MarkdownFootnoteReference, a3 as MarkdownFootnoteResult, a4 as MarkdownLinkReferenceResult, a5 as MatchResult, a6 as MimeEntry, a7 as MimeLookupResult, a8 as OPERATIONS, a9 as ParsedSpec, aa as PlaceholderStyle, ab as RedosFinding, ac as RedosResult, ad as RedosSeverity, ae as RegexBackreferenceInfo, af as RegexError, ag as RegexFlag, ah as RegexGroupAnalysis, ai as RegexGroupInfo, aj as RegexGroupIssue, ak as RegexMatch, al as RegexResult, am as RegexSuccess, an as ResolvedLinkReference, ao as SQL_DEFAULT_OPTIONS, ap as Segment, aq as SpecVersion, ar as SqlDialect, as as SqlFormatOptions, at as SqlPlaceholder, au as SqlPlaceholderResult, av as SvgSpriteResult, aw as SvgSpriteSymbol, ax as TestPatternResult, ay as TsconfigIssue, az as TsconfigValidationResult, aA as analyzeRegexGroups, aB as auditDependencyRanges, aC as buildDockerPull, aD as buildDockerRun, aE as buildGitCommand, aF as collapseHtmlWhitespace, aG as collapseJsWhitespace, aH as countProperties, aI as countRules, aJ as countSqlPlaceholders, aK as detectDialect, aL as detectOperationType, aM as detectRedos, aN as envToExport, aO as envToJson, aP as extractMarkdownFootnotes, aQ as extractMarkdownLinkReferences, aR as extractSvgSpriteSymbols, aS as formatCss, aT as formatGql, aU as formatHtml, aV as formatSql, aW as getEndpointsByTag, aX as getHtmlStats, aY as getJsStats, aZ as getMethodColor, a_ as isValidTag, a$ as lintConventionalCommit, b0 as lookupMime, b1 as minifyCss, b2 as minifyGql, b3 as minifyHtml, b4 as minifyJs, b5 as minifySql, b6 as normalizeRef, b7 as parseCommitTrailers, b8 as parseConnectionString, b9 as parseDockerImage, ba as parseEnv, bb as parseGitCommand, bc as parseGithubUrl, bd as parseSpec, be as removeConsoleCalls, bf as removeEmptyAttributes, bg as removeHtmlComments, bh as removeJsComments, bi as removeRedundantAttributes, bj as searchCheatsheet, bk as searchEndpoints, bl as splitStatements, bm as testGitignorePatterns, bn as testPattern, bo as testRegex, bp as validateAria, bq as validateEditorConfig, br as validateEnvKey, bs as validateFenceLanguageTags, bt as validatePackageExports, bu as validateTsconfig } from '../code-COUhffgE.cjs';
1
+ export { A as ALL_FLAGS, a as ApiEndpoint, b as ApiInfo, d as AriaIssue, e as AriaValidationResult, C as CHEATSHEET, f as CheatsheetEntry, g as CommitTrailer, h as CommitTrailerResult, i as ConnectionStringHost, j as ConnectionStringResult, k as ConventionalCommitFinding, l as ConventionalCommitFooter, m as ConventionalCommitOptions, n as ConventionalCommitParsed, o as ConventionalCommitResult, p as ConventionalCommitSeverity, q as CssResult, D as DEFAULT_COMMIT_TYPES, r as DependencyAuditDuplicate, s as DependencyAuditEntry, t as DependencyAuditIssue, u as DependencyAuditResult, v as DependencyRangeType, w as DependencySection, x as DockerImageRef, y as DockerfileLintFinding, z as DockerfileLintResult, B as DockerfileStage, E as EditorConfigIssue, F as EditorConfigProperty, G as EditorConfigSection, H as EditorConfigValidationResult, I as EnvEntry, J as EnvParseResult, K as ExportsIssue, L as ExportsShape, M as ExportsValidationResult, N as FenceTagIssue, O as FenceTagIssueType, P as FenceValidationResult, Q as GitCommandConfig, R as GitCommandResult, S as GitOperation, T as GithubUrlInfo, U as GithubUrlType, V as GitignoreTestResult, W as GqlFormatResult, X as HtmlFormatResult, Y as HtmlMinifyOptions, Z as HtmlMinifyResult, _ as JsMinifyOptions, $ as JsMinifyResult, a0 as KNOWN_LANGUAGE_TAGS, a1 as LinkReferenceDefinition, a2 as LinkReferenceUsage, a3 as MIME_TABLE, a4 as MarkdownFootnoteDefinition, a5 as MarkdownFootnoteReference, a6 as MarkdownFootnoteResult, a7 as MarkdownLinkReferenceResult, a8 as MatchResult, a9 as MimeEntry, aa as MimeLookupResult, ab as OPERATIONS, ac as ParsedSpec, ad as PlaceholderStyle, ae as RedosFinding, af as RedosResult, ag as RedosSeverity, ah as RegexBackreferenceInfo, ai as RegexError, aj as RegexFlag, ak as RegexGroupAnalysis, al as RegexGroupInfo, am as RegexGroupIssue, an as RegexMatch, ao as RegexResult, ap as RegexSuccess, aq as ResolvedLinkReference, ar as SQL_DEFAULT_OPTIONS, as as Segment, at as SpecVersion, au as SqlDialect, av as SqlFormatOptions, aw as SqlPlaceholder, ax as SqlPlaceholderResult, ay as SvgSpriteResult, az as SvgSpriteSymbol, aA as TestPatternResult, aB as TsconfigIssue, aC as TsconfigValidationResult, aD as analyzeRegexGroups, aE as auditDependencyRanges, aF as buildDockerPull, aG as buildDockerRun, aH as buildGitCommand, aI as collapseHtmlWhitespace, aJ as collapseJsWhitespace, aK as countProperties, aL as countRules, aM as countSqlPlaceholders, aN as detectDialect, aO as detectOperationType, aP as detectRedos, aQ as envToExport, aR as envToJson, aS as extractMarkdownFootnotes, aT as extractMarkdownLinkReferences, aU as extractSvgSpriteSymbols, aV as formatCss, aW as formatGql, aX as formatHtml, aY as formatSql, aZ as getEndpointsByTag, a_ as getHtmlStats, a$ as getJsStats, b0 as getMethodColor, b1 as isValidTag, b2 as lintConventionalCommit, b3 as lintDockerfile, b4 as lookupMime, b5 as minifyCss, b6 as minifyGql, b7 as minifyHtml, b8 as minifyJs, b9 as minifySql, ba as normalizeRef, bb as parseCommitTrailers, bc as parseConnectionString, bd as parseDockerImage, be as parseEnv, bf as parseGitCommand, bg as parseGithubUrl, bh as parseSpec, bi as removeConsoleCalls, bj as removeEmptyAttributes, bk as removeHtmlComments, bl as removeJsComments, bm as removeRedundantAttributes, bn as searchCheatsheet, bo as searchEndpoints, bp as splitStatements, bq as testGitignorePatterns, br as testPattern, bs as testRegex, bt as validateAria, bu as validateEditorConfig, bv as validateEnvKey, bw as validateFenceLanguageTags, bx as validatePackageExports, by as validateTsconfig } from '../code-mkKV7BQ4.cjs';
@@ -1 +1 @@
1
- export { A as ALL_FLAGS, a as ApiEndpoint, b as ApiInfo, d as AriaIssue, e as AriaValidationResult, C as CHEATSHEET, f as CheatsheetEntry, g as CommitTrailer, h as CommitTrailerResult, i as ConnectionStringHost, j as ConnectionStringResult, k as ConventionalCommitFinding, l as ConventionalCommitFooter, m as ConventionalCommitOptions, n as ConventionalCommitParsed, o as ConventionalCommitResult, p as ConventionalCommitSeverity, q as CssResult, D as DEFAULT_COMMIT_TYPES, r as DependencyAuditDuplicate, s as DependencyAuditEntry, t as DependencyAuditIssue, u as DependencyAuditResult, v as DependencyRangeType, w as DependencySection, x as DockerImageRef, E as EditorConfigIssue, y as EditorConfigProperty, z as EditorConfigSection, B as EditorConfigValidationResult, F as EnvEntry, G as EnvParseResult, H as ExportsIssue, I as ExportsShape, J as ExportsValidationResult, K as FenceTagIssue, L as FenceTagIssueType, M as FenceValidationResult, N as GitCommandConfig, O as GitCommandResult, P as GitOperation, Q as GithubUrlInfo, R as GithubUrlType, S as GitignoreTestResult, T as GqlFormatResult, U as HtmlFormatResult, V as HtmlMinifyOptions, W as HtmlMinifyResult, X as JsMinifyOptions, Y as JsMinifyResult, Z as KNOWN_LANGUAGE_TAGS, _ as LinkReferenceDefinition, $ as LinkReferenceUsage, a0 as MIME_TABLE, a1 as MarkdownFootnoteDefinition, a2 as MarkdownFootnoteReference, a3 as MarkdownFootnoteResult, a4 as MarkdownLinkReferenceResult, a5 as MatchResult, a6 as MimeEntry, a7 as MimeLookupResult, a8 as OPERATIONS, a9 as ParsedSpec, aa as PlaceholderStyle, ab as RedosFinding, ac as RedosResult, ad as RedosSeverity, ae as RegexBackreferenceInfo, af as RegexError, ag as RegexFlag, ah as RegexGroupAnalysis, ai as RegexGroupInfo, aj as RegexGroupIssue, ak as RegexMatch, al as RegexResult, am as RegexSuccess, an as ResolvedLinkReference, ao as SQL_DEFAULT_OPTIONS, ap as Segment, aq as SpecVersion, ar as SqlDialect, as as SqlFormatOptions, at as SqlPlaceholder, au as SqlPlaceholderResult, av as SvgSpriteResult, aw as SvgSpriteSymbol, ax as TestPatternResult, ay as TsconfigIssue, az as TsconfigValidationResult, aA as analyzeRegexGroups, aB as auditDependencyRanges, aC as buildDockerPull, aD as buildDockerRun, aE as buildGitCommand, aF as collapseHtmlWhitespace, aG as collapseJsWhitespace, aH as countProperties, aI as countRules, aJ as countSqlPlaceholders, aK as detectDialect, aL as detectOperationType, aM as detectRedos, aN as envToExport, aO as envToJson, aP as extractMarkdownFootnotes, aQ as extractMarkdownLinkReferences, aR as extractSvgSpriteSymbols, aS as formatCss, aT as formatGql, aU as formatHtml, aV as formatSql, aW as getEndpointsByTag, aX as getHtmlStats, aY as getJsStats, aZ as getMethodColor, a_ as isValidTag, a$ as lintConventionalCommit, b0 as lookupMime, b1 as minifyCss, b2 as minifyGql, b3 as minifyHtml, b4 as minifyJs, b5 as minifySql, b6 as normalizeRef, b7 as parseCommitTrailers, b8 as parseConnectionString, b9 as parseDockerImage, ba as parseEnv, bb as parseGitCommand, bc as parseGithubUrl, bd as parseSpec, be as removeConsoleCalls, bf as removeEmptyAttributes, bg as removeHtmlComments, bh as removeJsComments, bi as removeRedundantAttributes, bj as searchCheatsheet, bk as searchEndpoints, bl as splitStatements, bm as testGitignorePatterns, bn as testPattern, bo as testRegex, bp as validateAria, bq as validateEditorConfig, br as validateEnvKey, bs as validateFenceLanguageTags, bt as validatePackageExports, bu as validateTsconfig } from '../code-COUhffgE.js';
1
+ export { A as ALL_FLAGS, a as ApiEndpoint, b as ApiInfo, d as AriaIssue, e as AriaValidationResult, C as CHEATSHEET, f as CheatsheetEntry, g as CommitTrailer, h as CommitTrailerResult, i as ConnectionStringHost, j as ConnectionStringResult, k as ConventionalCommitFinding, l as ConventionalCommitFooter, m as ConventionalCommitOptions, n as ConventionalCommitParsed, o as ConventionalCommitResult, p as ConventionalCommitSeverity, q as CssResult, D as DEFAULT_COMMIT_TYPES, r as DependencyAuditDuplicate, s as DependencyAuditEntry, t as DependencyAuditIssue, u as DependencyAuditResult, v as DependencyRangeType, w as DependencySection, x as DockerImageRef, y as DockerfileLintFinding, z as DockerfileLintResult, B as DockerfileStage, E as EditorConfigIssue, F as EditorConfigProperty, G as EditorConfigSection, H as EditorConfigValidationResult, I as EnvEntry, J as EnvParseResult, K as ExportsIssue, L as ExportsShape, M as ExportsValidationResult, N as FenceTagIssue, O as FenceTagIssueType, P as FenceValidationResult, Q as GitCommandConfig, R as GitCommandResult, S as GitOperation, T as GithubUrlInfo, U as GithubUrlType, V as GitignoreTestResult, W as GqlFormatResult, X as HtmlFormatResult, Y as HtmlMinifyOptions, Z as HtmlMinifyResult, _ as JsMinifyOptions, $ as JsMinifyResult, a0 as KNOWN_LANGUAGE_TAGS, a1 as LinkReferenceDefinition, a2 as LinkReferenceUsage, a3 as MIME_TABLE, a4 as MarkdownFootnoteDefinition, a5 as MarkdownFootnoteReference, a6 as MarkdownFootnoteResult, a7 as MarkdownLinkReferenceResult, a8 as MatchResult, a9 as MimeEntry, aa as MimeLookupResult, ab as OPERATIONS, ac as ParsedSpec, ad as PlaceholderStyle, ae as RedosFinding, af as RedosResult, ag as RedosSeverity, ah as RegexBackreferenceInfo, ai as RegexError, aj as RegexFlag, ak as RegexGroupAnalysis, al as RegexGroupInfo, am as RegexGroupIssue, an as RegexMatch, ao as RegexResult, ap as RegexSuccess, aq as ResolvedLinkReference, ar as SQL_DEFAULT_OPTIONS, as as Segment, at as SpecVersion, au as SqlDialect, av as SqlFormatOptions, aw as SqlPlaceholder, ax as SqlPlaceholderResult, ay as SvgSpriteResult, az as SvgSpriteSymbol, aA as TestPatternResult, aB as TsconfigIssue, aC as TsconfigValidationResult, aD as analyzeRegexGroups, aE as auditDependencyRanges, aF as buildDockerPull, aG as buildDockerRun, aH as buildGitCommand, aI as collapseHtmlWhitespace, aJ as collapseJsWhitespace, aK as countProperties, aL as countRules, aM as countSqlPlaceholders, aN as detectDialect, aO as detectOperationType, aP as detectRedos, aQ as envToExport, aR as envToJson, aS as extractMarkdownFootnotes, aT as extractMarkdownLinkReferences, aU as extractSvgSpriteSymbols, aV as formatCss, aW as formatGql, aX as formatHtml, aY as formatSql, aZ as getEndpointsByTag, a_ as getHtmlStats, a$ as getJsStats, b0 as getMethodColor, b1 as isValidTag, b2 as lintConventionalCommit, b3 as lintDockerfile, b4 as lookupMime, b5 as minifyCss, b6 as minifyGql, b7 as minifyHtml, b8 as minifyJs, b9 as minifySql, ba as normalizeRef, bb as parseCommitTrailers, bc as parseConnectionString, bd as parseDockerImage, be as parseEnv, bf as parseGitCommand, bg as parseGithubUrl, bh as parseSpec, bi as removeConsoleCalls, bj as removeEmptyAttributes, bk as removeHtmlComments, bl as removeJsComments, bm as removeRedundantAttributes, bn as searchCheatsheet, bo as searchEndpoints, bp as splitStatements, bq as testGitignorePatterns, br as testPattern, bs as testRegex, bt as validateAria, bu as validateEditorConfig, bv as validateEnvKey, bw as validateFenceLanguageTags, bx as validatePackageExports, by as validateTsconfig } from '../code-mkKV7BQ4.js';
@@ -1,2 +1,2 @@
1
- export { ALL_FLAGS, CHEATSHEET, DEFAULT_COMMIT_TYPES, KNOWN_LANGUAGE_TAGS, MIME_TABLE, OPERATIONS, SQL_DEFAULT_OPTIONS, analyzeRegexGroups, auditDependencyRanges, buildDockerPull, buildDockerRun, buildGitCommand, collapseHtmlWhitespace, collapseJsWhitespace, countProperties, countRules, countSqlPlaceholders, detectDialect, detectOperationType, detectRedos, envToExport, envToJson, extractMarkdownFootnotes, extractMarkdownLinkReferences, extractSvgSpriteSymbols, formatCss, formatGql, formatHtml, formatSql, getEndpointsByTag, getHtmlStats, getJsStats, getMethodColor, isValidTag, lintConventionalCommit, lookupMime, minifyCss, minifyGql, minifyHtml, minifyJs, minifySql, normalizeRef, parseCommitTrailers, parseConnectionString, parseDockerImage, parseEnv, parseGitCommand, parseGithubUrl, parseSpec, removeConsoleCalls, removeEmptyAttributes, removeHtmlComments, removeJsComments, removeRedundantAttributes, searchCheatsheet, searchEndpoints, splitStatements, testGitignorePatterns, testPattern, testRegex, validateAria, validateEditorConfig, validateEnvKey, validateFenceLanguageTags, validatePackageExports, validateTsconfig } from '../chunk-KXUHXQFO.js';
1
+ export { ALL_FLAGS, CHEATSHEET, DEFAULT_COMMIT_TYPES, KNOWN_LANGUAGE_TAGS, MIME_TABLE, OPERATIONS, SQL_DEFAULT_OPTIONS, analyzeRegexGroups, auditDependencyRanges, buildDockerPull, buildDockerRun, buildGitCommand, collapseHtmlWhitespace, collapseJsWhitespace, countProperties, countRules, countSqlPlaceholders, detectDialect, detectOperationType, detectRedos, envToExport, envToJson, extractMarkdownFootnotes, extractMarkdownLinkReferences, extractSvgSpriteSymbols, formatCss, formatGql, formatHtml, formatSql, getEndpointsByTag, getHtmlStats, getJsStats, getMethodColor, isValidTag, lintConventionalCommit, lintDockerfile, lookupMime, minifyCss, minifyGql, minifyHtml, minifyJs, minifySql, normalizeRef, parseCommitTrailers, parseConnectionString, parseDockerImage, parseEnv, parseGitCommand, parseGithubUrl, parseSpec, removeConsoleCalls, removeEmptyAttributes, removeHtmlComments, removeJsComments, removeRedundantAttributes, searchCheatsheet, searchEndpoints, splitStatements, testGitignorePatterns, testPattern, testRegex, validateAria, validateEditorConfig, validateEnvKey, validateFenceLanguageTags, validatePackageExports, validateTsconfig } from '../chunk-RMXZMYSG.js';
2
2
  import '../chunk-MLKGABMK.js';
@@ -659,6 +659,42 @@ function getRunInterval(dates) {
659
659
  const days = Math.round(diffMins / 1440);
660
660
  return `Every ${days} days`;
661
661
  }
662
+ var MAX_CRON_OVERLAPS = 200;
663
+ function findCronOverlaps(expressions, windowDays = 30, fromDate) {
664
+ if (expressions.length < 2) return { error: "Provide at least two cron expressions to check for overlaps" };
665
+ if (expressions.length > 10) return { error: "Provide 10 or fewer cron expressions" };
666
+ if (windowDays < 1 || windowDays > 365) return { error: "windowDays must be between 1 and 365" };
667
+ const parsedList = [];
668
+ for (let i = 0; i < expressions.length; i++) {
669
+ const parsed = parseCronExpression(expressions[i]);
670
+ if (typeof parsed === "object" && "error" in parsed) {
671
+ return { error: `Expression ${i + 1} ("${expressions[i]}"): ${parsed.error}` };
672
+ }
673
+ parsedList.push(parsed);
674
+ }
675
+ const start = fromDate ? new Date(fromDate) : /* @__PURE__ */ new Date();
676
+ const cursor = new Date(start);
677
+ cursor.setSeconds(0, 0);
678
+ cursor.setMinutes(cursor.getMinutes() + 1);
679
+ const endTime = cursor.getTime() + windowDays * 24 * 60 * 60 * 1e3;
680
+ const overlaps = [];
681
+ let truncated = false;
682
+ while (cursor.getTime() < endTime) {
683
+ const matched = [];
684
+ for (let i = 0; i < parsedList.length; i++) {
685
+ if (matchesCron(cursor, parsedList[i])) matched.push(i);
686
+ }
687
+ if (matched.length >= 2) {
688
+ if (overlaps.length >= MAX_CRON_OVERLAPS) {
689
+ truncated = true;
690
+ break;
691
+ }
692
+ overlaps.push({ date: new Date(cursor), expressionIndexes: matched });
693
+ }
694
+ cursor.setMinutes(cursor.getMinutes() + 1);
695
+ }
696
+ return { overlaps, windowDays, truncated };
697
+ }
662
698
  var DURATION_SECONDS_PER_YEAR = 365 * 86400;
663
699
  var DURATION_SECONDS_PER_MONTH = 30 * 86400;
664
700
  function humanizeDurationParts(parts) {
@@ -756,6 +792,7 @@ exports.COMMON_DATE_PRESETS = COMMON_DATE_PRESETS;
756
792
  exports.TIMEZONES = TIMEZONES;
757
793
  exports.convertTime = convertTime;
758
794
  exports.diffDates = diffDates;
795
+ exports.findCronOverlaps = findCronOverlaps;
759
796
  exports.formatInTimezone = formatInTimezone;
760
797
  exports.formatIso8601Duration = formatIso8601Duration;
761
798
  exports.formatRelative = formatRelative;
@@ -1 +1 @@
1
- export { C as COMMON_CRONS, a as COMMON_DATE_PRESETS, b as CronField, c as CronNextField, d as CronResult, D as DateDiffResult, e as DurationFormatResult, f as DurationParseResult, P as ParsedCron, T as TIMEZONES, g as TimestampResult, h as TimezoneEntry, i as convertTime, j as diffDates, k as formatInTimezone, l as formatIso8601Duration, m as formatRelative, n as formatRunDate, o as fromIsoString, p as fromUnix, q as getAllZonesForTime, r as getNextRuns, s as getNow, u as getRunInterval, v as getTimezoneOffset, w as humanizeDiff, x as parseCron, y as parseCronExpression, z as parseDate, A as parseIso8601Duration } from '../time-KqJjdqII.cjs';
1
+ export { C as COMMON_CRONS, a as COMMON_DATE_PRESETS, b as CronField, c as CronNextField, d as CronOverlap, e as CronOverlapResult, f as CronResult, D as DateDiffResult, g as DurationFormatResult, h as DurationParseResult, P as ParsedCron, T as TIMEZONES, i as TimestampResult, j as TimezoneEntry, k as convertTime, l as diffDates, m as findCronOverlaps, n as formatInTimezone, o as formatIso8601Duration, p as formatRelative, q as formatRunDate, r as fromIsoString, s as fromUnix, u as getAllZonesForTime, v as getNextRuns, w as getNow, x as getRunInterval, y as getTimezoneOffset, z as humanizeDiff, A as parseCron, B as parseCronExpression, E as parseDate, F as parseIso8601Duration } from '../time-VMAy_SrV.cjs';
@@ -1 +1 @@
1
- export { C as COMMON_CRONS, a as COMMON_DATE_PRESETS, b as CronField, c as CronNextField, d as CronResult, D as DateDiffResult, e as DurationFormatResult, f as DurationParseResult, P as ParsedCron, T as TIMEZONES, g as TimestampResult, h as TimezoneEntry, i as convertTime, j as diffDates, k as formatInTimezone, l as formatIso8601Duration, m as formatRelative, n as formatRunDate, o as fromIsoString, p as fromUnix, q as getAllZonesForTime, r as getNextRuns, s as getNow, u as getRunInterval, v as getTimezoneOffset, w as humanizeDiff, x as parseCron, y as parseCronExpression, z as parseDate, A as parseIso8601Duration } from '../time-KqJjdqII.js';
1
+ export { C as COMMON_CRONS, a as COMMON_DATE_PRESETS, b as CronField, c as CronNextField, d as CronOverlap, e as CronOverlapResult, f as CronResult, D as DateDiffResult, g as DurationFormatResult, h as DurationParseResult, P as ParsedCron, T as TIMEZONES, i as TimestampResult, j as TimezoneEntry, k as convertTime, l as diffDates, m as findCronOverlaps, n as formatInTimezone, o as formatIso8601Duration, p as formatRelative, q as formatRunDate, r as fromIsoString, s as fromUnix, u as getAllZonesForTime, v as getNextRuns, w as getNow, x as getRunInterval, y as getTimezoneOffset, z as humanizeDiff, A as parseCron, B as parseCronExpression, E as parseDate, F as parseIso8601Duration } from '../time-VMAy_SrV.js';
@@ -1,2 +1,2 @@
1
- export { COMMON_CRONS, COMMON_DATE_PRESETS, TIMEZONES, convertTime, diffDates, formatInTimezone, formatIso8601Duration, formatRelative, formatRunDate, fromIsoString, fromUnix, getAllZonesForTime, getNextRuns, getNow, getRunInterval, getTimezoneOffset, humanizeDiff, parseCron, parseCronExpression, parseDate, parseIso8601Duration } from '../chunk-IEPWZERQ.js';
1
+ export { COMMON_CRONS, COMMON_DATE_PRESETS, TIMEZONES, convertTime, diffDates, findCronOverlaps, formatInTimezone, formatIso8601Duration, formatRelative, formatRunDate, fromIsoString, fromUnix, getAllZonesForTime, getNextRuns, getNow, getRunInterval, getTimezoneOffset, humanizeDiff, parseCron, parseCronExpression, parseDate, parseIso8601Duration } from '../chunk-6EJVNQSY.js';
2
2
  import '../chunk-MLKGABMK.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilix-tech/sdk",
3
- "version": "0.83.0",
3
+ "version": "0.84.0",
4
4
  "description": "154+ developer utility tools for Node.js: JSON, encoding, hashing, color, CSS, network and more. Runs locally, no API key required.",
5
5
  "author": "Utilix <hello@utilix.tech>",
6
6
  "license": "MIT",