diff --git a/.eslintrc.js b/.eslintrc.js index 8c4e480df8..3fb76ef2a0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ /** @type {import('eslint').ESLint.ConfigData} */ module.exports = { extends: '@react-native-community', - plugins: ['prettier', 'jest'], + plugins: ['prettier', 'jest', 'jsdoc'], overrides: [ { // Jest Overrides @@ -27,6 +27,7 @@ module.exports = { }, ], rules: { + 'jsdoc/no-undefined-types': 'warn', 'prettier/prettier': 'error', 'prefer-const': 'error', }, diff --git a/CHANGELOG.md b/CHANGELOG.md index e37a26b421..8af89f22be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ - Adds symbol files upload script ([#1137](https://github.com/Instabug/Instabug-React-Native/pull/1137)) - Support enabling NDK crash capturing on Android ([#1132](https://github.com/Instabug/Instabug-React-Native/pull/1132)). +- Add support for App Flows APIs `APM.startFlow`, `APM.setFlowAttribute` and `APM.endFlow` ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). + +### Deprecated + +- Deprecate Execution Traces APIs `APM.startExecutionTrace`, `Trace.end` and `Trace.setAttribute` in favor of the new App Flows APIs ([#1138](https://github.com/Instabug/Instabug-React-Native/pull/1138)). ### Changed diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java index b594a13f9c..d7662c6536 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java @@ -4,6 +4,7 @@ import android.os.SystemClock; import android.util.Log; +import androidx.annotation.NonNull; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -29,6 +30,8 @@ public class RNInstabugAPMModule extends ReactContextBaseJavaModule { public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); } + + @Deprecated HashMap traces = new HashMap(); @Nonnull @@ -121,10 +124,92 @@ public void run() { }); } + /** + * Starts an AppFlow with the specified name. + *
+ * On starting two flows with the same name the older flow will end with force abandon end reason. + * AppFlow name cannot exceed 150 characters otherwise it's truncated, + * leading and trailing whitespaces are also ignored. + * + * @param name AppFlow name. It can not be empty string or null. + * Starts a new AppFlow, if APM is enabled, feature is enabled + * and Instabug SDK is initialised. + */ + @ReactMethod + public void startFlow(@NonNull final String name) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + APM.startFlow(name); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Sets custom attributes for AppFlow with a given name. + *
+ * Setting an attribute value to null will remove its corresponding key if it already exists. + *
+ * Attribute key name cannot exceed 30 characters. + * Leading and trailing whitespaces are also ignored. + * Does not accept empty strings or null. + *
+ * Attribute value name cannot exceed 60 characters, + * leading and trailing whitespaces are also ignored. + * Does not accept empty strings. + *
+ * If a trace is ended, attributes will not be added and existing ones will not be updated. + *
+ * + * @param name AppFlow name. It can not be empty string or null + * @param key AppFlow attribute key. It can not be empty string or null + * @param value AppFlow attribute value. It can not be empty string. Null to remove attribute + */ + @ReactMethod + public void setFlowAttribute(@NonNull final String name, @NonNull final String key, final String value) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + APM.setFlowAttribute(name, key, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Ends AppFlow with a given name. + * + * @param name AppFlow name to be ended. It can not be empty string or null + */ + @ReactMethod + public void endFlow(@NonNull final String name) { + MainThreadHandler.runOnMainThread(new Runnable() { + @Override + public void run() { + try { + APM.endFlow(name); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + /** * Starts an execution trace + * * @param name string name of the trace. + * + * @deprecated see {@link #startFlow(String)} */ + @Deprecated @ReactMethod public void startExecutionTrace(final String name, final String id, final Promise promise) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -148,10 +233,14 @@ public void run() { /** * Adds a new attribute to trace - * @param id String id of the trace. + * + * @param id String id of the trace. * @param key attribute key * @param value attribute value. Null to remove attribute + * + * @deprecated see {@link #setFlowAttribute} */ + @Deprecated @ReactMethod public void setExecutionTraceAttribute(final String id, final String key, final String value) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -168,8 +257,12 @@ public void run() { /** * Ends a trace + * * @param id string id of the trace. + * + * @deprecated see {@link #endFlow} */ + @Deprecated @ReactMethod public void endExecutionTrace(final String id) { MainThreadHandler.runOnMainThread(new Runnable() { diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java index e43dbb129a..5045f929e6 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java @@ -125,6 +125,37 @@ public void givenTruesetEnabled_whenQuery_thenShouldCallNativeApiWithEnabled() { verify(promise).resolve(any()); } + @Test + public void testStartFlow() { + String appFlowName = "appFlowName"; + + apmModule.startFlow(appFlowName); + + mockAPM.verify(() -> APM.startFlow(appFlowName)); + mockAPM.verifyNoMoreInteractions(); + } + + @Test + public void testEndFlow() { + String appFlowName = "appFlowName"; + + apmModule.endFlow(appFlowName); + + mockAPM.verify(() -> APM.endFlow(appFlowName)); + mockAPM.verifyNoMoreInteractions(); + } + + @Test + public void testSetFlowAttribute() { + String appFlowName = "appFlowName"; + String flowAttributeKey = "attributeKey"; + String flowAttributeValue = "attributeValue"; + apmModule.setFlowAttribute(appFlowName, flowAttributeKey, flowAttributeValue); + + mockAPM.verify(() -> APM.setFlowAttribute(appFlowName, flowAttributeKey, flowAttributeValue)); + mockAPM.verifyNoMoreInteractions(); + } + // @Test // public void givenString$setExecutionTraceAttribute_whenQuery_thenShouldCallNativeApiWithIntArgs() { // // given diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m index d476602c82..dd96841dea 100644 --- a/examples/default/ios/InstabugTests/InstabugAPMTests.m +++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m @@ -62,7 +62,7 @@ - (void) testSetAPMEnabled { - (void) testSetAppLaunchEnabled { id mock = OCMClassMock([IBGAPM class]); BOOL isEnabled = YES; - + OCMStub([mock setColdAppLaunchEnabled:isEnabled]); [self.instabugBridge setAppLaunchEnabled:isEnabled]; OCMVerify([mock setColdAppLaunchEnabled:isEnabled]); @@ -70,7 +70,7 @@ - (void) testSetAppLaunchEnabled { - (void) testEndAppLaunch { id mock = OCMClassMock([IBGAPM class]); - + OCMStub([mock endAppLaunch]); [self.instabugBridge endAppLaunch]; OCMVerify([mock endAppLaunch]); @@ -79,7 +79,7 @@ - (void) testEndAppLaunch { - (void) testSetAutoUITraceEnabled { id mock = OCMClassMock([IBGAPM class]); BOOL isEnabled = YES; - + OCMStub([mock setAutoUITraceEnabled:isEnabled]); [self.instabugBridge setAutoUITraceEnabled:isEnabled]; OCMVerify([mock setAutoUITraceEnabled:isEnabled]); @@ -91,7 +91,7 @@ - (void) testStartExecutionTrace { NSString* traceKey = @"1"; RCTPromiseResolveBlock resolve = ^(id result) {}; RCTPromiseRejectBlock reject = ^(NSString *code, NSString *message, NSError *error) {}; - + OCMStub([mock startExecutionTraceWithName:traceName]); [self.instabugBridge startExecutionTrace:traceName :traceKey :resolve :reject]; OCMVerify([mock startExecutionTraceWithName:traceName]); @@ -107,10 +107,10 @@ - (void) testSetExecutionTraceAttribute { IBGExecutionTrace * trace = [IBGExecutionTrace alloc]; id mock = OCMClassMock([IBGAPM class]); id traceMock = OCMPartialMock(trace); - + OCMStub([mock startExecutionTraceWithName:traceName]).andReturn(trace); [self.instabugBridge startExecutionTrace:traceName :traceId :resolve :reject]; - + OCMStub([traceMock setAttributeWithKey:traceKey value:traceValue]); [self.instabugBridge setExecutionTraceAttribute:traceId :traceKey :traceValue]; OCMVerify([traceMock setAttributeWithKey:traceKey value:traceValue]); @@ -127,16 +127,42 @@ - (void) testEndExecutionTrace { OCMStub([apmMock startExecutionTraceWithName:traceName]).andReturn(trace); [self.instabugBridge startExecutionTrace:traceName :traceId :resolve :reject]; - + OCMStub([traceMock end]); [self.instabugBridge endExecutionTrace:traceId]; OCMVerify([traceMock end]); } +- (void) testStartFlow { + id mock = OCMClassMock([IBGAPM class]); + NSString* appFlowName = @"APP_Flow_1"; + + [self.instabugBridge startFlow:appFlowName]; + OCMVerify([mock startFlowWithName:appFlowName]); +} + +- (void) testEndFlow { + id mock = OCMClassMock([IBGAPM class]); + NSString* appFlowName = @"APP_Flow_1"; + + [self.instabugBridge endFlow:appFlowName]; + OCMVerify([mock endFlowWithName:appFlowName]); +} + +- (void) testSetFlowAttribute { + id mock = OCMClassMock([IBGAPM class]); + NSString* appFlowName = @"APP_Flow_1"; + NSString* attributeKey = @"Attribute_Key_1"; + NSString* attributeValue = @"Attribute_Value_1"; + + [self.instabugBridge setFlowAttribute:appFlowName :attributeKey :attributeValue]; + OCMVerify([mock setAttributeForFlowWithName:appFlowName key:attributeKey value:attributeValue]); +} + - (void) testStartUITrace { id mock = OCMClassMock([IBGAPM class]); NSString* traceName = @"UITrace_1"; - + OCMStub([mock startUITraceWithName:traceName]); [self.instabugBridge startUITrace:traceName]; OCMVerify([mock startUITraceWithName:traceName]); @@ -144,7 +170,7 @@ - (void) testStartUITrace { - (void) testEndUITrace { id mock = OCMClassMock([IBGAPM class]); - + OCMStub([mock endUITrace]); [self.instabugBridge endUITrace]; OCMVerify([mock endUITrace]); diff --git a/ios/RNInstabug/InstabugAPMBridge.h b/ios/RNInstabug/InstabugAPMBridge.h index 30dec6a84d..b15788d50c 100644 --- a/ios/RNInstabug/InstabugAPMBridge.h +++ b/ios/RNInstabug/InstabugAPMBridge.h @@ -17,10 +17,13 @@ - (void)setAutoUITraceEnabled:(BOOL)isEnabled; - (void)startExecutionTrace:(NSString *)name :(NSString *)id :(RCTPromiseResolveBlock)resolve - :(RCTPromiseRejectBlock)reject; + :(RCTPromiseRejectBlock)reject DEPRECATED_MSG_ATTRIBUTE("Please use APM.startFlow instead."); - (void)setExecutionTraceAttribute:(NSString *)id:(NSString *)key - :(NSString *)value; -- (void)endExecutionTrace:(NSString *)id; + :(NSString *)value DEPRECATED_MSG_ATTRIBUTE("Please use APM.setTraceAttribute instead."); +- (void)endExecutionTrace:(NSString *)id DEPRECATED_MSG_ATTRIBUTE("Please use APM.endFlow instead."); +- (void)startFlow:(NSString *)name; +- (void)endFlow:(NSString *)name; +- (void)setFlowAttribute:(NSString *)name :(NSString *)key :(NSString *_Nullable)value; - (void)startUITrace:(NSString *)name; - (void)endUITrace; diff --git a/ios/RNInstabug/InstabugAPMBridge.m b/ios/RNInstabug/InstabugAPMBridge.m index f72e029d79..0324be4a8b 100644 --- a/ios/RNInstabug/InstabugAPMBridge.m +++ b/ios/RNInstabug/InstabugAPMBridge.m @@ -88,6 +88,19 @@ - (id) init } } +RCT_EXPORT_METHOD(startFlow: (NSString *)name) { + [IBGAPM startFlowWithName:name]; +} + +RCT_EXPORT_METHOD(endFlow: (NSString *)name) { + [IBGAPM endFlowWithName:name]; +} + + +RCT_EXPORT_METHOD(setFlowAttribute:(NSString *)name :(NSString *)key :(NSString *_Nullable)value) { + [IBGAPM setAttributeForFlowWithName:name key:key value:value]; +} + RCT_EXPORT_METHOD(startUITrace:(NSString *)name) { [IBGAPM startUITraceWithName:name]; } diff --git a/package.json b/package.json index c3824f3202..c48a5b596f 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "commander": "^11.0.0", "danger": "^11.2.5", "eslint": "^8.24.0", + "eslint-plugin-jsdoc": "^48.1.0", "eslint-plugin-prettier": "^5.0.0", "esprima": "^4.0.1", "form-data": "^4.0.0", diff --git a/src/models/Trace.ts b/src/models/Trace.ts index 6baa5aec29..19cd26d588 100644 --- a/src/models/Trace.ts +++ b/src/models/Trace.ts @@ -1,4 +1,5 @@ import { NativeAPM } from '../native/NativeAPM'; +import type * as APM from '../modules/APM'; export default class Trace { constructor( @@ -8,9 +9,12 @@ export default class Trace { ) {} /** - * Add an attribute with key and value to the Trace to be sent. - * @param key - * @param value + * Adds an attribute with a specified key and value to the Trace to be sent. + * + * @param key - The key of the attribute. + * @param value - The value of the attribute. + * + * @deprecated Please migrate to the App Flows APIs: {@link APM.startFlow}, {@link APM.endFlow}, and {@link APM.setFlowAttribute}. */ setAttribute(key: string, value: string) { NativeAPM.setExecutionTraceAttribute(this.id, key, value); @@ -18,8 +22,11 @@ export default class Trace { } /** - * End Execution Trace + * Ends the execution trace. + * + * @deprecated Please migrate to the App Flows APIs: {@link APM.startFlow}, {@link APM.endFlow}, and {@link APM.setFlowAttribute}. */ + end() { NativeAPM.endExecutionTrace(this.id); } diff --git a/src/modules/APM.ts b/src/modules/APM.ts index 44c5b4552f..664f4473cc 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -46,9 +46,14 @@ export const setAutoUITraceEnabled = (isEnabled: boolean) => { }; /** - * Starts a custom trace - * Returns a promise, the promise delivers the trace reference if APM is enabled, otherwise it gets rejected - * @param name + * Starts a custom execution trace. + * + * Returns a promise which resolves with the trace reference if APM is enabled; otherwise, the promise is rejected. + * + * @param name - The name of the trace to start. + * @returns A promise that resolves with a Trace object. + * + * @deprecated Please migrate to the App Flows APIs: {@link startFlow}, {@link endFlow}, and {@link setFlowAttribute}. */ export const startExecutionTrace = async (name: string): Promise => { const TRACE_NOT_STARTED_APM_NOT_ENABLED = `Execution trace "${name}" wasn't created. Please make sure to enable APM first by following the instructions at this link: https://docs.instabug.com/reference#enable-or-disable-apm`; @@ -63,6 +68,51 @@ export const startExecutionTrace = async (name: string): Promise => { return new Trace(id, name); }; +/** + * Starts an AppFlow with the specified name. + * + * On starting two flows with the same name, the older flow will end with a force abandon end reason. + * The AppFlow name cannot exceed 150 characters; otherwise, it's truncated, + * leading and trailing whitespaces are also ignored. + * + * @param name - The name of the AppFlow. It cannot be an empty string or null. + * A new AppFlow is started if APM is enabled, the feature is enabled, + * and the Instabug SDK is initialized. + */ +export const startFlow = (name: string) => { + NativeAPM.startFlow(name); +}; + +/** + * Ends an AppFlow with the given name. + * + * @param name - The name of the AppFlow to end. It cannot be an empty string or null. + */ +export const endFlow = (name: string) => { + NativeAPM.endFlow(name); +}; + +/** + * Sets custom attributes for an AppFlow with a given name. + * + * Setting an attribute value to null will remove the corresponding key if it already exists. + * Attribute keys cannot exceed 30 characters and leading/trailing whitespaces are ignored. + * Empty strings or null for attribute keys are not accepted. + * + * Attribute values cannot exceed 60 characters and leading/trailing whitespaces are ignored. + * Empty strings for attribute values are not accepted, but null can be used to remove an attribute. + * + * If an AppFlow is ended, attributes will not be added and existing ones will not be updated. + * + * @param name - The name of the AppFlow. It cannot be an empty string or null. + * @param key - The key of the attribute. It cannot be an empty string or null. + * @param [value] - The value of the attribute. It cannot be an empty string. Use null to remove the attribute. + */ + +export const setFlowAttribute = (name: string, key: string, value?: string | null) => { + NativeAPM.setFlowAttribute(name, key, value); +}; + /** * Starts a custom trace * @param name diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts index 26ba21e037..2c2121587c 100644 --- a/src/native/NativeAPM.ts +++ b/src/native/NativeAPM.ts @@ -18,6 +18,11 @@ export interface ApmNativeModule extends NativeModule { setExecutionTraceAttribute(id: string, key: string, value: string): void; endExecutionTrace(id: string): void; + // App Flows APIs // + startFlow(name: string): void; + endFlow(name: string): void; + setFlowAttribute(name: string, key: string, value?: string | null): void; + // UI Traces APIs // setAutoUITraceEnabled(isEnabled: boolean): void; startUITrace(name: string): void; diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index 77997be861..ca9dd297de 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -9,6 +9,9 @@ const mockAPM: ApmNativeModule = { startExecutionTrace: jest.fn(), setExecutionTraceAttribute: jest.fn(), endExecutionTrace: jest.fn(), + startFlow: jest.fn(), + setFlowAttribute: jest.fn(), + endFlow: jest.fn(), startUITrace: jest.fn(), endUITrace: jest.fn(), endAppLaunch: jest.fn(), diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index d416bcf93f..d11cadf32b 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -103,6 +103,39 @@ describe('APM Module', () => { }); }); + it('should call the native method startFlow', () => { + const appFlowName = 'flowName'; + + APM.startFlow(appFlowName); + + expect(NativeAPM.startFlow).toBeCalledTimes(1); + expect(NativeAPM.startFlow).toBeCalledWith(appFlowName); + }); + + it('should call the native method setFlowAttributes', () => { + const appFlowName = 'flowName'; + const flowAttributeKey = 'attributeKey'; + const flowAttributeValue = 'attributeValue'; + + APM.setFlowAttribute(appFlowName, flowAttributeKey, flowAttributeValue); + + expect(NativeAPM.setFlowAttribute).toBeCalledTimes(1); + expect(NativeAPM.setFlowAttribute).toBeCalledWith( + appFlowName, + flowAttributeKey, + flowAttributeValue, + ); + }); + + it('should call the native method endFlow', () => { + const appFlowName = 'flowName'; + + APM.endFlow(appFlowName); + + expect(NativeAPM.endFlow).toBeCalledTimes(1); + expect(NativeAPM.endFlow).toBeCalledWith(appFlowName); + }); + it('should call the native method startUITrace', () => { APM.startUITrace('uiTrace'); diff --git a/yarn.lock b/yarn.lock index 0d64f1d6ef..a7cc47ffaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -814,6 +814,15 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@es-joy/jsdoccomment@~0.42.0": + version "0.42.0" + resolved "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz#59e878708336aaee88c2b34c894f73dbf77ae2b0" + integrity sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw== + dependencies: + comment-parser "1.4.1" + esquery "^1.5.0" + jsdoc-type-pratt-parser "~4.0.0" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2128,6 +2137,11 @@ appdirsjs@^1.2.4: resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== +are-docs-informative@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" + integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2740,6 +2754,11 @@ commander@~2.13.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== +comment-parser@1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" + integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3222,6 +3241,21 @@ eslint-plugin-jest@^26.5.3: dependencies: "@typescript-eslint/utils" "^5.10.0" +eslint-plugin-jsdoc@^48.1.0: + version "48.1.0" + resolved "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.1.0.tgz#565363770b433485bfc70dc862b50b7f780529ec" + integrity sha512-g9S8ukmTd1DVcV/xeBYPPXOZ6rc8WJ4yi0+MVxJ1jBOrz5kmxV9gJJQ64ltCqIWFnBChLIhLVx3tbTSarqVyFA== + dependencies: + "@es-joy/jsdoccomment" "~0.42.0" + are-docs-informative "^0.0.2" + comment-parser "1.4.1" + debug "^4.3.4" + escape-string-regexp "^4.0.0" + esquery "^1.5.0" + is-builtin-module "^3.2.1" + semver "^7.6.0" + spdx-expression-parse "^4.0.0" + eslint-plugin-prettier@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" @@ -3359,7 +3393,7 @@ esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: +esquery@^1.4.2, esquery@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -4861,6 +4895,11 @@ jscodeshift@^0.14.0: temp "^0.8.4" write-file-atomic "^2.3.0" +jsdoc-type-pratt-parser@~4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" + integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6593,6 +6632,13 @@ semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6735,6 +6781,24 @@ sourcemap-codec@^1.4.8: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +spdx-exceptions@^2.1.0: + version "2.5.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== + +spdx-expression-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794" + integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.17" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"