@sqldoc/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,102 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+ import { tsImport } from '../ts-import.ts'
4
+ import { unwrapDefault } from '../utils.ts'
5
+ import type { ProjectConfig, ResolvedConfig, SqldocConfig } from './types.ts'
6
+
7
+ const CONFIG_FILENAMES = ['sqldoc.config.ts', 'sqldoc.config.js', 'sqldoc.config.mjs']
8
+
9
+ export interface ConfigResult {
10
+ config: SqldocConfig
11
+ configPath: string | null
12
+ }
13
+
14
+ /**
15
+ * Helper for creating typed sqldoc config.
16
+ * Used in sqldoc.config.ts: export default defineConfig({ ... })
17
+ * Accepts a single ProjectConfig or an array for multi-project.
18
+ */
19
+ export function defineConfig(config: SqldocConfig): SqldocConfig {
20
+ return config
21
+ }
22
+
23
+ /**
24
+ * Resolve a single project from the config.
25
+ *
26
+ * - If config is a single ProjectConfig, returns it directly
27
+ * (projectName must be undefined or match config.name)
28
+ * - If config is an array, requires projectName to select one
29
+ * - Throws with available project names on mismatch
30
+ */
31
+ export function resolveProject(config: SqldocConfig, projectName?: string): ResolvedConfig {
32
+ // Single project config
33
+ if (!Array.isArray(config)) {
34
+ if (projectName && config.name && config.name !== projectName) {
35
+ throw new Error(`Project "${projectName}" not found. Available: ${config.name}`)
36
+ }
37
+ return config
38
+ }
39
+
40
+ // Multi-project config
41
+ const names = config.map((p) => p.name).filter(Boolean)
42
+
43
+ if (projectName) {
44
+ const found = config.find((p) => p.name === projectName)
45
+ if (!found) {
46
+ throw new Error(`Project "${projectName}" not found. Available: ${names.join(', ')}`)
47
+ }
48
+ return found
49
+ }
50
+
51
+ // No --project specified
52
+ if (config.length === 1) {
53
+ return config[0]
54
+ }
55
+
56
+ throw new Error(`Multiple projects configured. Use --project <name> or --all.\nAvailable: ${names.join(', ')}`)
57
+ }
58
+
59
+ /**
60
+ * Resolve all projects from the config.
61
+ * Returns an array regardless of single/multi config.
62
+ */
63
+ export function resolveAllProjects(config: SqldocConfig): ProjectConfig[] {
64
+ return Array.isArray(config) ? config : [config]
65
+ }
66
+
67
+ /**
68
+ * Load a config file by exact path using tsx.
69
+ */
70
+ async function loadConfigFile(configPath: string): Promise<ConfigResult> {
71
+ const abs = path.resolve(configPath)
72
+ let mod = (await tsImport(abs)) as any
73
+ // Unwrap ESM default exports (CJS compat can double-wrap)
74
+ // Detect both single config (has namespaces/dialect/schema) and arrays
75
+ mod = unwrapDefault(mod, (m: any) => !!m.namespaces || !!m.dialect || !!m.schema || Array.isArray(m))
76
+ const config: SqldocConfig = mod ?? { dialect: 'postgres' }
77
+ return { config, configPath: abs }
78
+ }
79
+
80
+ /**
81
+ * Load sqldoc config.
82
+ * If configFile is provided, loads that exact file.
83
+ * Otherwise searches projectRoot for sqldoc.config.{ts,js,mjs}.
84
+ * Returns default config if no config file found.
85
+ */
86
+ export async function loadConfig(projectRoot: string, configFile?: string): Promise<ConfigResult> {
87
+ if (configFile) {
88
+ const resolved = path.resolve(configFile)
89
+ if (!fs.existsSync(resolved)) {
90
+ throw new Error(`Config file not found: ${resolved}`)
91
+ }
92
+ return loadConfigFile(resolved)
93
+ }
94
+
95
+ for (const filename of CONFIG_FILENAMES) {
96
+ const configPath = path.resolve(projectRoot, filename)
97
+ if (!fs.existsSync(configPath)) continue
98
+ return loadConfigFile(configPath)
99
+ }
100
+
101
+ return { config: { dialect: 'postgres' } as ProjectConfig, configPath: null }
102
+ }
@@ -0,0 +1,29 @@
1
+ export type { CompileOptions } from './compile.ts'
2
+ export { compile } from './compile.ts'
3
+ export type { ConfigResult } from './config.ts'
4
+ export { defineConfig, loadConfig, resolveAllProjects, resolveProject } from './config.ts'
5
+ export type {
6
+ CodeOutput,
7
+ CompilerContext,
8
+ CompilerOutput,
9
+ DocsMeta,
10
+ LintConfig,
11
+ LintContext,
12
+ LintDiagnostic,
13
+ LintResult,
14
+ LintRule,
15
+ LintSeverity,
16
+ MigrationFormat,
17
+ MigrationNaming,
18
+ NamespaceConfig,
19
+ NamespacePlugin,
20
+ ProjectCompilerContext,
21
+ ProjectConfig,
22
+ ProjectContext,
23
+ ProjectOutput,
24
+ ResolvedConfig,
25
+ SqldocConfig,
26
+ SqlOutput,
27
+ TagContext,
28
+ TagOutput,
29
+ } from './types.ts'
@@ -0,0 +1,320 @@
1
+ import type { SqlStatement } from '../ast/types.ts'
2
+ import type { SqlTarget, TagNamespace } from '../types.ts'
3
+
4
+ // ── Project config ──────────────────────────────────────────────────
5
+
6
+ /** Migration file format — determines how up/down scripts are read and written */
7
+ export type MigrationFormat = 'atlas' | 'golang-migrate' | 'goose' | 'flyway' | 'dbmate' | 'plain'
8
+
9
+ /** File naming strategy for generated migration files */
10
+ export type MigrationNaming = 'timestamp' | 'sequential' | { provider: 'claude-code' }
11
+
12
+ /** A single project configuration */
13
+ export interface ProjectConfig {
14
+ /** Project name (required for multi-project, optional for single) */
15
+ name?: string
16
+ /** Schema source: file or directory of SQL files with sqldoc tags */
17
+ schema?: string
18
+ /** SQL dialect — mandatory */
19
+ dialect: 'postgres' | 'mysql' | 'sqlite'
20
+ /** Dev database URL. Default: pglite */
21
+ devUrl?: string
22
+ /** Migration settings */
23
+ migrations?: {
24
+ /** Directory containing migration files */
25
+ dir: string
26
+ /** Migration file format. Default: 'plain' */
27
+ format?: MigrationFormat
28
+ /** File naming strategy. Default: 'timestamp' */
29
+ naming?: MigrationNaming
30
+ }
31
+ /** Namespace plugin configuration */
32
+ namespaces?: Record<string, unknown>
33
+ /** Lint configuration */
34
+ lint?: LintConfig
35
+
36
+ // ── Legacy fields (backward compat) ──
37
+ /** @deprecated Use `schema` instead. Glob patterns for SQL source files */
38
+ include?: string[]
39
+ /** Output directory for generated SQL */
40
+ sqlOutDir?: string
41
+ /** Output directory for generated code artifacts */
42
+ codeOutDir?: string
43
+ }
44
+
45
+ /** Config can be a single project or array of projects */
46
+ export type SqldocConfig = ProjectConfig | ProjectConfig[]
47
+
48
+ /**
49
+ * Resolved single-project config — always a single ProjectConfig.
50
+ * Used internally after resolving --project/--all flags.
51
+ */
52
+ export type ResolvedConfig = ProjectConfig
53
+
54
+ /** Generic constraint for per-namespace config */
55
+ export type NamespaceConfig = Record<string, unknown>
56
+
57
+ // ── Tag context ────────────────────────────────────────────────────
58
+
59
+ /** Rich context passed to onTag for each tag occurrence */
60
+ export interface TagContext {
61
+ /** The SQL object this tag is attached to */
62
+ target: SqlTarget
63
+ /** Name of the SQL object (table name, function name, etc.) */
64
+ objectName: string
65
+ /** Column name when target is 'column' */
66
+ columnName?: string
67
+ /** Column data type when target is 'column' */
68
+ columnType?: string
69
+ /** The parsed tag that triggered this handler */
70
+ tag: {
71
+ name: string | null
72
+ args: Record<string, unknown> | unknown[]
73
+ }
74
+ /** All tags from the same namespace on the same SQL object */
75
+ namespaceTags: Array<{
76
+ tag: string | null
77
+ args: Record<string, unknown> | unknown[]
78
+ }>
79
+ /** All tags from ALL namespaces on the same SQL object (sibling introspection) */
80
+ siblingTags: Array<{
81
+ namespace: string
82
+ tag: string | null
83
+ args: Record<string, unknown> | unknown[]
84
+ }>
85
+ /** All tags across the entire file, grouped by SQL object */
86
+ fileTags: Array<{
87
+ objectName: string
88
+ target: SqlTarget
89
+ tags: Array<{
90
+ namespace: string
91
+ tag: string | null
92
+ args: Record<string, unknown> | unknown[]
93
+ }>
94
+ }>
95
+ /** The full AST statement for the SQL object */
96
+ astNode: unknown
97
+ /** All parsed SQL statements in the file */
98
+ fileStatements: SqlStatement[]
99
+ /** This namespace's config from sqldoc.config.ts */
100
+ config: NamespaceConfig
101
+ /** The source SQL file path */
102
+ filePath: string
103
+ /** Atlas-parsed table schema for this object (Tier 2 only, undefined in Tier 1) */
104
+ atlasTable?: unknown
105
+ /** Atlas-parsed column info (Tier 2 only, when target is 'column') */
106
+ atlasColumn?: unknown
107
+ /** Full Atlas realm with all schemas, tables, views (Tier 2 only) */
108
+ atlasRealm?: unknown
109
+ }
110
+
111
+ /** @deprecated Use TagContext instead */
112
+ export type CompilerContext = TagContext
113
+
114
+ /** Context for afterCompile hook — receives ALL compiled file data */
115
+ export interface ProjectContext {
116
+ /** All compiled file outputs */
117
+ outputs: CompilerOutput[]
118
+ /** The merged SQL from all files combined */
119
+ mergedSql: string
120
+ /** All tags across all files, grouped by file then by object */
121
+ allFileTags: Array<{
122
+ sourceFile: string
123
+ objects: Array<{
124
+ objectName: string
125
+ target: SqlTarget
126
+ tags: Array<{
127
+ namespace: string
128
+ tag: string | null
129
+ args: Record<string, unknown> | unknown[]
130
+ }>
131
+ }>
132
+ }>
133
+ /** Aggregated docs metadata from all plugins across all files */
134
+ docsMeta: DocsMeta[]
135
+ /** This namespace's config from sqldoc.config.ts */
136
+ config: NamespaceConfig
137
+ /** Project root directory */
138
+ projectRoot: string
139
+ /** Atlas-parsed schema realm (Tier 2, when available) */
140
+ atlasRealm?: unknown
141
+ }
142
+
143
+ /** @deprecated Use ProjectContext instead */
144
+ export type ProjectCompilerContext = ProjectContext
145
+
146
+ /** Output from an afterCompile hook */
147
+ export interface ProjectOutput {
148
+ /** Files to write (path relative to project root + content) */
149
+ files: Array<{
150
+ filePath: string
151
+ content: string
152
+ }>
153
+ }
154
+
155
+ // ── Docs metadata ──────────────────────────────────────────────────
156
+
157
+ /** Documentation metadata that plugins can return alongside SQL from onTag */
158
+ export interface DocsMeta {
159
+ /** Extra relationships to show in ER diagrams (e.g. audit trail arrows) */
160
+ relationships?: Array<{
161
+ from: string
162
+ to: string
163
+ label: string
164
+ style?: 'dashed'
165
+ }>
166
+ /** Table-level annotations (e.g. "RLS enabled", "Audited") */
167
+ annotations?: Array<{
168
+ object: string
169
+ text: string
170
+ }>
171
+ /**
172
+ * Extra doc columns contributed by plugins.
173
+ * If ANY plugin adds a column with a given header, that column appears on ALL tables.
174
+ * Each entry targets a specific table+column with a cell value.
175
+ */
176
+ columns?: Array<{
177
+ /** Column header name (e.g. "Validation", "RLS", "Anonymization") */
178
+ header: string
179
+ /** Table this cell applies to */
180
+ object: string
181
+ /** DB column name this cell applies to (omit for table-level row) */
182
+ column?: string
183
+ /** Cell value text */
184
+ value: string
185
+ }>
186
+ }
187
+
188
+ /** Return type from onTag — SQL statements + optional docs metadata */
189
+ export interface TagOutput {
190
+ sql?: SqlOutput[]
191
+ docs?: DocsMeta
192
+ }
193
+
194
+ // ── Compiler outputs ────────────────────────────────────────────────
195
+
196
+ /** A single SQL statement produced by a namespace */
197
+ export interface SqlOutput {
198
+ /** The SQL statement text (e.g., "ALTER TABLE users ENABLE ROW LEVEL SECURITY;") */
199
+ sql: string
200
+ /** Optional comment for clarity in output */
201
+ comment?: string
202
+ /** Source tag that produced this output (set by compiler, not by plugins) */
203
+ sourceTag?: string
204
+ }
205
+
206
+ /** A non-SQL file produced by a namespace */
207
+ export interface CodeOutput {
208
+ /** Relative file path for the output (e.g., "types/users.ts") */
209
+ filePath: string
210
+ /** File content */
211
+ content: string
212
+ }
213
+
214
+ /** Combined output from compiling one file */
215
+ export interface CompilerOutput {
216
+ /** Source SQL file path */
217
+ sourceFile: string
218
+ /** Complete SQL: original source with generated statements appended */
219
+ mergedSql: string
220
+ /** Individual SQL statements produced by namespaces (for inspection) */
221
+ sqlOutputs: SqlOutput[]
222
+ /** Code files to write */
223
+ codeOutputs: CodeOutput[]
224
+ /** Errors encountered during compilation */
225
+ errors: Array<{ namespace: string; message: string }>
226
+ /** Documentation metadata collected from all plugins */
227
+ docsMeta: DocsMeta[]
228
+ /** Per-file tag summary for project-level aggregation */
229
+ fileTags: Array<{
230
+ objectName: string
231
+ target: SqlTarget
232
+ tags: Array<{
233
+ namespace: string
234
+ tag: string | null
235
+ args: Record<string, unknown> | unknown[]
236
+ }>
237
+ }>
238
+ }
239
+
240
+ // ── Lint types ──────────────────────────────────────────────────────
241
+
242
+ /** Severity levels for lint rules */
243
+ export type LintSeverity = 'error' | 'warn' | 'off'
244
+
245
+ /** A lint rule defined by a namespace plugin */
246
+ export interface LintRule {
247
+ /** Full rule name: namespace.ruleName (e.g. "audit.require-audit") */
248
+ name: string
249
+ /** Human-readable description of what this rule checks */
250
+ description: string
251
+ /** Default severity when not overridden in config */
252
+ default: LintSeverity
253
+ /** Check function — receives the full lint context and returns diagnostics */
254
+ check: (ctx: LintContext) => LintDiagnostic[]
255
+ }
256
+
257
+ /** Context passed to lint rule check functions */
258
+ export interface LintContext {
259
+ /** All compiled file outputs */
260
+ outputs: CompilerOutput[]
261
+ /** All loaded plugins, keyed by namespace name */
262
+ plugins: Map<string, NamespacePlugin>
263
+ /** Project config (resolved single project) */
264
+ config: ResolvedConfig
265
+ }
266
+
267
+ /** A single lint diagnostic produced by a rule */
268
+ export interface LintDiagnostic {
269
+ /** The SQL object this diagnostic relates to (table name, etc.) */
270
+ objectName: string
271
+ /** Source file path */
272
+ sourceFile: string
273
+ /** Human-readable message */
274
+ message: string
275
+ }
276
+
277
+ /** A lint result after applying severity and ignore processing */
278
+ export interface LintResult {
279
+ /** Rule that produced this result */
280
+ ruleName: string
281
+ /** Effective severity (after config override, 'skip' if @lint.ignore suppressed) */
282
+ severity: LintSeverity | 'skip'
283
+ /** The SQL object name */
284
+ objectName: string
285
+ /** Source file path */
286
+ sourceFile: string
287
+ /** Human-readable message */
288
+ message: string
289
+ /** Ignore reason (when severity is 'skip') */
290
+ ignoreReason?: string
291
+ }
292
+
293
+ /** Lint config section in sqldoc.config.ts */
294
+ export interface LintConfig {
295
+ rules?: Record<string, LintSeverity>
296
+ }
297
+
298
+ // ── Namespace plugin contract ───────────────────────────────────────
299
+
300
+ /** Stable type contract for namespace packages. Extends TagNamespace with compiler hooks. */
301
+ export interface NamespacePlugin extends TagNamespace {
302
+ /** API version for forward compatibility. Must be 1 for v1. */
303
+ apiVersion: 1
304
+ /** JSON Schema or Zod-like descriptor for namespace config (optional). Reserved for future validation. */
305
+ configSchema?: unknown
306
+ /** Called for each tag occurrence — returns SQL statements and/or docs metadata */
307
+ onTag?: (ctx: TagContext) => SqlOutput[] | TagOutput | undefined
308
+ /** Generate non-SQL code artifacts for a tag occurrence */
309
+ generateCode?: (ctx: TagContext) => CodeOutput[] | undefined
310
+ /** Runs once after all per-file compilation completes — project-level aggregation */
311
+ afterCompile?: (ctx: ProjectContext) => Promise<ProjectOutput> | ProjectOutput
312
+ /** Lint rules defined by this plugin */
313
+ lintRules?: LintRule[]
314
+
315
+ // Deprecated aliases — will be removed in v2
316
+ /** @deprecated Use onTag instead */
317
+ generateSQL?: (ctx: TagContext) => SqlOutput[] | TagOutput | undefined
318
+ /** @deprecated Use afterCompile instead */
319
+ generateProject?: (ctx: ProjectContext) => Promise<ProjectOutput> | ProjectOutput
320
+ }
package/src/index.ts ADDED
@@ -0,0 +1,72 @@
1
+ // Types
2
+
3
+ export type { SqlAstAdapter, SqlColumn, SqlCommentOn, SqlStatement } from './ast/index.ts'
4
+ // AST Adapters
5
+ export { SqlparserTsAdapter } from './ast/index.ts'
6
+ // Blocks
7
+ export { buildBlocks } from './blocks.ts'
8
+ export type {
9
+ CodeOutput,
10
+ CompileOptions,
11
+ CompilerContext,
12
+ // CompilerContext is deprecated alias for TagContext
13
+ CompilerOutput,
14
+ ConfigResult,
15
+ DocsMeta,
16
+ LintConfig,
17
+ LintContext,
18
+ LintDiagnostic,
19
+ LintResult,
20
+ LintRule,
21
+ LintSeverity,
22
+ MigrationFormat,
23
+ MigrationNaming,
24
+ NamespaceConfig,
25
+ NamespacePlugin,
26
+ ProjectCompilerContext, // ProjectCompilerContext is deprecated alias
27
+ ProjectConfig,
28
+ ProjectContext,
29
+ ProjectOutput,
30
+ ResolvedConfig,
31
+ SqldocConfig,
32
+ SqlOutput,
33
+ TagContext,
34
+ TagOutput,
35
+ } from './compiler/index.ts'
36
+ // Compiler
37
+ export { compile, defineConfig, loadConfig, resolveAllProjects, resolveProject } from './compiler/index.ts'
38
+ // Lint engine
39
+ export { lint } from './lint.ts'
40
+ export type { ImportError, LoadResult } from './loader.ts'
41
+ // Loader
42
+ export { loadImports, setImportLogger } from './loader.ts'
43
+ export type { ArgValue, ImportStatement, ParsedArgs, ParsedTag, ParseResult } from './parser.ts'
44
+ // Parser
45
+ export { parse, parseArgs } from './parser.ts'
46
+
47
+ // TS import helper
48
+ export { tsImport } from './ts-import.ts'
49
+ export type {
50
+ ArgType,
51
+ ArrayType,
52
+ BooleanType,
53
+ EnumType,
54
+ InferArgType,
55
+ InferSchema,
56
+ NamedArgs,
57
+ NamespaceDef,
58
+ NoArgs,
59
+ NumberType,
60
+ PositionalArgs,
61
+ SqlTarget,
62
+ StringType,
63
+ TagArgs,
64
+ TagDef,
65
+ TagNamespace,
66
+ ValidationContext,
67
+ } from './types.ts'
68
+ // Shared utilities
69
+ export { findSqldocDir, unwrapDefault } from './utils.ts'
70
+ export type { AstInfo, Diagnostic } from './validator.ts'
71
+ // Validator
72
+ export { detectTarget, detectTargetFallback, validate } from './validator.ts'
package/src/lint.ts ADDED
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Lint engine — collects lint rules from all loaded plugins, runs them
3
+ * against compiled output, respects @lint.ignore tags, and applies
4
+ * severity overrides from config.
5
+ */
6
+
7
+ import type { CompilerOutput, LintContext, LintResult, NamespacePlugin, ResolvedConfig } from './compiler/types.ts'
8
+
9
+ /** Parsed @lint.ignore tag */
10
+ interface LintIgnore {
11
+ /** Rule name to ignore (e.g. "audit.require-audit") */
12
+ ruleName: string
13
+ /** Mandatory reason for suppression */
14
+ reason: string
15
+ /** SQL object name this ignore applies to */
16
+ objectName: string
17
+ /** Source file */
18
+ sourceFile: string
19
+ }
20
+
21
+ /**
22
+ * Run all lint rules from loaded plugins against compiled outputs.
23
+ *
24
+ * Collects lintRules from every plugin, runs each rule's check function,
25
+ * applies severity overrides from config.lint.rules, and respects
26
+ * @lint.ignore tags found in file tags.
27
+ */
28
+ export function lint(
29
+ outputs: CompilerOutput[],
30
+ plugins: Map<string, NamespacePlugin>,
31
+ config: ResolvedConfig,
32
+ ): LintResult[] {
33
+ const results: LintResult[] = []
34
+ const lintConfig = config.lint ?? {}
35
+ const ruleOverrides = lintConfig.rules ?? {}
36
+
37
+ // 1. Collect all lint rules from plugins
38
+ const allRules = collectRules(plugins)
39
+
40
+ // 2. Collect all @lint.ignore tags from outputs
41
+ const ignores = collectIgnores(outputs)
42
+
43
+ // 3. Build lint context
44
+ const ctx: LintContext = { outputs, plugins, config }
45
+
46
+ // 4. Run each rule
47
+ for (const rule of allRules) {
48
+ // Determine effective severity
49
+ const effectiveSeverity = ruleOverrides[rule.name] ?? rule.default
50
+ if (effectiveSeverity === 'off') continue
51
+
52
+ // Run the check
53
+ const diagnostics = rule.check(ctx)
54
+
55
+ for (const diag of diagnostics) {
56
+ // Check if this diagnostic is suppressed by @lint.ignore
57
+ const ignore = ignores.find(
58
+ (ig) => ig.ruleName === rule.name && ig.objectName === diag.objectName && ig.sourceFile === diag.sourceFile,
59
+ )
60
+
61
+ if (ignore) {
62
+ results.push({
63
+ ruleName: rule.name,
64
+ severity: 'skip',
65
+ objectName: diag.objectName,
66
+ sourceFile: diag.sourceFile,
67
+ message: diag.message,
68
+ ignoreReason: ignore.reason,
69
+ })
70
+ } else {
71
+ results.push({
72
+ ruleName: rule.name,
73
+ severity: effectiveSeverity,
74
+ objectName: diag.objectName,
75
+ sourceFile: diag.sourceFile,
76
+ message: diag.message,
77
+ })
78
+ }
79
+ }
80
+ }
81
+
82
+ return results
83
+ }
84
+
85
+ /** Collect all lint rules from all plugins */
86
+ function collectRules(plugins: Map<string, NamespacePlugin>) {
87
+ const rules = []
88
+ for (const plugin of plugins.values()) {
89
+ if (plugin.lintRules) {
90
+ rules.push(...plugin.lintRules)
91
+ }
92
+ }
93
+ return rules
94
+ }
95
+
96
+ /** Collect @lint.ignore tags from compiled outputs' fileTags */
97
+ function collectIgnores(outputs: CompilerOutput[]): LintIgnore[] {
98
+ const ignores: LintIgnore[] = []
99
+
100
+ for (const output of outputs) {
101
+ for (const obj of output.fileTags) {
102
+ for (const tag of obj.tags) {
103
+ if (tag.namespace === 'lint' && tag.tag === 'ignore') {
104
+ const args = tag.args
105
+ let ruleName: string | undefined
106
+ let reason: string | undefined
107
+
108
+ if (Array.isArray(args)) {
109
+ ruleName = args[0] as string | undefined
110
+ reason = args[1] as string | undefined
111
+ }
112
+
113
+ if (ruleName && reason) {
114
+ ignores.push({
115
+ ruleName,
116
+ reason,
117
+ objectName: obj.objectName,
118
+ sourceFile: output.sourceFile,
119
+ })
120
+ }
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ return ignores
127
+ }