@dereekb/firebase 13.35.0 → 13.37.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.
@@ -18078,6 +18078,500 @@ function _unsupported_iterable_to_array(o, minLen) {
18078
18078
  }
18079
18079
  };
18080
18080
 
18081
+ /**
18082
+ * Name of the `@dereekb/model` helper that expands an arktype definition to `T | null | undefined`.
18083
+ */ var CLEARABLE_FUNCTION_NAME = 'clearable';
18084
+ /**
18085
+ * Module that publishes {@link CLEARABLE_FUNCTION_NAME}.
18086
+ */ var CLEARABLE_IMPORT_MODULE = '@dereekb/model';
18087
+ /**
18088
+ * Identifier callees whose object-literal argument is an arktype definition (`type({ ... })`, `scope({ ... })`).
18089
+ */ var DEFAULT_ARKTYPE_DEFINITION_CALLEE_NAMES = [
18090
+ 'type',
18091
+ 'scope'
18092
+ ];
18093
+ /**
18094
+ * Arktype combinator methods that take an object-literal definition (`targetModelParamsType.merge({ ... })`).
18095
+ */ var DEFAULT_ARKTYPE_COMBINATOR_METHOD_NAMES = [
18096
+ 'merge',
18097
+ 'and',
18098
+ 'or',
18099
+ 'extend'
18100
+ ];
18101
+ /**
18102
+ * Method used to union an existing Type with another definition (`someType.or('null | undefined')`).
18103
+ */ var OR_METHOD_NAME = 'or';
18104
+ /**
18105
+ * The nullish arktype keywords {@link CLEARABLE_FUNCTION_NAME} appends to its definition.
18106
+ */ var NULLISH_KEYWORDS = new Set([
18107
+ 'null',
18108
+ 'undefined'
18109
+ ]);
18110
+ /**
18111
+ * Splits an arktype definition into its top-level `|` members, ignoring separators nested inside
18112
+ * quotes, parentheses, brackets, or braces (`${...}` template holes included).
18113
+ *
18114
+ * @param text - The definition text, without its surrounding quote/backtick delimiters.
18115
+ * @returns The union members in source order.
18116
+ */ function splitTopLevelUnion(text) {
18117
+ var members = [];
18118
+ var depth = 0;
18119
+ var quote = null;
18120
+ var start = 0;
18121
+ for(var i = 0; i < text.length; i += 1){
18122
+ var char = text[i];
18123
+ if (quote != null) {
18124
+ if (char === '\\') {
18125
+ i += 1;
18126
+ } else if (char === quote) {
18127
+ quote = null;
18128
+ }
18129
+ } else if (char === "'" || char === '"') {
18130
+ quote = char;
18131
+ } else if (char === '(' || char === '[' || char === '{') {
18132
+ depth += 1;
18133
+ } else if (char === ')' || char === ']' || char === '}') {
18134
+ depth -= 1;
18135
+ } else if (char === '|' && depth === 0) {
18136
+ members.push({
18137
+ text: text.slice(start, i),
18138
+ start: start
18139
+ });
18140
+ start = i + 1;
18141
+ }
18142
+ }
18143
+ members.push({
18144
+ text: text.slice(start),
18145
+ start: start
18146
+ });
18147
+ return members;
18148
+ }
18149
+ /**
18150
+ * Inspects an arktype definition for top-level `null` / `undefined` union members.
18151
+ *
18152
+ * @param text - The definition text, without its surrounding quote/backtick delimiters.
18153
+ * @returns The nullish members found and the definition text with a trailing nullish run removed.
18154
+ */ function splitNullishUnion(text) {
18155
+ var members = splitTopLevelUnion(text);
18156
+ var hasNull = false;
18157
+ var hasUndefined = false;
18158
+ var nullishIsSuffix = true;
18159
+ var firstNullishStart = null;
18160
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
18161
+ try {
18162
+ for(var _iterator = members[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
18163
+ var member = _step.value;
18164
+ var trimmed = member.text.trim();
18165
+ if (NULLISH_KEYWORDS.has(trimmed)) {
18166
+ hasNull = hasNull || trimmed === 'null';
18167
+ hasUndefined = hasUndefined || trimmed === 'undefined';
18168
+ if (firstNullishStart == null) {
18169
+ firstNullishStart = member.start;
18170
+ }
18171
+ } else if (firstNullishStart != null) {
18172
+ nullishIsSuffix = false;
18173
+ }
18174
+ }
18175
+ } catch (err) {
18176
+ _didIteratorError = true;
18177
+ _iteratorError = err;
18178
+ } finally{
18179
+ try {
18180
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
18181
+ _iterator.return();
18182
+ }
18183
+ } finally{
18184
+ if (_didIteratorError) {
18185
+ throw _iteratorError;
18186
+ }
18187
+ }
18188
+ }
18189
+ var base = firstNullishStart == null ? text : text.slice(0, firstNullishStart).replace(/[\s|]+$/, '');
18190
+ return {
18191
+ base: base,
18192
+ hasNull: hasNull,
18193
+ hasUndefined: hasUndefined,
18194
+ nullishIsSuffix: nullishIsSuffix
18195
+ };
18196
+ }
18197
+ /**
18198
+ * Returns true when the node is a string literal or a template literal — the two forms an arktype
18199
+ * definition string is written in.
18200
+ *
18201
+ * @param node - The property value node.
18202
+ * @returns True when the node is a definition string.
18203
+ */ function isDefinitionStringNode(node) {
18204
+ return (node === null || node === void 0 ? void 0 : node.type) === 'Literal' && typeof node.value === 'string' || (node === null || node === void 0 ? void 0 : node.type) === 'TemplateLiteral';
18205
+ }
18206
+ /**
18207
+ * Returns true when the callee is one an arktype object-literal definition is passed to.
18208
+ *
18209
+ * @param callee - The `CallExpression` callee node.
18210
+ * @param definitionCalleeNames - Identifier callee names (e.g. `type`).
18211
+ * @param combinatorMethodNames - Member-expression method names (e.g. `merge`).
18212
+ * @returns True when the call takes an arktype definition.
18213
+ */ function isArktypeDefinitionCallee(callee, definitionCalleeNames, combinatorMethodNames) {
18214
+ var _callee_property;
18215
+ var result = false;
18216
+ if ((callee === null || callee === void 0 ? void 0 : callee.type) === 'Identifier') {
18217
+ result = definitionCalleeNames.includes(callee.name);
18218
+ } else if ((callee === null || callee === void 0 ? void 0 : callee.type) === 'MemberExpression' && ((_callee_property = callee.property) === null || _callee_property === void 0 ? void 0 : _callee_property.type) === 'Identifier') {
18219
+ var _callee_object;
18220
+ // `someType.merge({ … })` / `type.enumerated({ … })`
18221
+ result = combinatorMethodNames.includes(callee.property.name) || ((_callee_object = callee.object) === null || _callee_object === void 0 ? void 0 : _callee_object.type) === 'Identifier' && definitionCalleeNames.includes(callee.object.name);
18222
+ }
18223
+ return result;
18224
+ }
18225
+ /**
18226
+ * Walks out of a property to the outermost object literal it belongs to and returns the arktype call
18227
+ * that literal is an argument of, or null when the property is not part of an arktype definition.
18228
+ *
18229
+ * Gating on the enclosing call keeps the rule off ordinary object literals that happen to hold a
18230
+ * `'… | null | undefined'` string, and off `clearable`'s own implementation.
18231
+ *
18232
+ * @param property - The `Property` node being checked.
18233
+ * @param definitionCalleeNames - Identifier callee names (e.g. `type`).
18234
+ * @param combinatorMethodNames - Member-expression method names (e.g. `merge`).
18235
+ * @returns The enclosing arktype `CallExpression`, or null.
18236
+ */ function arktypeDefinitionCallForProperty(property, definitionCalleeNames, combinatorMethodNames) {
18237
+ var current = property === null || property === void 0 ? void 0 : property.parent;
18238
+ var result = null;
18239
+ while(current != null){
18240
+ var parent = current.parent;
18241
+ if (current.type !== 'ObjectExpression') {
18242
+ current = null;
18243
+ } else if ((parent === null || parent === void 0 ? void 0 : parent.type) === 'Property') {
18244
+ current = parent.parent; // nested definition — climb to the enclosing object literal
18245
+ } else {
18246
+ if ((parent === null || parent === void 0 ? void 0 : parent.type) === 'CallExpression' && isArktypeDefinitionCallee(parent.callee, definitionCalleeNames, combinatorMethodNames)) {
18247
+ result = parent;
18248
+ }
18249
+ current = null;
18250
+ }
18251
+ }
18252
+ return result;
18253
+ }
18254
+ /**
18255
+ * Unwraps a `X.or('null').or('undefined')` / `X.or('null | undefined')` chain.
18256
+ *
18257
+ * @param node - The property value node.
18258
+ * @param sourceCode - The ESLint `SourceCode` object.
18259
+ * @returns The chain's receiver plus the nullish members it appends, or null when the node is not a nullish `.or(...)` chain.
18260
+ */ function unwrapNullishOrChain(node, sourceCode) {
18261
+ var current = node;
18262
+ var receiver = null;
18263
+ var hasNull = false;
18264
+ var hasUndefined = false;
18265
+ while(current != null){
18266
+ var _current_arguments, _callee_property;
18267
+ var callee = current.type === 'CallExpression' ? current.callee : null;
18268
+ var argument = current.type === 'CallExpression' && ((_current_arguments = current.arguments) === null || _current_arguments === void 0 ? void 0 : _current_arguments.length) === 1 ? current.arguments[0] : null;
18269
+ var isOrCall = (callee === null || callee === void 0 ? void 0 : callee.type) === 'MemberExpression' && ((_callee_property = callee.property) === null || _callee_property === void 0 ? void 0 : _callee_property.type) === 'Identifier' && callee.property.name === OR_METHOD_NAME;
18270
+ // only a wholly-nullish argument (`'null'`, `'undefined'`, `'null | undefined'`) is part of the chain
18271
+ var split = isOrCall && argument != null && isDefinitionStringNode(argument) ? splitNullishUnion(sourceCode.getText(argument).slice(1, -1)) : null;
18272
+ if ((split === null || split === void 0 ? void 0 : split.base.trim()) === '') {
18273
+ hasNull = hasNull || split.hasNull;
18274
+ hasUndefined = hasUndefined || split.hasUndefined;
18275
+ receiver = callee.object;
18276
+ current = receiver;
18277
+ } else {
18278
+ current = null;
18279
+ }
18280
+ }
18281
+ return receiver == null ? null : {
18282
+ receiver: receiver,
18283
+ hasNull: hasNull,
18284
+ hasUndefined: hasUndefined
18285
+ };
18286
+ }
18287
+ /**
18288
+ * Returns true when `name` is already bound at the top level of the program — imported, or declared
18289
+ * in the file itself (as it is inside `@dereekb/model`).
18290
+ *
18291
+ * @param programNode - The `Program` node.
18292
+ * @param name - The binding to look for.
18293
+ * @returns True when the name is already available.
18294
+ */ function hasTopLevelBinding(programNode, name) {
18295
+ var _ref;
18296
+ var body = (_ref = programNode === null || programNode === void 0 ? void 0 : programNode.body) !== null && _ref !== void 0 ? _ref : [];
18297
+ var result = false;
18298
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
18299
+ try {
18300
+ for(var _iterator = body[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
18301
+ var statement = _step.value;
18302
+ var declaration = (statement === null || statement === void 0 ? void 0 : statement.type) === 'ExportNamedDeclaration' ? statement.declaration : statement;
18303
+ if ((statement === null || statement === void 0 ? void 0 : statement.type) === 'ImportDeclaration') {
18304
+ var _statement_specifiers;
18305
+ result = result || ((_statement_specifiers = statement.specifiers) !== null && _statement_specifiers !== void 0 ? _statement_specifiers : []).some(function(specifier) {
18306
+ var _specifier_local;
18307
+ return (specifier === null || specifier === void 0 ? void 0 : (_specifier_local = specifier.local) === null || _specifier_local === void 0 ? void 0 : _specifier_local.name) === name;
18308
+ });
18309
+ } else if ((declaration === null || declaration === void 0 ? void 0 : declaration.type) === 'VariableDeclaration') {
18310
+ var _declaration_declarations;
18311
+ result = result || ((_declaration_declarations = declaration.declarations) !== null && _declaration_declarations !== void 0 ? _declaration_declarations : []).some(function(declarator) {
18312
+ var _declarator_id;
18313
+ return (declarator === null || declarator === void 0 ? void 0 : (_declarator_id = declarator.id) === null || _declarator_id === void 0 ? void 0 : _declarator_id.name) === name;
18314
+ });
18315
+ } else if ((declaration === null || declaration === void 0 ? void 0 : declaration.type) === 'FunctionDeclaration') {
18316
+ var _declaration_id;
18317
+ result = result || ((_declaration_id = declaration.id) === null || _declaration_id === void 0 ? void 0 : _declaration_id.name) === name;
18318
+ }
18319
+ }
18320
+ } catch (err) {
18321
+ _didIteratorError = true;
18322
+ _iteratorError = err;
18323
+ } finally{
18324
+ try {
18325
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
18326
+ _iterator.return();
18327
+ }
18328
+ } finally{
18329
+ if (_didIteratorError) {
18330
+ throw _iteratorError;
18331
+ }
18332
+ }
18333
+ }
18334
+ return result;
18335
+ }
18336
+ /**
18337
+ * ESLint rule that requires arktype model/params definitions to express a clearable field with
18338
+ * `clearable('TYPE')` rather than by unioning the nullish keywords inline
18339
+ * (`'TYPE | null | undefined'`) or by appending them with `.or(...)`.
18340
+ *
18341
+ * `clearable(...)` is the workspace's canonical spelling for the `Maybe<T>` fields on a params
18342
+ * interface: it names the semantic (`null` clears the field, `undefined` leaves it unchanged)
18343
+ * instead of restating the union at every property, and it is what the model-api validator's
18344
+ * `MAYBE_WITHOUT_CLEARABLE` check and the JSON Schema export helper both key off. An inline union
18345
+ * decodes the same way today but drifts from both.
18346
+ *
18347
+ * Only properties of an object literal passed to an arktype definition call (`type({ … })`,
18348
+ * `someType.merge({ … })`, …) are considered, so ordinary object literals — and `clearable`'s own
18349
+ * implementation — are left alone.
18350
+ *
18351
+ * The fix rewrites the property value and, when the helper is not already in scope, adds its import
18352
+ * (once per pass; the remaining properties are rewritten in the same pass alongside it). When no
18353
+ * import can be anchored the violation is reported without a fix rather than emitting a reference to
18354
+ * an unimported helper.
18355
+ *
18356
+ * @example
18357
+ * ```ts
18358
+ * // WARN — preferClearableDefinition
18359
+ * export const updateWidgetParamsType = type({
18360
+ * 'name?': 'string | null | undefined',
18361
+ * 'tags?': 'string[] | null | undefined'
18362
+ * });
18363
+ *
18364
+ * // WARN — preferClearableOrChain
18365
+ * export const publishWidgetParamsType = type({
18366
+ * 'entries?': widgetEntryParamsType.array().or('null | undefined')
18367
+ * });
18368
+ *
18369
+ * // OK
18370
+ * export const updateWidgetParamsType = type({
18371
+ * 'name?': clearable('string'),
18372
+ * 'tags?': clearable('string[]')
18373
+ * });
18374
+ * ```
18375
+ */ var FIREBASE_PREFER_CLEARABLE_ARKTYPE_RULE = {
18376
+ meta: {
18377
+ type: 'suggestion',
18378
+ fixable: 'code',
18379
+ docs: {
18380
+ description: 'Require `clearable(...)` from `@dereekb/model` for arktype definitions that union `null` / `undefined`, rather than spelling the nullish union inline.',
18381
+ recommended: true
18382
+ },
18383
+ messages: {
18384
+ preferClearableDefinition: 'Arktype definition `{{definition}}` unions the nullish keywords inline. Use `{{suggestion}}` instead — `{{helper}}(...)` from `{{module}}` is the canonical spelling for a clearable (`Maybe`) field.',
18385
+ preferClearableOrChain: 'Arktype definition `{{definition}}` appends the nullish keywords with `.or(...)`. Use `{{suggestion}}` instead — `{{helper}}(...)` from `{{module}}` is the canonical spelling for a clearable (`Maybe`) field.'
18386
+ },
18387
+ schema: [
18388
+ {
18389
+ type: 'object',
18390
+ additionalProperties: false,
18391
+ properties: {
18392
+ clearableFunctionName: {
18393
+ type: 'string'
18394
+ },
18395
+ importModule: {
18396
+ type: 'string'
18397
+ },
18398
+ autoImport: {
18399
+ type: 'boolean'
18400
+ },
18401
+ includeSingleNullish: {
18402
+ type: 'boolean'
18403
+ },
18404
+ definitionCalleeNames: {
18405
+ type: 'array',
18406
+ items: {
18407
+ type: 'string'
18408
+ }
18409
+ },
18410
+ combinatorMethodNames: {
18411
+ type: 'array',
18412
+ items: {
18413
+ type: 'string'
18414
+ }
18415
+ }
18416
+ }
18417
+ }
18418
+ ]
18419
+ },
18420
+ create: function create(context) {
18421
+ var _context_options_, _options_clearableFunctionName, _options_importModule, _options_definitionCalleeNames, _options_combinatorMethodNames;
18422
+ var options = (_context_options_ = context.options[0]) !== null && _context_options_ !== void 0 ? _context_options_ : {};
18423
+ var clearableName = (_options_clearableFunctionName = options.clearableFunctionName) !== null && _options_clearableFunctionName !== void 0 ? _options_clearableFunctionName : CLEARABLE_FUNCTION_NAME;
18424
+ var importModule = (_options_importModule = options.importModule) !== null && _options_importModule !== void 0 ? _options_importModule : CLEARABLE_IMPORT_MODULE;
18425
+ var autoImport = options.autoImport !== false;
18426
+ var includeSingleNullish = options.includeSingleNullish === true;
18427
+ var definitionCalleeNames = (_options_definitionCalleeNames = options.definitionCalleeNames) !== null && _options_definitionCalleeNames !== void 0 ? _options_definitionCalleeNames : DEFAULT_ARKTYPE_DEFINITION_CALLEE_NAMES;
18428
+ var combinatorMethodNames = (_options_combinatorMethodNames = options.combinatorMethodNames) !== null && _options_combinatorMethodNames !== void 0 ? _options_combinatorMethodNames : DEFAULT_ARKTYPE_COMBINATOR_METHOD_NAMES;
18429
+ var sourceCode = context.sourceCode;
18430
+ var programNode = null;
18431
+ var helperInScope = false;
18432
+ var importAnchored = false;
18433
+ var importFixUsed = false;
18434
+ /**
18435
+ * Returns the import declaration the helper's import is added to — an existing value import from
18436
+ * `importModule` when there is one, otherwise the file's last import (appended after).
18437
+ *
18438
+ * @returns The anchor import and whether the helper merges into its specifier list, or null when the file has no import to anchor to.
18439
+ */ function importAnchorFor() {
18440
+ var _ref;
18441
+ var imports = ((_ref = programNode === null || programNode === void 0 ? void 0 : programNode.body) !== null && _ref !== void 0 ? _ref : []).filter(function(statement) {
18442
+ return (statement === null || statement === void 0 ? void 0 : statement.type) === 'ImportDeclaration';
18443
+ });
18444
+ var mergeable = imports.find(function(statement) {
18445
+ var _statement_specifiers;
18446
+ var _statement_source;
18447
+ return ((_statement_source = statement.source) === null || _statement_source === void 0 ? void 0 : _statement_source.value) === importModule && statement.importKind !== 'type' && ((_statement_specifiers = statement.specifiers) !== null && _statement_specifiers !== void 0 ? _statement_specifiers : []).some(function(specifier) {
18448
+ return (specifier === null || specifier === void 0 ? void 0 : specifier.type) === 'ImportSpecifier';
18449
+ });
18450
+ });
18451
+ var result = null;
18452
+ if (mergeable != null) {
18453
+ result = {
18454
+ node: mergeable,
18455
+ merge: true
18456
+ };
18457
+ } else if (imports.length > 0) {
18458
+ result = {
18459
+ node: imports[imports.length - 1],
18460
+ merge: false
18461
+ };
18462
+ }
18463
+ return result;
18464
+ }
18465
+ /**
18466
+ * Builds the fix that brings the helper into scope, merging into an existing `importModule`
18467
+ * import when there is one.
18468
+ *
18469
+ * @param fixer - The ESLint fixer.
18470
+ * @returns The import fix, or null when no import can be anchored.
18471
+ */ function buildImportFix(fixer) {
18472
+ var anchor = importAnchorFor();
18473
+ var result = null;
18474
+ if ((anchor === null || anchor === void 0 ? void 0 : anchor.merge) === true) {
18475
+ var firstNamed = anchor.node.specifiers.find(function(specifier) {
18476
+ return (specifier === null || specifier === void 0 ? void 0 : specifier.type) === 'ImportSpecifier';
18477
+ });
18478
+ result = fixer.insertTextBefore(firstNamed, "".concat(clearableName, ", "));
18479
+ } else if (anchor != null) {
18480
+ result = fixer.insertTextAfter(anchor.node, "\nimport { ".concat(clearableName, " } from '").concat(importModule, "';"));
18481
+ }
18482
+ return result;
18483
+ }
18484
+ /**
18485
+ * Reports a definition, attaching the rewrite fix — plus the helper's import on the first report
18486
+ * of the pass — only when the result would compile.
18487
+ *
18488
+ * @param valueNode - The definition node to replace.
18489
+ * @param messageId - The message to report.
18490
+ * @param suggestion - The `clearable(...)` replacement text.
18491
+ */ function reportPreferClearable(valueNode, messageId, suggestion) {
18492
+ var data = {
18493
+ definition: sourceCode.getText(valueNode),
18494
+ suggestion: suggestion,
18495
+ helper: clearableName,
18496
+ module: importModule
18497
+ };
18498
+ if (helperInScope || importAnchored) {
18499
+ context.report({
18500
+ node: valueNode,
18501
+ messageId: messageId,
18502
+ data: data,
18503
+ fix: function fix(fixer) {
18504
+ var fixes = [
18505
+ fixer.replaceText(valueNode, suggestion)
18506
+ ];
18507
+ if (!helperInScope && !importFixUsed) {
18508
+ var importFix = buildImportFix(fixer);
18509
+ if (importFix != null) {
18510
+ importFixUsed = true;
18511
+ fixes.push(importFix);
18512
+ }
18513
+ }
18514
+ return fixes;
18515
+ }
18516
+ });
18517
+ } else {
18518
+ // no import can be anchored — reporting a fix here would reference an unimported helper
18519
+ context.report({
18520
+ node: valueNode,
18521
+ messageId: messageId,
18522
+ data: data
18523
+ });
18524
+ }
18525
+ }
18526
+ /**
18527
+ * Checks a string/template definition for an inline nullish union.
18528
+ *
18529
+ * @param valueNode - The definition node.
18530
+ */ function checkDefinitionString(valueNode) {
18531
+ var text = sourceCode.getText(valueNode);
18532
+ var delimiter = text.charAt(0);
18533
+ var split = splitNullishUnion(text.slice(1, -1));
18534
+ var bothNullish = split.hasNull && split.hasUndefined;
18535
+ var anyNullish = split.hasNull || split.hasUndefined;
18536
+ if ((bothNullish || includeSingleNullish && anyNullish) && split.nullishIsSuffix && split.base.trim() !== '') {
18537
+ reportPreferClearable(valueNode, 'preferClearableDefinition', "".concat(clearableName, "(").concat(delimiter).concat(split.base).concat(delimiter, ")"));
18538
+ }
18539
+ }
18540
+ /**
18541
+ * Checks a call expression for a nullish `.or(...)` chain.
18542
+ *
18543
+ * @param valueNode - The definition node.
18544
+ */ function checkOrChain(valueNode) {
18545
+ var chain = unwrapNullishOrChain(valueNode, sourceCode);
18546
+ if (chain != null) {
18547
+ var bothNullish = chain.hasNull && chain.hasUndefined;
18548
+ var anyNullish = chain.hasNull || chain.hasUndefined;
18549
+ if (bothNullish || includeSingleNullish && anyNullish) {
18550
+ reportPreferClearable(valueNode, 'preferClearableOrChain', "".concat(clearableName, "(").concat(sourceCode.getText(chain.receiver), ")"));
18551
+ }
18552
+ }
18553
+ }
18554
+ return {
18555
+ Program: function Program(node) {
18556
+ programNode = node;
18557
+ helperInScope = hasTopLevelBinding(node, clearableName);
18558
+ importFixUsed = false;
18559
+ importAnchored = autoImport && importAnchorFor() != null;
18560
+ },
18561
+ Property: function Property(node) {
18562
+ var valueNode = node === null || node === void 0 ? void 0 : node.value;
18563
+ if (valueNode != null && arktypeDefinitionCallForProperty(node, definitionCalleeNames, combinatorMethodNames) != null) {
18564
+ if (isDefinitionStringNode(valueNode)) {
18565
+ checkDefinitionString(valueNode);
18566
+ } else if (valueNode.type === 'CallExpression') {
18567
+ checkOrChain(valueNode);
18568
+ }
18569
+ }
18570
+ }
18571
+ };
18572
+ }
18573
+ };
18574
+
18081
18575
  /**
18082
18576
  * ESLint plugin for `@dereekb/firebase` rules.
18083
18577
  *
@@ -18101,7 +18595,8 @@ function _unsupported_iterable_to_array(o, minLen) {
18101
18595
  'require-canonical-api-spec-filename': FIREBASE_REQUIRE_CANONICAL_API_SPEC_FILENAME_RULE,
18102
18596
  'require-api-crud-spec-for-group': FIREBASE_REQUIRE_API_CRUD_SPEC_FOR_GROUP_RULE,
18103
18597
  'require-dbx-model-api-params-tag': FIREBASE_REQUIRE_DBX_MODEL_API_PARAMS_TAG_RULE,
18104
- 'require-use-model-roles': FIREBASE_REQUIRE_USE_MODEL_ROLES_RULE
18598
+ 'require-use-model-roles': FIREBASE_REQUIRE_USE_MODEL_ROLES_RULE,
18599
+ 'prefer-clearable-arktype': FIREBASE_PREFER_CLEARABLE_ARKTYPE_RULE
18105
18600
  }
18106
18601
  };
18107
18602
  /**
@@ -18111,10 +18606,14 @@ function _unsupported_iterable_to_array(o, minLen) {
18111
18606
  */ var firebaseESLintPlugin = FIREBASE_ESLINT_PLUGIN;
