Merge branch 'frappe:develop' into develop

This commit is contained in:
Manuel 2021-09-27 09:25:08 +02:00 committed by GitHub
commit ecdd2e55dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 339 additions and 373 deletions

View file

@ -102,7 +102,7 @@ def get_commands():
from .site import commands as site_commands
from .translate import commands as translate_commands
from .utils import commands as utils_commands
from .redis import commands as redis_commands
from .redis_utils import commands as redis_commands
clickable_link = (
"\x1b]8;;https://frappeframework.com/docs\afrappeframework.com\x1b]8;;\a"

View file

@ -3,7 +3,7 @@ import os
import click
import frappe
from frappe.utils.rq import RedisQueue
from frappe.utils.redis_queue import RedisQueue
from frappe.installer import update_site_config
@click.command('create-rq-users')

View file

@ -178,4 +178,4 @@ def set_link_title(doc):
for link in doc.links:
if not link.link_title:
linked_doc = frappe.get_doc(link.link_doctype, link.link_name)
link.link_title = linked_doc.get("title_field") or linked_doc.get("name")
link.link_title = linked_doc.get_title() or link.link_name

View file

@ -1,238 +1,80 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-01-10 16:34:24",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 0,
"actions": [],
"allow_copy": 1,
"creation": "2013-01-10 16:34:24",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"sms_gateway_url",
"message_parameter",
"receiver_parameter",
"static_parameters_section",
"parameters",
"use_post"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Eg. smsgateway.com/api/send_sms.cgi",
"fieldname": "sms_gateway_url",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "SMS Gateway URL",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"description": "Eg. smsgateway.com/api/send_sms.cgi",
"fieldname": "sms_gateway_url",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "SMS Gateway URL",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Enter url parameter for message",
"fieldname": "message_parameter",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Message Parameter",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"description": "Enter url parameter for message",
"fieldname": "message_parameter",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Message Parameter",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Enter url parameter for receiver nos",
"fieldname": "receiver_parameter",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Receiver Parameter",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"description": "Enter url parameter for receiver nos",
"fieldname": "receiver_parameter",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Receiver Parameter",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "static_parameters_section",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"fieldname": "static_parameters_section",
"fieldtype": "Column Break",
"width": "50%"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)",
"fieldname": "parameters",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Static Parameters",
"length": 0,
"no_copy": 0,
"options": "SMS Parameter",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"description": "Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)",
"fieldname": "parameters",
"fieldtype": "Table",
"label": "Static Parameters",
"options": "SMS Parameter"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "use_post",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Use POST",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"default": "0",
"fieldname": "use_post",
"fieldtype": "Check",
"label": "Use POST"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-cog",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2021-03-02 18:06:00.868688",
"modified_by": "Administrator",
"module": "Core",
"name": "SMS Settings",
"owner": "Administrator",
],
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
"links": [],
"modified": "2021-09-21 19:45:26.809793",
"modified_by": "Administrator",
"module": "Core",
"name": "SMS Settings",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View file

@ -22,11 +22,11 @@ class MariaDBDatabase(Database):
def setup_type_map(self):
self.db_type = 'mariadb'
self.type_map = {
'Currency': ('decimal', '18,6'),
'Currency': ('decimal', '21,9'),
'Int': ('int', '11'),
'Long Int': ('bigint', '20'),
'Float': ('decimal', '18,6'),
'Percent': ('decimal', '18,6'),
'Float': ('decimal', '21,9'),
'Percent': ('decimal', '21,9'),
'Check': ('int', '1'),
'Small Text': ('text', ''),
'Long Text': ('longtext', ''),
@ -51,7 +51,7 @@ class MariaDBDatabase(Database):
'Color': ('varchar', self.VARCHAR_LEN),
'Barcode': ('longtext', ''),
'Geolocation': ('longtext', ''),
'Duration': ('decimal', '18,6'),
'Duration': ('decimal', '21,9'),
'Icon': ('varchar', self.VARCHAR_LEN)
}

View file

@ -32,11 +32,11 @@ class PostgresDatabase(Database):
def setup_type_map(self):
self.db_type = 'postgres'
self.type_map = {
'Currency': ('decimal', '18,6'),
'Currency': ('decimal', '21,9'),
'Int': ('bigint', None),
'Long Int': ('bigint', None),
'Float': ('decimal', '18,6'),
'Percent': ('decimal', '18,6'),
'Float': ('decimal', '21,9'),
'Percent': ('decimal', '21,9'),
'Check': ('smallint', None),
'Small Text': ('text', ''),
'Long Text': ('text', ''),
@ -61,7 +61,7 @@ class PostgresDatabase(Database):
'Color': ('varchar', self.VARCHAR_LEN),
'Barcode': ('text', ''),
'Geolocation': ('text', ''),
'Duration': ('decimal', '18,6'),
'Duration': ('decimal', '21,9'),
'Icon': ('varchar', self.VARCHAR_LEN)
}

