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