18112
18607
 
18113
18608
  exports.API_DETAILS_IMPORT_MODULE = API_DETAILS_IMPORT_MODULE;
18609
+ exports.CLEARABLE_FUNCTION_NAME = CLEARABLE_FUNCTION_NAME;
18610
+ exports.CLEARABLE_IMPORT_MODULE = CLEARABLE_IMPORT_MODULE;
18114
18611
  exports.DBX_MODEL_API_PARAMS_MARKER = DBX_MODEL_API_PARAMS_MARKER;
18115
18612
  exports.DBX_MODEL_FIREBASE_INDEX_MARKER = DBX_MODEL_FIREBASE_INDEX_MARKER;
18116
18613
  exports.DBX_MODEL_SERVICE_FACTORY_TAG = DBX_MODEL_SERVICE_FACTORY_TAG;
18117
18614
  exports.DEFAULT_API_DETAILS_FACTORY_NAME = DEFAULT_API_DETAILS_FACTORY_NAME;
18615
+ exports.DEFAULT_ARKTYPE_COMBINATOR_METHOD_NAMES = DEFAULT_ARKTYPE_COMBINATOR_METHOD_NAMES;
18616
+ exports.DEFAULT_ARKTYPE_DEFINITION_CALLEE_NAMES = DEFAULT_ARKTYPE_DEFINITION_CALLEE_NAMES;
18118
18617
  exports.DEFAULT_CONSTRAINT_FACTORY_NAMES = DEFAULT_CONSTRAINT_FACTORY_NAMES;