View file

@ -303,6 +303,8 @@ def get_definition(fieldtype, precision=None, length=None):
size = d[1] if d[1] else None
if size:
# This check needs to exist for backward compatibility.
# Till V13, default size used for float, currency and percent are (18, 6).
if fieldtype in ["Float", "Currency", "Percent"] and cint(precision) > 6:
size = '21,9'

View file

@ -146,6 +146,7 @@ def get_context(context):
if doc.meta.get_field(fieldname).fieldtype in frappe.model.numeric_fieldtypes:
value = frappe.utils.cint(value)
doc.reload()
doc.set(fieldname, value)
doc.flags.updater_reference = {
'doctype': self.doctype,

View file

@ -20,6 +20,8 @@ class TestNotification(unittest.TestCase):
notification.event = 'Value Change'
notification.value_changed = 'status'
notification.send_to_all_assignees = 1
notification.set_property_after_alert = 'description'
notification.property_value = 'Changed by Notification'
notification.save()
if not frappe.db.exists('Notification', {'name': 'Contact Status Update'}, 'name'):
@ -237,6 +239,9 @@ class TestNotification(unittest.TestCase):
self.assertTrue(email_queue)
# check if description is changed after alert since set_property_after_alert is set
self.assertEquals(todo.description, 'Changed by Notification')
recipients = [d.recipient for d in email_queue.recipients]
self.assertTrue('test2@example.com' in recipients)
self.assertTrue('test1@example.com' in recipients)

View file

@ -0,0 +1,29 @@
// Copyright (c) 2021, Frappe Technologies and contributors
// For license information, please see license.txt
frappe.ui.form.on('Network Printer Settings', {
onload (frm) {
frm.trigger("connect_print_server");
},
server_ip (frm) {
frm.trigger("connect_print_server");
},
port (frm) {
frm.trigger("connect_print_server");
},
connect_print_server (frm) {
if (frm.doc.server_ip && frm.doc.port) {
frappe.call({
"doc": frm.doc,
"method": "get_printers_list",
"args": {
ip: frm.doc.server_ip,
port: frm.doc.port
},
callback: function(data) {
frm.set_df_property('printer_name', 'options', [""].concat(data.message));
}
});
}
}
});

View file

@ -0,0 +1,66 @@
{
"actions": [],
"autoname": "Prompt",
"creation": "2021-09-17 11:26:06.943999",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"server_ip",
"port",
"column_break_4",
"printer_name"
],
"fields": [
{
"default": "localhost",
"fieldname": "server_ip",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Server IP",
"reqd": 1
},
{
"default": "631",
"fieldname": "port",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Port",
"reqd": 1
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"fieldname": "printer_name",
"fieldtype": "Select",
"label": "Printer Name",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-09-17 11:30:16.781655",
"modified_by": "Administrator",
"module": "Printing",
"name": "Network Printer Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View file

@ -0,0 +1,37 @@
# Copyright (c) 2021, Frappe Technologies and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe import _
class NetworkPrinterSettings(Document):
@frappe.whitelist()
def get_printers_list(self,ip="localhost",port=631):
printer_list = []
try:
import cups
except ImportError:
frappe.throw(_('''This feature can not be used as dependencies are missing.
Please contact your system manager to enable this by installing pycups!'''))
return
try:
cups.setServer(self.server_ip)
cups.setPort(self.port)
conn = cups.Connection()
printers = conn.getPrinters()
for printer_id,printer in printers.items():
printer_list.append({
'value': printer_id,
'label': printer['printer-make-and-model']
})
except RuntimeError:
frappe.throw(_("Failed to connect to server"))
except frappe.ValidationError:
frappe.throw(_("Failed to connect to server"))
return printer_list
@frappe.whitelist()
def get_network_printer_settings():
return frappe.db.get_list('Network Printer Settings', pluck='name')

View file

@ -0,0 +1,8 @@
# Copyright (c) 2021, Frappe Technologies and Contributors
# See license.txt
# import frappe
import unittest
class TestNetworkPrinterSettings(unittest.TestCase):
pass

View file

@ -15,27 +15,5 @@ frappe.ui.form.on('Print Settings', {
},
onload: function(frm) {
frm.script_manager.trigger("print_style");
},
server_ip: function(frm) {
frm.trigger("connect_print_server");
},
port:function(frm) {
frm.trigger("connect_print_server");
},
connect_print_server:function(frm) {
if(frm.doc.server_ip && frm.doc.port){
frappe.call({
"doc": frm.doc,
"method": "get_printers",
"args": {
ip: frm.doc.server_ip,
port: frm.doc.port
},
callback: function(data) {
frm.set_df_property('printer_name', 'options', [""].concat(data.message));
},
error: (data) => frm.set_value("enable_print_server", 0)
});
}
}
});

View file

@ -19,9 +19,6 @@
"allow_print_for_cancelled",
"server_printer",
"enable_print_server",
"server_ip",
"printer_name",
"port",
"raw_printing_section",
"enable_raw_printing",
"print_style_section",
@ -107,29 +104,11 @@
},
{
"default": "0",
"depends_on": "enable_print_server",
"fieldname": "enable_print_server",
"fieldtype": "Check",
"label": "Enable Print Server"
},
{
"default": "localhost",
"depends_on": "enable_print_server",
"fieldname": "server_ip",
"fieldtype": "Data",
"label": "Server IP"
},
{
"depends_on": "enable_print_server",
"fieldname": "printer_name",
"fieldtype": "Select",
"label": "Printer Name"
},
{
"default": "631",
"depends_on": "enable_print_server",
"fieldname": "port",
"fieldtype": "Int",
"label": "Port"
"label": "Enable Print Server",
"mandatory_depends_on": "enable_print_server"
},
{
"fieldname": "raw_printing_section",
@ -183,7 +162,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2021-02-15 14:16:18.474254",
"modified": "2021-09-17 12:59:14.783694",
"modified_by": "Administrator",
"module": "Printing",
"name": "Print Settings",

View file

@ -12,26 +12,6 @@ class PrintSettings(Document):
def on_update(self):
frappe.clear_cache()
@frappe.whitelist()
def get_printers(self,ip="localhost",port=631):
printer_list = []
try:
import cups
except ImportError:
frappe.throw(_("You need to install pycups to use this feature!"))
return
try:
cups.setServer(self.server_ip)
cups.setPort(self.port)
conn = cups.Connection()
printers = conn.getPrinters()
printer_list = printers.keys()
except RuntimeError:
frappe.throw(_("Failed to connect to server"))
except frappe.ValidationError:
frappe.throw(_("Failed to connect to server"))
return printer_list
@frappe.whitelist()
def is_print_server_enabled():
if not hasattr(frappe.local, 'enable_print_server'):

View file

@ -165,10 +165,7 @@ frappe.ui.form.PrintView = class {
frappe.set_route('Form', 'Print Settings');
});
if (
frappe.model.get_doc(':Print Settings', 'Print Settings')
.enable_raw_printing == '1'
) {
if (this.print_settings.enable_raw_printing == '1') {
this.page.add_menu_item(__('Raw Printing Setting'), () => {
this.printer_setting_dialog();
});
@ -179,6 +176,12 @@ frappe.ui.form.PrintView = class {
this.edit_print_format()
);
}
if (this.print_settings.enable_print_server) {
this.page.add_menu_item(__('Select Network Printer'), () =>
this.network_printer_setting_dialog()
);
}
}
show(frm) {
@ -460,72 +463,108 @@ frappe.ui.form.PrintView = class {
printit() {
let me = this;
frappe.call({
method:
'frappe.printing.doctype.print_settings.print_settings.is_print_server_enabled',
callback: function(data) {
if (data.message) {
frappe.call({
method: 'frappe.utils.print_format.print_by_server',
args: {
doctype: me.frm.doc.doctype,
name: me.frm.doc.name,
print_format: me.selected_format(),
no_letterhead: me.with_letterhead(),
letterhead: this.get_letterhead(),
},
callback: function() {},
});
} else if (me.get_mapped_printer().length === 1) {
// printer is already mapped in localstorage (applies for both raw and pdf )
if (me.is_raw_printing()) {
me.get_raw_commands(function(out) {
frappe.ui.form
.qz_connect()
.then(function() {
let printer_map = me.get_mapped_printer()[0];
let data = [out.raw_commands];
let config = qz.configs.create(printer_map.printer);
return qz.print(config, data);
})
.then(frappe.ui.form.qz_success)
.catch((err) => {
frappe.ui.form.qz_fail(err);
});
if (me.print_settings.enable_print_server) {
if (localStorage.getItem('network_printer')) {
me.print_by_server();
} else {
me.network_printer_setting_dialog(() => me.print_by_server());
}
} else if (me.get_mapped_printer().length === 1) {
// printer is already mapped in localstorage (applies for both raw and pdf )
if (me.is_raw_printing()) {
me.get_raw_commands(function(out) {
frappe.ui.form
.qz_connect()
.then(function() {
let printer_map = me.get_mapped_printer()[0];
let data = [out.raw_commands];
let config = qz.configs.create(printer_map.printer);
return qz.print(config, data);
})
.then(frappe.ui.form.qz_success)
.catch((err) => {
frappe.ui.form.qz_fail(err);
});
} else {
frappe.show_alert(
});
} else {
frappe.show_alert(
{
message: __('PDF printing via "Raw Print" is not supported.'),
subtitle: __(
'Please remove the printer mapping in Printer Settings and try again.'
),
indicator: 'info',
},
14
);
//Note: need to solve "Error: Cannot parse (FILE)<URL> as a PDF file" to enable qz pdf printing.
}
} else if (me.is_raw_printing()) {
// printer not mapped in localstorage and the current print format is raw printing
frappe.show_alert(
{
message: __('Printer mapping not set.'),
subtitle: __(
'Please set a printer mapping for this print format in the Printer Settings'
),
indicator: 'warning',
},
14
);
me.printer_setting_dialog();
} else {
me.render_page('/printview?', true);
}
}
print_by_server() {
let me = this;
if (localStorage.getItem('network_printer')) {
frappe.call({
method: 'frappe.utils.print_format.print_by_server',
args: {
doctype: me.frm.doc.doctype,
name: me.frm.doc.name,
printer_setting: localStorage.getItem('network_printer'),
print_format: me.selected_format(),
no_letterhead: me.with_letterhead(),
letterhead: me.get_letterhead(),
},
callback: function() {},
});
}
}
network_printer_setting_dialog(callback) {
frappe.call({
method: 'frappe.printing.doctype.network_printer_settings.network_printer_settings.get_network_printer_settings',
callback: function(r) {
if (r.message) {
let d = new frappe.ui.Dialog({
title: __('Select Network Printer'),
fields: [
{
message: __('PDF printing via "Raw Print" is not supported.'),
subtitle: __(
'Please remove the printer mapping in Printer Settings and try again.'
),
indicator: 'info',
},
14
);
//Note: need to solve "Error: Cannot parse (FILE)<URL> as a PDF file" to enable qz pdf printing.
}
} else if (me.is_raw_printing()) {
// printer not mapped in localstorage and the current print format is raw printing
frappe.show_alert(
{
message: __('Printer mapping not set.'),
subtitle: __(
'Please set a printer mapping for this print format in the Printer Settings'
),
indicator: 'warning',
"label": "Printer",
"fieldname": "printer",
"fieldtype": "Select",
"reqd": 1,
"options": r.message
}
],
primary_action: function() {
localStorage.setItem('network_printer', d.get_values().printer);
if (typeof callback == "function") {
callback();
}
d.hide();
},
14
);
me.printer_setting_dialog();
} else {
me.render_page('/printview?', true);
primary_action_label: __('Select')
});
d.show();
}
},
});
}
render_page(method, printit = false) {
let w = window.open(
frappe.urllib.get_full_url(

View file

@ -5,7 +5,7 @@ import redis
import frappe
from frappe.utils import get_bench_id
from frappe.utils.rq import RedisQueue
from frappe.utils.redis_queue import RedisQueue
from frappe.utils.background_jobs import get_redis_conn
def version_tuple(version):

View file

@ -16,7 +16,7 @@ import frappe
from frappe import _
import frappe.monitor
from frappe.utils import cstr, get_bench_id
from frappe.utils.rq import RedisQueue
from frappe.utils.redis_queue import RedisQueue
from frappe.utils.commands import log

View file

@ -98,8 +98,8 @@ def report_to_pdf(html, orientation="Landscape"):
frappe.local.response.type = "pdf"
@frappe.whitelist()
def print_by_server(doctype, name, print_format=None, doc=None, no_letterhead=0):
print_settings = frappe.get_doc("Print Settings")
def print_by_server(doctype, name, printer_setting, print_format=None, doc=None, no_letterhead=0):
print_settings = frappe.get_doc("Network Printer Settings", printer_setting)
try:
import cups
except ImportError:
@ -123,4 +123,4 @@ def print_by_server(doctype, name, print_format=None, doc=None, no_letterhead=0)
except cups.IPPError:
frappe.throw(_("Printing failed"))
finally:
cleanup(file,{})
return

View file

@ -2938,9 +2938,9 @@ normalize-url@^4.5.0:
set-blocking "~2.0.0"
nth-check@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
version "2.0.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
dependencies:
boolbase "^1.0.0"