18119
18618
  exports.DEFAULT_CRUD_FUNCTIONS_CONFIG_SUFFIX = DEFAULT_CRUD_FUNCTIONS_CONFIG_SUFFIX;
18120
18619
  exports.DEFAULT_CRUD_FUNCTION_TYPE_VERBS = DEFAULT_CRUD_FUNCTION_TYPE_VERBS;
@@ -18138,6 +18637,7 @@ exports.FIREBASE_ESLINT_PLUGIN = FIREBASE_ESLINT_PLUGIN;
18138
18637
  exports.FIREBASE_MODEL_SERVICE_FACTORY_MODULE = FIREBASE_MODEL_SERVICE_FACTORY_MODULE;
18139
18638
  exports.FIREBASE_MODEL_SERVICE_FACTORY_NAME = FIREBASE_MODEL_SERVICE_FACTORY_NAME;
18140
18639
  exports.FIREBASE_MODULE = FIREBASE_MODULE;
18640
+ exports.FIREBASE_PREFER_CLEARABLE_ARKTYPE_RULE = FIREBASE_PREFER_CLEARABLE_ARKTYPE_RULE;
18141
18641
  exports.FIREBASE_REQUIRE_API_CRUD_SPEC_FOR_GROUP_RULE = FIREBASE_REQUIRE_API_CRUD_SPEC_FOR_GROUP_RULE;
18142
18642
  exports.FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE = FIREBASE_REQUIRE_API_DETAILS_FOR_CRUD_FUNCTION_RULE;
18143
18643
  exports.FIREBASE_REQUIRE_CANONICAL_API_SPEC_FILENAME_RULE = FIREBASE_REQUIRE_CANONICAL_API_SPEC_FILENAME_RULE;