0&&void 0!==arguments[0]?arguments[0]:A("url")||a.default_mount_path;return new v(t)}function A(t){var e=document.head.querySelector("meta[name='action-cable-"+t+"']");if(e)return e.getAttribute("content")}t.Connection=g,t.ConnectionMonitor=l,t.Consumer=v,t.INTERNAL=a,t.Subscription=y,t.Subscriptions=m,t.adapters=e,t.createWebSocketURL=S,t.logger=n,t.createConsumer=w,t.getConfig=A,Object.defineProperty(t,"__esModule",{value:!0})}(e)},,function(t,e,n){"use strict";n.r(e);var o=n(1);const i=function(){const t=this;t.settings={},t.settings.debug=!1,t.settings.notificationsContainer=document.querySelector("#notifications-chat"),t.settings.bell=document.querySelector("#notification-bell"),t.settings.inbox=document.querySelector("#chat-inbox"),t.listeningChannel=null,t.createSubscription=()=>{t.listeningChannel=o.a.subscriptions.create({channel:"notifications",room_id:"notifications-"+t.settings.notificationsContainer.getAttribute("data-current-user-id")},{received:function(e){document.dispatchEvent(new CustomEvent("chatNotification",{detail:e})),t.settings.debug&&(console.log("[Notifications] Notification received"),console.log(e))},connected:function(e){t.settings.debug&&console.log("[Notifications] Connected to channel and joined room notifications-"+t.settings.notificationsContainer.getAttribute("data-current-user-id"))}})},t.send=(e,n)=>{o.a.subscriptions.create({channel:"notifications",room_id:"notifications-"+e},{received:function(n){t.settings.debug&&(console.log(`[Notifications] Notification for user ${e} was send`),console.log(n))},connected:function(){t.settings.debug&&console.log("[Notifications] Connected to channel with user "+e)}}).send(n)},t.bell=e=>{e?(t.settings.bell.style.display="block",localStorage.bell="visible"):(t.settings.bell.style.display="none",localStorage.bell="hidden")},t.init=function(){t.createSubscription(),t.settings.inbox||document.addEventListener("chatNotification",e=>{t.bell(!0)}),"visible"===localStorage.bell&&t.bell(!0),t.settings.notificationsContainer.addEventListener("click",()=>{t.bell(!1)})},t.init()};document.querySelector("#notifications-chat")&&document.addEventListener("DOMContentLoaded",()=>{document.chatNotifications=Object.freeze(new i)})}]);
\ No newline at end of file
diff --git a/modules/chat/public/assets/js/pos-chat-consumer.js b/modules/chat/public/assets/js/pos-chat-consumer.js
new file mode 100644
index 0000000..e968dd2
--- /dev/null
+++ b/modules/chat/public/assets/js/pos-chat-consumer.js
@@ -0,0 +1,7 @@
+import { createConsumer } from "https://unpkg.com/@rails/actioncable@8.0.100/app/assets/javascripts/actioncable.esm.js";
+
+const getWebSocketURL = () => {
+ return `/websocket?authenticity_token=${window.pos.csrfToken}`;
+};
+
+export default createConsumer(getWebSocketURL);
diff --git a/modules/chat/src/js/csrfToken.js b/modules/chat/public/assets/js/pos-chat-csrfToken.js
similarity index 100%
rename from modules/chat/src/js/csrfToken.js
rename to modules/chat/public/assets/js/pos-chat-csrfToken.js
diff --git a/modules/chat/src/js/notifications.js b/modules/chat/public/assets/js/pos-chat-notifications.js
similarity index 100%
rename from modules/chat/src/js/notifications.js
rename to modules/chat/public/assets/js/pos-chat-notifications.js
diff --git a/modules/chat/src/js/chat.js b/modules/chat/public/assets/js/pos-chat.js
similarity index 71%
rename from modules/chat/src/js/chat.js
rename to modules/chat/public/assets/js/pos-chat.js
index a13e3f0..d3c9219 100644
--- a/modules/chat/src/js/chat.js
+++ b/modules/chat/public/assets/js/pos-chat.js
@@ -10,8 +10,8 @@
// imports
// ------------------------------------------------------------------------
-import consumer from "./consumer";
-import csrfToken from "./csrfToken";
+import consumer from 'pos-chat-consumer.js';
+
// purpose: handles sending and receiving messages as well as the inbox page
@@ -27,7 +27,7 @@ const chat = function(){
// do you want to enable debug mode that logs to console (bool)
module.settings.debug = false;
// the main container with the chat inbox (dom node)
- module.settings.inbox = document.querySelector('#chat-inbox');
+ module.settings.inbox = document.querySelector('#pos-chat-inbox');
// the input for typing new message (dom node)
module.settings.messageInput = document.querySelector('#chat-messageInput');
// the send button for new message (dom node)
@@ -42,7 +42,7 @@ const chat = function(){
try {
// the back-end returns the timezone formatted not according to tz identifier, so I'm going to risk the 'replace' here to make it work with .toLocaleString automatically
- timezonedDate = date.toLocaleString('en-US', { day: 'numeric', weekday: 'short', year: 'numeric', month: 'short', hour: 'numeric', minute: 'numeric', hour12: true, timeZone: api.profile.timezone.friendly_name_with_region.replace(' - ', '/') });
+ timezonedDate = date.toLocaleString('en-US', { day: 'numeric', weekday: 'short', year: 'numeric', month: 'short', hour: 'numeric', minute: 'numeric', hour12: true, timeZone: window.pos.profile.timezone.friendly_name_with_region.replace(' - ', '/') });
} catch {
if(typeof Intl == 'object' && typeof Intl.NumberFormat == 'function'){
timezonedDate = date.toLocaleString('en-US', { day: 'numeric', weekday: 'short', year: 'numeric', month: 'short', hour: 'numeric', minute: 'numeric', hour12: true, timeZone: 'Etc/UTC' });
@@ -53,43 +53,35 @@ const chat = function(){
return timezonedDate;
}
- // the html template for the single message (function that returns template literal);
- module.settings.messageTemplate = data => {
- let date = new Date(data.created_at);
-
- const message = encodeHtml(data.message).replace(/(\r\n|\r|\n)/g, " ");
-
- return `
-
- ${module.settings.timezonedDate(date)}
-
-
-
-
- `;
+ // html template for the single message
+ module.settings.messageTemplate = {
+ // whole html template for sent message (dom node)
+ sent: document.querySelector('#pos-chat-template-message-sent'),
+ // whole html template for received message (dom node)
+ received: document.querySelector('#pos-chat-template-message-received'),
+ // selector for date field in the template (string)
+ dateSelector: 'time',
+ // selector for the message container (string)
+ messageSelector: '.pos-chat-message-content'
};
// the id of the currently logged user (string)
- module.settings.currentUserId = module.settings.messageInput.getAttribute('data-current-profile-id');
- // converting the dates to user timezone if set in profile (string)
- module.settings.currentUserTimezone = api.profile.timezone;
+ module.settings.currentUserId = window.pos.profile.id;
+ // current user name
+ module.settings.currentUserName = window.pos.profile.name;
// the loading indicator when loading messages (dom node)
- module.settings.loadingIndicator = document.querySelector('#chat-loadingIndicator');
+ module.settings.loadingIndicator = document.querySelector('#pos-chat-loadingIndicator');
// current page of messages (int)
module.settings.currentPage = 1;
// are there more pages (bool)
- module.settings.morePages = module.settings.loadingIndicator.dataset.more === 'true';
+ module.settings.morePages = true
// the message that will appear when the connection is lost
- module.settings.lostConnection = module.settings.inbox.getAttribute('data-error-connection');
+ module.settings.lostConnection = pos.translations.connectionError;
// the channel to send messages through (Action Cable channel)
module.channel = null;
// the id for the conversation (string)
- module.conversationId = module.settings.messageInput.getAttribute('data-conversation-id');
- // the message that will appear when something fails
+ module.conversationId = module.settings.inbox.getAttribute('data-conversation-id');
+ // instance of the toast notification shown when something fails
module.errorNotification = null;
@@ -102,12 +94,6 @@ const chat = function(){
element.textContent = string;
string = element.textContent;
return string;
- }
-
- // purpose: measures the height of the screen and fits the inbox
- // ------------------------------------------------------------------------
- const resizeInbox = () => {
- module.settings.inbox.style.height = `calc(100vh - ${module.settings.inbox.offsetTop}px - 412px)`;
};
@@ -129,7 +115,7 @@ const chat = function(){
room_id: module.conversationId,
sender_name: module.settings.messageInput.getAttribute('data-from-name'),
autor_id: module.settings.messageInput.getAttribute('data-current-profile-id'),
- authenticity_token: csrfToken()
+ authenticity_token: window.pos.csrfToken
},
{
received: function(data){
@@ -141,12 +127,23 @@ const chat = function(){
//document.dispatchEvent(new CustomEvent('message', {detail: Object.assign(data, { status: (module.settings.currentUserId == data.autor_id) ? 'sent' : 'received'})}));
if(module.settings.debug){
- console.log('[Inbox] Message received');
- console.log(data);
+ if(data.status === 'received'){
+ console.log('[pos-module-chat] Message received', data);
+ }
}
},
+ initialized: function(){
+ if(module.settings.debug){
+ console.log('[pos-module-chat] Initialized');
+ }
+ },
+
connected: function(){
+ if(module.settings.debug){
+ console.log('[pos-module-chat] Connected')
+ }
+
module.settings.messageInput.disabled = false;
module.settings.messageInput.focus();
@@ -156,23 +153,25 @@ const chat = function(){
}
if(module.settings.debug){
- console.log(`[Inbox] Connected to channel and joined room ${module.conversationId}`);
+ console.log(`[pos-module-chat] Connected to channel and joined room ${module.conversationId}`);
}
},
rejected: function(){
+ console.log('rejected');
module.blocked();
if(module.settings.debug){
- console.log('[Inbox] The connection was rejected by the server');
+ console.log('[pos-module-chat] The connection was rejected by the server');
}
},
disconnected: function(){
+ console.log('disconnected')
module.blocked();
if(module.settings.debug){
- console.log(`[Inbox] You've been disconnected from the server`);
+ console.log(`[pos-module-chat] You've been disconnected from the server`);
}
}
}
@@ -187,15 +186,14 @@ const chat = function(){
let messageData = {
message: encodeHtml(message),
autor_id: module.settings.currentUserId,
- sender_name: module.settings.messageInput.getAttribute('data-from-name'),
+ sender_name: module.settings.currentUserName,
created_at: new Date()
};
module.channel.send(Object.assign(messageData, { create: true }));
if(module.settings.debug){
- console.log('[Inbox] Message sent');
- console.log(messageData);
+ console.log('[pos-module-chat] Message sent', messageData);
}
};
@@ -205,7 +203,15 @@ const chat = function(){
// according to the template in messageTemplate (object)
// ------------------------------------------------------------------------
module.showMessage = (messageData) => {
- module.settings.messagesList.insertAdjacentHTML('beforeend', module.settings.messageTemplate(messageData));
+
+ // clone message template
+ const messageHtml = messageData.status === 'received' ? module.settings.messageTemplate.received.content.cloneNode(true) : module.settings.messageTemplate.sent.content.cloneNode(true);
+ // fill template with data
+ messageHtml.querySelector(module.settings.messageTemplate.dateSelector).textContent = module.settings.timezonedDate(new Date(messageData.created_at));
+ messageHtml.querySelector(module.settings.messageTemplate.dateSelector).dateTime = messageData.created_at;
+ messageHtml.querySelector(module.settings.messageTemplate.messageSelector).innerHTML = encodeHtml(messageData.message).replace(/(\r\n|\r|\n)/g, ' ');
+ // append the message to the chat
+ module.settings.messagesList.append(messageHtml);
// scroll into the view
module.settings.messagesListContainer.scrollTo({
top: module.settings.messagesListContainer.scrollHeight - module.settings.messagesListContainer.clientHeight,
@@ -214,7 +220,7 @@ const chat = function(){
});
if(module.settings.debug){
- console.log('[Inbox] Message shown in chat');
+ console.log('[pos-module-chat] Message shown in chat');
}
};
@@ -224,10 +230,14 @@ const chat = function(){
// items per page to get (int, default: 30)
// ------------------------------------------------------------------------
module.loadPage = (page = 1, perPage = 30) => {
+ if(module.settings.debug){
+ console.log('[pos-module-chat] Trying to load previous messages');
+ }
+
let secondOldestMessage = module.settings.messagesList.querySelector('li:nth-of-type(2)');
// show the loading indicator at start
- module.settings.loadingIndicator.style.display = 'block';
+ module.settings.loadingIndicator.classList.add('active');
// get the data
fetch(`/api/chat/messages.json?conversation_id=${module.conversationId}&page=${page}&per_page=${perPage}`)
@@ -241,21 +251,33 @@ const chat = function(){
})
.then((data) => {
// construct HTML elements for messages
- let html = '';
+ let html = document.createDocumentFragment();
- Object.entries(data.results).reverse().forEach(([key, data]) => {
- data = Object.assign(data, { status: (module.settings.currentUserId == data.autor_id) ? 'sent' : 'received'});
+ Object.entries(data.results).reverse().forEach(([key, messageData]) => {
+ messageData = Object.assign(messageData, { status: (module.settings.currentUserId == messageData.autor_id) ? 'sent' : 'received'});
- html += module.settings.messageTemplate(data);
+ // clone message template
+ const messageHtml = messageData.status === 'received' ? module.settings.messageTemplate.received.content.cloneNode(true) : module.settings.messageTemplate.sent.content.cloneNode(true);
+ // fill template with data
+ messageHtml.querySelector(module.settings.messageTemplate.dateSelector).textContent = module.settings.timezonedDate(new Date(messageData.created_at));
+ messageHtml.querySelector(module.settings.messageTemplate.dateSelector).dateTime = messageData.created_at;
+ messageHtml.querySelector(module.settings.messageTemplate.messageSelector).innerHTML = encodeHtml(messageData.message).replace(/(\r\n|\r|\n)/g, ' ');
+
+ html.append(messageHtml);
});
+
// put the messages on top
- module.settings.messagesList.insertAdjacentHTML('afterbegin', html);
+ module.settings.messagesList.prepend(html);
// disable loading next pages if there is nothing left
if(!data.has_next_page){
module.settings.morePages = false;
}
+
+ if(module.settings.debug){
+ console.log('[pos-module-chat] Previous messages loaded');
+ }
})
.catch((error) => {
console.log(error);
@@ -263,11 +285,15 @@ const chat = function(){
})
.finally(() => {
// remove the loading indicator
- module.settings.loadingIndicator.style.display = 'none';
+ module.settings.loadingIndicator.classList.remove('active');
// scroll to the last seen message
if(secondOldestMessage) {
module.settings.messagesListContainer.scrollTop = secondOldestMessage.offsetTop - module.settings.messagesListContainer.clientHeight;
}
+
+ if(module.settings.debug){
+ console.log('[pos-module-chat] Finished trying to load previous messages');
+ }
});
};
@@ -276,9 +302,9 @@ const chat = function(){
// ------------------------------------------------------------------------
module.blocked = () => {
module.settings.messageInput.disabled = true;
- module.errorNotification = new posComponents.flash(
+ module.errorNotification = new window.pos.modules.toast(
'error',
- 'We cannot connect to the server. Check your internet connection or try reloading the page.'
+ window.pos.translations.chat.connectionError
);
};
@@ -286,8 +312,8 @@ const chat = function(){
// purpose: parses the dates outputted from BE with JS so that everyting uses browser locale
// ------------------------------------------------------------------------
module.parseDates = () => {
- document.querySelectorAll('[data-message-time]').forEach(date => {
- let currentDate = new Date(date.dataset.messageTime);
+ document.querySelectorAll('.pos-chat-message time').forEach(date => {
+ let currentDate = new Date(date.dateTime);
date.innerText = module.settings.timezonedDate(currentDate);
});
};
@@ -296,9 +322,6 @@ const chat = function(){
// purpose: initializes the module
// ------------------------------------------------------------------------
module.init = () => {
- // resize the inbox to the screen
- resizeInbox();
-
// create subscription for the channel
module.createSubscription();
@@ -317,6 +340,8 @@ const chat = function(){
// handling what will happen on pressing enter in the input
module.settings.messageInput.addEventListener('keypress', (event) => {
if(event.which == 13 && is_desktop && !event.shiftKey && module.settings.messageInput.value.trim()){
+ event.preventDefault();
+
module.sendMessage(module.settings.messageInput.value.trim());
setTimeout(() => {
module.settings.messageInput.value = '';
@@ -372,7 +397,7 @@ const chat = function(){
document.addEventListener('DOMContentLoaded', () => {
if(document.querySelector('#chat-messagesList-container')){
- document.chat = new chat();
+ window.pos.modules.chat = new chat();
}
});
diff --git a/modules/chat/public/assets/style/pos-chat-inbox.css b/modules/chat/public/assets/style/pos-chat-inbox.css
new file mode 100644
index 0000000..8c9fd8f
--- /dev/null
+++ b/modules/chat/public/assets/style/pos-chat-inbox.css
@@ -0,0 +1,308 @@
+/*
+ styling for the inbox
+
+ layout
+ converstations list
+ conversation
+*/
+
+
+
+/* layout
+============================================================================ */
+#pos-chat-inbox {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ overflow: hidden;
+ flex-grow: 1;
+}
+
+ /* when conversation is opened just show the conversation on mobile */
+ @media (max-width: 768px) {
+ #pos-chat-inbox {
+ grid-template-columns: auto;
+ }
+ }
+
+
+
+/* conversations list
+============================================================================ */
+.pos-chat-conversations {
+ min-width: 350px;
+ padding: calc(var(--pos-padding-page) / 2);
+ position: relative;
+ overflow: auto;
+ display: flex;
+ flex-direction: column;
+
+ border-inline-end: 1px solid var(--pos-color-divider);
+}
+
+ /* when conversation is opened just show the conversation on mobile */
+ @media (max-width: 768px) {
+ .pos-chat-conversations {
+ min-width: 0;
+ border-inline-end: 0;
+ }
+
+ .pos-chat-inbox-conversation-active .pos-chat-conversations {
+ display: none;
+ }
+ }
+
+ .pos-chat-conversations li {
+ z-index: 1;
+ }
+
+ .pos-chat-conversations li:not(:last-child) {
+ padding-block-end: var(--pos-gap-list);
+ }
+
+ .pos-chat-conversations a:hover {
+ color: inherit;
+ }
+
+
+/* conversation card */
+.pos-chat-conversationCard {
+ padding: var(--pos-padding-panel);
+ display: grid;
+ grid-template-columns: 48px auto;
+ grid-template-areas:
+ 'avatar name'
+ 'avatar message';
+ column-gap: var(--pos-padding-panel);
+
+ border-radius: var(--pos-radius-panel);
+
+ transition: background-color .1s linear;
+}
+
+ .pos-chat-conversations a:focus-visible .pos-chat-conversationCard {
+ background-color: color-mix(in srgb, var(--pos-color-navigation-hover) 50%, transparent 50%);
+
+ color: var(--pos-color-interactive-hover);
+ }
+
+ /* fallback for browsers that don't support anchor-name */
+ .pos-chat-conversationCard:hover {
+ background-color: color-mix(in srgb, var(--pos-color-navigation-hover) 50%, transparent 50%);
+ }
+ /* end fallback */
+
+ /* list hover effect */
+ @supports (anchor-name: --pos-chat-conversation-active) {
+ /* disable fallback */
+ .pos-chat-conversationCard:hover {
+ background-color: transparent;
+ }
+
+ #pos-chat-conversations:before {
+ width: anchor-size(width);
+ height: anchor-size(height);
+ position: absolute;
+ position-anchor: --pos-chat-conversation-active;
+ inset-block-start: anchor(start);
+
+ border-radius: var(--pos-radius-panel);
+ background-color: color-mix(in srgb, var(--pos-color-navigation-hover) 50%, transparent 50%);
+
+ content: '';
+
+ transition: all .2s ease-in-out;
+ }
+
+ .pos-chat-conversations:not(:has(.pos-chat-conversationCard:hover)) .pos-chat-conversationCard.active {
+ anchor-name: --pos-chat-conversation-active;
+ }
+
+ .pos-chat-conversations li:hover .pos-chat-conversationCard {
+ anchor-name: --pos-chat-conversation-active;
+ }
+ }
+ /* end list hover effect */
+
+ .pos-chat-conversationCard.active {
+ border-radius: var(--pos-radius-panel);
+ background-color: var(--pos-color-navigation-hover);
+ }
+
+.pos-chat-conversationCard .pos-avatar {
+ grid-row: 1 / 3;
+ align-self: center;
+ justify-self: center;
+}
+
+.pos-chat-conversationCard-name {
+ max-width: 230px;
+ overflow: hidden;
+
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ font-weight: 500;
+}
+
+.pos-chat-conversationCard-lastMessage {
+ display: flex;
+ gap: var(--pos-gap-navigation);
+ justify-content: space-between;
+
+ font-size: .9em;
+ color: var(--pos-color-content-supplementary);
+}
+
+ .pos-chat-conversationCard-lastMessage small {
+ max-width: 150px;
+ overflow: hidden;
+
+ text-overflow: ellipsis;
+ font-size: inherit;
+ white-space: nowrap;
+ }
+
+
+/* conversation
+============================================================================ */
+.pos-chat-inbox-empty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.pos-chat-loadingIndicator {
+ position: absolute;
+ inset-inline: 0;
+ inset-block-start: var(--pos-padding-page);
+ display: flex;
+ justify-content: center;
+
+ opacity: 0;
+
+ translate: 0 -4rem;
+ transition: all .2s ease-in-out;
+}
+
+ .pos-chat-loadingIndicator.active {
+ opacity: 1;
+
+ translate: 0 0;
+ }
+
+ .pos-chat-loadingIndicator span {
+ padding: .5em 1em;
+
+ background-color: var(--pos-color-content-foreground);
+ border-radius: var(--pos-radius-panel);
+
+ color: var(--pos-color-content-background);
+ }
+
+.pos-chat-conversation {
+ display: grid;
+ grid-template-rows: auto 1fr auto;
+ overflow: auto;
+}
+
+ /* hide current conversation on mobile */
+ @media (max-width: 768px) {
+ #pos-chat-inbox:not(.pos-chat-inbox-conversation-active) .pos-chat-conversation,
+ #pos-chat-inbox:not(.pos-chat-inbox-conversation-active) .pos-chat-inbox-empty {
+ display: none;
+ }
+ }
+
+.pos-chat-conversation-header {
+ padding: var(--pos-gap-navigation) var(--pos-padding-page);
+ display: flex;
+ gap: calc(var(--pos-gap-navigation) / 2);
+
+ border-block-end: 1px solid var(--pos-color-divider);
+
+ font-weight: 500;
+}
+
+ @media (min-width: 769px) {
+ .pos-chat-conversation-header-back {
+ display: none;
+ }
+ }
+
+ .pos-chat-conversation-header-back {
+ margin-block: calc(var(--pos-gap-navigation) * -1);
+ margin-inline-start: calc(var(--pos-padding-page) * -1);
+ padding: var(--pos-gap-navigation) .2em var(--pos-gap-navigation) var(--pos-padding-page);
+ }
+
+ .pos-chat-conversation-header-back .label {
+ position: absolute;
+ inset-inline-start: -100vw;
+ }
+
+.pos-chat-conversation-messagesContainer {
+ position: relative;
+ overflow: auto;
+ scrollbar-gutter: stable;
+}
+
+.pos-chat-messages {
+ padding: var(--pos-padding-page);
+ display: flex;
+ flex-direction: column;
+ gap: var(--pos-gap-navigation);
+}
+
+.pos-chat-message {
+ display: flex;
+ flex-direction: column;
+ align-items: start;
+ gap: var(--pos-gap-list);
+}
+
+.pos-chat-message-authored {
+ align-items: end;
+}
+
+.pos-chat-message time {
+ font-size: .9rem;
+ color: var(--pos-color-content-supplementary);
+}
+
+.pos-chat-message-content {
+ max-width: 100%;
+ padding: calc(var(--pos-padding-panel) / 2) calc(var(--pos-padding-panel) / 1.5);
+
+ background-color: color-mix(in srgb, var(--pos-color-content-supplementary) 30%, transparent 70%);
+ border-radius: var(--pos-radius-panel);
+
+ word-wrap: break-word;
+}
+
+ .pos-chat-message-authored .pos-chat-message-content {
+ background-color: var(--pos-color-highlighted);
+ }
+
+
+/* new message panel
+============================================================================ */
+.pos-chat-conversation-new {
+ padding: var(--pos-gap-navigation) var(--pos-padding-page) var(--pos-gap-navigation);
+ display: grid;
+ grid-template-columns: 1fr auto;
+ gap: var(--pos-gap-navigation);
+ overflow: auto;
+ scrollbar-gutter: stable;
+}
+
+.pos-chat-conversation-input {
+ padding: calc(var(--pos-padding-panel) / 2) calc(var(--pos-padding-panel) / 1.5);
+
+ border-radius: var(--pos-radius-input);
+ background-color: color-mix(in srgb, var(--pos-color-content-supplementary) 30%, transparent 70%);
+
+ transition: background-color .1s linear
+}
+
+.pos-chat-conversation-input:focus {
+ background-color: color-mix(in srgb, var(--pos-color-content-supplementary) 20%, transparent 80%);
+}
\ No newline at end of file
diff --git a/modules/chat/public/graphql/records/search.graphql b/modules/chat/public/graphql/records/search.graphql
index 7304979..d1f6e6a 100644
--- a/modules/chat/public/graphql/records/search.graphql
+++ b/modules/chat/public/graphql/records/search.graphql
@@ -4,6 +4,7 @@ query records_count(
records(
per_page: 1
filter: {
+ table: { value: "modules/profile/profile" }
properties: [
{ name: "uuid", value: $uuid }
]
diff --git a/modules/chat/public/views/pages/api/messages/show.json.liquid b/modules/chat/public/views/pages/api/messages/show.json.liquid
index 4fb6ab7..fb907a7 100644
--- a/modules/chat/public/views/pages/api/messages/show.json.liquid
+++ b/modules/chat/public/views/pages/api/messages/show.json.liquid
@@ -13,8 +13,11 @@ method: get
{% endcomment %}
{% liquid
- function current_profile = 'modules/community/helpers/current_profile', user_id: context.current_user.id
- include 'modules/community/helpers/profile_present_or_redirect', profile: current_profile
+ function current_profile = 'modules/profile/helpers/current_profile'
+
+ # platformos-check-disable ConvertIncludeToRenderl, UnreachableCode
+ include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: 'chat.inbox', return_url: '/'
+ # platformos-check-enable ConvertIncludeToRender, UnreachableCode
assign conversation_id = context.params.conversation_id
assign page = context.params.page | plus: 0 | default: 1
@@ -22,5 +25,5 @@ method: get
function messages = 'modules/chat/lib/queries/messages/search_by_participant', conversation_id: conversation_id, page: page, limit: limit, participant_id: current_profile.id
- render 'modules/chat/theme/json/messages/show', messages: messages, current_user_id: context.current_user.id
+ render 'modules/chat/theme/json/messages/show', messages: messages
%}
diff --git a/modules/chat/public/views/pages/inbox.html.liquid b/modules/chat/public/views/pages/inbox.html.liquid
index bc66412..ef930b0 100644
--- a/modules/chat/public/views/pages/inbox.html.liquid
+++ b/modules/chat/public/views/pages/inbox.html.liquid
@@ -1,26 +1,32 @@
---
slug: inbox
---
-
{% liquid
- function current_profile = 'modules/community/helpers/current_profile', user_id: context.current_user.id
- include 'modules/community/helpers/profile_present_or_redirect', profile: current_profile
+ function current_profile = 'modules/profile/helpers/current_profile'
+
+ # platformos-check-disable ConvertIncludeToRender, UnreachableCode
+ include 'modules/user/helpers/can_do_or_unauthorized', requester: current_profile, do: 'chat.inbox', return_url: '/'
+ # platformos-check-enable ConvertIncludeToRender, UnreachableCode
- function record = 'modules/chat/lib/queries/records/find_by_uuid', uuid: context.params['to_uuid']
+ if context.params.to_uuid != blank
+ function record = 'modules/chat/lib/queries/records/find_by_uuid', uuid: context.params['to_uuid']
+ endif
assign object = null | hash_merge: to_id: record.id, conversation_id: context.params['conversation_id']
- function current_conversation = 'modules/chat/lib/commands/conversations/find_or_create', object: object, current_profile: current_profile
+ if record or context.params.conversation_id
+ function current_conversation = 'modules/chat/lib/commands/conversations/find_or_create', object: object, current_profile: current_profile
+ endif
if current_conversation.valid == false
assign current_conversation = null
endif
if current_conversation
- function res = 'modules/chat/lib/commands/conversations/mark_read', conversation: current_conversation, participant_id: current_profile.id
+ function _res = 'modules/chat/lib/commands/conversations/mark_read', conversation: current_conversation, participant_id: current_profile.id
endif
function conversations = 'modules/chat/lib/queries/conversations/search_by_participant', participant_id: current_profile.id, limit: 20, page: 1
if conversations.total_entries > 0
- theme_render_rc 'components/pages/inbox', current_conversation: current_conversation, conversations: conversations, current_profile: current_profile
+ theme_render_rc 'inbox', current_conversation: current_conversation, conversations: conversations, current_profile: current_profile
else
- include 'modules/chat/theme/simple/inbox/blank'
+ render 'modules/chat/blank'
endif
%}
diff --git a/modules/chat/public/views/partials/theme/simple/inbox/blank.liquid b/modules/chat/public/views/partials/blank.liquid
similarity index 100%
rename from modules/chat/public/views/partials/theme/simple/inbox/blank.liquid
rename to modules/chat/public/views/partials/blank.liquid
diff --git a/modules/chat/public/views/partials/channels/conversate/receive.liquid b/modules/chat/public/views/partials/channels/conversate/receive.liquid
index a499d89..49fb02f 100644
--- a/modules/chat/public/views/partials/channels/conversate/receive.liquid
+++ b/modules/chat/public/views/partials/channels/conversate/receive.liquid
@@ -14,10 +14,11 @@
{% endcomment %}
{% liquid
- function current_profile = 'modules/community/helpers/current_profile', user_id: context.current_user.id
+ function current_profile = 'modules/profile/helpers/current_profile'
+
assign room_id = context.params.room_id
- function conversation = 'modules/chat/lib/queries/conversations/find_by_participant', id: room_id, participant_id: current_profile.id
+ function conversation = 'modules/chat/lib/queries/conversations/find_by_participant', id: room_id, participant_id: current_profile.id, include_messages: null
if conversation
assign message_safe = context.params.message | raw_escape_string
assign object = '{}' | parse_json
diff --git a/modules/chat/public/views/partials/channels/conversate/subscribed.liquid b/modules/chat/public/views/partials/channels/conversate/subscribed.liquid
index 243382a..69166f1 100644
--- a/modules/chat/public/views/partials/channels/conversate/subscribed.liquid
+++ b/modules/chat/public/views/partials/channels/conversate/subscribed.liquid
@@ -1,7 +1,8 @@
{% liquid
- function current_profile = 'modules/community/helpers/current_profile', user_id: context.current_user.id
+ function current_profile = 'modules/profile/helpers/current_profile'
+
assign room_id = context.params.room_id
- function conversation = 'modules/chat/lib/queries/conversations/find_by_participant', id: room_id, participant_id: current_profile.id
+ function conversation = 'modules/chat/lib/queries/conversations/find_by_participant', id: room_id, participant_id: current_profile.id, include_messages: null
if conversation
echo 'true'
diff --git a/modules/chat/public/views/partials/components/atoms/message.liquid b/modules/chat/public/views/partials/components/atoms/message.liquid
deleted file mode 100644
index 8b86cbf..0000000
--- a/modules/chat/public/views/partials/components/atoms/message.liquid
+++ /dev/null
@@ -1,41 +0,0 @@
----
-metadata:
- name: Chat message
- params:
- justify: ''
- bg_color: ''
- message: ''
- created_at: ''
- timezone: ''
- styleguide:
- - justify: 'justify-start'
- bg_color: 'bg-highlighted'
- message: 'In mollis velit a elit interdum blandit. Aenean volutpat urna vitae cursus hendrerit.'
- created_at: '2023-02-01T10:27:30.919Z'
- timezone: 'Pacific Time (US & Canada)'
- - justify: 'justify-end'
- bg_color: 'bg-interactive-disabled'
- message: 'Aenean volutpat urna vitae cursus hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
- created_at: '2023-02-01T10:27:30.919Z'
- timezone: 'Pacific Time (US & Canada)'
----
-{% liquid
- assign justify = justify | default: params.justify
- assign bg_color = bg_color | default: params.bg_color
- assign message = message | default: params.message
- assign created_at = created_at | default: params.created_at
-
- assign message = message | markdown: '{ "elements": [ "br" ] }'
-%}
-
-
- {{ created_at | l: 'long', timezone }}
-
-
-
-
-
diff --git a/modules/chat/public/views/partials/components/molecules/conversation.liquid b/modules/chat/public/views/partials/components/molecules/conversation.liquid
deleted file mode 100644
index b1194f4..0000000
--- a/modules/chat/public/views/partials/components/molecules/conversation.liquid
+++ /dev/null
@@ -1,92 +0,0 @@
----
-metadata:
- name: Conversation panel
- params:
- id: ''
- current:
- - true
- - false
- unread:
- - true
- - false
- name: ''
- imageSrc: ''
- last_message: ''
- created_at: ''
- timezone: ''
- styleguide:
- - id: '1'
- current: true
- unread: false
- name: 'John Doe'
- imageSrc: 'https://i.pravatar.cc/150?img=18'
- last_message: 'Aenean volutpat urna vitae cursus hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
- created_at: '2023-02-01T10:27:30.919Z'
- timezone: 'Pacific Time (US & Canada)'
- - id: '2'
- current: false
- unread: false
- name: 'John Doe'
- imageSrc: 'https://i.pravatar.cc/150?img=18'
- last_message: 'Aenean volutpat urna vitae cursus hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
- created_at: '2023-02-01T10:27:30.919Z'
- timezone: 'Pacific Time (US & Canada)'
- - id: '3'
- current: false
- unread: true
- name: 'John Doe'
- imageSrc: 'https://i.pravatar.cc/150?img=18'
- last_message: 'Aenean volutpat urna vitae cursus hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
- created_at: '2023-02-01T10:27:30.919Z'
- timezone: 'Pacific Time (US & Canada)'
----
-{% liquid
- assign id = id | default: params.id
- assign current = current | default: params.current | default: false
- assign unread = unread | default: params.unread | default: false
- assign name = name | default: params.name
- assign imageSrc = imageSrc | default: params.imageSrc
- assign last_message = last_message | default: params.last_message
- assign created_at = created_at | default: params.created_at
-%}
-{% if current == false %}
-
-{% endif %}
- {% liquid
- assign active_class = 'bg-panel border-l-4 border-interactive-graphic bg-input '
- if current == false
- assign active_class = 'pl-4 border-b border-divider '
- endif
-
- if unread == false
- assign text_class = 'text-supplementary'
- else
- assign text_class = 'text-normal font-bold'
- endif
-
- assign active_class = active_class | append: text_class
- %}
-
-
- {% theme_render_rc 'components/atoms/avatar', size: 'l', name: name, imageSrc: imageSrc %}
-
-
-
-
{{ name }}
- {% if last_message %}
-
- {{ created_at | strftime: "%b %d", timezone }}
-
- {% endif %}
-
- {% if last_message %}
- {% liquid
- assign message = last_message | truncatewords: 6
- theme_render_rc 'components/atoms/sidenote', content: message
- %}
- {% endif %}
-
-
-{% if current == false %}
-
-{% endif %}
diff --git a/modules/chat/public/views/partials/components/pages/inbox.liquid b/modules/chat/public/views/partials/components/pages/inbox.liquid
deleted file mode 100644
index 9542a46..0000000
--- a/modules/chat/public/views/partials/components/pages/inbox.liquid
+++ /dev/null
@@ -1,128 +0,0 @@
----
-metadata:
- name: Chat Inbox
- params:
- current_conversation: {}
- conversations: {}
- current_profile: {}
----
-
-
-
-
-
-
Messaging
- {% liquid
- for conversation in conversations.results
- assign participants = conversation.participants
- assign current_participants = participants | select: id: current_profile.id
- assign other_participants = participants | subtract_array: current_participants
- assign from_profile = other_participants | first
-
- if conversation.id != current_conversation.id
- assign current = false
- else
- assign current = true
- endif
-
- if conversation.participant_read_ids contains current_profile.id
- assign unread = false
- else
- assign unread = true
- endif
-
- assign name = from_profile.first_name | append: ' ' | append: from_profile.last_name | default: from_profile.name
- assign imageSrc = from_profile.avatar.photo.versions.sm
- assign last_message = conversation.last_message.message
- assign created_at = conversation.last_message.created_at
- if conversation.last_message
- theme_render_rc 'components/molecules/conversation', id: conversation.id, current: current, unread: unread, name: name, imageSrc: imageSrc, last_message: last_message, created_at: created_at, timezone: current_profile.timezone
- endif
- if conversation.id == current_conversation.id
- assign other_participant = from_profile
- endif
- endfor
- %}
-
-
-
- {% if current_conversation %}
-
-
-
- {{- 'modules/chat/loading_previous' | t -}}
-
-
-
-
-
- {% liquid
- assign list = current_conversation.messages | reverse
- for message in list
- if message.autor_id != current_profile.id
- theme_render_rc 'components/atoms/message', message: message.message, created_at: message.created_at, justify: 'justify-start', bg_color: 'bg-highlighted', timezone: current_profile.timezone
- else
- theme_render_rc 'components/atoms/message', message: message.message, created_at: message.created_at, justify: 'justify-end', bg_color: 'bg-interactive-disabled', timezone: current_profile.timezone
- endif
- endfor
- %}
-
-
-
-
-
-
-
- {% liquid
- assign button_text = 'modules/chat/send' | t
- assign attributes = '{}' | parse_json
- hash_assign attributes['id'] = "chat-sendButton"
- theme_render_rc 'components/atoms/button', size: 'small', weight: 'primary', content: button_text, attributes: attributes
- %}
-
-
-
- {% else %}
-
- {% assign heading_text = 'modules/chat/pick_conversation' | t %}
- {% theme_render_rc 'components/atoms/heading', content: heading_text, level: 3, tag: 'span', classes: 'uppercase' %}
-
- {% endif %}
-
-
-
diff --git a/modules/chat/public/views/partials/conversation.liquid b/modules/chat/public/views/partials/conversation.liquid
new file mode 100644
index 0000000..2006b52
--- /dev/null
+++ b/modules/chat/public/views/partials/conversation.liquid
@@ -0,0 +1,20 @@
+{% if current == false %}
+
+{% endif %}
+
+ {% render 'modules/common-styling/user/avatar', size: 'l', name: name, imageSrc: imageSrc %}
+
+ {{ name }}
+
+
+ {% if last_message %}
+ {{ last_message }}
+
+ {{ created_at | strftime: "%b %d", timezone }}
+
+ {% endif %}
+
+
+{% if current == false %}
+
+{% endif %}
diff --git a/modules/chat/public/views/partials/inbox.liquid b/modules/chat/public/views/partials/inbox.liquid
new file mode 100644
index 0000000..284d4af
--- /dev/null
+++ b/modules/chat/public/views/partials/inbox.liquid
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+ {% liquid
+ render 'modules/chat/message', message: '', authored: false
+ %}
+
+
+ {% liquid
+ render 'modules/chat/message', message: '', authored: true
+ %}
+
+
+
+
+
+
+
+ {% for conversation in conversations.results %}
+ {% liquid
+ assign participants = conversation.participants
+ assign current_participants = participants | select: id: current_profile.id
+ assign other_participants = participants | subtract_array: current_participants
+ assign from_profile = other_participants | first
+
+ if conversation.id != current_conversation.id
+ assign current = false
+ else
+ assign current = true
+ endif
+
+ if conversation.participant_read_ids contains current_profile.id
+ assign unread = false
+ else
+ assign unread = true
+ endif
+
+ assign name = from_profile.first_name | append: ' ' | append: from_profile.last_name | default: from_profile.name
+ assign imageSrc = from_profile.avatar.photo.versions.sm
+ assign last_message = conversation.last_message.message
+ assign created_at = conversation.last_message.created_at
+
+ if conversation.id == current_conversation.id
+ assign other_participant = from_profile
+ endif
+ %}
+ {% if conversation.last_message %}
+
+ {% liquid
+ theme_render_rc 'conversation', id: conversation.id, current: current, unread: unread, name: name, imageSrc: imageSrc, last_message: last_message, created_at: created_at, timezone: current_profile.timezone
+ %}
+
+ {% endif %}
+ {% endfor %}
+
+
+ {% if current_conversation %}
+
+
+
+
+
+ {{- 'modules/chat/loading_previous' | t -}}
+
+
+
+ {% liquid
+ assign list = current_conversation.messages | reverse
+ for message in list
+ if message.autor_id != current_profile.id
+ render 'modules/chat/message', message: message.message, created_at: message.created_at, authored: false, bg_color: 'bg-highlighted', timezone: current_profile.timezone
+ else
+ render 'modules/chat/message', message: message.message, created_at: message.created_at, authored: true, bg_color: 'bg-interactive-disabled', timezone: current_profile.timezone
+ endif
+ endfor
+ %}
+
+
+
+
+ {% else %}
+
+ {{ 'modules/chat/pick_conversation' | t }}
+
+ {% endif %}
+
+
\ No newline at end of file
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/find.liquid b/modules/chat/public/views/partials/lib/queries/conversations/find.liquid
index e8c5af5..6641148 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/find.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/find.liquid
@@ -5,14 +5,13 @@
endif
graphql r = 'modules/chat/conversations/search', limit: 1, id: id, participant_id: participant_id, include_messages: include_messages
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/find_by_participant'
assign conversation = r.conversations.results.first
assign participants = '[]' | parse_json
for participant_id in conversation.participant_ids
- function profile = 'modules/profile/queries/profiles/find_proxy', id: participant_id
+ function profile = 'modules/profile/queries/profiles/find', id: participant_id
assign participants = participants | add_to_array: profile
endfor
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/find_by_participant.liquid b/modules/chat/public/views/partials/lib/queries/conversations/find_by_participant.liquid
index 683d025..7e00b5a 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/find_by_participant.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/find_by_participant.liquid
@@ -10,14 +10,15 @@
endif
graphql r = 'modules/chat/conversations/search', limit: 1, id: id, participant_id: participant_id, include_messages: include_messages, messages_limit: 30
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/find_by_participant'
assign conversation = r.conversations.results.first
+ log r
+
assign participants = '[]' | parse_json
for participant_id in conversation.participant_ids
- function profile = 'modules/profile/queries/profiles/find_proxy', id: participant_id
+ function profile = 'modules/profile/queries/profiles/find', id: participant_id
assign participants = participants | add_to_array: profile
endfor
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/find_by_participants.liquid b/modules/chat/public/views/partials/lib/queries/conversations/find_by_participants.liquid
index 540a7ae..2e68976 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/find_by_participants.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/find_by_participants.liquid
@@ -5,7 +5,6 @@
endif
graphql r = 'modules/chat/conversations/search', limit: 1, participant_ids: participant_ids, include_messages: include_messages, messages_limit: 30
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/find_by_participants'
assign conversation = r.conversations.results.first
@@ -13,7 +12,7 @@
assign participants = '[]' | parse_json
for participant_id in conversation.participant_ids
- function profile = 'modules/profile/queries/profiles/find_proxy', id: participant_id
+ function profile = 'modules/profile/queries/profiles/find', id: participant_id, user_id: null, uuid: null, first_name: null, last_name: null
assign participants = participants | add_to_array: profile
endfor
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/number_of_unread_by_participant.liquid b/modules/chat/public/views/partials/lib/queries/conversations/number_of_unread_by_participant.liquid
index 3e5398e..356b7fc 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/number_of_unread_by_participant.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/number_of_unread_by_participant.liquid
@@ -5,7 +5,6 @@
endif
graphql r = 'modules/chat/conversations/number_unread_by_participant', participant_id: participant_id
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/number_of_unread_by_participant'
return r.conversations.total_entries
%}
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/search.liquid b/modules/chat/public/views/partials/lib/queries/conversations/search.liquid
index 1b08726..9deb872 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/search.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/search.liquid
@@ -1,7 +1,6 @@
{% liquid
assign page = page | to_positive_integer: 1
graphql r = 'modules/chat/conversations/search_by_message', limit: limit, page: page, participant_id: participant_id, message: message
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/search'
assign result = r.conversations
assign conversations = '[]' | parse_json
@@ -10,7 +9,7 @@
assign participants = '[]' | parse_json
for participant_id in conversation.participant_ids
- function profile = 'modules/profile/queries/profiles/find_proxy', id: participant_id
+ function profile = 'modules/profile/queries/profiles/find', id: participant_id
assign participants = participants | add_to_array: profile
endfor
diff --git a/modules/chat/public/views/partials/lib/queries/conversations/search_by_participant.liquid b/modules/chat/public/views/partials/lib/queries/conversations/search_by_participant.liquid
index 2b3589d..d375bb4 100644
--- a/modules/chat/public/views/partials/lib/queries/conversations/search_by_participant.liquid
+++ b/modules/chat/public/views/partials/lib/queries/conversations/search_by_participant.liquid
@@ -7,7 +7,6 @@
assign page = page | to_positive_integer: 1
graphql r = 'modules/chat/conversations/search', limit: limit, page: page, participant_id: participant_id
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/search'
assign result = r.conversations
assign conversations = '[]' | parse_json
@@ -16,7 +15,7 @@
assign participants = '[]' | parse_json
for participant_id in conversation.participant_ids
- function profile = 'modules/profile/queries/profiles/find_proxy', id: participant_id
+ function profile = 'modules/profile/queries/profiles/find', id: participant_id, user_id: null, uuid: null, filters: null
assign participants = participants | add_to_array: profile
endfor
diff --git a/modules/chat/public/views/partials/lib/queries/messages/search_by_participant.liquid b/modules/chat/public/views/partials/lib/queries/messages/search_by_participant.liquid
index a2d39c9..d6a6578 100644
--- a/modules/chat/public/views/partials/lib/queries/messages/search_by_participant.liquid
+++ b/modules/chat/public/views/partials/lib/queries/messages/search_by_participant.liquid
@@ -5,7 +5,6 @@
endif
graphql r = 'modules/chat/messages/search', limit: limit, page: page, participant_id: participant_id, conversation_id: conversation_id
- include 'modules/community/helpers/handle_graphql_response', r: r, name: 'modules/chat/conversations/search'
return r.messages
%}
diff --git a/modules/chat/public/views/partials/message.liquid b/modules/chat/public/views/partials/message.liquid
new file mode 100644
index 0000000..22520ea
--- /dev/null
+++ b/modules/chat/public/views/partials/message.liquid
@@ -0,0 +1,17 @@
+{% liquid
+ assign message = message | markdown: '{ "elements": [ "br" ] }'
+%}
+
+
+
+
+ {% if created_at %}
+ {{ created_at | l: 'long', timezone }}
+ {% endif %}
+
+
+
+ {{ message }}
+
+
+
diff --git a/modules/chat/public/views/partials/theme/simple/inbox/conversation.liquid b/modules/chat/public/views/partials/theme/simple/inbox/conversation.liquid
deleted file mode 100644
index 48c4df5..0000000
--- a/modules/chat/public/views/partials/theme/simple/inbox/conversation.liquid
+++ /dev/null
@@ -1,45 +0,0 @@
-{% if conversation.id != current_conversation.id %}
-
-{% endif %}
- {% liquid
- assign active_class = 'bg-panel border-l-4 border-interaction text-content'
- unless conversation.id == current_conversation.id
- assign active_class = 'border-l-4 border-transparent text-content-sidenote'
- endunless
-
- if from_user.first_name
- assign name = from_user.first_name | append: ' ' | append: from_user.last_name
- else
- assign name = from_user.name
- endif
- %}
-
-
-
-
- {% theme_render_rc 'components/atoms/avatar', size: 's', name: name, imageSrc: from_user.avatar.photo.versions.sm %}
-
-
-
-
-
{{ name }}
-
- {% unless conversation.participant_read_ids contains current_profile.id %}
-
- {% endunless %}
-
-
-
- {% if conversation.last_message %}
-
- {{ conversation.last_message.created_at | l: 'compact' }}
-
- {% endif %}
-
-
-
-
-
-{% if conversation.id != current_conversation.id %}
-
-{% endif %}
diff --git a/modules/chat/public/views/partials/theme/simple/inbox/inbox.liquid b/modules/chat/public/views/partials/theme/simple/inbox/inbox.liquid
deleted file mode 100644
index 88d4755..0000000
--- a/modules/chat/public/views/partials/theme/simple/inbox/inbox.liquid
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
-
-
- {% liquid
- for conversation in conversations.results
- assign participants = conversation.participants
- assign current_participants = participants | select: id: current_profile.id
- assign other_participants = participants | subtract_array: current_participants
- assign from_profile = other_participants | first
-
- render 'modules/chat/theme/simple/inbox/conversation', conversation: conversation, current_conversation: current_conversation, current_profile: current_profile, from_user: from_profile, messages: messages
-
- if conversation.id == current_conversation.id
- assign other_participant = from_profile
- endif
- endfor
- %}
-
-
-
- {% if current_conversation %}
-
-
- {{ 'modules/chat/loading_previous' | t }}
-
-
-
-
- {% liquid
- assign list = current_conversation.messages | reverse
- for message in list
- if message["autor_id"] != current_profile.id
- render "modules/chat/theme/simple/inbox/message", message: message, justify: 'justify-start', bg_color: 'bg-blue-100'
- else
- render "modules/chat/theme/simple/inbox/message", message: message, justify: 'justify-end', bg_color: 'bg-blue-200'
- endif
- endfor
- %}
-
-
-
-
-
-
-
-
- {{ 'modules/chat/send' | t }}
-
-
-
-
-
- {% else %}
-
-
- {{ 'modules/chat/pick_conversation' | t }}
-
-
- {% endif %}
-
-
-
diff --git a/modules/chat/public/views/partials/theme/simple/inbox/message.liquid b/modules/chat/public/views/partials/theme/simple/inbox/message.liquid
deleted file mode 100644
index 21e6d45..0000000
--- a/modules/chat/public/views/partials/theme/simple/inbox/message.liquid
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
{% print message["message"] %}
-
{{ message["created_at"] | l: 'short' }}
-
-
diff --git a/modules/chat/src/js/consumer.js b/modules/chat/src/js/consumer.js
deleted file mode 100644
index eeba47c..0000000
--- a/modules/chat/src/js/consumer.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { createConsumer } from "@rails/actioncable";
-import csrfToken from "./csrfToken";
-
-const getWebSocketURL = () => {
- const token = csrfToken();
- return `/websocket?authenticity_token=${token}`;
-};
-
-export default createConsumer(getWebSocketURL);
diff --git a/modules/chat/template-values.json b/modules/chat/template-values.json
index dba4f1f..69fb682 100644
--- a/modules/chat/template-values.json
+++ b/modules/chat/template-values.json
@@ -2,10 +2,11 @@
"name": "Pos Module Chat",
"machine_name": "chat",
"type": "module",
- "version": "0.0.10",
+ "version": "1.0.1",
"dependencies": {
- "components": "^1.1.3",
"core": "^1.0.0",
- "profile": "^1.0.0"
+ "profile": "^1.1.0",
+ "user": "^3.0.0",
+ "common-styling": "0.0.14"
}
}
diff --git a/modules/chat/webpack.config.js b/modules/chat/webpack.config.js
deleted file mode 100644
index 58d467e..0000000
--- a/modules/chat/webpack.config.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const path = require('path');
-const TerserPlugin = require('terser-webpack-plugin');
-const WebpackRequireFrom = require('webpack-require-from');
-
-const prod = process.env.NODE_ENV === 'production';
-
-const config = {
- entry: {
- chat: './src/js/chat',
- notifications: './src/js/notifications'
- },
- output: {
- filename: 'js/[name].js?v=[chunkhash:5]',
- chunkFilename: 'js/[name].js?v=[chunkhash:5]',
- path: path.resolve('public/assets'),
- },
- devServer: {
- contentBase: path.resolve(__dirname, 'chat'),
- watchContentBase: true,
- writeToDisk: true,
- open: true,
- },
- bail: true,
- performance: { hints: false },
- stats: {
- assetsSort: '!size',
- builtAt: false,
- children: false,
- modules: false,
- },
- module: {
- rules: [
- {
- test: /\.js$/,
- loader: 'babel-loader?cacheDirectory',
- }
- ],
- },
- optimization: {
- minimizer: [
- new TerserPlugin({
- parallel: true,
- cache: true,
- terserOptions: {
- output: {
- comments: false,
- },
- },
- extractComments: false,
- }),
- ],
- splitChunks: {
- cacheGroups: {
- vendors: false, // Do not emit vendors~* files that are almost empty in this setup
- },
- },
- },
- plugins: [
- new WebpackRequireFrom({
- variableName: 'window.cdnUrl',
- }),
- ],
- mode: prod ? 'production' : 'development',
-};
-
-module.exports = config;
diff --git a/modules/common-styling/.gitignore b/modules/common-styling/.gitignore
new file mode 100644
index 0000000..66eb503
--- /dev/null
+++ b/modules/common-styling/.gitignore
@@ -0,0 +1,14 @@
+node_modules
+.pos
+tmp
+test/pictures/
+test/screenshots
+test/reports/video/
+seed/data.csv
+seed/models.csv
+test-report.html
+test-report.json
+/test-results/
+/playwright-report/
+/blob-report/
+/playwright/.cache/
\ No newline at end of file
diff --git a/modules/common-styling/README.md b/modules/common-styling/README.md
new file mode 100644
index 0000000..be6aceb
--- /dev/null
+++ b/modules/common-styling/README.md
@@ -0,0 +1,155 @@
+vWIP
+
+This module contains reusable CSS and JS, which is or will be leveraged by [platformOS modules](https://documentation.platformos.com/developer-guide/modules/platformos-modules#our-modules), and which you wil be able to use in your projects. The idea is to provide a consistent and documented way of providing modules which look good from a start and which you can easily customize to fit your needs.
+
+This module follows the [platformOS DevKit best practices](https://documentation.staging.oregon.platform-os.com/developer-guide/modules/platformos-modules).
+
+## Installation
+
+The platformOS Common Styling Module is available on the [Partner Portal Modules Marketplace](https://partners.platformos.com/marketplace/pos_modules/154).
+
+### Prerequisites
+
+Before installing the module, ensure that you have [pos-cli](https://github.com/mdyd-dev/pos-cli#overview) installed. This tool is essential for managing and deploying platformOS projects.
+
+The platformOS Common Styling is fully compatible with [platformOS Check](https://github.com/Platform-OS/platformos-lsp#platformos-check----a-linter-for-platformos), a linter and language server that supports any IDE with Language Server Protocol (LSP) integration. For Visual Studio Code users, you can enhance your development experience by installing the [VSCode platformOS Check Extension](https://marketplace.visualstudio.com/items?itemName=platformOS.platformos-check-vscode).
+
+### Installation Steps
+
+1. **Navigate to your project directory** where you want to install the Common Styling Module.
+
+2. **Run the installation command**:
+
+```bash
+ pos-cli modules install common-styling
+```
+
+This command installs the Common Styling Module and updates or creates the `app/pos-modules.json` file in your project directory to track module configurations.
+
+### Setup
+
+1. **Install the module** using the [pos-cli](https://github.com/Platform-OS/pos-cli).
+2. **Import the following CSS files** into your layout's `` section:
+
+```html
+
+
+
+
+
+
+
+```
+
+3. **Optionally, import the following CSS reset**. It's not recommended to use in on an existing app probably, but you can safely use it on a fresh one. To use it just place the following CSS reference on top and use a `pos-app` class anywhere on your main content container.
+
+```html
+
+```
+
+## Customizing CSS
+
+When using the `common-styling` module you can easiliy configure the looks of components by overwriting the CSS variables stored in `pos-config.css`. Just copy the variables you need to overwrite to the CSS of your app so they can be overwritten.
+
+When building CSS don't hardcode any (well... probably with some exeptions) color or size. Everything should use CSS variables that are in line with [Figma variables](https://documentation.platformos.com/kits/ui/platformos-design-kit#download). (Pro tip - you can use calc(), from-color() or color-mix() if needed).
+
+
+## Scoping CSS
+
+When naming your module CSS files, please prefix them with `pos-` for coinsistency.
+
+When naming your CSS classes, please prefix those with `pos-`. We are trying to make sure that the CSS from modules won't interfere with any other CSS that could be used in the project. Keep in mind that the module can be used in various contextes so any styling needs to be scoped just to the module code.
+
+Every CSS is placed inside a `common-styling` CSS layer to lower it's specificity and so that you could always easily overwrite them without having to worry about selectors used.
+
+There are some CSS rules that will be inherited when the parent container has a specific class. Example of`.pos-form` class on a container will style the inputs, buttons and form-related stuff inside the container.
+
+Each component should have it's own separate CSS file.
+
+
+## JavaScript namespace for modules
+
+Use ESM Modules to build JavaScript.
+
+The modules should not pollute the global JavaScript namespace. For this purpose we are using the `pos` namespace attached to global `window` object. Extending the namespace is the preferred way to store all the needed data, translations and module public interface.
+
+There are several basic objects used across the modules that could be extended for consistency. Those are shared across many modules, so **remember not to overwrite them in your code** and extend the objects instead.
+
+| window.pos | Global namespace for all modules-related data. |
+| window.pos.modules | If your module provides a public API then you should attach it to this object namespacing your module accordingly `window.pos.module.myModule = {}` |
+| window.pos.profile | Stores all the profile-related data for currently logged in user. |
+| window.pos.translations | If your JavaScript code needs access to any translations you should append them to this object. |
+
+As an example starting point for defining JavaScript for your module you can use the following code:
+
+```
+
+```
+
+
+## Handling cache with importmaps
+
+When using `import` statement in your JavaScript files, you will request an JS file from the CDN that could be already cached by the browser. PlatformOS handles breaking the cache for assets by using `asset_url` filter. You cannot use it in the JS files though, but the browsers allows you to map any filename to any other URL using [Import Maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap). Currently only a single import map on a page can be used and it needs to be defined before any other JS script. (This will change in the near future as multiple import maps are in the works for all the browsers).
+
+An example import map looks like this:
+
+```
+
+```
+
+The first line allows to use relative `import` statements inside your JS files, the last line resets it back to default.
+
+
+## Components
+
+### Toast notifications
+
+1. Render the partial in your application layout (preferably at the very bottom)
+```
+{% liquid
+ function flash = 'modules/core/commands/session/get', key: 'sflash'
+ if context.location.pathname != flash.from or flash.force_clear
+ function _ = 'modules/core/commands/session/clear', key: 'sflash'
+ endif
+ theme_render_rc 'modules/common-styling/toasts', params: flash
+%}
+```
+
+From JavaScript you can use:
+```
+new pos.modules.toast('[severity]', '[message]') to show new notification
+```
+
+On the server-side:
+[TO DO]
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/js/pos-toast.js b/modules/common-styling/public/assets/js/pos-toast.js
new file mode 100644
index 0000000..6386433
--- /dev/null
+++ b/modules/common-styling/public/assets/js/pos-toast.js
@@ -0,0 +1,119 @@
+/*
+ handles showing the floating notifications
+
+ usage:
+ new window.pos.modules.toast('type', 'message');
+ or
+ let notification = new window.pos.modules.toast('type', 'message')
+ notification.remove();
+
+ types:
+ error
+ success
+ info
+*/
+
+
+
+// purpose: shows the floating alert
+// arguments: type of the message (string)
+// the message to show (string)
+// settings to overwrite the defaults (object)
+// ************************************************************************
+window.pos.modules.toast = function(type, message, userSettings){
+
+ // cache 'this' value not to be overwritten later
+ const module = this;
+
+ // purpose: settings that are being used across the module
+ // ------------------------------------------------------------------------
+ module.settings = {};
+ // notifications container (dom node)
+ module.settings.container = document.querySelector('#pos-toasts');
+ // the html template to be used for notifications (dom node)
+ module.settings.template = module.settings.container.querySelector('#pos-toast-template');
+ // the selector for the text content in the template (string)
+ module.settings.contentSelector = '.pos-toast-content';
+ // the selector for the button that closes the notification (string)
+ module.settings.closeSelector = '.pos-toast-close';
+ // the notification in dom (dom object)
+ module.settings.notification = null;
+ // if you want to overwrite the default autohide (bool)
+ module.settings.autohide = (userSettings?.autohide !== undefined) ? userSettings.autohide : (type === 'success') ? true : false;
+ // if you want a delay before the notification appears, miliseconds (int)
+ module.settings.delay = (userSettings?.delay) ? userSettings.delay : false;
+ // to enable debug mode (bool)
+ module.settings.debug = (userSettings?.debug) ? userSettings.debug : false;
+
+ let autoHideTimeout = null;
+
+
+
+ // purpose: initializes the component
+ // ------------------------------------------------------------------------
+ module.init = () => {
+ if(module.settings.delay){
+ setTimeout(() => {
+ module.show();
+ }, module.settings.delay);
+ } else {
+ module.show();
+ }
+
+ // auto hide the message when it is a success
+ if(module.settings.autohide){
+ autoHideTimeout = setTimeout(() => {
+ module.hide();
+ }, (module.settings.debug) ? 700 : 5000);
+ }
+
+ };
+
+
+ // purpose: shows the notification
+ // ------------------------------------------------------------------------
+ module.show = () => {
+ // clone the template
+ module.settings.notification = module.settings.template.content.firstElementChild.cloneNode(true);
+
+ // add class corresponding to the severity
+ module.settings.notification.classList.add(`pos-toast-${type}`);
+
+ // apply the message to content
+ module.settings.notification.querySelector(module.settings.contentSelector).innerHTML = message;
+
+ // set the option to close notification when clicking on close button
+ module.settings.notification.querySelector(module.settings.closeSelector).addEventListener('click', () => {
+ module.hide();
+ }, {once: true});
+
+ // add the class that will animate the appearing
+ module.settings.notification.classList.add('pos-toast-loading');
+
+ // when we append the template to the container we are loosing the reference so we need to get it back
+ module.settings.notification = module.settings.container.appendChild(module.settings.notification);
+
+ };
+
+
+ // purpose: hides the notification
+ // ------------------------------------------------------------------------
+ module.hide = () => {
+ // we don't need the autohide feature anymore
+ clearTimeout(autoHideTimeout);
+
+ // add a class that will animate removing the node
+ module.settings.notification.classList.add('pos-toast-unloading');
+
+ // remove the node from DOM as it's not needed anymore
+ module.settings.notification.addEventListener('animationend', () => {
+ module.settings.notification.remove();
+ });
+ };
+
+
+ module.init();
+
+};
+
+document.dispatchEvent(new Event('pos-modules-toast-ready'));
diff --git a/modules/common-styling/public/assets/style/pos-avatar.css b/modules/common-styling/public/assets/style/pos-avatar.css
new file mode 100644
index 0000000..a91874c
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-avatar.css
@@ -0,0 +1,67 @@
+/*
+ avatar component
+
+ no-image avatar
+*/
+
+
+
+/* no-image avatar
+============================================================================ */
+.pos-avatar {
+ all: unset;
+ display: revert;
+
+ width: 48px;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+
+ border-radius: 50%;
+ background-color: var(--pos-color-divider);
+
+ line-height: 0;
+ font-weight: 500;
+ color: var(--pos-color-content-supplementary);
+}
+
+.pos-avatar-xs {
+ width: 20px;
+ height: 20px;
+
+ font-size: .6rem;
+}
+
+.pos-avatar-s {
+ width: 24px;
+ height: 24px;
+
+ font-size: .7rem;
+}
+
+.pos-avatar-m {
+ width: 32px;
+ height: 32px;
+}
+
+.pos-avatar-l {
+ width: 48px;
+ height: 48px;
+}
+
+.pos-avatar-xl {
+ width: 94px;
+ height: 94px;
+}
+
+.pos-avatar-xxl {
+ width: 160px;
+ height: 160px;
+}
+
+.pos-avatar-xxxl {
+ width: 192px;
+ height: 192px;
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-button.css b/modules/common-styling/public/assets/style/pos-button.css
new file mode 100644
index 0000000..0aa6985
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-button.css
@@ -0,0 +1,130 @@
+/*
+ button component
+
+ basic
+ icon
+ label for screen readers
+ secondary
+*/
+
+
+
+@layer common-styling {
+
+ /* basic
+ ============================================================================ */
+ .pos-button,
+ .pos-button * {
+ box-sizing: border-box;
+ }
+
+ .pos-button {
+ all: unset;
+ display: revert;
+
+ user-select: none;
+ -webkit-user-select: none;
+ cursor: pointer;
+ }
+
+ .pos-button {
+ padding-inline: var(--pos-padding-input);
+ height: var(--pos-height-input);
+ position: relative;
+ z-index: 1;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ gap: 1em;
+ vertical-align: middle;
+
+ background-color: var(--pos-color-button-default-background);
+ border-width: var(--pos-border-input);
+ border-style: solid;
+ border-color: var(--pos-color-button-default-frame);
+ border-radius: var(--pos-radius-button);
+ outline: none;
+
+ line-height: 1.2em;
+ font-size: .95rem;
+ font-weight: 500;
+ color: var(--pos-color-button-default-foreground);
+
+ transition: all .1s linear;
+ }
+
+ .pos-button:hover {
+ background-color: var(--pos-color-button-default-hover-background);
+ border-color: var(--pos-color-button-default-hover-frame);
+
+ color: var(--pos-color-button-default-hover-foreground);
+ }
+
+ .pos-button:active {
+ transform: scale(98%);
+ }
+
+ .pos-button:focus-visible {
+ border-color: var(--pos-color-focused);
+ box-shadow: 0 0 6px 1px var(--pos-color-focused);
+ }
+
+ .pos-button:disabled {
+ background-color: var(--pos-color-button-default-disabled-background);
+ border-color: var(--pos-color-button-default-disabled-frame);
+
+ color: var(--pos-color-button-default-disabled-foreground);
+ }
+
+ /* icon */
+ .pos-button svg {
+ width: 1.5rem;
+ height: 1.5rem;
+ flex-shrink: 0;
+
+ fill: currentColor;
+
+ transition: fill .2s ease-in-out;
+ }
+
+ .pos-button:focus-visible svg {
+ fill: var(--color-page);
+ }
+
+ /* label for screen readers */
+ .pos-button .pos-label {
+ position: absolute;
+ left: -200vw;
+ top: -100vh;
+ }
+
+
+
+ /* secondary
+ ============================================================================ */
+ .pos-button-secondary {
+ background-color: var(--pos-color-button-secondary-background);
+ border-color: var(--pos-color-button-secondary-frame);
+
+ color: var(--pos-color-button-secondary-foreground);
+ }
+
+ .pos-button-secondary:hover {
+ background-color: var(--pos-color-button-secondary-hover-background);
+ border-color: var(--pos-color-button-secondary-hover-frame);
+
+ color: var(--pos-color-button-secondary-hover-foreground);
+ }
+
+ .pos-button-secondary:active {
+ transform: scale(98%);
+ }
+
+ .pos-button-secondary:disabled {
+ background-color: var(--pos-color-button-secondary-disabled-background);
+ border-color: var(--pos-color-button-secondary-disabled-frame);
+
+ color: var(--pos-color-button-secondary-disabled-foreground);
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-config.css b/modules/common-styling/public/assets/style/pos-config.css
new file mode 100644
index 0000000..c50aa47
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-config.css
@@ -0,0 +1,479 @@
+/*
+ stores all configurable variables used for styling
+
+ [TO DO: THIS NEEDS TO BE ADJUSTED WITH FIGMA, BOTH WAYS PROBABLY SO WE CAN JUST COPY THE VAR NAME, 1:1 WOULD BE NICE]
+
+ colors
+ light mode
+ dark mode
+ colors based on the choosen theme
+ fonts
+ spacing
+ buttons and inputs shape
+ card and panel shape
+*/
+
+
+
+/* colors
+============================================================================ */
+
+/* colors: light mode
+------------------------------ */
+:root {
+ /* general content */
+ --pos-color-light-content-background: #f7f8fa;
+ --pos-color-light-content-foreground: #384150;
+ --pos-color-light-content-inverted-background: var(--pos-color-content-foreground);
+ --pos-color-light-content-inverted-foreground: var(--pos-color-content-background);
+
+ --pos-color-light-content-supplementary: #6c727f;
+
+ --pos-color-light-focused: #2e70c1; /* outline for focused elements */
+ --pos-color-light-highlighted: #78e677; /* elements that needs user attention */
+
+ /* interactive elements */
+ --pos-color-light-interactive-text: #2e70c1;
+ --pos-color-light-interactive-hover: #214d8e;
+ --pos-color-light-interactive-active: #214d8e;
+ --pos-color-light-interactive-disabled: #daeafb;
+
+ /* colorful elements */
+ --pos-color-light-colorful-background: #299c64;
+ --pos-color-light-colorful-foreground: #fff;
+ --pos-color-light-colorful-hover: #39ac74;
+
+ /* content selection */
+ --pos-color-light-selection-background: #214d8e;
+ --pos-color-light-selection-foreground: #fff;
+
+ /* frames */
+ --pos-color-light-divider: #e2e8f0;
+
+ /* buttons */
+ --pos-color-light-button-default-background: #141414;
+ --pos-color-light-button-default-foreground: #ffffff;
+ --pos-color-light-button-default-frame: var(--pos-color-button-default-background);
+ --pos-color-light-button-default-hover-background: #2e70c1;
+ --pos-color-light-button-default-hover-foreground: #ffffff;
+ --pos-color-light-button-default-hover-frame: var(--pos-color-button-default-frame);
+ --pos-color-light-button-default-disabled-background: #7fa9dd;
+ --pos-color-light-button-default-disabled-foreground: #ffffff;
+ --pos-color-light-button-default-disabled-frame: var(--pos-color-button-default-disabled-background);
+
+ --pos-color-light-button-secondary-background: #ffffff;
+ --pos-color-light-button-secondary-foreground: #2e70c1;
+ --pos-color-light-button-secondary-frame: #e2e8f0;
+ --pos-color-light-button-secondary-hover-background: #ffffff;
+ --pos-color-light-button-secondary-hover-foreground: #141414;
+ --pos-color-light-button-secondary-hover-frame: #141414;
+ --pos-color-light-button-secondary-disabled-background: #ffffff;
+ --pos-color-light-button-secondary-disabled-foreground: #82abdd;
+ --pos-color-light-button-secondary-disabled-frame: var(--pos-color-button-secondary-frame);
+
+ /* links and interactive elements */
+ --pos-color-light-interactive-text: #2e70c1;
+ --pos-color-light-interactive-hover: #214d8e;
+
+ --pos-color-light-navigation-hover: #daeafb;
+
+ /* inputs */
+ --pos-color-light-input-default-placeholder: var(--pos-color-content-supplementary);
+ --pos-color-light-input-default-background: #ffffff;
+ --pos-color-light-input-default-foreground: #384150;
+ --pos-color-light-input-default-border: #6c727f;
+ --pos-color-light-input-default-hover-background: #ffffffX;
+ --pos-color-light-input-default-hover-foreground: #384150;
+ --pos-color-light-input-default-hover-border: var(--pos-color-input-default-border);
+ --pos-color-light-input-default-focus-background: var(--pos-color-input-default-background);
+ --pos-color-light-input-default-focus-foreground: var(--pos-color-input-default-foreground);
+ --pos-color-light-input-default-focus-border: var(--pos-color-input-default-border);
+
+ /* utility */
+ --pos-color-light-important: #b62324;
+ --pos-color-light-important-hover: #c73e37;
+ --pos-color-light-important-disabled: #fccbcb;
+ --pos-color-light-confirmation: #167b16;
+ --pos-color-light-confirmation-hover: #198f6a;
+ --pos-color-light-confirmation-disabled: #bcddd3;
+ --pos-color-light-warning: #f0b357;
+ --pos-color-light-warning-hover: #fcc064;
+ --pos-color-light-warning-disabled: #feeaca;
+}
+
+/* colors: dark mode
+------------------------------ */
+:root {
+ /* general content */
+ --pos-color-dark-content-background: #f7f8fa;
+ --pos-color-dark-content-foreground: #384150;
+ --pos-color-dark-content-inverted-background: var(--pos-color-content-foreground);
+ --pos-color-dark-content-inverted-foreground: var(--pos-color-content-background);
+
+ --pos-color-dark-content-supplementary: #6c727f;
+
+ --pos-color-dark-focused: #2e70c1; /* outline for focused elements */
+ --pos-color-dark-highlighted: #78e677; /* elements that needs user attention */
+
+ /* interactive elements */
+ --pos-color-dark-interactive-text: #2e70c1;
+ --pos-color-dark-interactive-hover: #214d8e;
+ --pos-color-dark-interactive-active: #214d8e;
+ --pos-color-dark-interactive-disabled: #daeafb;
+
+ /* colorful elements */
+ --pos-color-dark-colorful-background: #299c64;
+ --pos-color-dark-colorful-foreground: #fff;
+ --pos-color-dark-colorful-hover: #39ac74;
+
+ /* content selection */
+ --pos-color-dark-selection-background: #214d8e;
+ --pos-color-dark-selection-foreground: #fff;
+
+ /* frames */
+ --pos-color-dark-divider: #e2e8f0;
+
+ /* buttons */
+ --pos-color-dark-button-default-background: #141414;
+ --pos-color-dark-button-default-foreground: #ffffff;
+ --pos-color-dark-button-default-frame: var(--pos-color-button-default-background);
+ --pos-color-dark-button-default-hover-background: #2e70c1;
+ --pos-color-dark-button-default-hover-foreground: #ffffff;
+ --pos-color-dark-button-default-hover-frame: var(--pos-color-button-default-frame);
+ --pos-color-dark-button-default-disabled-background: #7fa9dd;
+ --pos-color-dark-button-default-disabled-foreground: #ffffff;
+ --pos-color-dark-button-default-disabled-frame: var(--pos-color-button-default-disabled-background);
+
+ --pos-color-dark-button-secondary-background: #ffffff;
+ --pos-color-dark-button-secondary-foreground: #2e70c1;
+ --pos-color-dark-button-secondary-frame: #e2e8f0;
+ --pos-color-dark-button-secondary-hover-background: #ffffff;
+ --pos-color-dark-button-secondary-hover-foreground: #141414;
+ --pos-color-dark-button-secondary-hover-frame: #141414;
+ --pos-color-dark-button-secondary-disabled-background: #ffffff;
+ --pos-color-dark-button-secondary-disabled-foreground: #82abdd;
+ --pos-color-dark-button-secondary-disabled-frame: var(--pos-color-button-secondary-frame);
+
+ /* links and interactive elements */
+ --pos-color-dark-interactive-text: #2e70c1;
+ --pos-color-dark-interactive-hover: #214d8e;
+
+ --pos-color-dark-navigation-hover: #daeafb;
+
+ /* inputs */
+ --pos-color-dark-input-default-placeholder: var(--pos-color-content-supplementary);
+ --pos-color-dark-input-default-background: #ffffff;
+ --pos-color-dark-input-default-foreground: #384150;
+ --pos-color-dark-input-default-border: #6c727f;
+ --pos-color-dark-input-default-hover-background: #ffffffX;
+ --pos-color-dark-input-default-hover-foreground: #384150;
+ --pos-color-dark-input-default-hover-border: var(--pos-color-input-default-border);
+ --pos-color-dark-input-default-focus-background: var(--pos-color-input-default-background);
+ --pos-color-dark-input-default-focus-foreground: var(--pos-color-input-default-foreground);
+ --pos-color-dark-input-default-focus-border: var(--pos-color-input-default-border);
+
+ /* utility */
+ --pos-color-dark-important: #b62324;
+ --pos-color-dark-important-hover: #c73e37;
+ --pos-color-dark-important-disabled: #fccbcb;
+ --pos-color-dark-confirmation: #167b16;
+ --pos-color-dark-confirmation-hover: #198f6a;
+ --pos-color-dark-confirmation-disabled: #bcddd3;
+ --pos-color-dark-warning: #f0b357;
+ --pos-color-dark-warning-hover: #fcc064;
+ --pos-color-dark-warning-disabled: #feeaca;
+}
+
+/* colors based on the theme choosen
+------------------------------ */
+:root,
+:root.pos-theme-light {
+ /* general content */
+ --pos-color-content-background: var(--pos-color-light-content-background);
+ --pos-color-content-foreground: var(--pos-color-light-content-foreground);
+ --pos-color-content-inverted-background: var(--pos-color-light-content-inverted-background);
+ --pos-color-content-inverted-foreground: var(--pos-color-light-content-inverted-foreground);
+
+ --pos-color-content-supplementary: var(--pos-color-light-content-supplementary);
+
+ --pos-color-focused: var(--pos-color-light-focused);
+ --pos-color-highlighted: var(--pos-color-light-highlighted);
+
+ /* interactive elements */
+ --pos-color-interactive-text: var(--pos-color-light-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-light-interactive-hover);
+ --pos-color-interactive-active: var(--pos-color-light-interactive-active);
+ --pos-color-interactive-disabled: var(--pos-color-light-interactive-disabled);
+
+ /* colorful elements */
+ --pos-color-colorful-background: var(--pos-color-light-colorful-background);
+ --pos-color-colorful-foreground: var(--pos-color-light-colorful-foreground);
+ --pos-color-colorful-hover: var(--pos-color-light-colorful-hover);
+
+ /* content selection */
+ --pos-color-selection-background: var(--pos-color-light-selection-background);
+ --pos-color-selection-foreground: var(--pos-color-light-selection-foreground);
+
+ /* frames */
+ --pos-color-divider: var(--pos-color-light-divider);
+
+ /* buttons */
+ --pos-color-button-default-background: var(--pos-color-light-button-default-background);
+ --pos-color-button-default-foreground: var(--pos-color-light-button-default-foreground);
+ --pos-color-button-default-frame: var(--pos-color-light-button-default-frame);
+ --pos-color-button-default-hover-background: var(--pos-color-light-button-default-hover-background);
+ --pos-color-button-default-hover-foreground: var(--pos-color-light-button-default-hover-foreground);
+ --pos-color-button-default-hover-frame: var(--pos-color-light-button-default-hover-frame);
+ --pos-color-button-default-disabled-background: var(--pos-color-light-button-default-disabled-background);
+ --pos-color-button-default-disabled-foreground: var(--pos-color-light-button-default-disabled-foreground);
+ --pos-color-button-default-disabled-frame: var(--pos-color-light-button-default-disabled-frame);
+
+ --pos-color-button-secondary-background: var(--pos-color-light-button-secondary-background);
+ --pos-color-button-secondary-foreground: var(--pos-color-light-button-secondary-foreground);
+ --pos-color-button-secondary-frame: var(--pos-color-light-button-secondary-frame);
+ --pos-color-button-secondary-hover-background: var(--pos-color-light-button-secondary-hover-background);
+ --pos-color-button-secondary-hover-foreground: var(--pos-color-light-button-secondary-hover-foreground);
+ --pos-color-button-secondary-hover-frame: var(--pos-color-light-button-secondary-hover-frame);
+ --pos-color-button-secondary-disabled-background: var(--pos-color-light-button-secondary-disabled-background);
+ --pos-color-button-secondary-disabled-foreground: var(--pos-color-light-button-secondary-disabled-foreground);
+ --pos-color-button-secondary-disabled-frame: var(--pos-color-light-button-secondary-disabled-frame);
+
+ /* links and interactive elements */
+ --pos-color-interactive-text: var(--pos-color-light-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-light-interactive-hover);
+
+ --pos-color-navigation-hover: var(--pos-color-light-navigation-hover);
+
+ /* inputs */
+ --pos-color-input-default-placeholder: var(--pos-color-light-input-default-placeholder);
+ --pos-color-input-default-background: var(--pos-color-light-input-default-background);
+ --pos-color-input-default-foreground: var(--pos-color-light-input-default-foreground);
+ --pos-color-input-default-border: var(--pos-color-light-input-default-border);
+ --pos-color-input-default-hover-background: var(--pos-color-light-input-default-hover-background);
+ --pos-color-input-default-hover-foreground: var(--pos-color-light-input-default-hover-foreground);
+ --pos-color-input-default-hover-border: var(--pos-color-light-input-default-hover-border);
+ --pos-color-input-default-focus-background: var(--pos-color-light-input-default-focus-background);
+ --pos-color-input-default-focus-foreground: var(--pos-color-light-input-default-focus-foreground);
+ --pos-color-input-default-focus-border: var(--pos-color-light-input-default-focus-border);
+
+ /* utility */
+ --pos-color-important: var(--pos-color-light-important);
+ --pos-color-important-hover: var(--pos-color-light-important-hover);
+ --pos-color-important-disabled: var(--pos-color-light-important);
+ --pos-color-confirmation: var(--pos-color-light-confirmation);
+ --pos-color-confirmation-hover: var(--pos-color-light-confirmation);
+ --pos-color-confirmation-disabled: var(--pos-color-light-confirmation-disabled);
+ --pos-color-warning: var(--pos-color-light-warning);
+ --pos-color-warning-hover: var(--pos-color-light-warning-hover);
+ --pos-color-warning-disabled: var(--pos-color-light-warning-disabled);
+}
+
+:root.pos-theme-dark {
+ /* general content */
+ --pos-color-content-background: var(--pos-color-dark-content-background);
+ --pos-color-content-foreground: var(--pos-color-dark-content-foreground);
+ --pos-color-content-inverted-background: var(--pos-color-dark-content-inverted-background);
+ --pos-color-content-inverted-foreground: var(--pos-color-dark-content-inverted-foreground);
+
+ --pos-color-content-supplementary: var(--pos-color-dark-content-supplementary);
+
+ --pos-color-focused: var(--pos-color-dark-focused);
+ --pos-color-highlighted: var(--pos-color-dark-highlighted);
+
+ /* interactive elements */
+ --pos-color-interactive-text: var(--pos-color-dark-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-dark-interactive-hover);
+ --pos-color-interactive-active: var(--pos-color-dark-interactive-active);
+ --pos-color-interactive-disabled: var(--pos-color-dark-interactive-disabled);
+
+ /* colorful elements */
+ --pos-color-colorful-background: var(--pos-color-dark-colorful-background);
+ --pos-color-colorful-foreground: var(--pos-color-dark-colorful-foreground);
+ --pos-color-colorful-hover: var(--pos-color-dark-colorful-hover);
+
+ /* content selection */
+ --pos-color-selection-background: var(--pos-color-dark-selection-background);
+ --pos-color-selection-foreground: var(--pos-color-dark-selection-foreground);
+
+ /* frames */
+ --pos-color-divider: var(--pos-color-dark-divider);
+
+ /* buttons */
+ --pos-color-button-default-background: var(--pos-color-dark-button-default-background);
+ --pos-color-button-default-foreground: var(--pos-color-dark-button-default-foreground);
+ --pos-color-button-default-frame: var(--pos-color-dark-button-default-frame);
+ --pos-color-button-default-hover-background: var(--pos-color-dark-button-default-hover-background);
+ --pos-color-button-default-hover-foreground: var(--pos-color-dark-button-default-hover-foreground);
+ --pos-color-button-default-hover-frame: var(--pos-color-dark-button-default-hover-frame);
+ --pos-color-button-default-disabled-background: var(--pos-color-dark-button-default-disabled-background);
+ --pos-color-button-default-disabled-foreground: var(--pos-color-dark-button-default-disabled-foreground);
+ --pos-color-button-default-disabled-frame: var(--pos-color-dark-button-default-disabled-frame);
+
+ --pos-color-button-secondary-background: var(--pos-color-dark-button-secondary-background);
+ --pos-color-button-secondary-foreground: var(--pos-color-dark-button-secondary-foreground);
+ --pos-color-button-secondary-frame: var(--pos-color-dark-button-secondary-frame);
+ --pos-color-button-secondary-hover-background: var(--pos-color-dark-button-secondary-hover-background);
+ --pos-color-button-secondary-hover-foreground: var(--pos-color-dark-button-secondary-hover-foreground);
+ --pos-color-button-secondary-hover-frame: var(--pos-color-dark-button-secondary-hover-frame);
+ --pos-color-button-secondary-disabled-background: var(--pos-color-dark-button-secondary-disabled-background);
+ --pos-color-button-secondary-disabled-foreground: var(--pos-color-dark-button-secondary-disabled-foreground);
+ --pos-color-button-secondary-disabled-frame: var(--pos-color-dark-button-secondary-disabled-frame);
+
+ /* links and interactive elements */
+ --pos-color-interactive-text: var(--pos-color-dark-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-dark-interactive-hover);
+
+ --pos-color-navigation-hover: var(--pos-color-dark-navigation-hover);
+
+ /* inputs */
+ --pos-color-input-default-placeholder: var(--pos-color-dark-input-default-placeholder);
+ --pos-color-input-default-background: var(--pos-color-dark-input-default-background);
+ --pos-color-input-default-foreground: var(--pos-color-dark-input-default-foreground);
+ --pos-color-input-default-border: var(--pos-color-dark-input-default-border);
+ --pos-color-input-default-hover-background: var(--pos-color-dark-input-default-hover-background);
+ --pos-color-input-default-hover-foreground: var(--pos-color-dark-input-default-hover-foreground);
+ --pos-color-input-default-hover-border: var(--pos-color-dark-input-default-hover-border);
+ --pos-color-input-default-focus-background: var(--pos-color-dark-input-default-focus-background);
+ --pos-color-input-default-focus-foreground: var(--pos-color-dark-input-default-focus-foreground);
+ --pos-color-input-default-focus-border: var(--pos-color-dark-input-default-focus-border);
+
+ /* utility */
+ --pos-color-important: var(--pos-color-dark-important);
+ --pos-color-important-hover: var(--pos-color-dark-important-hover);
+ --pos-color-important-disabled: var(--pos-color-dark-important-disabled);
+ --pos-color-confirmation: var(--pos-color-dark-confirmation);
+ --pos-color-confirmation-hover: var(--pos-color-dark-confirmation);
+ --pos-color-confirmation-disabled: var(--pos-color-dark-confirmation-disabled);
+ --pos-color-warning: var(--pos-color-dark-warning);
+ --pos-color-warning-hover: var(--pos-color-dark-warning-hover);
+ --pos-color-warning-disabled: var(--pos-color-dark-warning-disabled);
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ /* general content */
+ --pos-color-content-background: var(--pos-color-dark-content-background);
+ --pos-color-content-foreground: var(--pos-color-dark-content-foreground);
+ --pos-color-content-inverted-background: var(--pos-color-dark-content-inverted-background);
+ --pos-color-content-inverted-foreground: var(--pos-color-dark-content-inverted-foreground);
+
+ --pos-color-content-supplementary: var(--pos-color-dark-content-supplementary);
+
+ --pos-color-focused: var(--pos-color-dark-focused);
+ --pos-color-highlighted: var(--pos-color-dark-highlighted);
+
+ /* interactive elements */
+ --pos-color-interactive-text: var(--pos-color-dark-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-dark-interactive-hover);
+ --pos-color-interactive-active: var(--pos-color-dark-interactive-active);
+ --pos-color-interactive-disabled: var(--pos-color-dark-interactive-disabled);
+
+ /* colorful elements */
+ --pos-color-colorful-background: var(--pos-color-dark-colorful-background);
+ --pos-color-colorful-foreground: var(--pos-color-dark-colorful-foreground);
+ --pos-color-colorful-hover: var(--pos-color-dark-colorful-hover);
+
+ /* content selection */
+ --pos-color-selection-background: var(--pos-color-dark-selection-background);
+ --pos-color-selection-foreground: var(--pos-color-dark-selection-foreground);
+
+ /* frames */
+ --pos-color-divider: var(--pos-color-dark-divider);
+
+ /* buttons */
+ --pos-color-button-default-background: var(--pos-color-dark-button-default-background);
+ --pos-color-button-default-foreground: var(--pos-color-dark-button-default-foreground);
+ --pos-color-button-default-frame: var(--pos-color-dark-button-default-frame);
+ --pos-color-button-default-hover-background: var(--pos-color-dark-button-default-hover-background);
+ --pos-color-button-default-hover-foreground: var(--pos-color-dark-button-default-hover-foreground);
+ --pos-color-button-default-hover-frame: var(--pos-color-dark-button-default-hover-frame);
+ --pos-color-button-default-disabled-background: var(--pos-color-dark-button-default-disabled-background);
+ --pos-color-button-default-disabled-foreground: var(--pos-color-dark-button-default-disabled-foreground);
+ --pos-color-button-default-disabled-frame: var(--pos-color-dark-button-default-disabled-frame);
+
+ --pos-color-button-secondary-background: var(--pos-color-dark-button-secondary-background);
+ --pos-color-button-secondary-foreground: var(--pos-color-dark-button-secondary-foreground);
+ --pos-color-button-secondary-frame: var(--pos-color-dark-button-secondary-frame);
+ --pos-color-button-secondary-hover-background: var(--pos-color-dark-button-secondary-hover-background);
+ --pos-color-button-secondary-hover-foreground: var(--pos-color-dark-button-secondary-hover-foreground);
+ --pos-color-button-secondary-hover-frame: var(--pos-color-dark-button-secondary-hover-frame);
+ --pos-color-button-secondary-disabled-background: var(--pos-color-dark-button-secondary-disabled-background);
+ --pos-color-button-secondary-disabled-foreground: var(--pos-color-dark-button-secondary-disabled-foreground);
+ --pos-color-button-secondary-disabled-frame: var(--pos-color-dark-button-secondary-disabled-frame);
+
+ /* links and interactive elements */
+ --pos-color-interactive-text: var(--pos-color-dark-interactive-text);
+ --pos-color-interactive-hover: var(--pos-color-dark-interactive-hover);
+
+ --pos-color-navigation-hover: var(--pos-color-dark-navigation-hover);
+
+ /* inputs */
+ --pos-color-input-default-placeholder: var(--pos-color-dark-input-default-placeholder);
+ --pos-color-input-default-background: var(--pos-color-dark-input-default-background);
+ --pos-color-input-default-foreground: var(--pos-color-dark-input-default-foreground);
+ --pos-color-input-default-border: var(--pos-color-dark-input-default-border);
+ --pos-color-input-default-hover-background: var(--pos-color-dark-input-default-hover-background);
+ --pos-color-input-default-hover-foreground: var(--pos-color-dark-input-default-hover-foreground);
+ --pos-color-input-default-hover-border: var(--pos-color-dark-input-default-hover-border);
+ --pos-color-input-default-focus-background: var(--pos-color-dark-input-default-focus-background);
+ --pos-color-input-default-focus-foreground: var(--pos-color-dark-input-default-focus-foreground);
+ --pos-color-input-default-focus-border: var(--pos-color-dark-input-default-focus-border);
+
+ /* utility */
+ --pos-color-important: var(--pos-color-dark-important);
+ --pos-color-important-hover: var(--pos-color-dark-important-hover);
+ --pos-color-important-disabled: var(--pos-color-dark-important-disabled);
+ --pos-color-confirmation: var(--pos-color-dark-confirmation);
+ --pos-color-confirmation-hover: var(--pos-color-dark-confirmation);
+ --pos-color-confirmation-disabled: var(--pos-color-dark-confirmation-disabled);
+ --pos-color-warning: var(--pos-color-dark-warning);
+ --pos-color-warning-hover: var(--pos-color-dark-warning-hover);
+ --pos-color-warning-disabled: var(--pos-color-dark-warning-disabled);
+ }
+}
+
+
+/* fonts
+============================================================================ */
+:root {
+ --pos-font-default: system-ui, sans-serif;
+ --pos-font-heading: 'Source Code Pro', 'Consolas', monospace;
+}
+
+
+/* spacing
+============================================================================ */
+:root {
+ --pos-padding-page: 2rem;
+ --pos-padding-panel: 1rem;
+
+ --pos-gap-navigation: 1rem;
+ --pos-gap-list: .2rem;
+}
+
+@media (max-width: 768px) {
+ :root {
+ --pos-padding-page: 1rem;
+ }
+}
+
+
+/* buttons and inputs shape
+============================================================================ */
+:root {
+ --pos-padding-input: 8px;
+
+ --pos-height-input: 44px;
+
+ --pos-border-input: 1px;
+
+ --pos-radius-input: 0;
+ --pos-radius-button: 4px;
+}
+
+
+/* card and panel shape
+============================================================================ */
+:root {
+ --pos-radius-panel: 1rem;
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-forms.css b/modules/common-styling/public/assets/style/pos-forms.css
new file mode 100644
index 0000000..d31f5dd
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-forms.css
@@ -0,0 +1,110 @@
+/*
+ styling for forms and inputs
+
+ general form
+ form paragraphs/fieldsets
+ text inputs
+ textareas
+*/
+
+
+
+@layer common-styling {
+
+ /* page background and font
+ ============================================================================ */
+ .pos-form {
+
+ }
+
+
+ /* form paragraphs/fieldsets
+ ============================================================================ */
+ .pos-form fieldset + fieldset,
+ .pos-form-fieldset {
+ all: unset;
+ display: revert;
+
+ margin-top: var(--pos-gap-navigation);
+ }
+
+
+ /* text inputs
+ ============================================================================ */
+ .pos-form-input {
+ all: unset;
+ display: revert;
+ }
+
+ .pos-form [type="text"],
+ .pos-form-input[type="text"],
+ .pos-form [type="email"],
+ .pos-form-input[type="email"],
+ .pos-form [type="password"],
+ .pos-form-input[type="password"],
+ .pos-form [type="url"],
+ .pos-form-input[type="url"] {
+ height: var(--pos-height-input);
+ padding-inline: var(--pos-padding-input);
+
+ border-radius: var(--pos-radius-input);
+ border-width: var(--pos-border-input);
+ border-style: solid;
+ border-color: var(--pos-color-input-default-border);
+ border-radius: var(--pos-radius-input);
+ outline: none;
+ background-color: var(--pos-color-input-default-background);
+
+ color: var(--pos-color-input-default-foreground);
+
+ transition: all .2s linear;
+ }
+
+ .pos-form [type="text"]:hover:not(:focus),
+ .pos-form-input[type="text"]:hover:not(:focus),
+ .pos-form [type="email"]:hover:not(:focus),
+ .pos-form-input[type="email"]:hover:not(:focus),
+ .pos-form [type="password"]:hover:not(:focus),
+ .pos-form-input[type="password"]:hover:not(:focus),
+ .pos-form [type="url"]:hover:not(:focus),
+ .pos-form-input[type="url"]:hover:not(:focus) {
+ background-color: var(--pos-color-input-default-hover-background);
+ border-color: var(--pos-color-input-default-hover-border);
+
+ color: var(--pos-color-input-default-hover-foreground);
+ }
+
+ .pos-form [type="text"]:focus,
+ .pos-form-input[type="text"]:focus,
+ .pos-form [type="email"]:focus,
+ .pos-form-input[type="email"]:focus,
+ .pos-form [type="password"]:focus,
+ .pos-form-input[type="password"]:focus,
+ .pos-form [type="url"]:focus,
+ .pos-form-input[type="url"]:focus {
+ background-color: var(--pos-color-input-default-focus-background);
+ border-color: var(--pos-color-input-default-focus-border);
+
+ color: var(--pos-color-input-default-focus-foreground);
+ }
+
+ .pos-form [type="text"]:focus-visible,
+ .pos-form-input[type="text"]:focus-visible,
+ .pos-form [type="email"]:focus-visible,
+ .pos-form-input[type="email"]:focus-visible,
+ .pos-form [type="password"]:focus-visible,
+ .pos-form-input[type="password"]:focus-visible,
+ .pos-form [type="url"]:focus-visible,
+ .pos-form-input[type="url"]:focus-visible {
+ box-shadow: 0 0 0 2px var(--pos-color-focused);
+ }
+
+
+ /* textareas
+ ============================================================================ */
+ .pos-form textarea {
+ all: unset;
+ display: revert;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-page.css b/modules/common-styling/public/assets/style/pos-page.css
new file mode 100644
index 0000000..893db77
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-page.css
@@ -0,0 +1,35 @@
+/*
+ defines global page structure and looks
+
+ page background and font
+*/
+
+
+
+@layer common-styling {
+
+ /* page background and font
+ ============================================================================ */
+
+ .pos-app body {
+ min-height: 100%;
+ min-height: 100dvh;
+ padding: var(--pos-padding-page);
+ display: flex;
+ flex-direction: column;
+
+ background-color: var(--pos-color-content-background);
+
+ text-rendering: optimizeLegibility;
+ text-wrap: balance;
+ font-family: var(--pos-font-default);
+ color: var(--pos-color-content-foreground);
+ }
+
+ .pos-app ::selection {
+ background-color: var(--pos-color-selection-background);
+
+ color: var(--pos-color-selection-foreground);
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-reset.css b/modules/common-styling/public/assets/style/pos-reset.css
new file mode 100644
index 0000000..da74a46
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-reset.css
@@ -0,0 +1,81 @@
+/*
+ resets default browser styling and fixes some browser-specific issues
+ based on https://elad2412.github.io/the-new-css-reset/
+*/
+
+
+
+@layer common-styling {
+
+ :where(.pos-app) *:where(:not(html, iframe, canvas, img, svg, video, audio, input):not(svg *, symbol *)) {
+ all: unset;
+ display: revert;
+ }
+
+ :where(.pos-app) *,
+ :where(.pos-app) *::before,
+ :where(.pos-app) *::after {
+ box-sizing: border-box;
+ }
+
+ :where(.pos-app) a,
+ :where(.pos-app) button {
+ cursor: revert;
+ }
+
+ :where(.pos-app) label {
+ cursor: pointer;
+ }
+
+ :where(.pos-app) ol, :where(.pos-app) ul, :where(.pos-app) menu {
+ list-style: none;
+ }
+
+ :where(.pos-app) img {
+ max-width: 100%;
+ height: auto;
+ }
+
+ :where(.pos-app) table {
+ border-collapse: collapse;
+ }
+
+ :where(.pos-app) input, :where(.pos-app) textarea {
+ -webkit-user-select: auto;
+ }
+
+ :where(.pos-app) textarea {
+ white-space: revert;
+ }
+
+ :where(.pos-app) meter {
+ -webkit-appearance: revert;
+ appearance: revert;
+ }
+
+ :where(.pos-app) ::placeholder {
+ color: unset;
+ }
+
+ :where(.pos-app) :where([hidden]) {
+ display: none;
+ }
+
+ :where(.pos-app) :where([contenteditable]:not([contenteditable="false"])) {
+ -moz-user-modify: read-write;
+ -webkit-user-modify: read-write;
+ overflow-wrap: break-word;
+ -webkit-line-break: after-white-space;
+ -webkit-user-select: auto;
+ }
+
+ :where(.pos-app) :where([draggable="true"]) {
+ -webkit-user-drag: element;
+ }
+
+ :where(.pos-app) q:before,
+ :where(.pos-app) q:after {
+ display: none;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-toast.css b/modules/common-styling/public/assets/style/pos-toast.css
new file mode 100644
index 0000000..90390fe
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-toast.css
@@ -0,0 +1,136 @@
+/*
+ toast messages
+
+ container
+ message
+ variants
+ close button
+*/
+
+
+
+@layer common-styling {
+
+ /* container
+ ============================================================================ */
+ .pos-toasts {
+ width: 300px;
+ position: fixed;
+ inset-block-end: var(--pos-padding-page);
+ inset-inline-start: var(--pos-padding-page);
+ display: flex;
+ flex-direction: column;
+ gap: var(--pos-gap-navigation);
+ }
+
+ .pos-toast * {
+ box-sizing: border-box;
+ }
+
+
+ /* message
+ ============================================================================ */
+ .pos-toast {
+ padding: calc(var(--pos-padding-panel) / 2) var(--pos-padding-panel);
+ display: flex;
+ justify-content: space-between;
+
+ border-width: 1px;
+ border-style: solid;
+ border-color: var(--pos-color-content-background);
+ border-radius: var(--pos-radius-panel);
+ background-color: var(--pos-color-content-background);
+
+ text-box-trim: trim-both;
+ }
+
+ .pos-toast-loading {
+ overflow: hidden;
+
+ animation-name: pos-toast-in;
+ animation-duration: 1s;
+ animation-timing-function: ease-in-out;
+ }
+
+ @keyframes pos-toast-in {
+ from {
+ max-height: 0;
+ }
+ to {
+ max-height: 400px;
+ }
+ }
+
+ .pos-toast-unloading {
+ animation-name: pos-toast-out;
+ animation-duration: .4s;
+ animation-timing-function: ease-in-out;
+ }
+
+ @keyframes pos-toast-out {
+ 0% {
+ max-height: 400px;
+
+ translate: 0 0;
+ }
+
+ 100% {
+ max-height: 0;
+
+ translate: -400px 0;
+ }
+ }
+
+
+ /* variants
+ ============================================================================ */
+ .pos-toast-success .pos-toast {
+ border-color: var(--pos-color-confirmation);
+ background-color: var(--pos-color-confirmation-disabled);
+ }
+
+ .pos-toast-error .pos-toast {
+ border-color: var(--pos-color-important);
+ background-color: var(--pos-color-important-disabled);
+ }
+
+ .pos-toast-info .pos-toast {
+ border-color: var(--pos-color-warning);
+ background-color: var(--pos-color-warning-disabled);
+ }
+
+
+ /* close button
+ ============================================================================ */
+ .pos-toast-close {
+ margin-inline-end: calc(var(--pos-padding-panel) / -2);
+ padding: 0 .5em;
+ align-self: start;
+
+ cursor: pointer;
+
+ transition: color .1s linear
+ }
+
+ .pos-toast-close .label {
+ position: absolute;
+ left: -100vw;
+ }
+
+ .pos-toast-success .pos-toast-close {
+ color: var(--pos-color-confirmation);
+ }
+
+ .pos-toast-error .pos-toast-close {
+ color: var(--pos-color-important);
+ }
+
+ .pos-toast-info .pos-toast-close {
+ color: var(--pos-color-warning);
+ }
+
+ .pos-toast-close:hover {
+ color: var(--pos-color-content-foreground);
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/assets/style/pos-typography.css b/modules/common-styling/public/assets/style/pos-typography.css
new file mode 100644
index 0000000..a49c7d8
--- /dev/null
+++ b/modules/common-styling/public/assets/style/pos-typography.css
@@ -0,0 +1,47 @@
+/*
+ defines fonts, paragraphs and headings
+
+ links
+ headings
+*/
+
+
+
+@layer common-styling {
+
+ /* links
+ ============================================================================ */
+ a {
+ color: var(--pos-color-interactive);
+
+ transition: color .1s linear;
+ }
+
+ a:hover {
+ color: var(--pos-color-interactive-hover);
+ }
+
+ a:active {
+ color: var(--pos-color-interactive-active)
+ }
+
+ a:focus-visible {
+ color: var(--pos-color-interactive-hover);
+ }
+
+
+ /* headings
+ ============================================================================ */
+ .pos-heading-1 {
+
+ }
+
+ .pos-heading-2 {
+ display: block;
+
+ font-family: var(--pos-font-heading);
+ font-size: 2rem;
+ font-weight: 500;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/common-styling/public/translations/en.yml b/modules/common-styling/public/translations/en.yml
new file mode 100644
index 0000000..6ae7440
--- /dev/null
+++ b/modules/common-styling/public/translations/en.yml
@@ -0,0 +1,3 @@
+en:
+ toast:
+ close: Dismiss notification
diff --git a/modules/common-styling/public/views/partials/toasts.liquid b/modules/common-styling/public/views/partials/toasts.liquid
new file mode 100644
index 0000000..9b9f47b
--- /dev/null
+++ b/modules/common-styling/public/views/partials/toasts.liquid
@@ -0,0 +1,35 @@
+{% liquid
+ assign autohide = autohide | default: params.autohide
+ assign delay = delay | default: params.delay | default: 1000
+ assign message = message | default: params.message | default: null
+ assign severity = severity | default: params.severity
+%}
+
+
+
+
+
+
+
+
+
+ {{ 'modules/common-styling/toast.close' | t }}
+ ×
+
+
+
+
+
+ {% if message %}
+
+ {% endif %}
+
+
+
\ No newline at end of file
diff --git a/modules/common-styling/public/views/partials/user/avatar.liquid b/modules/common-styling/public/views/partials/user/avatar.liquid
new file mode 100644
index 0000000..3f1cc43
--- /dev/null
+++ b/modules/common-styling/public/views/partials/user/avatar.liquid
@@ -0,0 +1,39 @@
+{% liquid
+ assign size = size | default: params.size | default: 'md'
+ assign class = class | default: params.class
+ assign name = name | default: params.name
+ assign imageSrc = imageSrc | default: params.imageSrc
+
+ assign names = name | split: " "
+
+ case size
+ when 'xs'
+ assign dimensions = 20
+ when 'sm'
+ assign dimensions = 24
+ when 'md'
+ assign dimensions = 32
+ when 'lg'
+ assign dimensions = 48
+ when 'xl'
+ assign dimensions = 94
+ when '2xl'
+ assign dimensions = 160
+ when '3xl'
+ assign dimensions = 192
+ endcase
+%}
+
+{% if imageSrc == blank %}
+
+
+ {{ names[0] | slice: 0 }}{{ names[1] | slice: 0 }}
+
+
+{% else %}
+
+
+
+
+
+{% endif %}
diff --git a/modules/common-styling/template-values.json b/modules/common-styling/template-values.json
new file mode 100644
index 0000000..dad8073
--- /dev/null
+++ b/modules/common-styling/template-values.json
@@ -0,0 +1,7 @@
+{
+ "name": "platformOS common styling",
+ "machine_name": "common-styling",
+ "type": "module",
+ "version": "0.0.14",
+ "dependencies": {}
+}
\ No newline at end of file
diff --git a/modules/core/generators/command/index.js b/modules/core/generators/command/index.js
new file mode 100644
index 0000000..329fd3f
--- /dev/null
+++ b/modules/core/generators/command/index.js
@@ -0,0 +1,46 @@
+const Generator = require('yeoman-generator');
+const path = require('path');
+const pluralize = require('pluralize');
+const fs = require('fs');
+
+module.exports = class extends Generator {
+ constructor(args, opts) {
+ super(args, opts);
+
+ this.description = 'Generate basic command files with build and check phase';
+ this.argument('commandName', { type: String, required: true, description: 'name of the command' });
+ this.props = {
+ commandName: this.options.commandName,
+ actionName: this.options.commandName.split('/').pop(),
+ modelName: this.options.commandName.split('/')[0]
+ };
+ }
+
+ writing() {
+ try{
+ this.fs.copyTpl(
+ this.templatePath('./lib/commands/create.liquid'),
+ this.destinationPath(`app/lib/commands/${this.props.commandName}.liquid`),
+ this.props
+ )
+
+ this.fs.copyTpl(
+ this.templatePath('./lib/commands/create/'),
+ this.destinationPath(`app/lib/commands/${this.props.commandName}/`),
+ this.props
+ )
+
+ this.fs.copyTpl(
+ this.templatePath('./graphql/create.graphql'),
+ this.destinationPath(`app/graphql/${this.props.commandName}.graphql`),
+ this.props
+ )
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ end() {
+ console.log('Command generated');
+ }
+};
diff --git a/modules/core/generators/command/templates/graphql/create.graphql b/modules/core/generators/command/templates/graphql/create.graphql
new file mode 100644
index 0000000..0ffb1e5
--- /dev/null
+++ b/modules/core/generators/command/templates/graphql/create.graphql
@@ -0,0 +1,20 @@
+mutation <%= actionName %>(
+ # some arguments
+ # $foo: String!
+) {
+ record: record_create(
+ record: {
+ table: "<%= modelName %>"
+ properties: [
+ # { name: "foo" property: $foo }
+ ]
+ }
+ ){
+ id
+ created_at
+ deleted_at
+ type: table
+
+ # foo: (name: "foo")
+ }
+}
diff --git a/modules/core/generators/command/templates/lib/commands/create.liquid b/modules/core/generators/command/templates/lib/commands/create.liquid
new file mode 100644
index 0000000..6d7102e
--- /dev/null
+++ b/modules/core/generators/command/templates/lib/commands/create.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ function object = 'commands/<%= commandName %>/build', object: object
+ function object = 'commands/<%= commandName %>/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: '<%= commandName %>' object: object
+ endif
+
+ return object
+%}
diff --git a/modules/core/generators/command/templates/lib/commands/create/build.liquid b/modules/core/generators/command/templates/lib/commands/create/build.liquid
new file mode 100644
index 0000000..6a83151
--- /dev/null
+++ b/modules/core/generators/command/templates/lib/commands/create/build.liquid
@@ -0,0 +1,4 @@
+{% liquid
+ assign data = null | hash_merge: id: object.id, name: object.name
+ return data
+%}
diff --git a/modules/core/generators/command/templates/lib/commands/create/check.liquid b/modules/core/generators/command/templates/lib/commands/create/check.liquid
new file mode 100644
index 0000000..8f3da9c
--- /dev/null
+++ b/modules/core/generators/command/templates/lib/commands/create/check.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'name'
+
+ assign object = object | hash_merge: c
+
+ return object
+%}
diff --git a/modules/core/generators/crud/index.js b/modules/core/generators/crud/index.js
new file mode 100644
index 0000000..a97a592
--- /dev/null
+++ b/modules/core/generators/crud/index.js
@@ -0,0 +1,116 @@
+const Generator = require('yeoman-generator');
+const pluralize = require('pluralize');
+const startCase = require('lodash.startcase');
+
+module.exports = class extends Generator {
+ constructor(args, opts) {
+ super(args, opts);
+
+ this.description = 'Generate table definition and commands for CRUD with graphql files';
+ this.argument('modelName', { type: String, required: true, description: 'name of the table' });
+ this.argument('attributes', { type: Array, required: false, description: 'table column names with types', default: [] });
+ this.option('include-views', { type: Boolean, default: false, description: 'generate pages and partials', hide: 'no' });
+
+ const attributes = this.options.attributes.map((attr) => {
+ const values = attr.split(':');
+ return {
+ name: values[0],
+ nameHuman: startCase(values[0]),
+ type: values[1]
+ };
+ });
+ this.props = {
+ modelName: this.options.modelName,
+ modelNamePlural: pluralize(this.options.modelName),
+ attributes: attributes,
+ graphqlArgumentMap: {
+ string: "String",
+ text: "String",
+ integer: "Int",
+ boolean: "Boolean",
+ float: "Float",
+ date: "String",
+ datetime: "String",
+ array: "[String]"
+ },
+ graphqlArgumentValueMap: {
+ string: "value",
+ text: "value",
+ integer: "value_int",
+ boolean: "value_boolean",
+ float: "value_float",
+ date: "value",
+ datetime: "value",
+ array: "value_array"
+ },
+ graphqlPropertyMap: {
+ string: "property",
+ text: "property",
+ integer: "property_int",
+ boolean: "property_boolean",
+ float: "property_float",
+ date: "property",
+ datetime: "property",
+ array: "property_array"
+ }
+ };
+ }
+
+ writing() {
+ try{
+ this.fs.copyTpl(
+ this.templatePath('./translations/model.yml'),
+ this.destinationPath(`app/translations/en/${this.props.modelNamePlural}.yml`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./schema/model.yml'),
+ this.destinationPath(`app/schema/${this.props.modelName}.yml`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./graphql/*.graphql'),
+ this.destinationPath(`app/graphql/${this.props.modelNamePlural}/`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./lib/queries/model'),
+ this.destinationPath(`app/lib/queries/${this.props.modelNamePlural}`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./lib/commands/model'),
+ this.destinationPath(`app/lib/commands/${this.props.modelNamePlural}`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./config.yml'),
+ this.destinationPath(`app/config.yml`),
+ this.props
+ )
+ if(this.options['include-views']){
+ this.fs.copyTpl(
+ this.templatePath('./views/pages/model'),
+ this.destinationPath(`app/views/pages/${this.props.modelNamePlural}`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./views/partials/theme/simple/model'),
+ this.destinationPath(`app/views/partials/theme/simple/${this.props.modelNamePlural}`),
+ this.props
+ )
+ this.fs.copyTpl(
+ this.templatePath('./views/partials/theme/simple/field_error.liquid'),
+ this.destinationPath(`app/views/partials/theme/simple/field_error.liquid`),
+ this.props
+ )
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ end() {
+ console.log('CRUD generated');
+ }
+};
diff --git a/modules/core/generators/crud/templates/config.yml b/modules/core/generators/crud/templates/config.yml
new file mode 100644
index 0000000..45cd4ce
--- /dev/null
+++ b/modules/core/generators/crud/templates/config.yml
@@ -0,0 +1,16 @@
+---
+escape_output_instead_of_sanitize: true
+graphql_argument_type_mismatch_mode: 'error'
+liquid_add_old_variables: false
+liquid_check_mode: 'error'
+liquid_raise_mode: true
+require_table_for_record_delete_mutation: true
+safe_translate: true
+skip_elasticsearch: false
+slug_exact_match: true
+websockets_require_csrf_token: true
+maintenance:
+ enabled: false
+ password_constant: 'MAINTENANCE_PASSWORD'
+ partial: 'maintenance'
+---
diff --git a/modules/core/generators/crud/templates/graphql/create.graphql b/modules/core/generators/crud/templates/graphql/create.graphql
new file mode 100644
index 0000000..67905af
--- /dev/null
+++ b/modules/core/generators/crud/templates/graphql/create.graphql
@@ -0,0 +1,25 @@
+mutation create_<%= modelName %>(
+<% attributes.forEach((attr) => { -%>
+ $<%= attr.name %>: <%= graphqlArgumentMap[attr.type] %>!
+<% }); -%>
+) {
+ record: record_create(
+ record: {
+ table: "<%= modelName %>"
+ properties: [
+ <% attributes.forEach((attr) => { -%>
+ { name: "<%= attr.name %>" <%= graphqlArgumentValueMap[attr.type] %>: $<%= attr.name %> }
+ <% }); -%>
+ ]
+ }
+ ){
+ id
+ created_at
+ deleted_at
+ type: table
+
+ <% attributes.forEach((attr) => { -%>
+ <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>")
+ <% }); -%>
+ }
+}
diff --git a/modules/core/generators/crud/templates/graphql/delete.graphql b/modules/core/generators/crud/templates/graphql/delete.graphql
new file mode 100644
index 0000000..c77948f
--- /dev/null
+++ b/modules/core/generators/crud/templates/graphql/delete.graphql
@@ -0,0 +1,6 @@
+mutation delete($id: ID!) {
+ record: record_delete(
+ table: "<%= modelName %>"
+ id: $id
+ ){ id }
+}
diff --git a/modules/core/generators/crud/templates/graphql/search.graphql b/modules/core/generators/crud/templates/graphql/search.graphql
new file mode 100644
index 0000000..a22b2fd
--- /dev/null
+++ b/modules/core/generators/crud/templates/graphql/search.graphql
@@ -0,0 +1,39 @@
+query search(
+ $id: ID
+ $limit: Int = 20
+ $page: Int = 1
+<% attributes.forEach((attr) => { -%>
+ $<%= attr.name %>: String
+<% }); -%>
+) {
+ <%= modelNamePlural %>: records(
+ per_page: $limit
+ page: $page
+ filter: {
+ id: { value: $id }
+ table: { value: "<%= modelName %>" }
+ properties: [
+ <% attributes.forEach((attr) => { -%>
+ { name: "<%= attr.name %>" value: $<%= attr.name %> }
+ <% }); -%>
+ ]
+ }
+ sort: [
+ { created_at: { order: DESC }}
+ ]
+ ){
+ total_entries
+ total_pages
+ has_previous_page
+ has_next_page
+ results {
+ id
+ created_at
+ type: table
+
+ <% attributes.forEach((attr) => { -%>
+ <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>")
+ <% }); -%>
+ }
+ }
+}
diff --git a/modules/core/generators/crud/templates/graphql/update.graphql b/modules/core/generators/crud/templates/graphql/update.graphql
new file mode 100644
index 0000000..73e4556
--- /dev/null
+++ b/modules/core/generators/crud/templates/graphql/update.graphql
@@ -0,0 +1,27 @@
+mutation update_<%= modelName %>(
+ $id: ID!
+<% attributes.forEach((attr) => { -%>
+ $<%= attr.name %>: <%= graphqlArgumentMap[attr.type] %>
+<% }); -%>
+) {
+ record: record_update(
+ id: $id
+ record: {
+ table: "<%= modelName %>"
+ properties: [
+ <% attributes.forEach((attr) => { -%>
+ { name: "<%= attr.name %>" <%= graphqlArgumentValueMap[attr.type] %>: $<%= attr.name %> }
+ <% }); -%>
+ ]
+ }
+ ){
+ id
+ created_at
+ updated_at
+ type: table
+
+ <% attributes.forEach((attr) => { -%>
+ <%= attr.name %>: <%= graphqlPropertyMap[attr.type] %>(name: "<%= attr.name %>")
+ <% }); -%>
+ }
+}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/create.liquid b/modules/core/generators/crud/templates/lib/commands/model/create.liquid
new file mode 100644
index 0000000..26b0a03
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/create.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ function object = 'commands/<%= modelNamePlural %>/create/build', object: object
+ function object = 'commands/<%= modelNamePlural %>/create/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/create' object: object
+ endif
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid b/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid
new file mode 100644
index 0000000..94a17bf
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/create/build.liquid
@@ -0,0 +1,16 @@
+{% parse_json object %}
+ {
+ "id": {{ object.id | json }},
+<% attributes.forEach((attr, i) => { -%>
+ <% if (attr.type == 'integer' || attr.type == 'float') { %>
+ "<%= attr.name %>": {{ object.<%= attr.name %> | plus: 0 | json }}<% if (i+1 < attributes.length){ %>,<% } %>
+ <%} else { %>
+ "<%= attr.name %>": {{ object.<%= attr.name %> | json }}<% if (i+1 < attributes.length){ %>,<% } %>
+ <% } %>
+<% }); -%>
+ }
+{% endparse_json %}
+
+{% liquid
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid b/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid
new file mode 100644
index 0000000..df36e79
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/create/check.liquid
@@ -0,0 +1,11 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+<% attributes.forEach((attr, i) => { -%>
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: '<%= attr.name %>'
+<% }); -%>
+
+ assign object = object | hash_merge: valid: c.valid, errors: c.errors
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/delete.liquid b/modules/core/generators/crud/templates/lib/commands/model/delete.liquid
new file mode 100644
index 0000000..1ce0a60
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/delete.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ function object = 'commands/<%= modelNamePlural %>/delete/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/delete', object: object
+ endif
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid b/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid
new file mode 100644
index 0000000..4ae7fc6
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/delete/check.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ assign c = '{ "valid": true, "errors": {} }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+
+ assign object = object | hash_merge: valid: c.valid, errors: c.errors
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/update.liquid b/modules/core/generators/crud/templates/lib/commands/model/update.liquid
new file mode 100644
index 0000000..29a229c
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/update.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ function object = 'commands/<%= modelNamePlural %>/update/build', object: object
+ function object = 'commands/<%= modelNamePlural %>/update/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: '<%= modelNamePlural %>/update' object: object
+ endif
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid b/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid
new file mode 100644
index 0000000..94a17bf
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/update/build.liquid
@@ -0,0 +1,16 @@
+{% parse_json object %}
+ {
+ "id": {{ object.id | json }},
+<% attributes.forEach((attr, i) => { -%>
+ <% if (attr.type == 'integer' || attr.type == 'float') { %>
+ "<%= attr.name %>": {{ object.<%= attr.name %> | plus: 0 | json }}<% if (i+1 < attributes.length){ %>,<% } %>
+ <%} else { %>
+ "<%= attr.name %>": {{ object.<%= attr.name %> | json }}<% if (i+1 < attributes.length){ %>,<% } %>
+ <% } %>
+<% }); -%>
+ }
+{% endparse_json %}
+
+{% liquid
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid b/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid
new file mode 100644
index 0000000..c991577
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/commands/model/update/check.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+<% attributes.forEach((attr, i) => { -%>
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: '<%= attr.name %>'
+<% }); -%>
+
+ assign object = object | hash_merge: valid: c.valid, errors: c.errors
+
+ return object
+%}
diff --git a/modules/core/generators/crud/templates/lib/queries/model/find.liquid b/modules/core/generators/crud/templates/lib/queries/model/find.liquid
new file mode 100644
index 0000000..7f84e12
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/queries/model/find.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ if id == blank
+ return null
+ endif
+
+ graphql r = '<%= modelNamePlural %>/search', id: id, limit: 1
+
+ return r.<%= modelNamePlural %>.results.first
+%}
diff --git a/modules/core/generators/crud/templates/lib/queries/model/search.liquid b/modules/core/generators/crud/templates/lib/queries/model/search.liquid
new file mode 100644
index 0000000..369ec37
--- /dev/null
+++ b/modules/core/generators/crud/templates/lib/queries/model/search.liquid
@@ -0,0 +1,4 @@
+{% liquid
+ graphql r = '<%= modelNamePlural %>/search', limit: limit, page: 1
+ return r.<%= modelNamePlural %>
+%}
diff --git a/modules/core/generators/crud/templates/schema/model.yml b/modules/core/generators/crud/templates/schema/model.yml
new file mode 100644
index 0000000..380c67b
--- /dev/null
+++ b/modules/core/generators/crud/templates/schema/model.yml
@@ -0,0 +1,6 @@
+name: <%= modelName %>
+properties:
+<% attributes.forEach((attr) => { -%>
+ - name: <%= attr.name %>
+ type: <%= attr.type %>
+<% }); -%>
diff --git a/modules/core/generators/crud/templates/translations/model.yml b/modules/core/generators/crud/templates/translations/model.yml
new file mode 100644
index 0000000..879b076
--- /dev/null
+++ b/modules/core/generators/crud/templates/translations/model.yml
@@ -0,0 +1,15 @@
+en:
+ app:
+ <%= modelNamePlural %>:
+ new:
+ new: New <%= modelName %>
+ edit:
+ edit: Edit <%= modelName %>
+ list:
+ add: Add <%= modelName %>
+ empty_state: You haven't added any <%= modelNamePlural %> yet. Create your first one now!
+ edit: Edit
+ attr:
+ <% attributes.forEach((attr) => { -%>
+ <%= attr.name %>: <%= attr.nameHuman %>
+ <% }); -%>
diff --git a/modules/core/generators/crud/templates/views/pages/model/create.liquid b/modules/core/generators/crud/templates/views/pages/model/create.liquid
new file mode 100644
index 0000000..cf27c95
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/create.liquid
@@ -0,0 +1,14 @@
+---
+slug: <%= modelNamePlural %>
+method: post
+---
+{% liquid
+ function object = 'commands/<%= modelNamePlural %>/create', object: context.params.<%= modelName %>
+ if object.valid
+ # platformos-check-disable ConvertIncludeToRender
+ include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>'
+ # platformos-check-enable ConvertIncludeToRender
+ else
+ render 'theme/simple/<%= modelNamePlural %>/new', object: object
+ endif
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/delete.liquid b/modules/core/generators/crud/templates/views/pages/model/delete.liquid
new file mode 100644
index 0000000..f8781f5
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/delete.liquid
@@ -0,0 +1,16 @@
+---
+slug: <%= modelNamePlural %>
+method: delete
+---
+{% liquid
+ function object = 'queries/<%= modelNamePlural %>/find', id: context.params.id
+ function object = 'commands/<%= modelNamePlural %>/delete', object: object
+
+ # platformos-check-disable ConvertIncludeToRender
+ if object.valid
+ include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>', notice: 'app.models.shared.deleted'
+ else
+ include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>', error: 'app.models.shared.delete_failed'
+ endif
+ # platformos-check-enable ConvertIncludeToRender
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/edit.liquid b/modules/core/generators/crud/templates/views/pages/model/edit.liquid
new file mode 100644
index 0000000..b098d38
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/edit.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ function object = 'queries/<%= modelNamePlural %>/find', id: context.params.id
+
+ render 'theme/simple/<%= modelNamePlural %>/edit', object: object
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/index.liquid b/modules/core/generators/crud/templates/views/pages/model/index.liquid
new file mode 100644
index 0000000..75290a7
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/index.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ function <%= modelNamePlural %> = 'queries/<%= modelNamePlural %>/search', limit: 100
+
+ render 'theme/simple/<%= modelNamePlural %>/index', <%= modelNamePlural %>: <%= modelNamePlural %>
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/new.liquid b/modules/core/generators/crud/templates/views/pages/model/new.liquid
new file mode 100644
index 0000000..cb0e37a
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/new.liquid
@@ -0,0 +1,4 @@
+{% liquid
+ assign object = '{}' | parse_json
+ render 'theme/simple/<%= modelNamePlural %>/new', object: object
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/show.liquid b/modules/core/generators/crud/templates/views/pages/model/show.liquid
new file mode 100644
index 0000000..c9672cc
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/show.liquid
@@ -0,0 +1,13 @@
+---
+slug: <%= modelNamePlural %>/:id
+---
+{% liquid
+
+ assign <%= modelName %>_id = context.params.id | split: '-' | last
+ function <%= modelName %> = 'queries/<%= modelNamePlural %>/find', id: <%= modelName %>_id
+ if <%= modelName %>.id
+ render 'theme/simple/<%= modelNamePlural %>/show', <%= modelName %>: <%= modelName %>
+ else
+ response_status 404
+ endif
+%}
diff --git a/modules/core/generators/crud/templates/views/pages/model/update.liquid b/modules/core/generators/crud/templates/views/pages/model/update.liquid
new file mode 100644
index 0000000..06644bd
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/pages/model/update.liquid
@@ -0,0 +1,14 @@
+---
+slug: <%= modelNamePlural %>
+method: put
+---
+{% liquid
+ function object = 'commands/<%= modelNamePlural %>/update', object: context.params.<%= modelName %>
+ if object.valid
+ # platformos-check-disable ConvertIncludeToRender
+ include 'modules/core/helpers/redirect_to', url: '/<%= modelNamePlural %>'
+ # platformos-check-enable ConvertIncludeToRender
+ else
+ render 'theme/simple/<%= modelNamePlural %>/edit', object: object
+ endif
+%}
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid
new file mode 100644
index 0000000..16d306b
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/field_error.liquid
@@ -0,0 +1,5 @@
+{% if errors %}
+
+ {{ errors | join: ', ' }}
+
+{% endif %}
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid
new file mode 100644
index 0000000..6bd91f2
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/edit.liquid
@@ -0,0 +1,5 @@
+
+
{{ 'app.<%= modelNamePlural %>.edit.edit' | t }} {{ object.name }}
+
+
+{% render 'theme/simple/<%= modelNamePlural %>/form', object: object %}
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid
new file mode 100644
index 0000000..5abe317
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/empty_state.liquid
@@ -0,0 +1,9 @@
+
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid
new file mode 100644
index 0000000..e12d1ee
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/form.liquid
@@ -0,0 +1,27 @@
+{% liquid
+ if object.id
+ assign method = 'put'
+ else
+ assign method = 'post'
+ endif
+%}
+
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid
new file mode 100644
index 0000000..352f7a0
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/index.liquid
@@ -0,0 +1,49 @@
+
+
+
+ {% if <%= modelNamePlural %>.results.size > 0 %}
+
+
+
+<% attributes.forEach((attr) => { -%>
+
+ {{ "app.<%= modelNamePlural %>.attr.<%= attr.name %>" | t }}
+
+<% }); -%>
+
+
+
+ {% for <%= modelName %> in <%= modelNamePlural %>.results %}
+
+<% attributes.forEach((attr) => { -%>
+
+
+ {{ <%= modelName %>.<%= attr.name %> }}
+
+
+<% }); -%>
+
+
+ {{ 'app.<%= modelNamePlural %>.list.edit' | t }}
+
+
+
+
+ {% endfor %}
+
+
+ {% else %}
+ {% render 'theme/simple/<%= modelNamePlural %>/empty_state' %}
+ {% endif %}
+
+
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid
new file mode 100644
index 0000000..e15a8d4
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/new.liquid
@@ -0,0 +1,4 @@
+
+
{{ 'app.<%= modelNamePlural %>.new.new' | t }}
+ {% render 'theme/simple/<%= modelNamePlural %>/form', object: object %}
+
diff --git a/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid b/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid
new file mode 100644
index 0000000..483dd89
--- /dev/null
+++ b/modules/core/generators/crud/templates/views/partials/theme/simple/model/show.liquid
@@ -0,0 +1,15 @@
+
+
+ <%= modelName %> - {{ <%= modelName %>.id }}
+
+
+ <% attributes.forEach((attr) => { -%>
+
+ {{ 'app.<%= modelNamePlural %>.attr.<%= attr.name %>' | t }}
+
+
+ {{ <%= modelName %>.<%= attr.name %> }}
+
+
+ <% }); -%>
+
diff --git a/modules/core/package-lock.json b/modules/core/package-lock.json
new file mode 100644
index 0000000..23048d8
--- /dev/null
+++ b/modules/core/package-lock.json
@@ -0,0 +1,6703 @@
+{
+ "name": "pos-module-core",
+ "version": "1.2.1",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "pos-module-core",
+ "version": "1.2.1",
+ "license": "MIT",
+ "devDependencies": {
+ "auto-changelog": "^2.4.0",
+ "lodash.startcase": "^4.4.0",
+ "pluralize": "^8.0.0",
+ "yeoman-generator": "^5.9.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/code-frame/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+ "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz",
+ "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/promise-spawn": "^6.0.0",
+ "lru-cache": "^7.4.4",
+ "npm-pick-manifest": "^8.0.0",
+ "proc-log": "^3.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/installed-package-contents": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz",
+ "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==",
+ "dev": true,
+ "dependencies": {
+ "npm-bundled": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "bin": {
+ "installed-package-contents": "lib/index.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/node-gyp": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz",
+ "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz",
+ "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==",
+ "dev": true,
+ "dependencies": {
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/run-script": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz",
+ "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/node-gyp": "^3.0.0",
+ "@npmcli/promise-spawn": "^6.0.0",
+ "node-gyp": "^9.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/run-script/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@octokit/auth-token": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
+ "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/types": "^6.0.3"
+ }
+ },
+ "node_modules/@octokit/core": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
+ "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/auth-token": "^2.4.4",
+ "@octokit/graphql": "^4.5.8",
+ "@octokit/request": "^5.6.3",
+ "@octokit/request-error": "^2.0.5",
+ "@octokit/types": "^6.0.3",
+ "before-after-hook": "^2.2.0",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "node_modules/@octokit/endpoint": {
+ "version": "6.0.12",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
+ "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/types": "^6.0.3",
+ "is-plain-object": "^5.0.0",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "node_modules/@octokit/graphql": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
+ "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/request": "^5.6.0",
+ "@octokit/types": "^6.0.3",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "12.11.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
+ "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==",
+ "dev": true
+ },
+ "node_modules/@octokit/plugin-paginate-rest": {
+ "version": "2.21.3",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
+ "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/types": "^6.40.0"
+ },
+ "peerDependencies": {
+ "@octokit/core": ">=2"
+ }
+ },
+ "node_modules/@octokit/plugin-request-log": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
+ "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
+ "dev": true,
+ "peerDependencies": {
+ "@octokit/core": ">=3"
+ }
+ },
+ "node_modules/@octokit/plugin-rest-endpoint-methods": {
+ "version": "5.16.2",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
+ "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/types": "^6.39.0",
+ "deprecation": "^2.3.1"
+ },
+ "peerDependencies": {
+ "@octokit/core": ">=3"
+ }
+ },
+ "node_modules/@octokit/request": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
+ "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/endpoint": "^6.0.1",
+ "@octokit/request-error": "^2.1.0",
+ "@octokit/types": "^6.16.1",
+ "is-plain-object": "^5.0.0",
+ "node-fetch": "^2.6.7",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "node_modules/@octokit/request-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
+ "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/types": "^6.0.3",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/@octokit/rest": {
+ "version": "18.12.0",
+ "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
+ "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/core": "^3.5.1",
+ "@octokit/plugin-paginate-rest": "^2.16.8",
+ "@octokit/plugin-request-log": "^1.0.4",
+ "@octokit/plugin-rest-endpoint-methods": "^5.12.0"
+ }
+ },
+ "node_modules/@octokit/types": {
+ "version": "6.41.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
+ "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/openapi-types": "^12.11.0"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@sigstore/bundle": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz",
+ "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/protobuf-specs": "^0.2.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@sigstore/protobuf-specs": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz",
+ "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@sigstore/sign": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz",
+ "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/bundle": "^1.1.0",
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "make-fetch-happen": "^11.0.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@sigstore/tuf": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz",
+ "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "tuf-js": "^1.1.7"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tufjs/canonical-json": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz",
+ "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@tufjs/models": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz",
+ "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==",
+ "dev": true,
+ "dependencies": {
+ "@tufjs/canonical-json": "1.0.0",
+ "minimatch": "^9.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@tufjs/models/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "dev": true
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz",
+ "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+ "dev": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+ "dev": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "dev": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/array-differ": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
+ "dev": true
+ },
+ "node_modules/auto-changelog": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz",
+ "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==",
+ "dev": true,
+ "dependencies": {
+ "commander": "^7.2.0",
+ "handlebars": "^4.7.7",
+ "node-fetch": "^2.6.1",
+ "parse-github-url": "^1.0.2",
+ "semver": "^7.3.5"
+ },
+ "bin": {
+ "auto-changelog": "src/index.js"
+ },
+ "engines": {
+ "node": ">=8.3"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/before-after-hook": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
+ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
+ "dev": true
+ },
+ "node_modules/binaryextensions": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz",
+ "integrity": "sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.0.0"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "17.1.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz",
+ "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^7.7.1",
+ "minipass": "^7.0.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cacache/node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+ "dev": true
+ },
+ "node_modules/deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
+ "dev": true
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/ejs": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+ "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
+ "dev": true,
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exponential-backoff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
+ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
+ "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fs-minipass/node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "dev": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/gauge/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/gauge/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/github-username": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/github-username/-/github-username-6.0.0.tgz",
+ "integrity": "sha512-7TTrRjxblSI5l6adk9zd+cV5d6i1OrJSo3Vr9xdGqFLBQo0mz5P9eIfKCDJ7eekVGGFLbce0qbPSnktXV2BjDQ==",
+ "dev": true,
+ "dependencies": {
+ "@octokit/rest": "^18.0.6"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+ "dev": true
+ },
+ "node_modules/hosted-git-info": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
+ "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^7.5.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "dev": true
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dev": true,
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/ignore-walk": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz",
+ "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^9.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/ignore-walk/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+ "dev": true
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+ "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "dev": true
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isbinaryfile": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz",
+ "integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/gjtorikian/"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jake": {
+ "version": "10.8.7",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz",
+ "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.4",
+ "minimatch": "^3.1.2"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jake/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/jake/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz",
+ "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.startcase": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
+ "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==",
+ "dev": true,
+ "dependencies": {
+ "agentkeepalive": "^4.2.1",
+ "cacache": "^17.0.0",
+ "http-cache-semantics": "^4.1.1",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^7.7.1",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.3",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^7.0.0",
+ "ssri": "^10.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/make-fetch-happen/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mem-fs-editor": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-9.7.0.tgz",
+ "integrity": "sha512-ReB3YD24GNykmu4WeUL/FDIQtkoyGB6zfJv60yfCo3QjKeimNcTqv2FT83bP0ccs6uu+sm5zyoBlspAzigmsdg==",
+ "dev": true,
+ "dependencies": {
+ "binaryextensions": "^4.16.0",
+ "commondir": "^1.0.1",
+ "deep-extend": "^0.6.0",
+ "ejs": "^3.1.8",
+ "globby": "^11.1.0",
+ "isbinaryfile": "^5.0.0",
+ "minimatch": "^7.2.0",
+ "multimatch": "^5.0.0",
+ "normalize-path": "^3.0.0",
+ "textextensions": "^5.13.0"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ },
+ "peerDependencies": {
+ "mem-fs": "^2.1.0"
+ },
+ "peerDependenciesMeta": {
+ "mem-fs": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
+ "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-collect/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz",
+ "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^7.0.3",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.1.2"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.13"
+ }
+ },
+ "node_modules/minipass-fetch/node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-flush/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ }
+ },
+ "node_modules/minipass-json-stream/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/multimatch": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
+ "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "^3.0.3",
+ "array-differ": "^3.0.0",
+ "array-union": "^2.1.0",
+ "arrify": "^2.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/multimatch/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/multimatch/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-gyp": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz",
+ "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==",
+ "dev": true,
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "exponential-backoff": "^3.1.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^11.0.3",
+ "nopt": "^6.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": "^12.13 || ^14.13 || >=16"
+ }
+ },
+ "node_modules/node-gyp/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/node-gyp/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/node-gyp/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
+ "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "^1.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/normalize-package-data": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz",
+ "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-bundled": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz",
+ "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==",
+ "dev": true,
+ "dependencies": {
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-install-checks": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz",
+ "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.1.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-normalize-package-bin": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
+ "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-package-arg": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz",
+ "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "proc-log": "^3.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-packlist": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz",
+ "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==",
+ "dev": true,
+ "dependencies": {
+ "ignore-walk": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-pick-manifest": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz",
+ "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==",
+ "dev": true,
+ "dependencies": {
+ "npm-install-checks": "^6.0.0",
+ "npm-normalize-package-bin": "^3.0.0",
+ "npm-package-arg": "^10.0.0",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-registry-fetch": {
+ "version": "14.0.5",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz",
+ "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==",
+ "dev": true,
+ "dependencies": {
+ "make-fetch-happen": "^11.0.0",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.1.2",
+ "npm-package-arg": "^10.0.0",
+ "proc-log": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "dev": true,
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pacote": {
+ "version": "15.2.0",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz",
+ "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/git": "^4.0.0",
+ "@npmcli/installed-package-contents": "^2.0.1",
+ "@npmcli/promise-spawn": "^6.0.1",
+ "@npmcli/run-script": "^6.0.0",
+ "cacache": "^17.0.0",
+ "fs-minipass": "^3.0.0",
+ "minipass": "^5.0.0",
+ "npm-package-arg": "^10.0.0",
+ "npm-packlist": "^7.0.0",
+ "npm-pick-manifest": "^8.0.0",
+ "npm-registry-fetch": "^14.0.0",
+ "proc-log": "^3.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json": "^6.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "sigstore": "^1.3.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11"
+ },
+ "bin": {
+ "pacote": "lib/bin.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "dev": true,
+ "bin": {
+ "parse-github-url": "cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-json/node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
+ "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
+ "dev": true,
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/proc-log": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
+ "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "dev": true
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/read-package-json": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz",
+ "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.2.2",
+ "json-parse-even-better-errors": "^3.0.0",
+ "normalize-package-data": "^5.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-package-json-fast": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
+ "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
+ "dev": true,
+ "dependencies": {
+ "json-parse-even-better-errors": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg/node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/read-pkg/node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/read-pkg/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.6",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz",
+ "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shelljs": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/shelljs/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/shelljs/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/shelljs/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/sigstore": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz",
+ "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/bundle": "^1.1.0",
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "@sigstore/sign": "^1.0.0",
+ "@sigstore/tuf": "^1.0.3",
+ "make-fetch-happen": "^11.0.1"
+ },
+ "bin": {
+ "sigstore": "bin/sigstore.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
+ "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
+ "dev": true,
+ "dependencies": {
+ "ip": "^2.0.0",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/sort-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz",
+ "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==",
+ "dev": true,
+ "dependencies": {
+ "is-plain-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.15",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz",
+ "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==",
+ "dev": true
+ },
+ "node_modules/ssri": {
+ "version": "10.0.5",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz",
+ "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/ssri/node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/textextensions": {
+ "version": "5.16.0",
+ "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.16.0.tgz",
+ "integrity": "sha512-7D/r3s6uPZyU//MCYrX6I14nzauDwJ5CxazouuRGNuvSCihW87ufN6VLoROLCrHg6FblLuJrT6N2BVaPVzqElw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/tuf-js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz",
+ "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==",
+ "dev": true,
+ "dependencies": {
+ "@tufjs/models": "1.0.4",
+ "debug": "^4.3.4",
+ "make-fetch-happen": "^11.1.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "dev": true,
+ "dependencies": {
+ "unique-slug": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/universal-user-agent": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
+ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==",
+ "dev": true
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz",
+ "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==",
+ "dev": true,
+ "dependencies": {
+ "builtins": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/wide-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wide-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wide-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wide-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yeoman-generator": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-5.9.0.tgz",
+ "integrity": "sha512-sN1e01Db4fdd8P/n/yYvizfy77HdbwzvXmPxps9Gwz2D24slegrkSn+qyj+0nmZhtFwGX2i/cH29QDrvAFT9Aw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "dargs": "^7.0.0",
+ "debug": "^4.1.1",
+ "execa": "^5.1.1",
+ "github-username": "^6.0.0",
+ "lodash": "^4.17.11",
+ "mem-fs-editor": "^9.0.0",
+ "minimist": "^1.2.5",
+ "pacote": "^15.2.0",
+ "read-pkg-up": "^7.0.1",
+ "run-async": "^2.0.0",
+ "semver": "^7.2.1",
+ "shelljs": "^0.8.5",
+ "sort-keys": "^4.2.0",
+ "text-table": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ },
+ "peerDependencies": {
+ "yeoman-environment": "^3.2.0"
+ },
+ "peerDependenciesMeta": {
+ "yeoman-environment": {
+ "optional": true
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@npmcli/fs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+ "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.3.5"
+ }
+ },
+ "@npmcli/git": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz",
+ "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==",
+ "dev": true,
+ "requires": {
+ "@npmcli/promise-spawn": "^6.0.0",
+ "lru-cache": "^7.4.4",
+ "npm-pick-manifest": "^8.0.0",
+ "proc-log": "^3.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^3.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true
+ },
+ "which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@npmcli/installed-package-contents": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz",
+ "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==",
+ "dev": true,
+ "requires": {
+ "npm-bundled": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ }
+ },
+ "@npmcli/node-gyp": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz",
+ "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==",
+ "dev": true
+ },
+ "@npmcli/promise-spawn": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz",
+ "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==",
+ "dev": true,
+ "requires": {
+ "which": "^3.0.0"
+ },
+ "dependencies": {
+ "which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@npmcli/run-script": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz",
+ "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==",
+ "dev": true,
+ "requires": {
+ "@npmcli/node-gyp": "^3.0.0",
+ "@npmcli/promise-spawn": "^6.0.0",
+ "node-gyp": "^9.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "which": "^3.0.0"
+ },
+ "dependencies": {
+ "which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@octokit/auth-token": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
+ "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
+ "dev": true,
+ "requires": {
+ "@octokit/types": "^6.0.3"
+ }
+ },
+ "@octokit/core": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
+ "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
+ "dev": true,
+ "requires": {
+ "@octokit/auth-token": "^2.4.4",
+ "@octokit/graphql": "^4.5.8",
+ "@octokit/request": "^5.6.3",
+ "@octokit/request-error": "^2.0.5",
+ "@octokit/types": "^6.0.3",
+ "before-after-hook": "^2.2.0",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "@octokit/endpoint": {
+ "version": "6.0.12",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
+ "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
+ "dev": true,
+ "requires": {
+ "@octokit/types": "^6.0.3",
+ "is-plain-object": "^5.0.0",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "@octokit/graphql": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
+ "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
+ "dev": true,
+ "requires": {
+ "@octokit/request": "^5.6.0",
+ "@octokit/types": "^6.0.3",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "@octokit/openapi-types": {
+ "version": "12.11.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
+ "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==",
+ "dev": true
+ },
+ "@octokit/plugin-paginate-rest": {
+ "version": "2.21.3",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
+ "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
+ "dev": true,
+ "requires": {
+ "@octokit/types": "^6.40.0"
+ }
+ },
+ "@octokit/plugin-request-log": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
+ "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
+ "dev": true,
+ "requires": {}
+ },
+ "@octokit/plugin-rest-endpoint-methods": {
+ "version": "5.16.2",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
+ "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
+ "dev": true,
+ "requires": {
+ "@octokit/types": "^6.39.0",
+ "deprecation": "^2.3.1"
+ }
+ },
+ "@octokit/request": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
+ "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
+ "dev": true,
+ "requires": {
+ "@octokit/endpoint": "^6.0.1",
+ "@octokit/request-error": "^2.1.0",
+ "@octokit/types": "^6.16.1",
+ "is-plain-object": "^5.0.0",
+ "node-fetch": "^2.6.7",
+ "universal-user-agent": "^6.0.0"
+ }
+ },
+ "@octokit/request-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
+ "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
+ "dev": true,
+ "requires": {
+ "@octokit/types": "^6.0.3",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ }
+ },
+ "@octokit/rest": {
+ "version": "18.12.0",
+ "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
+ "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
+ "dev": true,
+ "requires": {
+ "@octokit/core": "^3.5.1",
+ "@octokit/plugin-paginate-rest": "^2.16.8",
+ "@octokit/plugin-request-log": "^1.0.4",
+ "@octokit/plugin-rest-endpoint-methods": "^5.12.0"
+ }
+ },
+ "@octokit/types": {
+ "version": "6.41.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
+ "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
+ "dev": true,
+ "requires": {
+ "@octokit/openapi-types": "^12.11.0"
+ }
+ },
+ "@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true
+ },
+ "@sigstore/bundle": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz",
+ "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==",
+ "dev": true,
+ "requires": {
+ "@sigstore/protobuf-specs": "^0.2.0"
+ }
+ },
+ "@sigstore/protobuf-specs": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz",
+ "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==",
+ "dev": true
+ },
+ "@sigstore/sign": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz",
+ "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==",
+ "dev": true,
+ "requires": {
+ "@sigstore/bundle": "^1.1.0",
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "make-fetch-happen": "^11.0.1"
+ }
+ },
+ "@sigstore/tuf": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz",
+ "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==",
+ "dev": true,
+ "requires": {
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "tuf-js": "^1.1.7"
+ }
+ },
+ "@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true
+ },
+ "@tufjs/canonical-json": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz",
+ "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==",
+ "dev": true
+ },
+ "@tufjs/models": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz",
+ "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==",
+ "dev": true,
+ "requires": {
+ "@tufjs/canonical-json": "1.0.0",
+ "minimatch": "^9.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "dev": true
+ },
+ "@types/normalize-package-data": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz",
+ "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "requires": {
+ "debug": "4"
+ }
+ },
+ "agentkeepalive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+ "dev": true,
+ "requires": {
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+ "dev": true
+ },
+ "are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "dev": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ }
+ },
+ "array-differ": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
+ "dev": true
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "dev": true
+ },
+ "async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
+ "dev": true
+ },
+ "auto-changelog": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz",
+ "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==",
+ "dev": true,
+ "requires": {
+ "commander": "^7.2.0",
+ "handlebars": "^4.7.7",
+ "node-fetch": "^2.6.1",
+ "parse-github-url": "^1.0.2",
+ "semver": "^7.3.5"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "before-after-hook": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
+ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
+ "dev": true
+ },
+ "binaryextensions": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz",
+ "integrity": "sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "cacache": {
+ "version": "17.1.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz",
+ "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==",
+ "dev": true,
+ "requires": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^7.7.1",
+ "minipass": "^7.0.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true
+ },
+ "minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true
+ }
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true
+ },
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+ "dev": true
+ },
+ "deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
+ "dev": true
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "ejs": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+ "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
+ "dev": true,
+ "requires": {
+ "jake": "^10.8.5"
+ }
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true
+ },
+ "err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true
+ },
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "exponential-backoff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
+ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^5.0.1"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "dependencies": {
+ "signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true
+ }
+ }
+ },
+ "fs-minipass": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
+ "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
+ "dev": true,
+ "requires": {
+ "minipass": "^7.0.3"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true
+ }
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true
+ },
+ "github-username": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/github-username/-/github-username-6.0.0.tgz",
+ "integrity": "sha512-7TTrRjxblSI5l6adk9zd+cV5d6i1OrJSo3Vr9xdGqFLBQo0mz5P9eIfKCDJ7eekVGGFLbce0qbPSnktXV2BjDQ==",
+ "dev": true,
+ "requires": {
+ "@octokit/rest": "^18.0.6"
+ }
+ },
+ "glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "requires": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4",
+ "wordwrap": "^1.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
+ "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^7.5.1"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true
+ }
+ }
+ },
+ "http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "dev": true
+ },
+ "http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dev": true,
+ "requires": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "requires": {
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ }
+ },
+ "ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true
+ },
+ "ignore-walk": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz",
+ "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^9.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "dev": true
+ },
+ "ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "is-core-module": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+ "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ },
+ "isbinaryfile": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz",
+ "integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "requires": {
+ "@isaacs/cliui": "^8.0.2",
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "jake": {
+ "version": "10.8.7",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz",
+ "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==",
+ "dev": true,
+ "requires": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.4",
+ "minimatch": "^3.1.2"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "json-parse-even-better-errors": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz",
+ "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==",
+ "dev": true
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true
+ },
+ "lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lodash.startcase": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "make-fetch-happen": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
+ "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==",
+ "dev": true,
+ "requires": {
+ "agentkeepalive": "^4.2.1",
+ "cacache": "^17.0.0",
+ "http-cache-semantics": "^4.1.1",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^7.7.1",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.3",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^7.0.0",
+ "ssri": "^10.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true
+ }
+ }
+ },
+ "mem-fs-editor": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-9.7.0.tgz",
+ "integrity": "sha512-ReB3YD24GNykmu4WeUL/FDIQtkoyGB6zfJv60yfCo3QjKeimNcTqv2FT83bP0ccs6uu+sm5zyoBlspAzigmsdg==",
+ "dev": true,
+ "requires": {
+ "binaryextensions": "^4.16.0",
+ "commondir": "^1.0.1",
+ "deep-extend": "^0.6.0",
+ "ejs": "^3.1.8",
+ "globby": "^11.1.0",
+ "isbinaryfile": "^5.0.0",
+ "minimatch": "^7.2.0",
+ "multimatch": "^5.0.0",
+ "normalize-path": "^3.0.0",
+ "textextensions": "^5.13.0"
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
+ "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true
+ },
+ "minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true
+ },
+ "minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "minipass-fetch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz",
+ "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.13",
+ "minipass": "^7.0.3",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.1.2"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true
+ }
+ }
+ },
+ "minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "multimatch": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
+ "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "^3.0.3",
+ "array-differ": "^3.0.0",
+ "array-union": "^2.1.0",
+ "arrify": "^2.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
+ "node-gyp": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz",
+ "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==",
+ "dev": true,
+ "requires": {
+ "env-paths": "^2.2.0",
+ "exponential-backoff": "^3.1.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^11.0.3",
+ "nopt": "^6.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "nopt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
+ "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "dev": true,
+ "requires": {
+ "abbrev": "^1.0.0"
+ }
+ },
+ "normalize-package-data": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz",
+ "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^6.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "npm-bundled": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz",
+ "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==",
+ "dev": true,
+ "requires": {
+ "npm-normalize-package-bin": "^3.0.0"
+ }
+ },
+ "npm-install-checks": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz",
+ "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.1.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
+ "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz",
+ "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^6.0.0",
+ "proc-log": "^3.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^5.0.0"
+ }
+ },
+ "npm-packlist": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz",
+ "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==",
+ "dev": true,
+ "requires": {
+ "ignore-walk": "^6.0.0"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz",
+ "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==",
+ "dev": true,
+ "requires": {
+ "npm-install-checks": "^6.0.0",
+ "npm-normalize-package-bin": "^3.0.0",
+ "npm-package-arg": "^10.0.0",
+ "semver": "^7.3.5"
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "14.0.5",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz",
+ "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==",
+ "dev": true,
+ "requires": {
+ "make-fetch-happen": "^11.0.0",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.1.2",
+ "npm-package-arg": "^10.0.0",
+ "proc-log": "^3.0.0"
+ }
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "dev": true,
+ "requires": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pacote": {
+ "version": "15.2.0",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz",
+ "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==",
+ "dev": true,
+ "requires": {
+ "@npmcli/git": "^4.0.0",
+ "@npmcli/installed-package-contents": "^2.0.1",
+ "@npmcli/promise-spawn": "^6.0.1",
+ "@npmcli/run-script": "^6.0.0",
+ "cacache": "^17.0.0",
+ "fs-minipass": "^3.0.0",
+ "minipass": "^5.0.0",
+ "npm-package-arg": "^10.0.0",
+ "npm-packlist": "^7.0.0",
+ "npm-pick-manifest": "^8.0.0",
+ "npm-registry-fetch": "^14.0.0",
+ "proc-log": "^3.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json": "^6.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "sigstore": "^1.3.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11"
+ }
+ },
+ "parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "dependencies": {
+ "json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ }
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
+ "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
+ "dev": true
+ }
+ }
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true
+ },
+ "proc-log": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
+ "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
+ "dev": true
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "dev": true
+ },
+ "promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "requires": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ }
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "read-package-json": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz",
+ "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==",
+ "dev": true,
+ "requires": {
+ "glob": "^10.2.2",
+ "json-parse-even-better-errors": "^3.0.0",
+ "normalize-package-data": "^5.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ }
+ },
+ "read-package-json-fast": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
+ "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
+ "dev": true,
+ "requires": {
+ "json-parse-even-better-errors": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ }
+ },
+ "read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "requires": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "dependencies": {
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.1.6"
+ }
+ },
+ "resolve": {
+ "version": "1.22.6",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz",
+ "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "shelljs": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "sigstore": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz",
+ "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==",
+ "dev": true,
+ "requires": {
+ "@sigstore/bundle": "^1.1.0",
+ "@sigstore/protobuf-specs": "^0.2.0",
+ "@sigstore/sign": "^1.0.0",
+ "@sigstore/tuf": "^1.0.3",
+ "make-fetch-happen": "^11.0.1"
+ }
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "dev": true
+ },
+ "socks": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
+ "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
+ "dev": true,
+ "requires": {
+ "ip": "^2.0.0",
+ "smart-buffer": "^4.2.0"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ }
+ },
+ "sort-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz",
+ "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^2.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.15",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz",
+ "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "10.0.5",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz",
+ "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==",
+ "dev": true,
+ "requires": {
+ "minipass": "^7.0.3"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "requires": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "string-width-cjs": {
+ "version": "npm:string-width@4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^6.0.1"
+ }
+ },
+ "strip-ansi-cjs": {
+ "version": "npm:strip-ansi@6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ }
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "dev": true,
+ "requires": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "dependencies": {
+ "fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "textextensions": {
+ "version": "5.16.0",
+ "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.16.0.tgz",
+ "integrity": "sha512-7D/r3s6uPZyU//MCYrX6I14nzauDwJ5CxazouuRGNuvSCihW87ufN6VLoROLCrHg6FblLuJrT6N2BVaPVzqElw==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "tuf-js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz",
+ "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==",
+ "dev": true,
+ "requires": {
+ "@tufjs/models": "1.0.4",
+ "debug": "^4.3.4",
+ "make-fetch-happen": "^11.1.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "dev": true,
+ "optional": true
+ },
+ "unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^4.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universal-user-agent": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
+ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz",
+ "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.0"
+ }
+ },
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true
+ }
+ }
+ },
+ "wrap-ansi-cjs": {
+ "version": "npm:wrap-ansi@7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yeoman-generator": {
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-5.9.0.tgz",
+ "integrity": "sha512-sN1e01Db4fdd8P/n/yYvizfy77HdbwzvXmPxps9Gwz2D24slegrkSn+qyj+0nmZhtFwGX2i/cH29QDrvAFT9Aw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "dargs": "^7.0.0",
+ "debug": "^4.1.1",
+ "execa": "^5.1.1",
+ "github-username": "^6.0.0",
+ "lodash": "^4.17.11",
+ "mem-fs-editor": "^9.0.0",
+ "minimist": "^1.2.5",
+ "pacote": "^15.2.0",
+ "read-pkg-up": "^7.0.1",
+ "run-async": "^2.0.0",
+ "semver": "^7.2.1",
+ "shelljs": "^0.8.5",
+ "sort-keys": "^4.2.0",
+ "text-table": "^0.2.0"
+ }
+ }
+ }
+}
diff --git a/modules/core/package.json b/modules/core/package.json
new file mode 100644
index 0000000..c99c7f7
--- /dev/null
+++ b/modules/core/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "pos-module-core",
+ "version": "1.2.1",
+ "description": "Module description",
+ "scripts": {
+ "version": "(cd ../../ && pos-cli modules version core -p) && git add template-values.json && auto-changelog -p && git add CHANGELOG.md"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Platform-OS/pos-module-core.git"
+ },
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/Platform-OS/pos-module-core/issues"
+ },
+ "homepage": "https://github.com/Platform-OS/pos-module-core#readme",
+ "devDependencies": {
+ "auto-changelog": "^2.4.0",
+ "lodash.startcase": "^4.4.0",
+ "pluralize": "^8.0.0",
+ "yeoman-generator": "^5.9.0"
+ },
+ "auto-changelog": {
+ "template": "changelog-template.hbs",
+ "unreleased": true,
+ "commitLimit": false
+ }
+}
diff --git a/modules/core/public/api_calls/generic.liquid b/modules/core/public/api_calls/generic.liquid
new file mode 100644
index 0000000..0a3289b
--- /dev/null
+++ b/modules/core/public/api_calls/generic.liquid
@@ -0,0 +1,6 @@
+---
+request_type: "{{ data.request_type }}"
+request_headers: '{{ data.headers | json }}'
+to: "{{ data.to }}"
+---
+{{ data.payload }}
diff --git a/modules/core/public/api_calls/generic_x_form_encoded.liquid b/modules/core/public/api_calls/generic_x_form_encoded.liquid
new file mode 100644
index 0000000..4085222
--- /dev/null
+++ b/modules/core/public/api_calls/generic_x_form_encoded.liquid
@@ -0,0 +1,10 @@
+---
+request_type: "{{ data.request_type }}"
+request_headers: '{{ data.headers | json }}'
+to: "{{ data.to }}"
+---
+{% liquid
+ function url = 'modules/core/helpers/hash_to_x_form_encoded', payload: data.payload
+ print url
+%}
+
diff --git a/modules/core/public/emails/generic.liquid b/modules/core/public/emails/generic.liquid
new file mode 100644
index 0000000..240ce94
--- /dev/null
+++ b/modules/core/public/emails/generic.liquid
@@ -0,0 +1,13 @@
+---
+from: "{{ data.from }}"
+layout: "{{ data.layout }}"
+to: "{{ data.to }}"
+cc: "{{ data.cc }}"
+bcc: "{{ data.bcc }}"
+subject: "{{ data.subject }}"
+---
+{% liquid
+ # platformos-check-disable
+ include data.partial, data: data.data
+ # platformos-check-enable
+%}
diff --git a/modules/core/public/graphql/api_calls/send.graphql b/modules/core/public/graphql/api_calls/send.graphql
new file mode 100644
index 0000000..b26d03f
--- /dev/null
+++ b/modules/core/public/graphql/api_calls/send.graphql
@@ -0,0 +1,12 @@
+mutation ($template: String!, $data: HashObject!, $options: ApiCallSendOptions) {
+ api_call: api_call_send(
+ data: $data
+ template: { name: $template }
+ options: $options
+ ) {
+ response{ status body }
+ errors {
+ message
+ }
+ }
+}
diff --git a/modules/core/public/graphql/email/send.graphql b/modules/core/public/graphql/email/send.graphql
new file mode 100644
index 0000000..2f9fc39
--- /dev/null
+++ b/modules/core/public/graphql/email/send.graphql
@@ -0,0 +1,9 @@
+mutation ($data: HashObject!, $template: String!){
+ email_send(
+ template: { name: $template }
+ data: $data
+ ){
+ is_scheduled_to_send
+ errors { message }
+ }
+}
diff --git a/modules/core/public/graphql/events/consumers.graphql b/modules/core/public/graphql/events/consumers.graphql
new file mode 100644
index 0000000..b13d23b
--- /dev/null
+++ b/modules/core/public/graphql/events/consumers.graphql
@@ -0,0 +1,15 @@
+query consumers($name: String) {
+ admin_liquid_partials(
+ filter: {
+ path: { contains: $name }
+ }
+ sort: {
+ path: { order: ASC }
+ }
+ ) {
+ results {
+ path
+ metadata
+ }
+ }
+}
diff --git a/modules/core/public/graphql/events/create.graphql b/modules/core/public/graphql/events/create.graphql
new file mode 100644
index 0000000..77bc1d9
--- /dev/null
+++ b/modules/core/public/graphql/events/create.graphql
@@ -0,0 +1,7 @@
+mutation create_event($payload: ActivityStreamsPayload!) {
+ activity_create(
+ payload: $payload
+ ) {
+ payload
+ }
+}
diff --git a/modules/core/public/graphql/events/events_checks.graphql b/modules/core/public/graphql/events/events_checks.graphql
new file mode 100644
index 0000000..c326d87
--- /dev/null
+++ b/modules/core/public/graphql/events/events_checks.graphql
@@ -0,0 +1,11 @@
+query events_checks($name: String) {
+ admin_liquid_partials(
+ filter: {
+ path: { ends_with: $name }
+ }
+ ) {
+ results {
+ path
+ }
+ }
+}
diff --git a/modules/core/public/graphql/events/search.graphql b/modules/core/public/graphql/events/search.graphql
new file mode 100644
index 0000000..4e78dd2
--- /dev/null
+++ b/modules/core/public/graphql/events/search.graphql
@@ -0,0 +1,14 @@
+query ac($limit: Int = 100 $page: Int = 1 $uuids: [String!]) {
+ activities: activities(
+ per_page: $limit,
+ page: $page
+ uuids: $uuids
+ sort: { created_at: { order: DESC } }
+ ){
+ total_entries
+ total_pages
+ results {
+ payload
+ }
+ }
+}
diff --git a/modules/core/public/graphql/hook/search.graphql b/modules/core/public/graphql/hook/search.graphql
new file mode 100644
index 0000000..37e31e2
--- /dev/null
+++ b/modules/core/public/graphql/hook/search.graphql
@@ -0,0 +1,7 @@
+query ($hook: String) {
+ admin_liquid_partials(filter: { path: { ends_with: $hook } }) {
+ results {
+ path
+ }
+ }
+}
diff --git a/modules/core/public/graphql/records/count.graphql b/modules/core/public/graphql/records/count.graphql
new file mode 100644
index 0000000..9a21894
--- /dev/null
+++ b/modules/core/public/graphql/records/count.graphql
@@ -0,0 +1,26 @@
+query records_count(
+ $property_name: String!
+ $property_value: String!
+ $scope_name: String!
+ $scope_value: String
+ $table: String!
+ $not_ids: [ID!]
+ $ids: [ID!]
+ $exclude_name: String!
+ $exclude_value: String
+) {
+ records(
+ per_page: 1
+ filter: {
+ id: { not_value_in: $not_ids, value_in: $ids }
+ table: { value: $table }
+ properties: [
+ { name: $property_name, value: $property_value }
+ { name: $scope_name, value: $scope_value }
+ { name: $exclude_name, not_value: $exclude_value }
+ ]
+ }
+ ) {
+ total_entries
+ }
+}
diff --git a/modules/core/public/graphql/session/delete.graphql b/modules/core/public/graphql/session/delete.graphql
new file mode 100644
index 0000000..c83de59
--- /dev/null
+++ b/modules/core/public/graphql/session/delete.graphql
@@ -0,0 +1,5 @@
+mutation ($name: String!){
+ session_delete_field(
+ name: $name
+ )
+}
diff --git a/modules/core/public/graphql/session/set.graphql b/modules/core/public/graphql/session/set.graphql
new file mode 100644
index 0000000..9069f25
--- /dev/null
+++ b/modules/core/public/graphql/session/set.graphql
@@ -0,0 +1,6 @@
+mutation ($name: String!, $value: Any!){
+ session_create_field(
+ name: $name
+ value: $value
+ )
+}
diff --git a/modules/core/public/graphql/statuses/create.graphql b/modules/core/public/graphql/statuses/create.graphql
new file mode 100644
index 0000000..7274afc
--- /dev/null
+++ b/modules/core/public/graphql/statuses/create.graphql
@@ -0,0 +1,34 @@
+mutation create_status(
+ $name: String!
+ $timestamp: String!
+ $reference_id: String!
+ $reference_schema: String
+ $payload: String
+ $requester_id: String!
+) {
+ record: record_create(
+ record: {
+ table: "modules/core/status"
+ properties: [
+ { name: "name", value: $name }
+ { name: "timestamp", value: $timestamp }
+ { name: "reference_id", value: $reference_id }
+ { name: "reference_schema", value: $reference_schema }
+ { name: "payload", value: $payload }
+ { name: "requester_id", value: $requester_id }
+ ]
+ }
+ ) {
+ id
+ created_at
+ deleted_at
+ type: table
+
+ name: property(name: "name")
+ timestamp: property(name: "timestamp")
+ reference_id: property(name: "reference_id")
+ reference_schema: property(name: "reference_schema")
+ payload: property(name: "payload")
+ requester_id: property(name: "requester_id")
+ }
+}
diff --git a/modules/core/public/graphql/statuses/delete.graphql b/modules/core/public/graphql/statuses/delete.graphql
new file mode 100644
index 0000000..fb333ab
--- /dev/null
+++ b/modules/core/public/graphql/statuses/delete.graphql
@@ -0,0 +1,5 @@
+mutation delete_status($id: ID!) {
+ record_delete(table: "modules/core/status", id: $id) {
+ id
+ }
+}
diff --git a/modules/core/public/graphql/statuses/search.graphql b/modules/core/public/graphql/statuses/search.graphql
new file mode 100644
index 0000000..8beffdc
--- /dev/null
+++ b/modules/core/public/graphql/statuses/search.graphql
@@ -0,0 +1,45 @@
+query search(
+ $id: ID
+ $limit: Int!
+ $page: Int!
+ $name: String
+ $timestamp: String
+ $reference_id: String
+ $reference_schema: String
+ $requester_id: String
+) {
+ statuses: records(
+ per_page: $limit
+ page: $page
+ filter: {
+ id: { value: $id }
+ table: { value: "modules/core/status" }
+ properties: [
+ { name: "name", value: $name }
+ { name: "timestamp", value: $timestamp }
+ { name: "reference_id", value: $reference_id }
+ { name: "reference_schema", value: $reference_schema }
+ { name: "requester_id", value: $requester_id }
+ ]
+ }
+ sort: [{ created_at: { order: DESC } }]
+ ) {
+ total_entries
+ has_next_page
+ has_previous_page
+ current_page
+
+ results {
+ id
+ created_at
+ type: table
+
+ name: property(name: "name")
+ timestamp: property(name: "timestamp")
+ reference_id: property(name: "reference_id")
+ reference_schema: property(name: "reference_schema")
+ payload: property(name: "payload")
+ requester_id: property(name: "requester_id")
+ }
+ }
+}
diff --git a/modules/core/public/graphql/variable/set.graphql b/modules/core/public/graphql/variable/set.graphql
new file mode 100644
index 0000000..3c7b0d9
--- /dev/null
+++ b/modules/core/public/graphql/variable/set.graphql
@@ -0,0 +1,6 @@
+mutation ($name: String!, $value: String!) {
+ variable: constant_set(name: $name, value: $value) {
+ name
+ value
+ }
+}
diff --git a/modules/core/public/lib/commands/email/send.liquid b/modules/core/public/lib/commands/email/send.liquid
new file mode 100644
index 0000000..bd0a46e
--- /dev/null
+++ b/modules/core/public/lib/commands/email/send.liquid
@@ -0,0 +1,18 @@
+{% liquid
+ function object = 'modules/core/commands/email/send/build', object: object
+ function object = 'modules/core/commands/email/send/check', object: object
+
+ if object.valid
+ graphql r = 'modules/core/email/send', template: 'modules/core/generic', data: object
+ if r.errors
+ log r.errors, type: 'errors.graphql.invalid'
+
+ hash_assign object['valid'] = false
+ hash_assign object['errors'] = r.errors
+ endif
+ else
+ log object.errors, type: 'payload validation error in core: commands/email'
+ endif
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/email/send/build.liquid b/modules/core/public/lib/commands/email/send/build.liquid
new file mode 100644
index 0000000..5e57d28
--- /dev/null
+++ b/modules/core/public/lib/commands/email/send/build.liquid
@@ -0,0 +1,13 @@
+{% parse_json object %}
+ {
+ "layout": {{ object.layout | default: 'modules/core/mailer' | json }},
+ "from": {{ object.from | json }},
+ "to": {{ object.to | json }},
+ "subject": {{ object.subject | json }},
+ "cc": {{ object.cc | json }},
+ "bcc": {{ object.bcc | json }},
+ "partial": {{ object.partial | json }},
+ "data": {{ object.data | json }}
+ }
+{% endparse_json %}
+{% return object %}
diff --git a/modules/core/public/lib/commands/email/send/check.liquid b/modules/core/public/lib/commands/email/send/check.liquid
new file mode 100644
index 0000000..83f4269
--- /dev/null
+++ b/modules/core/public/lib/commands/email/send/check.liquid
@@ -0,0 +1,13 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'from'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'to'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'layout'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'partial'
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/events/broadcast.liquid b/modules/core/public/lib/commands/events/broadcast.liquid
new file mode 100644
index 0000000..5cf9440
--- /dev/null
+++ b/modules/core/public/lib/commands/events/broadcast.liquid
@@ -0,0 +1,24 @@
+{% liquid
+ if object.type == blank
+ log 'ERROR: events broadcast type blank'
+ return null
+ endif
+ assign priorities = 'low,default,high' | split: ','
+
+ assign name = 'consumers/' | append: object.type | append: '/'
+ graphql consumers = 'modules/core/events/consumers', name: name | fetch: "admin_liquid_partials" | fetch: "results"
+
+ hash_assign object['consumers'] = consumers
+ for consumer in consumers
+ assign priority = 'default'
+ if priorities contains consumer.metadata.priority
+ assign priority = consumer.metadata.priority
+ endif
+ assign max_attempts = consumer.metadata.max_attempts | default: deprecated_max_attempts | default: 9
+ assign delay = consumer.metadata.delay | default: deprecated_delay | default: 0
+
+ background _id = consumer.path, event: object, priority: priority, delay: delay, max_attempts: max_attempts
+ endfor
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/events/create.liquid b/modules/core/public/lib/commands/events/create.liquid
new file mode 100644
index 0000000..9c4655c
--- /dev/null
+++ b/modules/core/public/lib/commands/events/create.liquid
@@ -0,0 +1,16 @@
+{% liquid
+ function event = 'modules/core/commands/events/create/build', type: type, object: object
+ function event = 'modules/core/commands/events/create/check', object: event, type: type
+ if event.valid
+ function event = 'modules/core/commands/events/create/execute', object: event
+ if event.valid
+ function _r = 'modules/core/commands/events/broadcast', object: event, deprecated_max_attempts: deprecated_max_attempts, deprecated_delay: deprecated_delay
+ else
+ log event, type: 'ERROR: modules/core/commands/events invalid'
+ endif
+ else
+ log event, type: 'ERROR: modules/core/commands/events invalid'
+ endif
+
+ return event
+%}
diff --git a/modules/core/public/lib/commands/events/create/build.liquid b/modules/core/public/lib/commands/events/create/build.liquid
new file mode 100644
index 0000000..8276ea4
--- /dev/null
+++ b/modules/core/public/lib/commands/events/create/build.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ assign now = 'now' | to_time
+ assign data = object | hash_merge: type: type, date: now
+
+ return data
+%}
diff --git a/modules/core/public/lib/commands/events/create/check.liquid b/modules/core/public/lib/commands/events/create/check.liquid
new file mode 100644
index 0000000..bcb1708
--- /dev/null
+++ b/modules/core/public/lib/commands/events/create/check.liquid
@@ -0,0 +1,22 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'type'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'date'
+
+ assign name = 'events/' | append: object.type
+ graphql event_check_partial = 'modules/core/events/events_checks', name: name | fetch: "admin_liquid_partials" | fetch: "results" | first
+ if event_check_partial
+ function event_result = event_check_partial.path, event: object
+ if event_result.valid != true
+ hash_assign c['errors']['object'] = event_result.errors
+ hash_assign c['valid'] = false
+ endif
+ else
+ assign message = 'There is no such event: ' | append: object.type | append: '. Please add event check in events/' | append: object.type
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: type, message: message
+ endif
+
+ assign object = object | hash_merge: c
+ return object
+%}
diff --git a/modules/core/public/lib/commands/events/create/execute.liquid b/modules/core/public/lib/commands/events/create/execute.liquid
new file mode 100644
index 0000000..bff75bf
--- /dev/null
+++ b/modules/core/public/lib/commands/events/create/execute.liquid
@@ -0,0 +1,8 @@
+{% liquid
+ graphql r = 'modules/core/events/create', payload: object
+
+ assign object = r.activity_create.payload
+ hash_assign object['valid'] = true
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/events/publish.liquid b/modules/core/public/lib/commands/events/publish.liquid
new file mode 100644
index 0000000..7657b3e
--- /dev/null
+++ b/modules/core/public/lib/commands/events/publish.liquid
@@ -0,0 +1,23 @@
+{% liquid
+ if delay > 0
+ log 'use metadata.delay in the consumer file instead of passing it to modules/core/commands/events/publish', type: 'DEPRECATION'
+ endif
+ if max_attempts
+ log 'use metadata.max_attempts in the consumer file instead of passing it to modules/core/commands/events/publish', type: 'DEPRECATION'
+ endif
+
+ unless type
+ log 'type is required', type: 'ERROR: modules/core/commands/events publish'
+ return null
+ endunless
+ unless object
+ log 'object is required', type: 'ERROR: modules/core/commands/events publish'
+ return null
+ endunless
+
+ assign source_name = 'modules/core/commands/events/create:' | append: type
+
+ background job_id = "modules/core/commands/events/create", source_name: source_name, priority: 'high', type: type, object: object, deprecated_max_attempts: max_attempts, deprecated_delay: delay
+
+ return job_id
+%}
diff --git a/modules/core/public/lib/commands/execute.liquid b/modules/core/public/lib/commands/execute.liquid
new file mode 100644
index 0000000..0c9e1cd
--- /dev/null
+++ b/modules/core/public/lib/commands/execute.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ assign selection = selection | default: 'record'
+
+ graphql r = mutation_name, args: object
+ if r.errors
+ log r, type: "ERROR: modules/core/commands/execute"
+ endif
+
+ assign object = r[selection]
+ hash_assign object['valid'] = true
+ return object
+%}
diff --git a/modules/core/public/lib/commands/hook/alter.liquid b/modules/core/public/lib/commands/hook/alter.liquid
new file mode 100644
index 0000000..64e2245
--- /dev/null
+++ b/modules/core/public/lib/commands/hook/alter.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ hook: string
+ the hook name without hook_ prefix and _alter suffix.
+ params_to_modify: object
+ the object that will be passed to the alter hook to modify
+ params: object
+ the object that will be passed to the alter hook to give extra information
+{% endcomment %}
+{% liquid
+ assign original_params = params_to_modify | deep_clone
+
+ assign hook = '/hook_' | append: hook | append: '_alter'
+ function implementations = 'modules/core/queries/hook/search', hook: hook
+
+ for implementation in implementations
+ function _ = implementation.path, params_to_modify: params_to_modify, params: params
+ endfor
+
+ assign result = '{}' | parse_json | hash_merge: original_params: original_params
+ return result
+%}
diff --git a/modules/core/public/lib/commands/hook/fire.liquid b/modules/core/public/lib/commands/hook/fire.liquid
new file mode 100644
index 0000000..c4956c8
--- /dev/null
+++ b/modules/core/public/lib/commands/hook/fire.liquid
@@ -0,0 +1,41 @@
+{% comment %}
+ hook: string
+ the hook name without hook_ prefix.
+ params: object
+ the object to pass to the fired hook
+ merge_to_object boolean
+ merge the result objects to one object or collect them in an array
+{% endcomment %}
+{% liquid
+ if merge_to_object
+ assign results = '{}' | parse_json
+ else
+ assign results = '[]' | parse_json
+ endif
+
+ assign hook = '/hook_' | append: hook
+ function implementations = 'modules/core/queries/hook/search', hook: hook
+
+ for implementation in implementations
+ function hook_result = implementation.path, params: params
+ if hook_result != nil
+ comment
+ Check if the result is an array and merge the values one by one.
+ endcomment
+ if hook_result[0]
+ for h_result in hook_result
+ assign results = results | add_to_array: h_result
+ endfor
+ comment
+ Check if the result is an object.
+ endcomment
+ elsif hook_result.first and merge_to_object
+ assign results = results | hash_merge: hook_result
+ else
+ assign results = results | add_to_array: hook_result
+ endif
+ endif
+ endfor
+
+ return results
+%}
diff --git a/modules/core/public/lib/commands/session/clear.liquid b/modules/core/public/lib/commands/session/clear.liquid
new file mode 100644
index 0000000..65a82ef
--- /dev/null
+++ b/modules/core/public/lib/commands/session/clear.liquid
@@ -0,0 +1,7 @@
+{% liquid
+ if context.session[key] != blank
+ graphql _ = 'modules/core/session/delete', name: key
+ return true
+ endif
+ return false
+%}
diff --git a/modules/core/public/lib/commands/session/get.liquid b/modules/core/public/lib/commands/session/get.liquid
new file mode 100644
index 0000000..5ed4854
--- /dev/null
+++ b/modules/core/public/lib/commands/session/get.liquid
@@ -0,0 +1,11 @@
+{% liquid
+ if context.session[key] != blank
+ assign value = context.session[key] | parse_json
+ if clear
+ graphql _ = 'modules/core/session/delete', name: key
+ endif
+
+ return value
+ endif
+ return null
+%}
diff --git a/modules/core/public/lib/commands/session/set.liquid b/modules/core/public/lib/commands/session/set.liquid
new file mode 100644
index 0000000..0dfb2e4
--- /dev/null
+++ b/modules/core/public/lib/commands/session/set.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ assign value = value | json
+ graphql _ = 'modules/core/session/set', name: key, value: value
+ return true
+%}
diff --git a/modules/core/public/lib/commands/statuses/create.liquid b/modules/core/public/lib/commands/statuses/create.liquid
new file mode 100644
index 0000000..10e483e
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/create.liquid
@@ -0,0 +1,30 @@
+{% comment %}
+ Creates a status object.
+
+ Params:
+ - name: String
+ the name of the status. For example: 'app.status.transaction.failed'
+ - reference_id
+ - requester_id
+ the ID of the requester. It can be a user ID or 'stripe_webhook' or anything else that represents who stored the status
+ - timestamp (optional)
+ - reference_schema (optional)
+ - payload (optional)
+ - delay (optional)
+ - max_attempts (optional)
+{% endcomment %}
+{% liquid
+ function object = 'modules/core/commands/statuses/create/build', name: name, timestamp: timestamp, reference_id: reference_id, reference_schema: reference_schema, payload: payload, requester_id: requester_id
+ function object = 'modules/core/commands/statuses/create/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/core/statuses/create' object: object
+ if object.valid
+ function _ = 'modules/core/commands/events/publish', type: 'status_created', object: object, delay: delay, max_attempts: max_attempts
+ endif
+ else
+ log object, 'showme STATUS-INVALID'
+ endif
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/statuses/create/build.liquid b/modules/core/public/lib/commands/statuses/create/build.liquid
new file mode 100644
index 0000000..6cf9f0c
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/create/build.liquid
@@ -0,0 +1,14 @@
+{% parse_json object %}
+ {
+ "name": {{ name | json }},
+ "timestamp": {{ timestamp | default: 'now' | to_time | json }},
+ "reference_id": {{ reference_id | json }},
+ "reference_schema": {{ reference_schema | json }},
+ "payload": {{ payload | json }},
+ "requester_id": {{ requester_id | json }}
+ }
+{% endparse_json %}
+
+{% liquid
+ return object
+%}
diff --git a/modules/core/public/lib/commands/statuses/create/check.liquid b/modules/core/public/lib/commands/statuses/create/check.liquid
new file mode 100644
index 0000000..acbcb25
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/create/check.liquid
@@ -0,0 +1,13 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'name'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'timestamp'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'reference_id'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'requester_id'
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/statuses/delete.liquid b/modules/core/public/lib/commands/statuses/delete.liquid
new file mode 100644
index 0000000..e115b0c
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/delete.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ Deletes a status object.
+
+ Params:
+ - id: String
+{% endcomment %}
+{% liquid
+ function object = 'modules/core/commands/statuses/delete/build', id: id
+ function object = 'modules/core/commands/statuses/delete/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/core/statuses/delete', selection: 'record_delete', object: object
+ endif
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/statuses/delete/build.liquid b/modules/core/public/lib/commands/statuses/delete/build.liquid
new file mode 100644
index 0000000..d26bbdf
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/delete/build.liquid
@@ -0,0 +1,4 @@
+{% liquid
+ assign object = null | hash_merge: id: id
+ return object
+%}
diff --git a/modules/core/public/lib/commands/statuses/delete/check.liquid b/modules/core/public/lib/commands/statuses/delete/check.liquid
new file mode 100644
index 0000000..51f8988
--- /dev/null
+++ b/modules/core/public/lib/commands/statuses/delete/check.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign c = '{ "valid": true, "errors": {} }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/core/public/lib/commands/variable/set.liquid b/modules/core/public/lib/commands/variable/set.liquid
new file mode 100644
index 0000000..aa88b52
--- /dev/null
+++ b/modules/core/public/lib/commands/variable/set.liquid
@@ -0,0 +1,9 @@
+{% comment %}
+ Required params:
+ - name string
+ - value string
+{% endcomment %}
+{% liquid
+ graphql result = 'modules/core/variable/set', name: name, value: value
+ return result.variable
+%}
diff --git a/modules/core/public/lib/events/status_created.liquid b/modules/core/public/lib/events/status_created.liquid
new file mode 100644
index 0000000..6718a16
--- /dev/null
+++ b/modules/core/public/lib/events/status_created.liquid
@@ -0,0 +1,18 @@
+---
+metadata:
+ event:
+ name
+ reference_id
+ reference_schema
+ requester_id
+ payload
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'name'
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'reference_id'
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'requester_id'
+
+ return c
+%}
diff --git a/modules/core/public/lib/helpers/authenticity_token.liquid b/modules/core/public/lib/helpers/authenticity_token.liquid
new file mode 100644
index 0000000..b435480
--- /dev/null
+++ b/modules/core/public/lib/helpers/authenticity_token.liquid
@@ -0,0 +1,5 @@
+{% assign token = token | default: authenticity_token | default: context.authenticity_token %}
+{% unless token %}
+ Liquid Error AuthenticityTokenNotFound
+{% endunless %}
+
diff --git a/modules/core/public/lib/helpers/flash/publish.liquid b/modules/core/public/lib/helpers/flash/publish.liquid
new file mode 100644
index 0000000..41f14d9
--- /dev/null
+++ b/modules/core/public/lib/helpers/flash/publish.liquid
@@ -0,0 +1,29 @@
+{% liquid
+ if error and error contains 'app.'
+ assign error = error | t
+ endif
+
+ if notice and notice contains 'app.'
+ assign notice = notice | t
+ endif
+
+ if info and info contains 'app.'
+ assign info = info | t
+ endif
+%}
+
+{% parse_json flash %}
+ {
+ "error": {{ error | json }},
+ "notice": {{ notice | json }},
+ "info": {{ info | json }},
+ "from": {{ context.location.pathname | json }},
+ "now": {{ force_clear | default: false }}
+ }
+{% endparse_json %}
+
+{% liquid
+ assign sflash = flash | json
+ session sflash = sflash
+%}
+
diff --git a/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid b/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid
new file mode 100644
index 0000000..73e48bb
--- /dev/null
+++ b/modules/core/public/lib/helpers/hash_to_x_form_encoded.liquid
@@ -0,0 +1,15 @@
+{% liquid
+ assign parameters = '' | split: ','
+ for pair in payload
+ assign component = pair[0] | append: '={' | append: pair[0] | append: '}'
+ assign parameters = parameters | add_to_array: component
+ endfor
+ if parameters.size > 0
+ assign x_form_encoded = parameters | join: '&' | expand_url_template: payload
+ else
+ assign x_form_encoded = ''
+ endif
+
+ return x_form_encoded
+%}
+
diff --git a/modules/core/public/lib/helpers/log_time.liquid b/modules/core/public/lib/helpers/log_time.liquid
new file mode 100644
index 0000000..76ef86d
--- /dev/null
+++ b/modules/core/public/lib/helpers/log_time.liquid
@@ -0,0 +1,11 @@
+{% liquid
+ assign _stop = 'now' | to_time
+ assign _diff = _start | time_diff: _stop
+ if env
+ log _diff, type: type, env: env
+ else
+ log _diff, type: type
+ endif
+
+ return true
+%}
diff --git a/modules/core/public/lib/helpers/redirect_to.liquid b/modules/core/public/lib/helpers/redirect_to.liquid
new file mode 100644
index 0000000..b9025b5
--- /dev/null
+++ b/modules/core/public/lib/helpers/redirect_to.liquid
@@ -0,0 +1,42 @@
+{% liquid
+ if url == blank and context.session.return_to != blank
+ assign url = context.session.return_to
+ endif
+
+ if context.params.return_to
+ assign url = context.params.return_to | url_decode
+ endif
+
+ assign url = url | default: '/'
+
+ assign not_start_with_slash = url | matches: '^(?!\/)(.+)'
+ assign wrong_url = url | matches: '^\/\/'
+ if not_start_with_slash or wrong_url
+ assign url = '/'
+ endif
+
+
+ # platformos-check-disable ConvertIncludeToRender
+ include 'modules/core/helpers/flash/publish', notice: notice, error: error, info: info
+ # platformos-check-enable ConvertIncludeToRender
+
+ if format == 'json'
+ assign response_json = null | hash_merge: type: 'redirect', url: url
+ if object.valid
+ echo response_json
+ else
+ response_status 422
+ assign res = '{ "errors": {} }' | parse_json
+ hash_assign res['errors'] = response_json.errors
+
+ echo res
+ endif
+
+ else
+ redirect_to url
+ endif
+
+ break
+%}
+
+
diff --git a/modules/core/public/lib/helpers/register_error.liquid b/modules/core/public/lib/helpers/register_error.liquid
new file mode 100644
index 0000000..2f252ef
--- /dev/null
+++ b/modules/core/public/lib/helpers/register_error.liquid
@@ -0,0 +1,27 @@
+{% comment %}
+ @params
+ contract - { errors: {}, valid: true }
+ field_name
+ message:
+ key: i18n to be resolved into message
+{% endcomment %}
+
+{% liquid
+ assign key = key | default: null
+ assign message = message | default: null
+ if key
+ assign msg = key | t
+ else
+ assign msg = message
+ endif
+
+ assign errors = contract.errors
+
+ assign field_errors = errors[field_name] | default: '[]' | parse_json
+ assign field_errors = field_errors | add_to_array: msg
+
+ hash_assign errors[field_name] = field_errors
+ hash_assign contract['valid'] = false
+
+ return contract
+%}
diff --git a/modules/core/public/lib/helpers/timezone/get_all.liquid b/modules/core/public/lib/helpers/timezone/get_all.liquid
new file mode 100644
index 0000000..f16a4f8
--- /dev/null
+++ b/modules/core/public/lib/helpers/timezone/get_all.liquid
@@ -0,0 +1,18 @@
+{% comment %}
+ we need the to_json | parse_json hack because time_zones.all is an array of TimeZoneDrop (not an object)
+ this prevents us from using array filters or pass the timezone as reference (return it from a function, etc)
+ should be fixed on the platform level
+{% endcomment %}
+{% comment %}
+Returns an array of timezone objects in the following format:
+{
+ "formatted_name":"(GMT-12:00) International Date Line West",
+ "formatted_offset":"-12:00",
+ "name":"International Date Line West",
+ "utc_offset":-43200,
+ "abbreviation":"-12",
+ "friendly_name_with_region":"Etc - GMT+12",
+ "friendly_name_without_region":"GMT+12"
+}
+{% endcomment %}
+{% return context.globals.time_zones.all | to_json | parse_json %}
diff --git a/modules/core/public/lib/helpers/timezone/get_by_name.liquid b/modules/core/public/lib/helpers/timezone/get_by_name.liquid
new file mode 100644
index 0000000..766affe
--- /dev/null
+++ b/modules/core/public/lib/helpers/timezone/get_by_name.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ params:
+ - name: string
+
+returns a timezone object in the following format:
+{
+ "formatted_name":"(GMT-12:00) International Date Line West",
+ "formatted_offset":"-12:00",
+ "name":"International Date Line West",
+ "utc_offset":-43200,
+ "abbreviation":"-12",
+ "friendly_name_with_region":"Etc - GMT+12",
+ "friendly_name_without_region":"GMT+12"
+}
+{% endcomment %}
+{% liquid
+ function timezones = 'modules/core/helpers/timezone/get_all'
+ assign timezone = timezones | array_detect: name: name
+
+ return timezone
+%}
diff --git a/modules/core/public/lib/helpers/timezone/get_by_offset.liquid b/modules/core/public/lib/helpers/timezone/get_by_offset.liquid
new file mode 100644
index 0000000..f10f26e
--- /dev/null
+++ b/modules/core/public/lib/helpers/timezone/get_by_offset.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ params:
+ - offset: string, e.g. "+2:00"
+
+returns a timezone object in the following format:
+{
+ "formatted_name":"(GMT-12:00) International Date Line West",
+ "formatted_offset":"-12:00",
+ "name":"International Date Line West",
+ "utc_offset":-43200,
+ "abbreviation":"-12",
+ "friendly_name_with_region":"Etc - GMT+12",
+ "friendly_name_without_region":"GMT+12"
+}
+{% endcomment %}
+{% liquid
+ function timezones = 'modules/core/helpers/timezone/get_all'
+ assign timezone = timezones | array_detect: formatted_offset: offset
+
+ return timezone
+%}
diff --git a/modules/core/public/lib/hooks/hook_module_info.liquid b/modules/core/public/lib/hooks/hook_module_info.liquid
new file mode 100644
index 0000000..9915449
--- /dev/null
+++ b/modules/core/public/lib/hooks/hook_module_info.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ Implements hook_module_info.
+{% endcomment %}
+{% parse_json info %}
+{
+ "name": "<%= &name =%>",
+ "machine_name": "<%= &machine_name =%>",
+ "type": "<%= &type =%>",
+ "version": "<%= &version =%>",
+ "dependencies": "<%= &dependencies =%>"
+}
+{% endparse_json %}
+
+{% liquid
+ return info
+%}
diff --git a/modules/core/public/lib/queries/events/find.liquid b/modules/core/public/lib/queries/events/find.liquid
new file mode 100644
index 0000000..8b16384
--- /dev/null
+++ b/modules/core/public/lib/queries/events/find.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ if uuid == blank
+ return null
+ endif
+
+ function events = 'modules/core/queries/events/search', limit: 1, uuids: uuid
+
+ return events.results.first.payload
+%}
diff --git a/modules/core/public/lib/queries/events/search.liquid b/modules/core/public/lib/queries/events/search.liquid
new file mode 100644
index 0000000..3363d0a
--- /dev/null
+++ b/modules/core/public/lib/queries/events/search.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign page = page | to_positive_integer: 1
+ assign uuids = uuids | default: null
+
+ graphql r = 'modules/core/events/search', limit: limit, page: page, uuids: uuids
+
+ assign events = r.activities
+
+ return events
+%}
diff --git a/modules/core/public/lib/queries/headscripts/get.liquid b/modules/core/public/lib/queries/headscripts/get.liquid
new file mode 100644
index 0000000..f35c496
--- /dev/null
+++ b/modules/core/public/lib/queries/headscripts/get.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ function res = 'modules/core/queries/headscripts/search'
+ return res
+%}
diff --git a/modules/core/public/lib/queries/headscripts/search.liquid b/modules/core/public/lib/queries/headscripts/search.liquid
new file mode 100644
index 0000000..40b4c03
--- /dev/null
+++ b/modules/core/public/lib/queries/headscripts/search.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ function headscript_implementations = 'modules/core/commands/hook/fire', hook: 'headscripts', merge_to_object: false
+ assign results = headscript_implementations | join: ''
+ return results | html_safe
+%}
diff --git a/modules/core/public/lib/queries/hook/search.liquid b/modules/core/public/lib/queries/hook/search.liquid
new file mode 100644
index 0000000..b78fd16
--- /dev/null
+++ b/modules/core/public/lib/queries/hook/search.liquid
@@ -0,0 +1,11 @@
+{% comment %}
+ Get a list of all hook impltementation paths.
+ Params:
+ - hook: string
+ the hook's name with '/' prefix for example '/hook_user_create'.
+{% endcomment %}
+
+{% liquid
+ graphql implementations = 'modules/core/hook/search', hook: hook
+ return implementations.admin_liquid_partials.results
+%}
diff --git a/modules/core/public/lib/queries/module/exists.liquid b/modules/core/public/lib/queries/module/exists.liquid
new file mode 100644
index 0000000..1e76c73
--- /dev/null
+++ b/modules/core/public/lib/queries/module/exists.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ Required params:
+ - name string
+ - type string (optional)
+ it can be: module, theme
+{% endcomment %}
+{% liquid
+ function modules = 'modules/core/queries/registry/search', type: type
+ assign module = modules | array_detect: machine_name: name
+
+ if module
+ return true
+ endif
+
+ return false
+%}
diff --git a/modules/core/public/lib/queries/registry/get.liquid b/modules/core/public/lib/queries/registry/get.liquid
new file mode 100644
index 0000000..83dde39
--- /dev/null
+++ b/modules/core/public/lib/queries/registry/get.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ function registry = 'modules/core/queries/registry/search', type: type
+ return registry
+%}
diff --git a/modules/core/public/lib/queries/registry/search.liquid b/modules/core/public/lib/queries/registry/search.liquid
new file mode 100644
index 0000000..60e1126
--- /dev/null
+++ b/modules/core/public/lib/queries/registry/search.liquid
@@ -0,0 +1,28 @@
+{% comment %}
+ Required params:
+ - type string
+ it can be: all, module, theme
+{% endcomment %}
+{% liquid
+ function registry = 'modules/core/commands/hook/fire', hook: 'module_info', merge_to_object: false
+
+ case type
+ when 'module'
+ assign modules = '[]' | parse_json
+ for module in registry
+ if module.type == 'module'
+ assign modules = modules | add_to_array: module
+ endif
+ endfor
+ return modules
+ when 'theme'
+ assign themes = '[]' | parse_json
+ for module in registry
+ if module.type == 'theme'
+ assign themes = themes | add_to_array: module
+ endif
+ endfor
+ return themes
+ endcase
+ return registry
+%}
diff --git a/modules/core/public/lib/queries/statuses/find.liquid b/modules/core/public/lib/queries/statuses/find.liquid
new file mode 100644
index 0000000..2055b3f
--- /dev/null
+++ b/modules/core/public/lib/queries/statuses/find.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ Find a status object.
+
+ Params:
+ - id: String
+{% endcomment %}
+{% liquid
+ if id == blank
+ return null
+ endif
+
+ graphql r = 'modules/core/statuses/search', id: id, limit: 1, page: 1
+
+ return r.statuses.results.first
+%}
diff --git a/modules/core/public/lib/queries/statuses/search.liquid b/modules/core/public/lib/queries/statuses/search.liquid
new file mode 100644
index 0000000..36f2b8e
--- /dev/null
+++ b/modules/core/public/lib/queries/statuses/search.liquid
@@ -0,0 +1,25 @@
+{% comment %}
+ Creates a status object.
+
+ Params:
+ - page
+ default: 1
+ - limit
+ default: 20
+ - id
+ - name: String
+ the name of the status. For example: 'app.status.transaction.failed'
+ - reference_id
+ - requester_id
+ the ID of the requester. It can be a user ID or 'stripe_webhook' or anything else that represents who stored the status
+ - timestamp (optional)
+ - reference_schema (optional)
+{% endcomment %}
+{% liquid
+ assign page = page | to_positive_integer: 1
+ assign limit = limit | default: 20
+
+ graphql r = 'modules/core/statuses/search', limit: limit, page: page, id: id, name: name, reference_id: reference_id, requester_id: requester_id, reference_schema: reference_schema, timestamp: timestamp
+
+ return r.statuses
+%}
diff --git a/modules/core/public/lib/queries/variable/find.liquid b/modules/core/public/lib/queries/variable/find.liquid
new file mode 100644
index 0000000..b7012e3
--- /dev/null
+++ b/modules/core/public/lib/queries/variable/find.liquid
@@ -0,0 +1,31 @@
+{% comment %}
+ Required params:
+ - name string
+ - default any
+ the default vaue of the variable
+ - type string (optional)
+ it can be: array, integer, float, boolean, object
+{% endcomment %}
+{% liquid
+ assign value = context.constants[name] | default: default, allow_false: true
+
+ case type
+ when 'boolean'
+ if value == 'true' or value == true
+ return true
+ else
+ return false
+ endif
+ when 'integer'
+ assign value = value | plus: 0
+ return value
+ when 'float'
+ assign value = value | plus: 0
+ return value
+ when 'array'
+ assign value = value | split: ','
+ return value
+ else
+ return value
+ endcase
+%}
diff --git a/modules/core/public/lib/queries/variable/get.liquid b/modules/core/public/lib/queries/variable/get.liquid
new file mode 100644
index 0000000..6f11259
--- /dev/null
+++ b/modules/core/public/lib/queries/variable/get.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ function res = 'modules/core/queries/variable/find', name: name, default: default, type: type
+ return res
+%}
diff --git a/modules/core/public/lib/validations/date.liquid b/modules/core/public/lib/validations/date.liquid
new file mode 100644
index 0000000..15cb224
--- /dev/null
+++ b/modules/core/public/lib/validations/date.liquid
@@ -0,0 +1,67 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @date
+ @can_be_past
+{% endcomment %}
+{% liquid
+ assign date = date | default: object[field_name] | to_date
+
+ assign is_past = date | is_date_in_past
+ assign now = 'now' | to_date
+
+ if date > now
+ assign is_future = true
+ else
+ assign is_future = false
+ endif
+
+ if can_be_past == false and is_past
+ assign message = message_can_be_past | default: 'modules/core/validation.date.can_be_past' | t: count: can_be_past, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if can_be_future == false and is_future
+ assign message = message_can_be_future | default: 'modules/core/validation.date.can_be_future' | t: count: can_be_future, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if lt != null
+ assign lt = lt | to_date
+ if date >= lt
+ assign localized_date = lt | l
+ assign message = message_lt | default: 'modules/core/validation.date.lt' | t: date: localized_date, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if lte != null
+ assign lte = lte | to_date
+ if date > lte
+ assign localized_date = lte | l
+ assign message = message_lte | default: 'modules/core/validation.date.lte' | t: date: localized_date, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if gt != null
+ assign gt = gt | to_date
+ if date <= gt
+ assign localized_date = gt | l
+ assign message = message_gt | default: 'modules/core/validation.date.gt' | t: date: localized_date, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if gte != null
+ assign gte = gte | to_date
+ if date < gte
+ assign localized_date = gte | l
+ assign message = message_gte | default: 'modules/core/validation.date.gte' | t: date: localized_date, value: date
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/lib/validations/each_element_length.liquid b/modules/core/public/lib/validations/each_element_length.liquid
new file mode 100644
index 0000000..8513f87
--- /dev/null
+++ b/modules/core/public/lib/validations/each_element_length.liquid
@@ -0,0 +1,35 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+{% endcomment %}
+{% liquid
+
+ for el in object[field_name]
+
+ assign size = el.size
+
+ if minimum != null and size < minimum
+ assign message = 'modules/core/validation.length.minimum' | t: count: minimum, value: size
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if maximum != null and size > maximum
+ assign message = 'modules/core/validation.length.maximum' | t: count: maximum, value: size
+ assign message = el | append: ' ' | append: message
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if is != null and size != is
+ assign message = 'modules/core/validation.length.is' | t: count: is, value: size
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ endfor
+
+ return c
+
+%}
diff --git a/modules/core/public/lib/validations/elements_included.liquid b/modules/core/public/lib/validations/elements_included.liquid
new file mode 100644
index 0000000..ec64b3a
--- /dev/null
+++ b/modules/core/public/lib/validations/elements_included.liquid
@@ -0,0 +1,20 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @array
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ for val in object[field_name]
+ unless array contains val
+ assign key = key | default: "modules/core/validation.array.not_included"
+ assign message = key | t: value: val
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endunless
+ endfor
+
+ return c
+%}
+
diff --git a/modules/core/public/lib/validations/email.liquid b/modules/core/public/lib/validations/email.liquid
new file mode 100644
index 0000000..d8a1188
--- /dev/null
+++ b/modules/core/public/lib/validations/email.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ assign valid_email = object[field_name] | is_email_valid
+ unless valid_email
+ assign key = key | default: "modules/core/validation.email"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/lib/validations/equal.liquid b/modules/core/public/lib/validations/equal.liquid
new file mode 100644
index 0000000..12645af
--- /dev/null
+++ b/modules/core/public/lib/validations/equal.liquid
@@ -0,0 +1,20 @@
+{% comment %}
+ params: @given
+ @expected
+ @field_name
+ @c
+{% endcomment %}
+{% liquid
+ if given != expected
+
+ if message == blank and key == blank
+ if not_verbose
+ assign message = 'modules/core/validation.equal_not_verbose' | t
+ else
+ assign message = 'modules/core/validation.equal' | t: given: given, expected: expected
+ endif
+ endif
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/exist_in_db.liquid b/modules/core/public/lib/validations/exist_in_db.liquid
new file mode 100644
index 0000000..64256c8
--- /dev/null
+++ b/modules/core/public/lib/validations/exist_in_db.liquid
@@ -0,0 +1,31 @@
+{% comment %}
+ params: @field_name
+ @property_name
+ @property_value
+ @scope_name
+ @scope_value
+ @exclude_name
+ @exclude_value
+ @ids
+ @not_ids
+ @table
+ @key
+ @c
+{% endcomment %}
+{% liquid
+ assign property_name = property_name | default: ''
+ assign property_value = property_value | default: ''
+ assign scope_name = scope_name | default: ''
+ assign scope_value = scope_value | default: ''
+ assign exclude_name = exclude_name | default: ''
+ assign exclude_value = exclude_value | default: ''
+ assign key = key | default: 'modules/core/validation.not_exist'
+
+ graphql r = 'modules/core/records/count', ids: ids, not_ids: not_ids, property_name: property_name, property_value: property_value, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value
+
+ assign count = r.records.total_entries
+ if count == 0
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/hcaptcha.liquid b/modules/core/public/lib/validations/hcaptcha.liquid
new file mode 100644
index 0000000..2d41b0c
--- /dev/null
+++ b/modules/core/public/lib/validations/hcaptcha.liquid
@@ -0,0 +1,14 @@
+{% comment %}
+ params: @hcaptcha_params
+ @key
+ @c
+{% endcomment %}
+
+{% liquid
+ assign hcaptcha_solved = hcaptcha_params | hcaptcha
+ unless hcaptcha_solved
+ assign key = key | default: "modules/core/validation.hcaptcha"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: 'hcaptcha', key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/lib/validations/included.liquid b/modules/core/public/lib/validations/included.liquid
new file mode 100644
index 0000000..17142bc
--- /dev/null
+++ b/modules/core/public/lib/validations/included.liquid
@@ -0,0 +1,17 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @array
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ assign value = value | default: object[field_name]
+ unless array contains value
+ assign key = key | default: "modules/core/validation.not_included"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
+
diff --git a/modules/core/public/lib/validations/length.liquid b/modules/core/public/lib/validations/length.liquid
new file mode 100644
index 0000000..3415946
--- /dev/null
+++ b/modules/core/public/lib/validations/length.liquid
@@ -0,0 +1,45 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+ @message_minimum
+ @message_maximum
+ @message_is
+{% endcomment %}
+{% liquid
+ assign value = value | default: object[field_name]
+ assign size = value.size
+ assign is = is | default: null
+ assign minimum = minimum | default: null
+ assign maximum = maximum | default: null
+
+ if allow_blank == null
+ assign allow_blank = true
+ endif
+ if allow_blank != true
+ if value == blank
+ assign message = message_blank | default: 'modules/core/validation.length.blank' | t
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if minimum != null and size < minimum
+ assign message = message_minimum | default: 'modules/core/validation.length.minimum' | t: count: minimum, value: size
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if maximum != null and size > maximum
+ assign message = message_maximum | default: 'modules/core/validation.length.maximum' | t: count: maximum, value: size
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if is != null and size != is
+ assign message = message_is | default: 'modules/core/validation.length.is' | t: count: is, value: size
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/lib/validations/matches.liquid b/modules/core/public/lib/validations/matches.liquid
new file mode 100644
index 0000000..e538a7c
--- /dev/null
+++ b/modules/core/public/lib/validations/matches.liquid
@@ -0,0 +1,19 @@
+{% comment %}
+ params: @object
+ @field_name
+ @regexp
+ @c
+ @message
+{% endcomment %}
+{% liquid
+ if allow_blank and object[field_name] == blank
+ return c
+ endif
+
+ assign matches = object[field_name] | matches: regexp
+ if matches != true
+ assign message = message | default: 'modules/core/validation.matches' | t
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/not_null.liquid b/modules/core/public/lib/validations/not_null.liquid
new file mode 100644
index 0000000..986541b
--- /dev/null
+++ b/modules/core/public/lib/validations/not_null.liquid
@@ -0,0 +1,14 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ if object[field_name] == null
+ assign key = key | default: "modules/core/validation.null"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/number.liquid b/modules/core/public/lib/validations/number.liquid
new file mode 100644
index 0000000..a0fea11
--- /dev/null
+++ b/modules/core/public/lib/validations/number.liquid
@@ -0,0 +1,62 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @number
+ @lt - less than
+ @lte - less than or equal
+ @gt - greater than
+ @gte - greater than or equal
+ @eq - equal
+ @ne - not equal
+{% endcomment %}
+{% liquid
+ assign number = number | default: object[field_name]
+%}
+{% capture test1 %}{{ number }}{% endcapture %}
+{% capture test2 %}{{ test1 | plus: 0 }}{% endcapture %}
+{% liquid
+ if test1 != test2
+ assign message = message | default: 'modules/core/validation.number.invalid' | t: value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+
+ return c
+ endif
+
+ assign number = number | plus: 0
+
+ if lt != null and number >= lt
+ assign message = message_lt | default: 'modules/core/validation.number.lt' | t: count: lt, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if lte == blank
+ assign lte = 2147483647
+ endif
+ if number > lte
+ assign message = message_lte | default: 'modules/core/validation.number.lte' | t: count: lte, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if gt != null and number <= gt
+ assign message = message_gt | default: 'modules/core/validation.number.gt' | t: count: gt, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if gte != null and number < gte
+ assign message = message_gte | default: 'modules/core/validation.number.gte' | t: count: gte, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if eq != null and number != eq
+ assign message = message_eq | default: 'modules/core/validation.number.eq' | t: count: eq, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if ne != null and number == ne
+ assign message = message_ne | default: 'modules/core/validation.number.ne' | t: count: ne, value: number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/lib/validations/password_complexity.liquid b/modules/core/public/lib/validations/password_complexity.liquid
new file mode 100644
index 0000000..ad4b34d
--- /dev/null
+++ b/modules/core/public/lib/validations/password_complexity.liquid
@@ -0,0 +1,35 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ assign decoded_pw = object.password
+ assign minimum = minimum | default: 6
+ assign maximum = maximum | default: 256
+ assign field_name = field_name | default: 'password'
+
+ function complex_password = 'modules/core/queries/variable/find' name: "MODULES/CORE/USE_COMPLEX_PASSWORD", type: "boolean", context: context
+ if complex_password
+ assign has_lowercase = decoded_pw | matches: '[a-z]'
+ unless has_lowercase
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.lowercase'
+ endunless
+
+ assign has_uppercase = decoded_pw | matches: '[A-Z]'
+ unless has_uppercase
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.uppercase'
+ endunless
+
+ assign has_number = decoded_pw | matches: '\d'
+ unless has_number
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.password.number'
+ endunless
+ endif
+
+ function c = 'modules/core/validations/length', c: c, object: object, value: decoded_pw, field_name: field_name, maximum: maximum, minimum: minimum, message_minimum: key: 'modules/core/validation.too_short', allow_blank: null
+
+ return c
+%}
diff --git a/modules/core/public/lib/validations/presence.liquid b/modules/core/public/lib/validations/presence.liquid
new file mode 100644
index 0000000..70b1f54
--- /dev/null
+++ b/modules/core/public/lib/validations/presence.liquid
@@ -0,0 +1,14 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ if object[field_name] == blank
+ assign key = key | default: "modules/core/validation.blank"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/truthy.liquid b/modules/core/public/lib/validations/truthy.liquid
new file mode 100644
index 0000000..6e9a734
--- /dev/null
+++ b/modules/core/public/lib/validations/truthy.liquid
@@ -0,0 +1,14 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ unless object[field_name]
+ assign key = key | default: "modules/core/validation.not_truthy"
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/lib/validations/unique_elements.liquid b/modules/core/public/lib/validations/unique_elements.liquid
new file mode 100644
index 0000000..3af3717
--- /dev/null
+++ b/modules/core/public/lib/validations/unique_elements.liquid
@@ -0,0 +1,19 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+{% endcomment %}
+{% liquid
+
+ assign unique_count = object[field_name] | uniq | size
+
+ if unique_count != object[field_name].size
+ assign key = key | default: 'modules/core/validation.array.not_unique'
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/lib/validations/uniqueness.liquid b/modules/core/public/lib/validations/uniqueness.liquid
new file mode 100644
index 0000000..42b2af8
--- /dev/null
+++ b/modules/core/public/lib/validations/uniqueness.liquid
@@ -0,0 +1,28 @@
+{% liquid
+ assign key = key | default: 'modules/core/validation.taken'
+ assign value = object[field_name]
+ if value != blank
+ if object.id != blank
+ assign not_ids = object.id | split: ','
+ endif
+ if scope_name
+ assign scope_value = object[scope_name]
+ else
+ assign scope_name = ''
+ endif
+
+ if exclude_name
+ assign exclude_value = object[exclude_name]
+ else
+ assign exclude_name = ''
+ endif
+
+ graphql r = 'modules/core/records/count', property_name: field_name, property_value: value, not_ids: not_ids, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value
+
+ assign count = r.records.total_entries
+ if count > 0
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ endif
+ return c
+%}
diff --git a/modules/core/public/lib/validations/valid_object.liquid b/modules/core/public/lib/validations/valid_object.liquid
new file mode 100644
index 0000000..b29a9b1
--- /dev/null
+++ b/modules/core/public/lib/validations/valid_object.liquid
@@ -0,0 +1,20 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @check_function
+{% endcomment %}
+
+{% liquid
+ assign value = value | default: object[field_name]
+ if value
+ function check_object = check_function, object: value
+ if check_object.valid != true
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.invalid'
+ assign errors_key = field_name | append: '_errors'
+ hash_assign c['errors'][errors_key] = check_object.errors
+ endif
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/schema/status.yml b/modules/core/public/schema/status.yml
new file mode 100644
index 0000000..5a8a0de
--- /dev/null
+++ b/modules/core/public/schema/status.yml
@@ -0,0 +1,14 @@
+name: status
+properties:
+ - name: name
+ type: string
+ - name: timestamp
+ type: datetime
+ - name: reference_id
+ type: string
+ - name: reference_schema
+ type: string
+ - name: payload
+ type: string
+ - name: requester_id
+ type: string
diff --git a/modules/core/public/translations/en/validation.yml b/modules/core/public/translations/en/validation.yml
new file mode 100644
index 0000000..06a1a48
--- /dev/null
+++ b/modules/core/public/translations/en/validation.yml
@@ -0,0 +1,50 @@
+---
+en:
+ validation:
+ disallowed: is not valid
+ not_url: is not valid url
+ blank: cannot be blank
+ email: must be a valid email
+ equal: expected %{given} to equal %{expected}
+ equal_not_verbose: does not match
+ array:
+ not_included: '`%{value}` is not a valid value'
+ not_unique: elements must be unique
+ hcaptcha: Captcha has not been solved properly, please try again
+ length:
+ minimum: is too short (minimum is %{count} characters)
+ maximum: is too long (maximum is %{count} characters)
+ is: is the wrong length (should be %{count} characters)
+ blank: is blank
+ number:
+ invalid: '`%{value}` is not a number'
+ greater_than: must be greater than %{count}
+ greater_than_or_equal: must be greater than or equal to %{count}
+ less_than: must be less than %{count}
+ less_than_or_equal: must be less than or equal to %{count}
+ equal_to: must be equal to %{count}
+ gt: must be greater than %{count}
+ gte: must be greater than or equal to %{count}
+ lt: must be less than %{count}
+ lte: must be less than or equal to %{count}
+ eq: must be equal to %{count}
+ ne: must be not equal to %{count}
+ date:
+ can_be_past: The date cannot be in the past
+ can_be_future: The date cannot be in the future
+ lt: must be before %{date}
+ lte: must be before %{date}
+ gt: must be after %{date}
+ gte: must be after or equal to %{date}
+ too_short: has to be longer than %{value} characters
+ taken: already taken
+ not_uniq: not unique
+ matches: not valid format
+ not_truthy: not true
+ not_null: not null
+ password:
+ lowercase: must include at least one lower case
+ uppercase: must include at least one upper case
+ number: must include at least one number
+ invalid: invalid
+ not_exist: not exist
diff --git a/modules/core/public/views/layouts/basic.liquid b/modules/core/public/views/layouts/basic.liquid
new file mode 100644
index 0000000..6b57c72
--- /dev/null
+++ b/modules/core/public/views/layouts/basic.liquid
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+
+ {{ content_for_layout }}
+
+
+
+
diff --git a/modules/core/public/views/layouts/mailer.html.liquid b/modules/core/public/views/layouts/mailer.html.liquid
new file mode 100644
index 0000000..510f6a1
--- /dev/null
+++ b/modules/core/public/views/layouts/mailer.html.liquid
@@ -0,0 +1,46 @@
+{% liquid
+ assign rtl_languages = 'ar,arc,dv,fa,ha,he,khw,ks,ku,ps,ur,yi' | split: ','
+ if rtl_languages contains context.language
+ assign direction = 'rtl'
+ else
+ assign direction = 'ltr'
+ endif
+ assign url = 'https://' | append: context.location.host
+%}
+
+
+
+
+
+
+
+
+
+ {{ content_for_layout }}
+
+
+
+
+
+
diff --git a/modules/core/public/views/pages/_events/index.liquid b/modules/core/public/views/pages/_events/index.liquid
new file mode 100644
index 0000000..c5b67f5
--- /dev/null
+++ b/modules/core/public/views/pages/_events/index.liquid
@@ -0,0 +1,11 @@
+---
+layout: modules/core/basic
+slug: _events
+---
+{% liquid
+ if context.environment == 'staging' or context.environment == 'development'
+ function events = 'modules/core/queries/events/search', limit: 50
+
+ render 'modules/core/events/list', events: events
+ endif
+%}
diff --git a/modules/core/public/views/pages/_events/trigger.liquid b/modules/core/public/views/pages/_events/trigger.liquid
new file mode 100644
index 0000000..9ac9edd
--- /dev/null
+++ b/modules/core/public/views/pages/_events/trigger.liquid
@@ -0,0 +1,20 @@
+---
+layout: modules/core/basic
+slug: _events/:uuid/trigger
+---
+{% liquid
+ if context.environment == 'staging' or context.environment == 'development'
+ function event = 'modules/core/queries/events/find', uuid: context.params.uuid
+
+ if context.params.trigger
+ function event = 'modules/core/commands/events/broadcast', object: event
+ echo 'BROADCASTED'
+ else
+ assign name = 'consumers/' | append: event.type | append: '/'
+ graphql consumers = 'modules/core/events/consumers', name: name | fetch: "admin_liquid_partials" | fetch: "results"
+ hash_assign event['consumers'] = consumers
+ endif
+
+ render 'modules/core/events/show', event: event
+ endif
+%}
diff --git a/modules/core/public/views/partials/events/event_card.liquid b/modules/core/public/views/partials/events/event_card.liquid
new file mode 100644
index 0000000..269dbaf
--- /dev/null
+++ b/modules/core/public/views/partials/events/event_card.liquid
@@ -0,0 +1,53 @@
+{% liquid
+ assign event_slim = event | deep_clone
+ assign _ = event_slim | hash_delete_key: 'object'
+ assign _ = event_slim | hash_delete_key: 'actor'
+ assign _ = event_slim | hash_delete_key: 'target'
+ assign _ = event_slim | hash_delete_key: 'id'
+ assign _ = event_slim | hash_delete_key: 'uuid'
+ assign _ = event_slim | hash_delete_key: 'date'
+ assign _ = event_slim | hash_delete_key: 'valid'
+ assign _ = event_slim | hash_delete_key: 'errors'
+ assign _ = event_slim | hash_delete_key: 'attributed_to'
+ assign _ = event_slim | hash_delete_key: 'type'
+ assign consumers = event_slim | hash_delete_key: 'consumers'
+%}
+
+
+ Event: {{ event.type }} {{ event.object.name | replace: "app.statuses.", "" }}
+
+
+ Date: {{ event.date | l }}
+
+
+ Attributes:
+
+
{{ event_slim }}
+
+
+
+
+
+
+
UUID: {{ event.uuid }}
+ {% if consumers %}
+
+ Consumers:
+
+ {% for consumer in consumers %}
+ {{ consumer.path }}
+ {% endfor %}
+
+
+ {% endif %}
+
+ show |
+ broadcast |
+
+
+
diff --git a/modules/core/public/views/partials/events/list.liquid b/modules/core/public/views/partials/events/list.liquid
new file mode 100644
index 0000000..a08712a
--- /dev/null
+++ b/modules/core/public/views/partials/events/list.liquid
@@ -0,0 +1,10 @@
+
+
Events
+ {{ events.results.size }} / {{ events.total_entries }}
+ {% for event in events.results %}
+ {% render 'modules/core/events/event_card', event: event.payload %}
+
+ {% else %}
+ no events found
+ {% endfor %}
+
diff --git a/modules/core/public/views/partials/events/show.liquid b/modules/core/public/views/partials/events/show.liquid
new file mode 100644
index 0000000..2561104
--- /dev/null
+++ b/modules/core/public/views/partials/events/show.liquid
@@ -0,0 +1,3 @@
+Event
+<< List
+{% render 'modules/core/events/event_card', event: event %}
diff --git a/modules/core/public/views/partials/lib/commands/email/send.liquid b/modules/core/public/views/partials/lib/commands/email/send.liquid
new file mode 100644
index 0000000..e6ad1be
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/email/send.liquid
@@ -0,0 +1,19 @@
+{% liquid
+ log 'Use modules/core/commands/email/send instead of modules/core/lib/commands/email/send', type: 'DEPRECATION'
+ function object = 'modules/core/commands/email/send/build', object: object
+ function object = 'modules/core/commands/email/send/check', object: object
+
+ if object.valid
+ graphql r = 'modules/core/email/send', template: 'modules/core/generic', data: object
+ if r.errors
+ log r.errors, type: 'errors.graphql.invalid'
+
+ hash_assign object['valid'] = false
+ hash_assign object['errors'] = r.errors
+ endif
+ else
+ log object.errors, type: 'payload validation error in core: lib/commands/email'
+ endif
+
+ return object
+%}
diff --git a/modules/core/public/views/partials/lib/commands/email/send/build.liquid b/modules/core/public/views/partials/lib/commands/email/send/build.liquid
new file mode 100644
index 0000000..5e57d28
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/email/send/build.liquid
@@ -0,0 +1,13 @@
+{% parse_json object %}
+ {
+ "layout": {{ object.layout | default: 'modules/core/mailer' | json }},
+ "from": {{ object.from | json }},
+ "to": {{ object.to | json }},
+ "subject": {{ object.subject | json }},
+ "cc": {{ object.cc | json }},
+ "bcc": {{ object.bcc | json }},
+ "partial": {{ object.partial | json }},
+ "data": {{ object.data | json }}
+ }
+{% endparse_json %}
+{% return object %}
diff --git a/modules/core/public/views/partials/lib/commands/email/send/check.liquid b/modules/core/public/views/partials/lib/commands/email/send/check.liquid
new file mode 100644
index 0000000..83f4269
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/email/send/check.liquid
@@ -0,0 +1,13 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'from'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'to'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'layout'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'partial'
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/core/public/views/partials/lib/commands/hook/alter.liquid b/modules/core/public/views/partials/lib/commands/hook/alter.liquid
new file mode 100644
index 0000000..3418a8a
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/hook/alter.liquid
@@ -0,0 +1,22 @@
+{% comment %}
+ hook: string
+ the hook name without hook_ prefix and _alter suffix.
+ params_to_modify: object
+ the object that will be passed to the alter hook to modify
+ params: object
+ the object that will be passed to the alter hook to give extra information
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/commands/hook/alter instead of modules/core/lib/commands/hook/alter', type: 'DEPRECATION'
+ assign original_params = params_to_modify | deep_clone
+
+ assign hook = '/hook_' | append: hook | append: '_alter'
+ function implementations = 'modules/core/lib/queries/hook/search', hook: hook
+
+ for implementation in implementations
+ function _ = implementation.path, params_to_modify: params_to_modify, params: params
+ endfor
+
+ assign result = '{}' | parse_json | hash_merge: original_params: original_params
+ return result
+%}
diff --git a/modules/core/public/views/partials/lib/commands/hook/fire.liquid b/modules/core/public/views/partials/lib/commands/hook/fire.liquid
new file mode 100644
index 0000000..5af969b
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/hook/fire.liquid
@@ -0,0 +1,41 @@
+{% comment %}
+ hook: string
+ the hook name without hook_ prefix.
+ params: object
+ the object to pass to the fired hook
+ merge_to_object boolean
+ merge the result objects to one object or collect them in an array
+{% endcomment %}
+{% liquid
+ if merge_to_object
+ assign results = '{}' | parse_json
+ else
+ assign results = '[]' | parse_json
+ endif
+
+ assign hook = '/hook_' | append: hook
+ function implementations = 'modules/core/lib/queries/hook/search', hook: hook
+
+ for implementation in implementations
+ function hook_result = implementation.path, params: params
+ if hook_result != nil
+ comment
+ Check if the result is an array and merge the values one by one.
+ endcomment
+ if hook_result[0]
+ for h_result in hook_result
+ assign results = results | add_to_array: h_result
+ endfor
+ comment
+ Check if the result is an object.
+ endcomment
+ elsif hook_result.first and merge_to_object
+ assign results = results | hash_merge: hook_result
+ else
+ assign results = results | add_to_array: hook_result
+ endif
+ endif
+ endfor
+
+ return results
+%}
diff --git a/modules/core/public/views/partials/lib/commands/variable/set.liquid b/modules/core/public/views/partials/lib/commands/variable/set.liquid
new file mode 100644
index 0000000..ddf03fb
--- /dev/null
+++ b/modules/core/public/views/partials/lib/commands/variable/set.liquid
@@ -0,0 +1,10 @@
+{% comment %}
+ Required params:
+ - name string
+ - value string
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/commands/variable/set instead of modules/core/lib/commands/variable/set', type: 'DEPRECATION'
+ graphql result = 'modules/core/variable/set', name: name, value: value
+ return result.variable
+%}
diff --git a/modules/core/public/views/partials/lib/helpers/register_error.liquid b/modules/core/public/views/partials/lib/helpers/register_error.liquid
new file mode 100644
index 0000000..2f252ef
--- /dev/null
+++ b/modules/core/public/views/partials/lib/helpers/register_error.liquid
@@ -0,0 +1,27 @@
+{% comment %}
+ @params
+ contract - { errors: {}, valid: true }
+ field_name
+ message:
+ key: i18n to be resolved into message
+{% endcomment %}
+
+{% liquid
+ assign key = key | default: null
+ assign message = message | default: null
+ if key
+ assign msg = key | t
+ else
+ assign msg = message
+ endif
+
+ assign errors = contract.errors
+
+ assign field_errors = errors[field_name] | default: '[]' | parse_json
+ assign field_errors = field_errors | add_to_array: msg
+
+ hash_assign errors[field_name] = field_errors
+ hash_assign contract['valid'] = false
+
+ return contract
+%}
diff --git a/modules/core/public/views/partials/lib/hooks/hook_module_info.liquid b/modules/core/public/views/partials/lib/hooks/hook_module_info.liquid
new file mode 100644
index 0000000..9915449
--- /dev/null
+++ b/modules/core/public/views/partials/lib/hooks/hook_module_info.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ Implements hook_module_info.
+{% endcomment %}
+{% parse_json info %}
+{
+ "name": "<%= &name =%>",
+ "machine_name": "<%= &machine_name =%>",
+ "type": "<%= &type =%>",
+ "version": "<%= &version =%>",
+ "dependencies": "<%= &dependencies =%>"
+}
+{% endparse_json %}
+
+{% liquid
+ return info
+%}
diff --git a/modules/core/public/views/partials/lib/queries/headscripts/get.liquid b/modules/core/public/views/partials/lib/queries/headscripts/get.liquid
new file mode 100644
index 0000000..37efd30
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/headscripts/get.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ log 'Use queries/headscripts/get instead of lib/queries/headscripts/get', type: 'DEPRECATION'
+ function res = 'modules/core/lib/queries/headscripts/search', merge_to_object: false
+ return res
+%}
diff --git a/modules/core/public/views/partials/lib/queries/headscripts/search.liquid b/modules/core/public/views/partials/lib/queries/headscripts/search.liquid
new file mode 100644
index 0000000..e1ef6d8
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/headscripts/search.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ log 'Use queries/headscripts/search instead of lib/queries/headscripts/search', type: 'DEPRECATION'
+ function headscript_implementations = 'modules/core/lib/commands/hook/fire', hook: 'headscripts', merge_to_object: merge_to_object
+ assign results = headscript_implementations | join: ''
+ return results | html_safe
+%}
diff --git a/modules/core/public/views/partials/lib/queries/hook/search.liquid b/modules/core/public/views/partials/lib/queries/hook/search.liquid
new file mode 100644
index 0000000..da311bb
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/hook/search.liquid
@@ -0,0 +1,12 @@
+{% comment %}
+ Get a list of all hook impltementation paths.
+ Params:
+ - hook: string
+ the hook's name with '/' prefix for example '/hook_user_create'.
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/queries/hook/search instead of modules/core/lib/queries/hook/search', type: 'DEPRECATION'
+ graphql implementations = 'modules/core/hook/search', hook: hook
+ return implementations.admin_liquid_partials.results
+%}
diff --git a/modules/core/public/views/partials/lib/queries/module/exists.liquid b/modules/core/public/views/partials/lib/queries/module/exists.liquid
new file mode 100644
index 0000000..c91e5f1
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/module/exists.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ Required params:
+ - name string
+ - type string (optional)
+ it can be: module, theme
+{% endcomment %}
+{% liquid
+ function modules = 'modules/core/lib/queries/registry/search', type: type
+ assign module = modules | array_detect: machine_name: name
+
+ if module
+ return true
+ endif
+
+ return false
+%}
diff --git a/modules/core/public/views/partials/lib/queries/registry/get.liquid b/modules/core/public/views/partials/lib/queries/registry/get.liquid
new file mode 100644
index 0000000..14e34d1
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/registry/get.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ function registry = 'modules/core/lib/queries/registry/search', type: type
+ return registry
+%}
diff --git a/modules/core/public/views/partials/lib/queries/registry/search.liquid b/modules/core/public/views/partials/lib/queries/registry/search.liquid
new file mode 100644
index 0000000..9c2cb22
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/registry/search.liquid
@@ -0,0 +1,28 @@
+{% comment %}
+ Required params:
+ - type string
+ it can be: all, module, theme
+{% endcomment %}
+{% liquid
+ function registry = 'modules/core/lib/commands/hook/fire', hook: 'module_info', merge_to_object: false
+
+ case type
+ when 'module'
+ assign modules = '[]' | parse_json
+ for module in registry
+ if module.type == 'module'
+ assign modules = modules | add_to_array: module
+ endif
+ endfor
+ return modules
+ when 'theme'
+ assign themes = '[]' | parse_json
+ for module in registry
+ if module.type == 'theme'
+ assign themes = themes | add_to_array: module
+ endif
+ endfor
+ return themes
+ endcase
+ return registry
+%}
diff --git a/modules/core/public/views/partials/lib/queries/variable/find.liquid b/modules/core/public/views/partials/lib/queries/variable/find.liquid
new file mode 100644
index 0000000..b7012e3
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/variable/find.liquid
@@ -0,0 +1,31 @@
+{% comment %}
+ Required params:
+ - name string
+ - default any
+ the default vaue of the variable
+ - type string (optional)
+ it can be: array, integer, float, boolean, object
+{% endcomment %}
+{% liquid
+ assign value = context.constants[name] | default: default, allow_false: true
+
+ case type
+ when 'boolean'
+ if value == 'true' or value == true
+ return true
+ else
+ return false
+ endif
+ when 'integer'
+ assign value = value | plus: 0
+ return value
+ when 'float'
+ assign value = value | plus: 0
+ return value
+ when 'array'
+ assign value = value | split: ','
+ return value
+ else
+ return value
+ endcase
+%}
diff --git a/modules/core/public/views/partials/lib/queries/variable/get.liquid b/modules/core/public/views/partials/lib/queries/variable/get.liquid
new file mode 100644
index 0000000..6651eb2
--- /dev/null
+++ b/modules/core/public/views/partials/lib/queries/variable/get.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ # TODO: remove after rewriting dependent modules
+ function res = 'modules/core/lib/queries/variable/find', name: name, default: default, type: type
+ return res
+%}
diff --git a/modules/core/public/views/partials/lib/validations/date.liquid b/modules/core/public/views/partials/lib/validations/date.liquid
new file mode 100644
index 0000000..206eccf
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/date.liquid
@@ -0,0 +1,68 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @date
+ @can_be_past
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/date instead of modules/core/lib/validations/date ', type: 'DEPRECATION'
+ assign date = date | default: object[field_name] | to_date
+
+ assign is_past = date | is_date_in_past
+ assign now = 'now' | to_date
+
+ if date > now
+ assign is_future = true
+ else
+ assign is_future = false
+ endif
+
+ if can_be_past == false and is_past
+ assign message = message_can_be_past | default: 'modules/core/validation.date.can_be_past' | t: count: can_be_past, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if can_be_future == false and is_future
+ assign message = message_can_be_future | default: 'modules/core/validation.date.can_be_future' | t: count: can_be_future, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if lt != null
+ assign lt = lt | to_date
+ if date >= lt
+ assign localized_date = lt | l
+ assign message = message_lt | default: 'modules/core/validation.date.lt' | t: date: localized_date, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if lte != null
+ assign lte = lte | to_date
+ if date > lte
+ assign localized_date = lte | l
+ assign message = message_lte | default: 'modules/core/validation.date.lte' | t: date: localized_date, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if gt != null
+ assign gt = gt | to_date
+ if date <= gt
+ assign localized_date = gt | l
+ assign message = message_gt | default: 'modules/core/validation.date.gt' | t: date: localized_date, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if gte != null
+ assign gte = gte | to_date
+ if date < gte
+ assign localized_date = gte | l
+ assign message = message_gte | default: 'modules/core/validation.date.gte' | t: date: localized_date, value: date
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/each_element_length.liquid b/modules/core/public/views/partials/lib/validations/each_element_length.liquid
new file mode 100644
index 0000000..371c397
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/each_element_length.liquid
@@ -0,0 +1,35 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/each_element_length instead of modules/core/lib/validations/each_element_length ', type: 'DEPRECATION'
+ for el in object[field_name]
+
+ assign size = el.size
+
+ if minimum != null and size < minimum
+ assign message = 'modules/core/validation.length.minimum' | t: count: minimum, value: size
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if maximum != null and size > maximum
+ assign message = 'modules/core/validation.length.maximum' | t: count: maximum, value: size
+ assign message = el | append: ' ' | append: message
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if is != null and size != is
+ assign message = 'modules/core/validation.length.is' | t: count: is, value: size
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ endfor
+
+ return c
+
+%}
diff --git a/modules/core/public/views/partials/lib/validations/elements_included.liquid b/modules/core/public/views/partials/lib/validations/elements_included.liquid
new file mode 100644
index 0000000..ef06223
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/elements_included.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @array
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/elements_included instead of modules/core/lib/validations/elements_included ', type: 'DEPRECATION'
+ for val in object[field_name]
+ unless array contains val
+ assign key = key | default: "modules/core/validation.array.not_included"
+ assign message = key | t: value: val
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endunless
+ endfor
+
+ return c
+%}
+
diff --git a/modules/core/public/views/partials/lib/validations/email.liquid b/modules/core/public/views/partials/lib/validations/email.liquid
new file mode 100644
index 0000000..2248f8f
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/email.liquid
@@ -0,0 +1,16 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/email instead of modules/core/lib/validations/email ', type: 'DEPRECATION'
+ assign valid_email = object[field_name] | is_email_valid
+ unless valid_email
+ assign key = key | default: "modules/core/validation.email"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/equal.liquid b/modules/core/public/views/partials/lib/validations/equal.liquid
new file mode 100644
index 0000000..7d5bf65
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/equal.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ params: @given
+ @expected
+ @field_name
+ @c
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/equal instead of modules/core/lib/validations/equal ', type: 'DEPRECATION'
+ if given != expected
+
+ if message == blank and key == blank
+ if not_verbose
+ assign message = 'modules/core/validation.equal_not_verbose' | t
+ else
+ assign message = 'modules/core/validation.equal' | t: given: given, expected: expected
+ endif
+ endif
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/exist_in_db.liquid b/modules/core/public/views/partials/lib/validations/exist_in_db.liquid
new file mode 100644
index 0000000..37808b0
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/exist_in_db.liquid
@@ -0,0 +1,32 @@
+{% comment %}
+ params: @field_name
+ @property_name
+ @property_value
+ @scope_name
+ @scope_value
+ @exclude_name
+ @exclude_value
+ @ids
+ @not_ids
+ @table
+ @key
+ @c
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/exist_in_db instead of modules/core/lib/validations/exist_in_db ', type: 'DEPRECATION'
+ assign property_name = property_name | default: ''
+ assign property_value = property_value | default: ''
+ assign scope_name = scope_name | default: ''
+ assign scope_value = scope_value | default: ''
+ assign exclude_name = exclude_name | default: ''
+ assign exclude_value = exclude_value | default: ''
+ assign key = key | default: 'modules/core/validation.not_exist'
+
+ graphql r = 'modules/core/records/count', ids: ids, not_ids: not_ids, property_name: property_name, property_value: property_value, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value
+
+ assign count = r.records.total_entries
+ if count == 0
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/hcaptcha.liquid b/modules/core/public/views/partials/lib/validations/hcaptcha.liquid
new file mode 100644
index 0000000..f936542
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/hcaptcha.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ params: @hcaptcha_params
+ @key
+ @c
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/hcaptcha instead of modules/core/lib/validations/hcaptcha ', type: 'DEPRECATION'
+ assign hcaptcha_solved = hcaptcha_params | hcaptcha
+ unless hcaptcha_solved
+ assign key = key | default: "modules/core/validation.hcaptcha"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'hcaptcha', key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/included.liquid b/modules/core/public/views/partials/lib/validations/included.liquid
new file mode 100644
index 0000000..a194d71
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/included.liquid
@@ -0,0 +1,18 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @array
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/included instead of modules/core/lib/validations/included ', type: 'DEPRECATION'
+ assign value = value | default: object[field_name]
+ unless array contains value
+ assign key = key | default: "modules/core/validation.not_included"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
+
diff --git a/modules/core/public/views/partials/lib/validations/length.liquid b/modules/core/public/views/partials/lib/validations/length.liquid
new file mode 100644
index 0000000..2e440d5
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/length.liquid
@@ -0,0 +1,46 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+ @message_minimum
+ @message_maximum
+ @message_is
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/length instead of modules/core/lib/validations/length ', type: 'DEPRECATION'
+ assign value = value | default: object[field_name]
+ assign size = value.size
+ assign is = is | default: null
+ assign minimum = minimum | default: null
+ assign maximum = maximum | default: null
+
+ if allow_blank == null
+ assign allow_blank = true
+ endif
+ if allow_blank != true
+ if size == blank
+ assign message = message_blank | default: 'modules/core/validation.length.blank' | t
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ endif
+
+ if minimum != null and size < minimum
+ assign message = message_minimum | default: 'modules/core/validation.length.minimum' | t: count: minimum, value: size
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if maximum != null and size > maximum
+ assign message = message_maximum | default: 'modules/core/validation.length.maximum' | t: count: maximum, value: size
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if is != null and size != is
+ assign message = message_is | default: 'modules/core/validation.length.is' | t: count: is, value: size
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/matches.liquid b/modules/core/public/views/partials/lib/validations/matches.liquid
new file mode 100644
index 0000000..9127098
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/matches.liquid
@@ -0,0 +1,20 @@
+{% comment %}
+ params: @object
+ @field_name
+ @regexp
+ @c
+ @message
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/matches instead of modules/core/lib/validations/matches ', type: 'DEPRECATION'
+ if allow_blank and object[field_name] == blank
+ return c
+ endif
+
+ assign matches = object[field_name] | matches: regexp
+ if matches != true
+ assign message = message | default: 'modules/core/validation.matches' | t
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/not_null.liquid b/modules/core/public/views/partials/lib/validations/not_null.liquid
new file mode 100644
index 0000000..f7bb4c6
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/not_null.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/not_null instead of modules/core/lib/validations/not_null ', type: 'DEPRECATION'
+ if object[field_name] == null
+ assign key = key | default: "modules/core/validation.null"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/number.liquid b/modules/core/public/views/partials/lib/validations/number.liquid
new file mode 100644
index 0000000..77368ba
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/number.liquid
@@ -0,0 +1,63 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @number
+ @lt - less than
+ @lte - less than or equal
+ @gt - greater than
+ @gte - greater than or equal
+ @eq - equal
+ @ne - not equal
+{% endcomment %}
+{% liquid
+ assign number = number | default: object[field_name]
+ log 'Use modules/core/validations/number instead of modules/core/lib/validations/number ', type: 'DEPRECATION'
+%}
+{% capture test1 %}{{ number }}{% endcapture %}
+{% capture test2 %}{{ test1 | plus: 0 }}{% endcapture %}
+{% liquid
+ if test1 != test2
+ assign message = message | default: 'modules/core/validation.number.invalid' | t: value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+
+ return c
+ endif
+
+ assign number = number | plus: 0
+
+ if lt != null and number >= lt
+ assign message = message_lt | default: 'modules/core/validation.number.lt' | t: count: lt, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if lte == blank
+ assign lte = 2147483647
+ endif
+ if number > lte
+ assign message = message_lte | default: 'modules/core/validation.number.lte' | t: count: lte, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if gt != null and number <= gt
+ assign message = message_gt | default: 'modules/core/validation.number.gt' | t: count: gt, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if gte != null and number < gte
+ assign message = message_gte | default: 'modules/core/validation.number.gte' | t: count: gte, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if eq != null and number != eq
+ assign message = message_eq | default: 'modules/core/validation.number.eq' | t: count: eq, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ if ne != null and number == ne
+ assign message = message_ne | default: 'modules/core/validation.number.ne' | t: count: ne, value: number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, message: message
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/password_complexity.liquid b/modules/core/public/views/partials/lib/validations/password_complexity.liquid
new file mode 100644
index 0000000..d5848f6
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/password_complexity.liquid
@@ -0,0 +1,33 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/password_complexity instead of modules/core/lib/validations/password_complexity ', type: 'DEPRECATION'
+ assign decoded_pw = object.password
+
+ function complex_password = 'modules/core/lib/queries/variable/find' name: "MODULES/CORE/USE_COMPLEX_PASSWORD", type: "boolean", context: context
+ if complex_password
+ assign has_lowercase = decoded_pw | matches: '[a-z]'
+ unless has_lowercase
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.lowercase'
+ endunless
+
+ assign has_uppercase = decoded_pw | matches: '[A-Z]'
+ unless has_uppercase
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.uppercase'
+ endunless
+
+ assign has_number = decoded_pw | matches: '\d'
+ unless has_number
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: 'password', key: 'modules/core/validation.password.number'
+ endunless
+ endif
+
+ function c = 'modules/core/lib/validations/length', c: c, object: object, value: decoded_pw, field_name: 'password', maximum: 256, minimum: 6, message_minimum: key: 'modules/core/validation.too_short', allow_blank: null
+
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/presence.liquid b/modules/core/public/views/partials/lib/validations/presence.liquid
new file mode 100644
index 0000000..5d34276
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/presence.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/presence instead of modules/core/lib/validations/presence ', type: 'DEPRECATION'
+ if object[field_name] == blank
+ assign key = key | default: "modules/core/validation.blank"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/truthy.liquid b/modules/core/public/views/partials/lib/validations/truthy.liquid
new file mode 100644
index 0000000..0efd280
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/truthy.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @key[optional]
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/truthy instead of modules/core/lib/validations/truthy ', type: 'DEPRECATION'
+ unless object[field_name]
+ assign key = key | default: "modules/core/validation.not_truthy"
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endunless
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/unique_elements.liquid b/modules/core/public/views/partials/lib/validations/unique_elements.liquid
new file mode 100644
index 0000000..3eb74e5
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/unique_elements.liquid
@@ -0,0 +1,19 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @minimum
+ @maximum
+ @is
+{% endcomment %}
+{% liquid
+ log 'Use modules/core/validations/unique_elements instead of modules/core/lib/validations/unique_elements ', type: 'DEPRECATION'
+ assign unique_count = object[field_name] | uniq | size
+
+ if unique_count != object[field_name].size
+ assign key = key | default: 'modules/core/validation.array.not_unique'
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/uniqueness.liquid b/modules/core/public/views/partials/lib/validations/uniqueness.liquid
new file mode 100644
index 0000000..3942836
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/uniqueness.liquid
@@ -0,0 +1,29 @@
+{% liquid
+ log 'Use modules/core/validations/uniqueness instead of modules/core/lib/validations/uniqueness ', type: 'DEPRECATION'
+ assign key = key | default: 'modules/core/validation.taken'
+ assign value = object[field_name]
+ if value != blank
+ if object.id != blank
+ assign not_ids = object.id | split: ','
+ endif
+ if scope_name
+ assign scope_value = object[scope_name]
+ else
+ assign scope_name = ''
+ endif
+
+ if exclude_name
+ assign exclude_value = object[exclude_name]
+ else
+ assign exclude_name = ''
+ endif
+
+ graphql r = 'modules/core/records/count', property_name: field_name, property_value: value, not_ids: not_ids, table: table, scope_name: scope_name, scope_value: scope_value, exclude_name: exclude_name, exclude_value: exclude_value
+
+ assign count = r.records.total_entries
+ if count > 0
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: key
+ endif
+ endif
+ return c
+%}
diff --git a/modules/core/public/views/partials/lib/validations/valid_object.liquid b/modules/core/public/views/partials/lib/validations/valid_object.liquid
new file mode 100644
index 0000000..7b1b317
--- /dev/null
+++ b/modules/core/public/views/partials/lib/validations/valid_object.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ params: @object
+ @field_name
+ @c
+ @check_function
+{% endcomment %}
+
+{% liquid
+ log 'Use modules/core/validations/valid_object instead of modules/core/lib/validations/valid_object ', type: 'DEPRECATION'
+ assign value = value | default: object[field_name]
+ if value
+ function check_object = check_function, object: value
+ if check_object.valid != true
+ function c = 'modules/core/lib/helpers/register_error', contract: c, field_name: field_name, key: 'modules/core/validation.invalid'
+ assign errors_key = field_name | append: '_errors'
+ hash_assign c['errors'][errors_key] = check_object.errors
+ endif
+ endif
+
+ return c
+%}
diff --git a/modules/core/template-values.json b/modules/core/template-values.json
new file mode 100644
index 0000000..9b470e3
--- /dev/null
+++ b/modules/core/template-values.json
@@ -0,0 +1,7 @@
+{
+ "name": "Pos Module Core",
+ "machine_name": "core",
+ "type": "module",
+ "version": "1.5.5",
+ "dependencies": {}
+}
\ No newline at end of file
diff --git a/modules/profile/public/graphql/profiles/create.graphql b/modules/profile/public/graphql/profiles/create.graphql
new file mode 100644
index 0000000..2493d98
--- /dev/null
+++ b/modules/profile/public/graphql/profiles/create.graphql
@@ -0,0 +1,29 @@
+mutation (
+ $uuid: String!
+ $user_id: String!,
+ $first_name: String,
+ $last_name: String
+ $name: String
+ $email: String
+ $c__names: String
+) {
+ record: record_create(
+ record: {
+ table: "modules/profile/profile"
+ properties: [
+ { name: "user_id", value: $user_id }
+ { name: "first_name", value: $first_name }
+ { name: "last_name", value: $last_name }
+ { name: "uuid", value: $uuid }
+ { name: "name", value: $name }
+ { name: "email", value: $email }
+ { name: "c__names", value: $c__names }
+ ]
+ }
+ ) {
+ id
+ created_at
+ type: table
+ properties
+ }
+}
diff --git a/modules/profile/public/graphql/profiles/delete.graphql b/modules/profile/public/graphql/profiles/delete.graphql
new file mode 100644
index 0000000..2f858b5
--- /dev/null
+++ b/modules/profile/public/graphql/profiles/delete.graphql
@@ -0,0 +1,6 @@
+mutation delete_profile($id: ID!) {
+ record: record_delete(
+ table: "modules/profile/profile"
+ id: $id
+ ){ id }
+}
diff --git a/modules/profile/public/graphql/profiles/search.graphql b/modules/profile/public/graphql/profiles/search.graphql
new file mode 100644
index 0000000..288a4f0
--- /dev/null
+++ b/modules/profile/public/graphql/profiles/search.graphql
@@ -0,0 +1,45 @@
+query (
+ $page: Int = 1
+ $limit: Int = 20
+ $first_name: String
+ $last_name: String
+ $email: String
+ $emails: [String!]
+ $id: ID
+ $ids: [ID!]
+ $not_ids: [ID!]
+ $uuid: String
+ $user_id: String
+ $sort: RecordsSortInput = { created_at: { order: DESC } }
+ $query: String
+) {
+ records(
+ page: $page
+ per_page: $limit
+ filter: {
+ id: { value: $id, value_in: $ids, not_value_in: $not_ids }
+ table: { value: "modules/profile/profile" }
+ properties: [
+ { name: "uuid", value: $uuid }
+ { name: "first_name", value: $first_name }
+ { name: "last_name", value: $last_name }
+ { name: "user_id", value: $user_id }
+ { name: "email", value: $email, value_in: $emails }
+ { name: "c__names", contains: $query }
+ ]
+ }
+ sort: [$sort]
+ ) {
+ total_entries
+ total_pages
+ has_previous_page
+ has_next_page
+ results {
+ id
+ created_at
+ type: table
+
+ properties
+ }
+ }
+}
diff --git a/modules/profile/public/graphql/profiles/update.graphql b/modules/profile/public/graphql/profiles/update.graphql
new file mode 100644
index 0000000..a2bbdc7
--- /dev/null
+++ b/modules/profile/public/graphql/profiles/update.graphql
@@ -0,0 +1,28 @@
+mutation profiles_update(
+ $id: ID!
+ $name: String
+ $first_name: String
+ $last_name: String
+ $email: String
+ $c__names: String
+) {
+ record: record_update(
+ id: $id
+ record: {
+ table: "modules/profile/profile"
+ properties: [
+ { name: "name", value: $name }
+ { name: "first_name", value: $first_name }
+ { name: "last_name", value: $last_name }
+ { name: "email", value: $email }
+ { name: "c__names", value: $c__names }
+ ]
+ }
+ ) {
+ id
+ created_at
+ type: table
+
+ properties
+ }
+}
diff --git a/modules/profile/public/lib/commands/profiles/create.liquid b/modules/profile/public/lib/commands/profiles/create.liquid
new file mode 100644
index 0000000..357e82c
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ function object = 'modules/profile/commands/profiles/create/build', object: object, name: null
+ function object = 'modules/profile/commands/profiles/create/check', object: object
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/profile/profiles/create', object: object
+ assign object = object | hash_merge: object.properties
+ endif
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/create/build.liquid b/modules/profile/public/lib/commands/profiles/create/build.liquid
new file mode 100644
index 0000000..bdb30ef
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create/build.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ function tokenized_names = 'modules/profile/commands/profiles/tokenize_names', object: object
+ assign uuid_new = '' | uuid
+ assign uuid = object.uuid | default: uuid_new
+ assign name = object.first_name | append: ' ' | append: object.last_name
+
+ assign data = null | hash_merge: first_name: object.first_name, last_name: object.last_name, user_id: object.user_id, email: object.email, uuid: uuid, name: name, c__names: tokenized_names
+
+ return data
+%}
diff --git a/modules/profile/public/lib/commands/profiles/create/check.liquid b/modules/profile/public/lib/commands/profiles/create/check.liquid
new file mode 100644
index 0000000..580d7c7
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create/check.liquid
@@ -0,0 +1,15 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'user_id', key: 'validation.blank'
+ function table = 'modules/profile/helpers/table_name'
+ function c = 'modules/core/validations/uniqueness', c: c, object: object, field_name: 'user_id', table: table, key: 'validation.user_already_has_profile', scope_name: null, exclude_name: null
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'uuid', key: 'validation.blank'
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'name', maximum: 80, allow_blank: null
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'first_name', maximum: 40, allow_blank: null
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'last_name', maximum: 40, allow_blank: null
+
+ assign object = object | hash_merge: c
+
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/create_proxy.liquid b/modules/profile/public/lib/commands/profiles/create_proxy.liquid
new file mode 100644
index 0000000..5f4de9a
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create_proxy.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/commands/profiles/create'
+ function profile = function_name, object: object
+ return profile
+%}
diff --git a/modules/profile/public/lib/commands/profiles/create_validate.liquid b/modules/profile/public/lib/commands/profiles/create_validate.liquid
new file mode 100644
index 0000000..39cfa19
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create_validate.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function object = 'modules/profile/commands/profiles/create/build', object: object, name: null
+ function object = 'modules/profile/commands/profiles/create/check', object: object
+
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/create_validate_proxy.liquid b/modules/profile/public/lib/commands/profiles/create_validate_proxy.liquid
new file mode 100644
index 0000000..967d7cf
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/create_validate_proxy.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/commands/profiles/create_validate'
+ function profile = function_name, object: object
+ return profile
+%}
diff --git a/modules/profile/public/lib/commands/profiles/delete.liquid b/modules/profile/public/lib/commands/profiles/delete.liquid
new file mode 100644
index 0000000..635c481
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/delete.liquid
@@ -0,0 +1,8 @@
+{% liquid
+ function object = 'modules/profile/commands/profiles/delete/build', object: object
+ function object = 'modules/profile/commands/profiles/delete/check', object: object
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/profile/profiles/delete', object: object
+ endif
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/delete/build.liquid b/modules/profile/public/lib/commands/profiles/delete/build.liquid
new file mode 100644
index 0000000..d10a19e
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/delete/build.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ assign data = null | hash_merge: id: object.id
+
+ return data
+%}
diff --git a/modules/profile/public/lib/commands/profiles/delete/check.liquid b/modules/profile/public/lib/commands/profiles/delete/check.liquid
new file mode 100644
index 0000000..4cf1ee5
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/delete/check.liquid
@@ -0,0 +1,9 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: 'validation.blank'
+
+ assign object = object | hash_merge: c
+
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/delete_proxy.liquid b/modules/profile/public/lib/commands/profiles/delete_proxy.liquid
new file mode 100644
index 0000000..91a5cba
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/delete_proxy.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/commands/profiles/delete'
+ function profile = function_name, object: object
+ return profile
+%}
diff --git a/modules/profile/public/lib/commands/profiles/tokenize_names.liquid b/modules/profile/public/lib/commands/profiles/tokenize_names.liquid
new file mode 100644
index 0000000..f4b04c8
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/tokenize_names.liquid
@@ -0,0 +1,4 @@
+{% liquid
+ assign tokenized_names = '[]' | parse_json | array_add: object.email | array_add: object.first_name | array_add: object.last_name | compact | uniq | join: ' ' | downcase
+ return tokenized_names
+%}
diff --git a/modules/profile/public/lib/commands/profiles/update.liquid b/modules/profile/public/lib/commands/profiles/update.liquid
new file mode 100644
index 0000000..13e80f9
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/update.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ function object = 'modules/profile/commands/profiles/update/build', object: object, profile: profile, name: null
+ function object = 'modules/profile/commands/profiles/update/check', object: object
+
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/profile/profiles/update', object: object
+ assign object = object | hash_merge: object.properties
+ endif
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/update/build.liquid b/modules/profile/public/lib/commands/profiles/update/build.liquid
new file mode 100644
index 0000000..5cb50bb
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/update/build.liquid
@@ -0,0 +1,8 @@
+{% liquid
+ function tokenized_names = 'modules/profile/commands/profiles/tokenize_names', object: object
+ assign name = object.first_name | append: ' ' | append: object.last_name
+
+ assign data = null | hash_merge: id: profile.id, first_name: object.first_name, last_name: object.last_name, name: name, c__names: tokenized_names, email: object.email
+
+ return data
+%}
diff --git a/modules/profile/public/lib/commands/profiles/update/check.liquid b/modules/profile/public/lib/commands/profiles/update/check.liquid
new file mode 100644
index 0000000..ed177e0
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/update/check.liquid
@@ -0,0 +1,14 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id', key: 'validation.blank'
+ function c = 'modules/core/validations/uniqueness', c: c, object: object, field_name: 'email', table: 'modules/profile/profile', scope_name: null, exclude_name: null
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'name', maximum: 80, allow_blank: null
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'first_name', maximum: 40, allow_blank: null
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'last_name', maximum: 40, allow_blank: null
+
+
+ assign object = object | hash_merge: c
+
+ return object
+%}
diff --git a/modules/profile/public/lib/commands/profiles/update_proxy.liquid b/modules/profile/public/lib/commands/profiles/update_proxy.liquid
new file mode 100644
index 0000000..fbf2853
--- /dev/null
+++ b/modules/profile/public/lib/commands/profiles/update_proxy.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/commands/profiles/update'
+ function profile = function_name, object: object, profile: profile
+ return profile
+%}
diff --git a/modules/profile/public/lib/helpers/current_profile.liquid b/modules/profile/public/lib/helpers/current_profile.liquid
new file mode 100644
index 0000000..7ef1730
--- /dev/null
+++ b/modules/profile/public/lib/helpers/current_profile.liquid
@@ -0,0 +1,11 @@
+{% liquid
+ function user = 'modules/user/queries/user/current'
+ if user.id
+ function current_profile = 'modules/profile/queries/profiles/find', user_id: user.id, id: null, uuid: null, first_name: null, last_name: null
+ endif
+
+ assign current_profile = current_profile | hash_merge: roles: user.roles, permissions: user.permissions, user: user
+
+ export current_profile
+ return current_profile
+%}
diff --git a/modules/profile/public/lib/helpers/profiles/slugs/build.liquid b/modules/profile/public/lib/helpers/profiles/slugs/build.liquid
new file mode 100644
index 0000000..58033ea
--- /dev/null
+++ b/modules/profile/public/lib/helpers/profiles/slugs/build.liquid
@@ -0,0 +1,8 @@
+{% liquid
+ assign profile = profile | default: current_profile
+ assign first_name = profile.first_name | default: current_profile.properties.first_name
+ assign last_name = profile.last_name | default: current_profile.properties.last_name
+ assign slug = first_name | append: '-' | append: last_name | append: '-' | append: profile.id | slugify
+
+ return slug
+%}
diff --git a/modules/profile/public/lib/helpers/table_name.liquid b/modules/profile/public/lib/helpers/table_name.liquid
new file mode 100644
index 0000000..f31aef7
--- /dev/null
+++ b/modules/profile/public/lib/helpers/table_name.liquid
@@ -0,0 +1,5 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+
+ return profile_module | append: '/profile'
+%}
diff --git a/modules/profile/public/lib/hooks/hook_module_info.liquid b/modules/profile/public/lib/hooks/hook_module_info.liquid
new file mode 100644
index 0000000..cb6782c
--- /dev/null
+++ b/modules/profile/public/lib/hooks/hook_module_info.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ Implements hook_module_info.
+{% endcomment %}
+{% parse_json info %}
+{
+ "name": "<%= &name =%>",
+ "machine_name": "<%= &machine_name =%>",
+ "type": "<%= &type =%>",
+ "version": "<%= &version =%>"
+}
+{% endparse_json %}
+
+{% liquid
+ return info
+%}
diff --git a/modules/profile/public/lib/queries/profiles/filters.liquid b/modules/profile/public/lib/queries/profiles/filters.liquid
new file mode 100644
index 0000000..0e490b4
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/filters.liquid
@@ -0,0 +1,15 @@
+{% parse_json sort_options %}
+{
+ "first_name_desc": { "properties": { "name": "first_name", "order": "DESC" }},
+ "first_name_desc": { "properties": { "name": "first_name", "order": "ASC" }}
+}
+{% endparse_json %}
+{% liquid
+ assign filters = '{}' | parse_json
+ hash_assign filters['page'] = params.page | to_positive_integer: 1
+ hash_assign filters['keyword'] = params.keyword | default: ''
+ hash_assign filters['sort_by'] = params.sort_by | default: 'first_name_desc'
+ hash_assign filters['sort'] = sort_options[filters.sort_by]
+
+ return filters
+%}
diff --git a/modules/profile/public/lib/queries/profiles/filters_proxy.liquid b/modules/profile/public/lib/queries/profiles/filters_proxy.liquid
new file mode 100644
index 0000000..e8cf272
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/filters_proxy.liquid
@@ -0,0 +1,7 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/queries/profiles/filters'
+ function filters = function_name, params: params
+
+ return filters
+%}
diff --git a/modules/profile/public/lib/queries/profiles/find.liquid b/modules/profile/public/lib/queries/profiles/find.liquid
new file mode 100644
index 0000000..d1b78e0
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/find.liquid
@@ -0,0 +1,18 @@
+{% liquid
+ if user_id == blank and id == blank and uuid == blank
+ log 'ERROR: missing ID argument in modules/profile/queries/profile/find'
+ return nil
+ endif
+
+ graphql result = 'modules/profile/profiles/search', user_id: user_id, id: id, first_name: first_name, last_name: last_name, uuid: uuid, limit: 1, page: 1
+ assign profile = result.records.results.first
+
+ if profile
+ function slug = 'modules/profile/helpers/profiles/slugs/build' , current_profile: profile
+ hash_assign profile['properties']['slug'] = slug
+ assign profile = profile | hash_merge: profile.properties
+ endif
+
+
+ return profile
+%}
diff --git a/modules/profile/public/lib/queries/profiles/find_proxy.liquid b/modules/profile/public/lib/queries/profiles/find_proxy.liquid
new file mode 100644
index 0000000..94409e5
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/find_proxy.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/queries/profiles/find'
+ function profile = function_name, user_id: user_id, id: id, uuid: uuid, filters: filters
+ return profile
+%}
diff --git a/modules/profile/public/lib/queries/profiles/search.liquid b/modules/profile/public/lib/queries/profiles/search.liquid
new file mode 100644
index 0000000..7b959d6
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/search.liquid
@@ -0,0 +1,22 @@
+{% liquid
+ assign page = page | to_positive_integer: 1
+ if not_ids == blank
+ assign not_ids = null
+ endif
+
+ graphql r = 'modules/profile/profiles/search', limit: limit, uuid: uuid, id: id, ids: ids, first_name: first_name , last_name: last_name , user_id: user_id, not_ids: not_ids, query: query, emails: emails, sort: sort, page: page
+
+ assign records = r.records
+ assign profiles = '[]' | parse_json
+ for profile in records.results
+ function slug = 'modules/profile/helpers/profiles/slugs/build' , current_profile: profile
+ hash_assign profile['properties']['slug'] = slug
+ assign p = profile | hash_merge: profile.properties
+
+ assign profiles = profiles | array_add: p
+ endfor
+ hash_assign records['results'] = profiles
+
+ return records
+%}
+
diff --git a/modules/profile/public/lib/queries/profiles/search_proxy.liquid b/modules/profile/public/lib/queries/profiles/search_proxy.liquid
new file mode 100644
index 0000000..55a436b
--- /dev/null
+++ b/modules/profile/public/lib/queries/profiles/search_proxy.liquid
@@ -0,0 +1,7 @@
+{% liquid
+ function profile_module = 'modules/core/queries/variable/get', name: 'PROFILE_MODULE', default: 'modules/profile', type: null
+ assign function_name = profile_module | append: '/queries/profiles/search'
+ function profile = function_name, limit: limit, uuid: uuid, id: id, ids: ids, first_name: first_name, last_name: last_name, user_id: user_id, not_ids: not_ids, query: query, emails: emails, sort: sort, page: page, filters: filters
+
+ return profile
+%}
diff --git a/modules/profile/public/schema/profile.yml b/modules/profile/public/schema/profile.yml
new file mode 100644
index 0000000..94af257
--- /dev/null
+++ b/modules/profile/public/schema/profile.yml
@@ -0,0 +1,11 @@
+name: profile
+properties:
+ - name: uuid
+ - name: user_id
+ - name: name
+ - name: first_name
+ - name: last_name
+ - name: email # duplication from user
+
+ # tokenized downcased names for searching
+ - name: c__names
diff --git a/modules/profile/template-values.json b/modules/profile/template-values.json
new file mode 100644
index 0000000..f79ef44
--- /dev/null
+++ b/modules/profile/template-values.json
@@ -0,0 +1,10 @@
+{
+ "name": "Profile",
+ "machine_name": "profile",
+ "type": "module",
+ "version": "1.1.0",
+ "dependencies": {
+ "core": "^1.0.0",
+ "user": "^3.0.0"
+ }
+}
diff --git a/modules/user/package-lock.json b/modules/user/package-lock.json
new file mode 100644
index 0000000..378a87d
--- /dev/null
+++ b/modules/user/package-lock.json
@@ -0,0 +1,318 @@
+{
+ "name": "user",
+ "version": "1.0.2",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "user",
+ "version": "1.0.2",
+ "license": "MIT",
+ "devDependencies": {
+ "auto-changelog": "^2.4.0"
+ }
+ },
+ "node_modules/auto-changelog": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz",
+ "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==",
+ "dev": true,
+ "dependencies": {
+ "commander": "^7.2.0",
+ "handlebars": "^4.7.7",
+ "node-fetch": "^2.6.1",
+ "parse-github-url": "^1.0.2",
+ "semver": "^7.3.5"
+ },
+ "bin": {
+ "auto-changelog": "src/index.js"
+ },
+ "engines": {
+ "node": ">=8.3"
+ }
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "dev": true,
+ "bin": {
+ "parse-github-url": "cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/uglify-js": {
+ "version": "3.17.2",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz",
+ "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ },
+ "dependencies": {
+ "auto-changelog": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.4.0.tgz",
+ "integrity": "sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==",
+ "dev": true,
+ "requires": {
+ "commander": "^7.2.0",
+ "handlebars": "^4.7.7",
+ "node-fetch": "^2.6.1",
+ "parse-github-url": "^1.0.2",
+ "semver": "^7.3.5"
+ }
+ },
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4",
+ "wordwrap": "^1.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
+ "parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.17.2",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz",
+ "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==",
+ "dev": true,
+ "optional": true
+ },
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+}
diff --git a/modules/user/package.json b/modules/user/package.json
new file mode 100644
index 0000000..720b25a
--- /dev/null
+++ b/modules/user/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "user",
+ "version": "1.0.4",
+ "description": "This module handles the user operations, assign users to roles and add permissions to roles.",
+ "scripts": {
+ "version": "(cd ../../ && pos-cli modules version user -p) && git add template-values.json && auto-changelog -p && git add CHANGELOG.md"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Platform-OS/pos-module-user.git"
+ },
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/Platform-OS/pos-module-user/issues"
+ },
+ "homepage": "https://github.com/Platform-OS/pos-module-user#readme",
+ "devDependencies": {
+ "auto-changelog": "^2.4.0"
+ },
+ "auto-changelog": {
+ "template": "changelog-template.hbs",
+ "unreleased": true,
+ "commitLimit": false
+ }
+}
diff --git a/modules/user/public/graphql/session/destroy.graphql b/modules/user/public/graphql/session/destroy.graphql
new file mode 100644
index 0000000..a268679
--- /dev/null
+++ b/modules/user/public/graphql/session/destroy.graphql
@@ -0,0 +1,3 @@
+mutation {
+ user_session_destroy
+}
diff --git a/modules/user/public/graphql/user/count.graphql b/modules/user/public/graphql/user/count.graphql
new file mode 100644
index 0000000..aa197dd
--- /dev/null
+++ b/modules/user/public/graphql/user/count.graphql
@@ -0,0 +1,5 @@
+query {
+ users(per_page: 1) {
+ total_entries
+ }
+}
diff --git a/modules/user/public/graphql/user/create.graphql b/modules/user/public/graphql/user/create.graphql
new file mode 100644
index 0000000..c5a66a1
--- /dev/null
+++ b/modules/user/public/graphql/user/create.graphql
@@ -0,0 +1,7 @@
+mutation ($email: String!, $password: String!, $roles: [String] = []) {
+ user: user_create(user: { email: $email, password: $password, properties: [{ name: "roles", value_array: $roles }]}) {
+ id
+ email
+ roles: property_array(name: "roles")
+ }
+}
diff --git a/modules/user/public/graphql/user/delete.graphql b/modules/user/public/graphql/user/delete.graphql
new file mode 100644
index 0000000..639c772
--- /dev/null
+++ b/modules/user/public/graphql/user/delete.graphql
@@ -0,0 +1,8 @@
+mutation ($id: ID!) {
+ user: user_delete(id: $id) {
+ created_at
+ deleted_at
+ id
+ email
+ }
+}
diff --git a/modules/user/public/graphql/user/find.graphql b/modules/user/public/graphql/user/find.graphql
new file mode 100644
index 0000000..908deb3
--- /dev/null
+++ b/modules/user/public/graphql/user/find.graphql
@@ -0,0 +1,24 @@
+query (
+ $id: ID
+ $email: String
+ $with_token: Boolean = false
+ $valid_for: Int = 1
+ $expires_in: Float = 48
+ $limit: Int = 1
+) {
+ users(
+ per_page: $limit,
+ filter: {
+ id: { value: $id }
+ email: { value: $email }
+ }
+ ) {
+ results {
+ created_at
+ email
+ id
+ roles: property_array(name: "roles")
+ token: temporary_token(valid_for: $valid_for, expires_in: $expires_in) @include(if: $with_token)
+ }
+ }
+}
diff --git a/modules/user/public/graphql/user/list.graphql b/modules/user/public/graphql/user/list.graphql
new file mode 100644
index 0000000..35a4b57
--- /dev/null
+++ b/modules/user/public/graphql/user/list.graphql
@@ -0,0 +1,11 @@
+query users_list($email:String) {
+ users(per_page: 1000, filter: { email: { exact: $email } }) {
+ total_entries
+ results {
+ created_at
+ email
+ id
+ roles: property_array(name: "roles")
+ }
+ }
+}
diff --git a/modules/user/public/graphql/user/load.graphql b/modules/user/public/graphql/user/load.graphql
new file mode 100644
index 0000000..97cf765
--- /dev/null
+++ b/modules/user/public/graphql/user/load.graphql
@@ -0,0 +1,10 @@
+query ($id: ID!) {
+ users(per_page: 1, filter: { id: { value: $id } }) {
+ results {
+ created_at
+ email
+ id
+ roles: property_array(name: "roles")
+ }
+ }
+}
diff --git a/modules/user/public/graphql/user/roles/append.graphql b/modules/user/public/graphql/user/roles/append.graphql
new file mode 100644
index 0000000..c8f91b6
--- /dev/null
+++ b/modules/user/public/graphql/user/roles/append.graphql
@@ -0,0 +1,13 @@
+mutation user_roles_append($id: ID!, $role: String!) {
+ user: user_update(
+ id: $id
+ user: {
+ properties: [
+ { name: "roles", array_append: $role }
+ ]
+ }
+ ) {
+ id
+ roles: property_array(name: "roles")
+ }
+}
diff --git a/modules/user/public/graphql/user/roles/remove.graphql b/modules/user/public/graphql/user/roles/remove.graphql
new file mode 100644
index 0000000..ab4a9a5
--- /dev/null
+++ b/modules/user/public/graphql/user/roles/remove.graphql
@@ -0,0 +1,13 @@
+mutation user_roles_remove($id: ID!, $role: String!) {
+ user: user_update(
+ id: $id
+ user: {
+ properties: [
+ { name: "roles", array_remove: $role }
+ ]
+ }
+ ) {
+ id
+ roles: property_array(name: "roles")
+ }
+}
diff --git a/modules/user/public/graphql/user/roles/set.graphql b/modules/user/public/graphql/user/roles/set.graphql
new file mode 100644
index 0000000..81d8a1e
--- /dev/null
+++ b/modules/user/public/graphql/user/roles/set.graphql
@@ -0,0 +1,7 @@
+mutation ($id: ID!, $roles: [String]!) {
+ user: user_update(id: $id, user: { properties: [{ name: "roles", value_array: $roles }] }) {
+ id
+ email
+ roles: property_array(name: "roles")
+ }
+}
diff --git a/modules/user/public/graphql/user/search.graphql b/modules/user/public/graphql/user/search.graphql
new file mode 100644
index 0000000..19b543b
--- /dev/null
+++ b/modules/user/public/graphql/user/search.graphql
@@ -0,0 +1,30 @@
+query (
+ $id: ID
+ $not_ids: [ID!]
+ $email: String
+ $limit: Int = 20
+ $page: Int = 1
+ $sort: UsersSortInput = { id: { order: DESC } }
+ $role: String
+ $roles: [String!]
+) {
+ users(
+ per_page: $limit
+ page: $page
+ filter: {
+ id: { value: $id, not_value_in: $not_ids }
+ email: { value: $email }
+ properties: [{
+ name: "role", value: $role, value_in: $roles
+ }]
+ }
+ sort: [$sort]
+ ) {
+ results {
+ id
+ email
+ roles: property_array(name: "roles")
+ created_at
+ }
+ }
+}
diff --git a/modules/user/public/graphql/user/update.graphql b/modules/user/public/graphql/user/update.graphql
new file mode 100644
index 0000000..3c59dbe
--- /dev/null
+++ b/modules/user/public/graphql/user/update.graphql
@@ -0,0 +1,7 @@
+mutation ($id: ID!, $email: String, $password: String, $roles: [String]) {
+ user: user_update(id: $id, user: { email: $email, password: $password, properties: [{ name: "roles", value_array: $roles }] }) {
+ id
+ email
+ roles: property_array(name: "roles")
+ }
+}
diff --git a/modules/user/public/graphql/user/update_password.graphql b/modules/user/public/graphql/user/update_password.graphql
new file mode 100644
index 0000000..5951eab
--- /dev/null
+++ b/modules/user/public/graphql/user/update_password.graphql
@@ -0,0 +1,10 @@
+mutation update_password($id: ID!, $password: String) {
+ user: user_update(
+ id: $id
+ user: {
+ password: $password
+ }
+ ){
+ id
+ }
+}
diff --git a/modules/user/public/graphql/user/verify_password.graphql b/modules/user/public/graphql/user/verify_password.graphql
new file mode 100644
index 0000000..37a543a
--- /dev/null
+++ b/modules/user/public/graphql/user/verify_password.graphql
@@ -0,0 +1,11 @@
+query ($email: String!, $password: String!) {
+ users(filter: { email: { value: $email } }, per_page: 1) {
+ results {
+ id
+ email
+ authenticate {
+ password(password: $password)
+ }
+ }
+ }
+}
diff --git a/modules/user/public/lib/commands/authentication_links/create.liquid b/modules/user/public/lib/commands/authentication_links/create.liquid
new file mode 100644
index 0000000..3babc6a
--- /dev/null
+++ b/modules/user/public/lib/commands/authentication_links/create.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ function object = 'modules/user/commands/authentication_links/create/build', email: email, host: host, valid_for: valid_for
+ function object = 'modules/user/commands/authentication_links/create/check', object: object, hcaptcha_params: hcaptcha_params
+
+ if object.valid
+ function object = 'modules/user/commands/authentication_links/create/execute', object: object
+ assign event_payload = null | hash_merge: email: email
+ function _ = 'modules/core/commands/events/publish', type: 'authentication_link_created', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/authentication_links/create/build.liquid b/modules/user/public/lib/commands/authentication_links/create/build.liquid
new file mode 100644
index 0000000..435aaa7
--- /dev/null
+++ b/modules/user/public/lib/commands/authentication_links/create/build.liquid
@@ -0,0 +1,17 @@
+{% liquid
+ assign valid_for = valid_for | default: 5
+ function user = 'modules/user/queries/user/find', email: email, with_token: true
+%}
+
+{% parse_json object %}
+{
+ "email": "{{ email }}",
+ "id": "{{ user.id }}",
+ "token": "{{ user.token }}",
+ "host": "{{ host }}"
+}
+{% endparse_json %}
+
+{% liquid
+ return object
+%}
diff --git a/modules/user/public/lib/commands/authentication_links/create/check.liquid b/modules/user/public/lib/commands/authentication_links/create/check.liquid
new file mode 100644
index 0000000..cdd52a2
--- /dev/null
+++ b/modules/user/public/lib/commands/authentication_links/create/check.liquid
@@ -0,0 +1,16 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'host'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'token'
+
+ if context.constants.VERIFY_HCAPTCHA == "true"
+ function c = 'modules/core/validations/hcaptcha', c: c, hcaptcha_params: hcaptcha_params
+ endif
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/authentication_links/create/execute.liquid b/modules/user/public/lib/commands/authentication_links/create/execute.liquid
new file mode 100644
index 0000000..2b5ea1e
--- /dev/null
+++ b/modules/user/public/lib/commands/authentication_links/create/execute.liquid
@@ -0,0 +1,7 @@
+{% liquid
+ if object.valid
+ hash_assign object['url'] = 'https://{host}/passwords/new?token={token}&email={email}' | expand_url_template: object
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/emails/auth-link.liquid b/modules/user/public/lib/commands/emails/auth-link.liquid
new file mode 100644
index 0000000..5ce5df4
--- /dev/null
+++ b/modules/user/public/lib/commands/emails/auth-link.liquid
@@ -0,0 +1,28 @@
+---
+metadata:
+ parameters:
+ object:
+ - url
+ - email
+ - id
+---
+{% parse_json object %}
+ {
+ "to": {{ object.email | json }},
+ "from": {% print 'modules/user/emails.from_email' | t: default: 'noreply@platformos.com' | json %},
+ "subject": {% print 'modules/user/emails.passwords.reset.subject' | t | json %},
+ "partial": "modules/user/emails/passwords/reset",
+ "layout": null,
+ "data": {
+ "url": {% print object.url | json %},
+ "user": {
+ "id": {% print object.id | json %}
+ }
+ }
+ }
+{% endparse_json %}
+
+{% liquid
+ function object = 'modules/core/commands/email/send', object: object
+ return object
+%}
diff --git a/modules/user/public/lib/commands/passwords/create.liquid b/modules/user/public/lib/commands/passwords/create.liquid
new file mode 100644
index 0000000..fb11f56
--- /dev/null
+++ b/modules/user/public/lib/commands/passwords/create.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ function object = 'modules/user/commands/passwords/create/build', object: object
+ function object = 'modules/user/commands/passwords/create/check', object: object
+
+ if object.valid
+ function object = 'modules/user/commands/passwords/create/execute', object: object
+ assign event_payload = null | hash_merge: user_id: object.user_id
+ function _ = 'modules/core/commands/events/publish', type: 'password_created', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/passwords/create/build.liquid b/modules/user/public/lib/commands/passwords/create/build.liquid
new file mode 100644
index 0000000..3fb14d0
--- /dev/null
+++ b/modules/user/public/lib/commands/passwords/create/build.liquid
@@ -0,0 +1,16 @@
+---
+metadata:
+ parameters:
+ - name: password
+ - name: password_confirmation
+ - name: user_id
+---
+{% parse_json object %}
+{
+ "id": {{ object.user_id | json }},
+ "password": {{ object.password | json }},
+ "password_confirmation": {{ object.password_confirmation | json }}
+}
+{% endparse_json %}
+
+{% return object %}
diff --git a/modules/user/public/lib/commands/passwords/create/check.liquid b/modules/user/public/lib/commands/passwords/create/check.liquid
new file mode 100644
index 0000000..877fbe9
--- /dev/null
+++ b/modules/user/public/lib/commands/passwords/create/check.liquid
@@ -0,0 +1,14 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password_confirmation'
+ function c = 'modules/core/validations/equal', c: c, given: object.password, expected: object.password_confirmation, field_name: 'password_confirmation', key: 'modules/user/validation.password.do_not_match', not_verbose: true, message: null
+ function c = 'modules/core/validations/password_complexity', c: c, object: object, field_name: 'password', key: null
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/passwords/create/execute.liquid b/modules/user/public/lib/commands/passwords/create/execute.liquid
new file mode 100644
index 0000000..4c0a7fd
--- /dev/null
+++ b/modules/user/public/lib/commands/passwords/create/execute.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ graphql r = 'modules/user/user/update_password', args: object
+
+ if r.errors
+ log r.errors, type: 'errors.graphql.invalid'
+
+ hash_assign object['valid'] = false
+ hash_assign object['errors'] = r.errors
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/session/create.liquid b/modules/user/public/lib/commands/session/create.liquid
new file mode 100644
index 0000000..1a6ea79
--- /dev/null
+++ b/modules/user/public/lib/commands/session/create.liquid
@@ -0,0 +1,45 @@
+{% comment %}
+ Creates a user sessions.
+ Params:
+ - user_id string (optional)
+ - validate_password boolean
+ default: true
+ - email: string (optional)
+ the user's email address
+ - password: string (optional)
+ the user's password
+ - hook_params: object
+ the other params that will be passed to hook_user_login
+{% endcomment %}
+{% liquid
+ if validate_password == nil
+ assign validate_password = true
+ endif
+
+ if validate_password
+ function user = 'modules/user/commands/user/verify_password', email: email, password: password
+ unless user.valid
+ return user
+ endunless
+ assign user_id = user.id
+ endif
+
+ function object = 'modules/user/commands/session/create/build', id: user_id
+ function object = 'modules/user/commands/session/create/check', object: object
+
+ if object.valid
+ function user = 'modules/user/queries/user/load', id: object.id
+ if user.id
+ sign_in user_id: user.id
+ assign params = '{}' | parse_json | hash_merge: user: user, hook_params: hook_params
+ function results = 'modules/core/commands/hook/fire', hook: 'user_login', params: params, merge_to_object: true
+ hash_assign user['hook_results'] = results
+ endif
+ hash_assign object['user'] = user
+
+ assign event_payload = null | hash_merge: user_id: object.id
+ function _ = 'modules/core/commands/events/publish', type: 'user_signed_in', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/session/create/build.liquid b/modules/user/public/lib/commands/session/create/build.liquid
new file mode 100644
index 0000000..3cefb8b
--- /dev/null
+++ b/modules/user/public/lib/commands/session/create/build.liquid
@@ -0,0 +1,7 @@
+{% parse_json object %}
+ {
+ "id": {{ id | json }}
+ }
+{% endparse_json %}
+
+{% return object %}
diff --git a/modules/user/public/lib/commands/session/create/check.liquid b/modules/user/public/lib/commands/session/create/check.liquid
new file mode 100644
index 0000000..a8e6310
--- /dev/null
+++ b/modules/user/public/lib/commands/session/create/check.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/session/destroy.liquid b/modules/user/public/lib/commands/session/destroy.liquid
new file mode 100644
index 0000000..f53d1a8
--- /dev/null
+++ b/modules/user/public/lib/commands/session/destroy.liquid
@@ -0,0 +1,18 @@
+{% comment %}
+ Destroys the current user's session.
+{% endcomment %}
+{% liquid
+ function user = 'modules/user/queries/user/current'
+ graphql destroy = 'modules/user/session/destroy'
+ hash_assign destroy['user'] = user
+
+ unless destroy.errors
+ assign params = '{}' | parse_json | hash_merge: destroy: destroy
+ function results = 'modules/core/commands/hook/fire', hook: 'user_logout', params: params, merge_to_object: null
+ hash_assign destroy['hook_results'] = results
+ assign event_payload = null | hash_merge: user_id: user.id
+ function _ = 'modules/core/commands/events/publish', type: 'user_logout', object: event_payload, delay: null, max_attempts: null
+ endunless
+
+ return destroy
+%}
diff --git a/modules/user/public/lib/commands/user/create.liquid b/modules/user/public/lib/commands/user/create.liquid
new file mode 100644
index 0000000..07c2235
--- /dev/null
+++ b/modules/user/public/lib/commands/user/create.liquid
@@ -0,0 +1,21 @@
+{% comment %}
+ Creates a user.
+ Params:
+ - email: string
+ user's email address
+ - password: string
+ user's password
+ - roles: Array[string]
+ user's initial roles
+{% endcomment %}
+{% liquid
+ function object = 'modules/user/commands/user/create/build', email: email, password: password, hook_params: hook_params, roles: roles
+ function object = 'modules/user/commands/user/create/check', object: object
+ if object.valid
+ function object = 'modules/core/commands/execute', mutation_name: 'modules/user/user/create', object: object, selection: 'user'
+ assign event_payload = null | hash_merge: user_id: object.id
+ function _ = 'modules/core/commands/events/publish', type: 'user_created', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/create/build.liquid b/modules/user/public/lib/commands/user/create/build.liquid
new file mode 100644
index 0000000..0c6d328
--- /dev/null
+++ b/modules/user/public/lib/commands/user/create/build.liquid
@@ -0,0 +1,30 @@
+{% liquid
+ if roles == null
+ assign roles = '[]' | parse_json
+ if context.constants.USER_DEFAULT_ROLE != blank
+ assign roles = roles | array_add: context.constants.USER_DEFAULT_ROLE
+ endif
+ else
+ assign roles_type = roles | type_of
+ if roles_type == 'String'
+ assign roles = roles | append: '' | split: ','
+ elsif roles_type == 'Array'
+ else
+ # accepts only String and Array
+ log roles, type: 'ERROR: roles must be an array or a coma separated string'
+ assign roles = null
+ endif
+ endif
+%}
+
+{% parse_json object %}
+ {
+ "email": {{ email | json }},
+ "password": {{ password | json }},
+ "hook_params": {{ hook_params | json }}
+ }
+{% endparse_json %}
+
+{% hash_assign object['roles'] = roles %}
+
+{% return object %}
diff --git a/modules/user/public/lib/commands/user/create/check.liquid b/modules/user/public/lib/commands/user/create/check.liquid
new file mode 100644
index 0000000..c7da643
--- /dev/null
+++ b/modules/user/public/lib/commands/user/create/check.liquid
@@ -0,0 +1,22 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password'
+ function c = 'modules/core/validations/password_complexity', c: c, object: object, field_name: 'password', key: null
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email', key: 'modules/user/validation.email.required'
+ function c = 'modules/core/validations/length', c: c, object: object, field_name: 'roles', minimum: 0, allow_blank: true
+ function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email', key: 'modules/user/validation.email.format'
+
+ if object.email != blank
+ graphql user_exists = 'modules/user/user/list', email: object.email
+ if user_exists.users.total_entries > 0
+ assign message = 'modules/user/validation.user_exists' | t
+ function c = 'modules/core/helpers/register_error', contract: c, field_name: 'email', message: message
+ endif
+ endif
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/delete.liquid b/modules/user/public/lib/commands/user/delete.liquid
new file mode 100644
index 0000000..31ba099
--- /dev/null
+++ b/modules/user/public/lib/commands/user/delete.liquid
@@ -0,0 +1,20 @@
+{% comment %}
+ Deletes a user.
+ Params:
+ - id: string
+ the user's id
+{% endcomment %}
+{% liquid
+ graphql user = 'modules/user/user/delete', id: id
+
+ unless user.errors
+ assign params = '{}' | parse_json | hash_merge: user: user.user
+ function results = 'modules/core/commands/hook/fire', hook: 'user_delete', params: params, merge_to_object: null
+ hash_assign user['hook_results'] = results
+
+ assign event_payload = null | hash_merge: user_id: id
+ function _ = 'modules/core/commands/events/publish', type: 'user_deleted', object: event_payload, delay: null, max_attempts: null
+ endunless
+
+ return user
+%}
diff --git a/modules/user/public/lib/commands/user/roles/append.liquid b/modules/user/public/lib/commands/user/roles/append.liquid
new file mode 100644
index 0000000..c9cb499
--- /dev/null
+++ b/modules/user/public/lib/commands/user/roles/append.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ assign object = '{}' | parse_json | hash_merge: valid: true, id: id, role : role
+ function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/user/roles/append', selection: 'user'
+
+ if object.errors == blank
+
+ assign event_payload = null | hash_merge: user_id: id, role: role
+ function _ = 'modules/core/commands/events/publish', type: 'user_role_appended', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/roles/remove.liquid b/modules/user/public/lib/commands/user/roles/remove.liquid
new file mode 100644
index 0000000..e83891f
--- /dev/null
+++ b/modules/user/public/lib/commands/user/roles/remove.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign object = '{}' | parse_json | hash_merge: valid: true, id: id, role : role
+ function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/user/roles/remove', selection: 'user'
+
+ if object.errors == blank
+ assign event_payload = null | hash_merge: user_id: id, role: role
+ function _ = 'modules/core/commands/events/publish', type: 'user_role_removed', object: event_payload, delay: null, max_attempts: null
+ endif
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/roles/set.liquid b/modules/user/public/lib/commands/user/roles/set.liquid
new file mode 100644
index 0000000..0662c3c
--- /dev/null
+++ b/modules/user/public/lib/commands/user/roles/set.liquid
@@ -0,0 +1,10 @@
+{% liquid
+ assign object = '{}' | parse_json | hash_merge: valid: true, id: id, roles: roles
+ function object = 'modules/core/commands/execute', object: object, mutation_name: 'modules/user/user/roles/set', selection: 'user'
+
+ if object.errors == blank
+ assign event_payload = null | hash_merge: user_id: id, roles: roles
+ function _ = 'modules/core/commands/events/publish', type: 'user_roles_set', object: event_payload, delay: null, max_attempts: null
+ endif
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/update.liquid b/modules/user/public/lib/commands/user/update.liquid
new file mode 100644
index 0000000..d2502fa
--- /dev/null
+++ b/modules/user/public/lib/commands/user/update.liquid
@@ -0,0 +1,39 @@
+{% comment %}
+ Updates a user.
+ Params:
+ - id: string
+ - email: string
+ the user's email address
+ - password: string
+ the user's password
+ - hook_params: object
+ the other params that will be passed to hook_user_update
+{% endcomment %}
+{% liquid
+ function object = 'modules/user/commands/user/update/build', id: id, email: email, password: password
+ function object = 'modules/user/commands/user/update/check', object: object
+
+ if object.valid
+ graphql user = 'modules/user/user/update', args: object
+ hash_assign object['update_result'] = user
+ unless user.errors
+ assign params = '{}' | parse_json | hash_merge: updated_user: user.user, hook_params: hook_params
+ # todo: merge_to_object for hooks with the same name will overwrite the validity of previous results
+ function results = 'modules/core/commands/hook/fire', hook: 'user_update', params: params, merge_to_object: true
+ for result in results
+ # using the errors key for a quick workaround for now
+ if result[1].valid == false or result[1].errors != blank
+ hash_assign object['valid'] = false
+ hash_assign object['errors'] = result[1].errors
+ break
+ endif
+ endfor
+ hash_assign object['hook_results'] = results
+ endunless
+
+ assign event_payload = null | hash_merge: user_id: object.id
+ function _ = 'modules/core/commands/events/publish', type: 'user_updated', object: event_payload, delay: null, max_attempts: null
+ endif
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/update/build.liquid b/modules/user/public/lib/commands/user/update/build.liquid
new file mode 100644
index 0000000..978272d
--- /dev/null
+++ b/modules/user/public/lib/commands/user/update/build.liquid
@@ -0,0 +1,9 @@
+{% parse_json object %}
+ {
+ "id": {{ id | json }},
+ "email": {{ email | json }},
+ "password": {{ password | json }}
+ }
+{% endparse_json %}
+
+{% return object %}
diff --git a/modules/user/public/lib/commands/user/update/check.liquid b/modules/user/public/lib/commands/user/update/check.liquid
new file mode 100644
index 0000000..3719f9e
--- /dev/null
+++ b/modules/user/public/lib/commands/user/update/check.liquid
@@ -0,0 +1,12 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ if object['email']
+ function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email'
+ endif
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/verify_password.liquid b/modules/user/public/lib/commands/user/verify_password.liquid
new file mode 100644
index 0000000..58bdd42
--- /dev/null
+++ b/modules/user/public/lib/commands/user/verify_password.liquid
@@ -0,0 +1,13 @@
+{% comment %}
+ Verifies a user's password.
+ Params:
+ - email: string
+ the user's email address
+ - password: string
+{% endcomment %}
+{% liquid
+ function object = 'modules/user/commands/user/verify_password/build', email: email, password: password
+ function object = 'modules/user/commands/user/verify_password/check', object: object
+
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/verify_password/build.liquid b/modules/user/public/lib/commands/user/verify_password/build.liquid
new file mode 100644
index 0000000..f1bbf6c
--- /dev/null
+++ b/modules/user/public/lib/commands/user/verify_password/build.liquid
@@ -0,0 +1,10 @@
+{% parse_json object %}
+ {
+ "email": {{ email | json }},
+ "password": {{ password | json }}
+ }
+{% endparse_json %}
+
+{% liquid
+ return object
+%}
diff --git a/modules/user/public/lib/commands/user/verify_password/check.liquid b/modules/user/public/lib/commands/user/verify_password/check.liquid
new file mode 100644
index 0000000..19a55b6
--- /dev/null
+++ b/modules/user/public/lib/commands/user/verify_password/check.liquid
@@ -0,0 +1,20 @@
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/email', c: c, object: object, field_name: 'email'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'email'
+ function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'password'
+
+ if c.valid
+ graphql user = 'modules/user/user/verify_password', args: object
+ assign user = user.users.results.first
+
+ function c = 'modules/core/validations/truthy', c: c, field_name: 'password', object: user.authenticate, key: 'modules/user/validation.invalid_email_or_password'
+ hash_assign object['id'] = user.id
+ endif
+
+ hash_assign object['valid'] = c.valid
+ hash_assign object['errors'] = c.errors
+
+ return object
+%}
diff --git a/modules/user/public/lib/events/authentication_link_created.liquid b/modules/user/public/lib/events/authentication_link_created.liquid
new file mode 100644
index 0000000..6a9dfa1
--- /dev/null
+++ b/modules/user/public/lib/events/authentication_link_created.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ email
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'email'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/password_created.liquid b/modules/user/public/lib/events/password_created.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/password_created.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_created.liquid b/modules/user/public/lib/events/user_created.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/user_created.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_deleted.liquid b/modules/user/public/lib/events/user_deleted.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/user_deleted.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_logout.liquid b/modules/user/public/lib/events/user_logout.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/user_logout.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_role_appended.liquid b/modules/user/public/lib/events/user_role_appended.liquid
new file mode 100644
index 0000000..69fbfdc
--- /dev/null
+++ b/modules/user/public/lib/events/user_role_appended.liquid
@@ -0,0 +1,14 @@
+---
+metadata:
+ event:
+ user_id
+ role
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'role'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_role_removed.liquid b/modules/user/public/lib/events/user_role_removed.liquid
new file mode 100644
index 0000000..69fbfdc
--- /dev/null
+++ b/modules/user/public/lib/events/user_role_removed.liquid
@@ -0,0 +1,14 @@
+---
+metadata:
+ event:
+ user_id
+ role
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'role'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_roles_set.liquid b/modules/user/public/lib/events/user_roles_set.liquid
new file mode 100644
index 0000000..2e82e37
--- /dev/null
+++ b/modules/user/public/lib/events/user_roles_set.liquid
@@ -0,0 +1,14 @@
+---
+metadata:
+ event:
+ user_id
+ roles
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+ function c = 'modules/core/validations/length', c: c, object: event, field_name: 'roles', minimum: 0, allow_blank: false
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_signed_in.liquid b/modules/user/public/lib/events/user_signed_in.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/user_signed_in.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/events/user_updated.liquid b/modules/user/public/lib/events/user_updated.liquid
new file mode 100644
index 0000000..427444a
--- /dev/null
+++ b/modules/user/public/lib/events/user_updated.liquid
@@ -0,0 +1,12 @@
+---
+metadata:
+ event:
+ user_id
+---
+{% liquid
+ assign c = '{ "errors": {}, "valid": true }' | parse_json
+
+ function c = 'modules/core/validations/presence', c: c, object: event, field_name: 'user_id'
+
+ return c
+%}
diff --git a/modules/user/public/lib/helpers/can_do.liquid b/modules/user/public/lib/helpers/can_do.liquid
new file mode 100644
index 0000000..1467f59
--- /dev/null
+++ b/modules/user/public/lib/helpers/can_do.liquid
@@ -0,0 +1,42 @@
+{% comment %}
+ Checks if the requester can do domething on the given entiry.
+
+ Params:
+ - requester Object
+ The requester must have a string array field called 'roles'
+ - entity Object
+ - do String
+ - access_callback String
+ The callback function that checks the request. By default searches that the `requester`
+ has `do` permission or not.
+{% endcomment %}
+{% liquid
+ assign roles_type = requester.roles | type_of
+ unless roles_type == 'Array'
+ log requester, type: 'ERROR the requester does not have "roles" array in modules/user/helpers/can_do'
+ return false
+ endunless
+
+ if access_callback
+ function can = access_callback, requester: requester, entity: entity, do: do
+ return can
+ endif
+
+ function permissions = 'modules/user/queries/role_permissions/permissions'
+ assign found_permission = false
+ for role in requester.roles
+ if permissions[role] == null
+ assign msg = 'WARNING: the following role is not defined in modules/user/queries/role_permissions/permissions: ' | append: role
+ log requester, type: msg
+ endif
+ if role == 'superadmin'
+ assign found_permission = true
+ break
+ elsif permissions[role] contains do
+ assign found_permission = true
+ break
+ endif
+ endfor
+
+ return found_permission
+ %}
diff --git a/modules/user/public/lib/helpers/can_do_or_redirect.liquid b/modules/user/public/lib/helpers/can_do_or_redirect.liquid
new file mode 100644
index 0000000..042bee2
--- /dev/null
+++ b/modules/user/public/lib/helpers/can_do_or_redirect.liquid
@@ -0,0 +1,23 @@
+{% comment %}
+ Redirects if the the requester does not have right to do something on the given entity.
+
+ Params:
+ - requester Object
+ The requester must has a string array field called 'permissions'
+ - entity Object
+ - do String
+ - access_callback String
+ The callback function that checks the request. By default searches that the `requester`
+ has `do` permission or not.
+ - return_url String
+ The url where to redirect if the requester does not have right to do something in the given entity.
+{% endcomment %}
+{% liquid
+ function can = 'modules/user/helpers/can_do', requester: requester, entity: entity, do: do, access_callback: access_callback
+ unless can
+ assign return_url = return_url | default: '/'
+
+ redirect_to return_url
+ break
+ endunless
+%}
diff --git a/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid b/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid
new file mode 100644
index 0000000..df1367e
--- /dev/null
+++ b/modules/user/public/lib/helpers/can_do_or_unauthorized.liquid
@@ -0,0 +1,24 @@
+{% comment %}
+ Renders 401 if the the requester does not have right to do something on the given entity.
+
+ Params:
+ - requester Object
+ The requester must has a string array field called 'permissions'
+ - entity Object
+ - do String
+ - access_callback String
+ The callback function that checks the request. By default searches that the `requester`
+ has `do` permission or not.
+{% endcomment %}
+{% liquid
+ function can = 'modules/user/helpers/can_do', requester: requester, entity: entity, do: do, access_callback: access_callback
+ unless can
+ response_status 403
+ try
+ theme_render_rc 'components/pages/403'
+ catch err
+ render 'modules/user/components/pages/403' #TODO
+ endtry
+ break
+ endunless
+%}
diff --git a/modules/user/public/lib/helpers/flash.liquid b/modules/user/public/lib/helpers/flash.liquid
new file mode 100644
index 0000000..5087333
--- /dev/null
+++ b/modules/user/public/lib/helpers/flash.liquid
@@ -0,0 +1,22 @@
+{% liquid
+ assign error = error
+ assign notice = notice
+ assign info = info
+ assign force_clear = force_clear | default: false
+
+ if error
+ assign message = error | t
+ assign severity = 'error'
+ elsif notice
+ assign message = notice | t
+ assign severity = 'success'
+ elsif info
+ assign message = info | t
+ assign severity = 'info'
+ endif
+ assign flash = null | hash_merge: message: message, severity: severity, from: context.location.pathname, force_clear: force_clear
+
+ function _ = 'modules/core/commands/session/set', key: 'sflash', value: flash
+
+ return null
+%}
diff --git a/modules/user/public/lib/helpers/user_from_temporary_token.liquid b/modules/user/public/lib/helpers/user_from_temporary_token.liquid
new file mode 100644
index 0000000..044fe7c
--- /dev/null
+++ b/modules/user/public/lib/helpers/user_from_temporary_token.liquid
@@ -0,0 +1,17 @@
+{% liquid
+ if token == blank or email == blank
+ return null
+ endif
+
+ function user = 'modules/user/queries/user/find', email: email
+
+ if user
+ assign authenticated = token | is_token_valid: user.id
+ endif
+
+ if user and authenticated
+ return user
+ else
+ return null
+ endif
+%}
diff --git a/modules/user/public/lib/hooks/hook_admin_page.liquid b/modules/user/public/lib/hooks/hook_admin_page.liquid
new file mode 100644
index 0000000..62da040
--- /dev/null
+++ b/modules/user/public/lib/hooks/hook_admin_page.liquid
@@ -0,0 +1,29 @@
+{% comment %}
+ Implements hook_admin_page.
+{% endcomment %}
+
+{% parse_json admin_pages %}
+[
+ {
+ "relative_path": "/admin/users",
+ "partial": "modules/user/admin_pages/list",
+ "menu": {
+ "title": "Users",
+ "link_attributes": {}
+ },
+ "permission": "admin.users.manage"
+ },
+ {
+ "relative_path": null,
+ "menu": {
+ "title": "Log out",
+ "link_attributes": {
+ "href": "/sessions/destroy"
+ }
+ },
+ "permission": "sessions.destroy"
+ }
+]
+{% endparse_json %}
+
+{% return admin_pages %}
diff --git a/modules/user/public/lib/hooks/hook_module_info.liquid b/modules/user/public/lib/hooks/hook_module_info.liquid
new file mode 100644
index 0000000..cb6782c
--- /dev/null
+++ b/modules/user/public/lib/hooks/hook_module_info.liquid
@@ -0,0 +1,15 @@
+{% comment %}
+ Implements hook_module_info.
+{% endcomment %}
+{% parse_json info %}
+{
+ "name": "<%= &name =%>",
+ "machine_name": "<%= &machine_name =%>",
+ "type": "<%= &type =%>",
+ "version": "<%= &version =%>"
+}
+{% endparse_json %}
+
+{% liquid
+ return info
+%}
diff --git a/modules/user/public/lib/queries/registration_fields/load.liquid b/modules/user/public/lib/queries/registration_fields/load.liquid
new file mode 100644
index 0000000..0864892
--- /dev/null
+++ b/modules/user/public/lib/queries/registration_fields/load.liquid
@@ -0,0 +1,25 @@
+{% comment %}
+ Loads the registration fields.
+{% endcomment %}
+
+{% parse_json fields %}
+[
+ {
+ "name": "email",
+ "required": true,
+ "type": "email",
+ "weight": 0,
+ "label": "Email"
+ },
+ {
+ "name": "password",
+ "required": true,
+ "type": "password",
+ "weight": 1,
+ "label": "Password"
+ }
+]
+{% endparse_json %}
+{% liquid
+ return fields
+%}
diff --git a/modules/user/public/lib/queries/role_permissions/permissions.liquid b/modules/user/public/lib/queries/role_permissions/permissions.liquid
new file mode 100644
index 0000000..12376fd
--- /dev/null
+++ b/modules/user/public/lib/queries/role_permissions/permissions.liquid
@@ -0,0 +1,11 @@
+{% parse_json data %}
+{
+ {% if context.constants.USER_DEFAULT_ROLE != blank %}
+ "{{ context.constants.USER_DEFAULT_ROLE }}": [],
+ {% endif %}
+ "anonymous": ["sessions.create", "users.register"],
+ "authenticated": ["sessions.destroy"]
+}
+{% endparse_json %}
+
+{% return data %}
diff --git a/modules/user/public/lib/queries/roles/all.liquid b/modules/user/public/lib/queries/roles/all.liquid
new file mode 100644
index 0000000..0d481bb
--- /dev/null
+++ b/modules/user/public/lib/queries/roles/all.liquid
@@ -0,0 +1,3 @@
+{% function permissions = 'modules/user/queries/role_permissions/permissions' %}
+
+{% return permissions | hash_keys | sort %}
diff --git a/modules/user/public/lib/queries/roles/custom.liquid b/modules/user/public/lib/queries/roles/custom.liquid
new file mode 100644
index 0000000..bebd8aa
--- /dev/null
+++ b/modules/user/public/lib/queries/roles/custom.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ function roles = 'modules/user/queries/roles/all'
+ assign built_in_roles = 'anonymous,authenticated' | split: ','
+
+ return roles | array_subtract: built_in_roles
+%}
diff --git a/modules/user/public/lib/queries/user/count.liquid b/modules/user/public/lib/queries/user/count.liquid
new file mode 100644
index 0000000..3c8098a
--- /dev/null
+++ b/modules/user/public/lib/queries/user/count.liquid
@@ -0,0 +1,7 @@
+{% comment %}
+ Counts the created users
+{% endcomment %}
+{% liquid
+ graphql count = 'modules/user/user/count'
+ return count.users.total_entries
+%}
diff --git a/modules/user/public/lib/queries/user/current.liquid b/modules/user/public/lib/queries/user/current.liquid
new file mode 100644
index 0000000..f8b34ee
--- /dev/null
+++ b/modules/user/public/lib/queries/user/current.liquid
@@ -0,0 +1,13 @@
+{% comment %}
+ Loads the current user. Automatically adds `authenticated` role or `anonymous` role, depending if the user is logged in or not
+{% endcomment %}
+{% liquid
+ if context.current_user
+ function user = 'modules/user/queries/user/load', id: context.current_user.id
+ hash_assign user['roles'] = user['roles'] | array_add: 'authenticated'
+ else
+ assign user = '{ "roles": ["anonymous"] }' | parse_json
+ endif
+
+ return user
+%}
diff --git a/modules/user/public/lib/queries/user/find.liquid b/modules/user/public/lib/queries/user/find.liquid
new file mode 100644
index 0000000..f121e76
--- /dev/null
+++ b/modules/user/public/lib/queries/user/find.liquid
@@ -0,0 +1,13 @@
+{% liquid
+ assign id = id
+ assign email = email
+ assign with_token = with_token | default: false
+
+ if id == blank and email == blank
+ return null
+ endif
+
+ graphql r = 'modules/user/user/find', id: id, email: email, limit: 1, with_token: with_token
+
+ return r.users.results.first
+%}
diff --git a/modules/user/public/lib/queries/user/get_all.liquid b/modules/user/public/lib/queries/user/get_all.liquid
new file mode 100644
index 0000000..a700388
--- /dev/null
+++ b/modules/user/public/lib/queries/user/get_all.liquid
@@ -0,0 +1,6 @@
+{% liquid
+ # log 1, type: 'user/list'
+ graphql g = 'modules/user/user/list'
+
+ return g.users.results
+%}
diff --git a/modules/user/public/lib/queries/user/load.liquid b/modules/user/public/lib/queries/user/load.liquid
new file mode 100644
index 0000000..efdb00a
--- /dev/null
+++ b/modules/user/public/lib/queries/user/load.liquid
@@ -0,0 +1,13 @@
+{% comment %}
+ Loads a user's data.
+ Params:
+ - id: string
+ the user's id
+{% endcomment %}
+{% liquid
+
+ graphql g = 'modules/user/user/load', id: id
+ assign user = g.users.results.first
+
+ return user
+%}
diff --git a/modules/user/public/lib/queries/user/search.liquid b/modules/user/public/lib/queries/user/search.liquid
new file mode 100644
index 0000000..5045094
--- /dev/null
+++ b/modules/user/public/lib/queries/user/search.liquid
@@ -0,0 +1,7 @@
+{% liquid
+ assign limit = limit | default: 20
+ assign page = page | to_positive_integer: 1
+
+ graphql r = 'modules/user/user/search', id: id, not_ids: not_ids, email: email, role: role, roles: roles, page: page, limit: limit, sort: sort
+ return r.users
+%}
diff --git a/modules/user/public/translations/en/authentication_links.yml b/modules/user/public/translations/en/authentication_links.yml
new file mode 100644
index 0000000..3f0000e
--- /dev/null
+++ b/modules/user/public/translations/en/authentication_links.yml
@@ -0,0 +1,6 @@
+en:
+ authentication_links:
+ created:
+ Please check your inbox. If the provided email was correct, you'll
+ receive some instructions on how to reset your password.
+ something_went_wrong: Something went wrong
diff --git a/modules/user/public/translations/en/emails.yml b/modules/user/public/translations/en/emails.yml
new file mode 100644
index 0000000..3a312a8
--- /dev/null
+++ b/modules/user/public/translations/en/emails.yml
@@ -0,0 +1,14 @@
+en:
+ emails:
+ from_email: noreply@platformos.com
+ passwords:
+ reset:
+ subject: Reset password
+ title: Password reset request
+ cta: Reset password
+ cta_button: Go to reset password form
+ content: It seems that you requested a password reset. To proceed use the
+ following button.
+ ignore: If it wasn’t you who requested this just ignore this message.
+
+
diff --git a/modules/user/public/translations/en/passwords.yml b/modules/user/public/translations/en/passwords.yml
new file mode 100644
index 0000000..ffea07b
--- /dev/null
+++ b/modules/user/public/translations/en/passwords.yml
@@ -0,0 +1,23 @@
+en:
+ passwords:
+ password: Password
+ password_confirmation: Confirm password
+ password_update: Update password
+ login: Login
+ register: Register
+ reset_password: Email an authentication link
+ edit: Reset Password
+ email: Email
+ email_desc: Enter your registered email and we will send you a link to reset your password
+ reset_password_title: Reset password
+
+ emails:
+ passwords:
+ reset:
+ subject: Reset password
+ title: Password reset request
+ cta: Reset password
+ cta_button: Go to reset password form
+ content: It seems that you requested a password reset. To proceed use the
+ following button.
+ ignore: If it wasn’t you who requested this just ignore this message.
diff --git a/modules/user/public/translations/en/users.yml b/modules/user/public/translations/en/users.yml
new file mode 100644
index 0000000..6b070d2
--- /dev/null
+++ b/modules/user/public/translations/en/users.yml
@@ -0,0 +1,5 @@
+en:
+ users:
+ new:
+ create_account: Create an Account
+ logout: Log out
diff --git a/modules/user/public/translations/en/validation.yml b/modules/user/public/translations/en/validation.yml
new file mode 100644
index 0000000..62657bf
--- /dev/null
+++ b/modules/user/public/translations/en/validation.yml
@@ -0,0 +1,18 @@
+en:
+ validation:
+ email:
+ required: Please provide your email address
+ format: The email doesn't look right, please check again
+ user_exists: It seems you already have a registered account. Please check the email field again or sign in with your credentials.
+ taken: already taken
+ not_uniq: not unique
+ invalid_email_or_password: Invalid email or password
+ invalid_password: Invalid password.
+ matches: not valid format
+ not_truthy: not true
+ password:
+ lowercase: must include at least one lower case
+ uppercase: must include at least one upper case
+ number: must include at least one number
+ do_not_match: passwords do not match
+ invalid: invalid
diff --git a/modules/user/public/views/pages/authentication_links/create.liquid b/modules/user/public/views/pages/authentication_links/create.liquid
new file mode 100644
index 0000000..2083015
--- /dev/null
+++ b/modules/user/public/views/pages/authentication_links/create.liquid
@@ -0,0 +1,33 @@
+---
+method: post
+slug: authentication_links
+---
+{% liquid
+ function object = 'modules/user/commands/authentication_links/create', email: context.params.authentication_link.email, host: context.location.host, hcaptcha_params: context.params, valid_for: null
+ if object.valid
+ function email = 'modules/user/commands/emails/auth-link', object: object
+ if email.valid
+ if object.email == 'change-password@example.com' and context.environment == 'staging'
+ echo object.url
+ break
+ endif
+
+ function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.created'
+ redirect_to '/'
+ else
+ log email.errors, type: 'ERROR: authentication_links/create email'
+
+ function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.something_went_wrong'
+ redirect_to '/'
+ endif
+ elsif object.token == blank
+ if context.environment == 'staging'
+ log object, type: 'DEBUG: reset-password-user-not-found'
+ endif
+
+ function _ = 'modules/user/helpers/flash', notice: 'modules/user/authentication_links.created'
+ redirect_to '/'
+ else
+ theme_render_rc 'passwords/reset', context: context, errors: object.errors
+ endif
+%}
diff --git a/modules/user/public/views/pages/passwords/create.liquid b/modules/user/public/views/pages/passwords/create.liquid
new file mode 100644
index 0000000..97d2e78
--- /dev/null
+++ b/modules/user/public/views/pages/passwords/create.liquid
@@ -0,0 +1,19 @@
+---
+slug: passwords
+method: post
+---
+{% liquid
+ assign input = context.params.password
+ assign redirect_url = context.params.redirect_to | default: '/'
+ hash_assign input['user_id'] = context.session.reset_password_session_user_id
+
+ function object = 'modules/user/commands/passwords/create', object: input
+ if object.valid
+ session reset_password_session_user_id = null
+
+ function _ = 'modules/user/commands/session/create', user_id: object.id, validate_password: false, email: null, password: null, hook_params: null
+ redirect_to redirect_url
+ else
+ theme_render_rc 'passwords/new', context: context, errors: object.errors
+ endif
+%}
diff --git a/modules/user/public/views/pages/passwords/new.liquid b/modules/user/public/views/pages/passwords/new.liquid
new file mode 100644
index 0000000..c34dc09
--- /dev/null
+++ b/modules/user/public/views/pages/passwords/new.liquid
@@ -0,0 +1,15 @@
+{% liquid
+ if context.session.reset_password_session_user_id == blank
+ function user = 'modules/user/helpers/user_from_temporary_token', token: context.params.token, email: context.params.email
+
+ if user
+ session reset_password_session_user_id = user.id
+ else
+ function _ = 'modules/user/helpers/flash', error: 'modules/user/account.reset_password.expired_link'
+ redirect_to '/sessions/new'
+ break
+ endif
+ endif
+
+ theme_render_rc 'passwords/new', context: context
+%}
diff --git a/modules/user/public/views/pages/passwords/reset.liquid b/modules/user/public/views/pages/passwords/reset.liquid
new file mode 100644
index 0000000..521b6b0
--- /dev/null
+++ b/modules/user/public/views/pages/passwords/reset.liquid
@@ -0,0 +1 @@
+{% theme_render_rc 'passwords/reset', context: context %}
diff --git a/modules/user/public/views/pages/sessions/create.liquid b/modules/user/public/views/pages/sessions/create.liquid
new file mode 100644
index 0000000..da4de86
--- /dev/null
+++ b/modules/user/public/views/pages/sessions/create.liquid
@@ -0,0 +1,18 @@
+---
+method: post
+slug: sessions
+---
+{% liquid
+ function current_user = 'modules/user/queries/user/current'
+ # platformos-check-disable UnreachableCode
+ include 'modules/user/helpers/can_do_or_redirect', requester: current_user, do: 'sessions.create', return_url: '/'
+ # platformos-check-enable UnreachableCode
+
+ function res = 'modules/user/commands/session/create', email: params.email, password: params.password, hook_params: params, validate_password: true
+ assign redirect_path = res.hook_results.redirect_to | default: params.redirect_to | default: '/'
+ if res.valid
+ redirect_to redirect_path
+ else
+ theme_render_rc 'sessions/new', context: context, errors: res.errors
+ endif
+%}
diff --git a/modules/user/public/views/pages/sessions/destroy.liquid b/modules/user/public/views/pages/sessions/destroy.liquid
new file mode 100644
index 0000000..509e844
--- /dev/null
+++ b/modules/user/public/views/pages/sessions/destroy.liquid
@@ -0,0 +1,14 @@
+---
+slug: sessions
+method: delete
+---
+{% liquid
+ function current_user = 'modules/user/queries/user/current'
+ # platformos-check-disable UnreachableCode
+ include 'modules/user/helpers/can_do_or_redirect', requester: current_user, do: 'sessions.destroy', return_url: '/'
+ # platformos-check-enable UnreachableCode
+
+ function res = 'modules/user/commands/session/destroy'
+ assign redirect_path = res.hook_results.redirect_to | default: params.redirect_to | default: '/'
+ redirect_to redirect_path
+%}
diff --git a/modules/user/public/views/pages/sessions/new.liquid b/modules/user/public/views/pages/sessions/new.liquid
new file mode 100644
index 0000000..d15a652
--- /dev/null
+++ b/modules/user/public/views/pages/sessions/new.liquid
@@ -0,0 +1,8 @@
+{% liquid
+ function current_user = 'modules/user/queries/user/current'
+ # platformos-check-disable UnreachableCode
+ include 'modules/user/helpers/can_do_or_redirect', requester: current_user, do: 'sessions.create', return_url: '/'
+ # platformos-check-enable UnreachableCode
+
+ theme_render_rc 'sessions/new', context: context
+%}
diff --git a/modules/user/public/views/pages/users/create.liquid b/modules/user/public/views/pages/users/create.liquid
new file mode 100644
index 0000000..c92fdb8
--- /dev/null
+++ b/modules/user/public/views/pages/users/create.liquid
@@ -0,0 +1,24 @@
+---
+method: post
+slug: users
+---
+{% liquid
+ function current_user = 'modules/user/queries/user/current'
+
+ # platformos-check-disable UnreachableCode
+ include 'modules/user/helpers/can_do_or_redirect', requester: current_user, do: 'users.register', redirect_url: "/"
+ # platformos-check-enable UnreachableCode
+
+ function object = 'modules/user/commands/user/create', email: params.email, password: params.password, hook_params: params, roles: null
+ if object.valid
+ assign redirect_path = object.redirect_to | default: params.redirect_to | default: '/'
+ redirect_to redirect_path
+ else
+ assign values = object | default: null | hash_merge: password: '', authenticity_token: ''
+
+ function registration_fields = 'modules/user/queries/registration_fields/load'
+
+ assign values = params | hash_merge: password: ''
+ theme_render_rc 'users/new', context: context, registration_fields: registration_fields, errors: object.errors, values: values
+ endif
+%}
diff --git a/modules/user/public/views/pages/users/new.liquid b/modules/user/public/views/pages/users/new.liquid
new file mode 100644
index 0000000..1bf8d09
--- /dev/null
+++ b/modules/user/public/views/pages/users/new.liquid
@@ -0,0 +1,11 @@
+{% liquid
+ function current_user = 'modules/user/queries/user/current'
+ # platformos-check-disable UnreachableCode
+ include 'modules/user/helpers/can_do_or_redirect', requester: current_user, do: 'users.register', redirect_url: "/"
+ # platformos-check-enable UnreachableCode
+
+ function registration_fields = 'modules/user/queries/registration_fields/load'
+ assign values = null | hash_merge: email: context.params.email
+
+ theme_render_rc 'users/new', context: context, registration_fields: registration_fields, values: values
+%}
diff --git a/modules/user/public/views/partials/admin_pages/list.liquid b/modules/user/public/views/partials/admin_pages/list.liquid
new file mode 100644
index 0000000..61021c0
--- /dev/null
+++ b/modules/user/public/views/partials/admin_pages/list.liquid
@@ -0,0 +1,52 @@
+{% function users = 'modules/user/queries/user/get_all' %}
+
+
+ {% theme_render_rc 'components/atoms/heading', content: 'Users', level: 2, classes: 'pb-8' %}
+
+
+
+ ID
+ {% for property in users.first %}
+ {% unless property[0] == 'id' or property[0] == 'hook_results' %}
+ {{ property[0] }}
+ {% endunless %}
+ {% endfor %}
+ Additional fields
+
+
+
+ {% for user in users %}
+ {% liquid
+ assign id = user.id
+ assign hook_results = user.hook_results
+ assign user = user | hash_delete_key: 'id'
+ assign user = user | hash_delete_key: 'hook_results'
+ %}
+
+ {{ id }}
+ {% for property in user %}
+
+ {% assign type = property[1] | type_of %}
+ {% if type == 'Array' %}
+ {{ property[1] | join: ', ' }}
+ {% else %}
+ {{ property[1] }}
+ {% endif %}
+
+ {% endfor %}
+
+ {% if hook_results %}
+ {% for hook_result in hook_results %}
+ {% if hook_result[1] %}
+ {{ hook_result[0] }}:
+ {{ hook_result[1] }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+
+ {% endfor %}
+
+
+
+
diff --git a/modules/user/public/views/partials/components/atoms/button.liquid b/modules/user/public/views/partials/components/atoms/button.liquid
new file mode 100644
index 0000000..31e96ef
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/button.liquid
@@ -0,0 +1,101 @@
+---
+metadata:
+ name: Button
+ params:
+ tag:
+ - button
+ - a
+ classes: ''
+ weight:
+ - primary
+ - secondary
+ variant:
+ - normal
+ - important
+ - confirmation
+ - inverted
+ filled:
+ - false
+ - true
+ size:
+ - normal
+ - small
+ disabled:
+ - false
+ - true
+ attributes: {}
+ href: ''
+ content: Click me
+ type: 'button'
+---
+{% liquid
+ assign tag = tag | default: params.tag | default: 'button'
+ assign type = type | default: params.type | default: 'button'
+ assign weight = weight | default: params.weight | default: 'primary'
+ assign variant = variant | default: params.variant | default: 'normal'
+ assign filled = filled | default: params.filled | default: false
+ assign size = size | default: params.size | default: 'normal'
+ assign disabled = disabled | default: params.disabled | default: false
+ assign attributes = attributes | default: params.attributes
+ assign content = content | default: params.content
+ assign href = href | default: params.href
+ if href != blank
+ assign tag = 'a'
+ endif
+
+ assign classes = classes | default: params.classes | append: ' inline-flex items-center justify-center gap-3 rounded-button whitespace-nowrap transition-colors disabled:opacity-30 disabled:pointer-events-none'
+ if tag == 'a'
+ assign classes = classes | prepend: 'pos-clean '
+ endif
+ if disabled
+ assign classes = classes | prepend: 'opacity-30 pointer-events-none '
+ endif
+
+ if weight == 'primary'
+ assign classes = classes | append: ' border'
+ case variant
+ when 'normal'
+ assign classes = classes | append: ' border-button-primary-stroke hover:border-button-primary-stroke-hover bg-button-primary hover:bg-button-primary-hover text-button-primary-foreground hover:text-button-primary-hover-foreground'
+ when 'inverted'
+ assign classes = classes | append: ' border-button-primary-foreground bg-button-primary-foreground text-button-primary hover:text-button-primary-hover'
+ when 'important'
+ assign classes = classes | append: ' border-important hover:border-important-hover bg-important hover:bg-important-hover text-button-primary-foreground hover:text-button-primary-hover-foreground'
+ when 'confirmation'
+ assign classes = classes | append: ' border-confirmation hover:border-confirmation-hover bg-confirmation hover:bg-confirmation-hover text-button-primary-foreground hover:text-button-primary-hover-foreground'
+ endcase
+
+ elsif weight == 'secondary'
+ assign classes = classes | append: ' border-secondary'
+ case variant
+ when 'normal'
+ assign classes = classes | append: ' border-button-secondary-stroke hover:border-button-secondary-stroke-hover text-button-secondary-foreground hover:text-button-secondary-foreground-hover'
+ when 'inverted'
+ assign classes = classes | append: ' border-inverted text-inverted'
+ when 'important'
+ assign classes = classes | append: ' border-important hover:border-important-hover text-important hover:text-important-hover'
+ when 'confirmation'
+ assign classes = classes | append: ' border-confirmation hover:border-confirmation-hover text-confirmation hover:text-confirmation-hover'
+ endcase
+
+ if filled
+ assign classes = classes | append: ' bg-button-secondary-background'
+ endif
+ endif
+
+
+ if size == 'small'
+ assign classes = classes | prepend: 'h-7 px-4 py-1 text-sm leading-[1.43] '
+ else
+ assign classes = classes | prepend: 'h-11 px-4 py-2.5 leading-tight '
+ endif
+%}
+<{{ tag }}
+ class="{{ classes }}"
+ {% for attribute in attributes %}
+ {{ attribute[0] | html_safe }}="{{ attribute[1] | html_safe }}"
+ {% endfor %}
+ {% if href and disabled != true %}href="{{href}}"{% endif %}
+ {% if tag == 'button' and disabled %}disabled{% endif %}
+ {% if tag == 'button' %}type="{{type}}"{% endif %}
+>{{ content | html_safe }}{{ tag }}>
+
diff --git a/modules/user/public/views/partials/components/atoms/card.liquid b/modules/user/public/views/partials/components/atoms/card.liquid
new file mode 100644
index 0000000..d76565f
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/card.liquid
@@ -0,0 +1,34 @@
+---
+metadata:
+ name: Card
+ params:
+ tag: "div"
+ classes: ''
+ variant:
+ - default
+ - highlighted
+ content: This is an example card
+---
+{% liquid
+ assign tag = tag | default: params.tag | default: 'div'
+ assign variant = variant | default: params.variant | default: 'default'
+ assign content = content | default: params.content
+ assign classes = classes | default: params.classes
+ assign attributes = attributes | default: params.attributes
+
+ assign classes = 'p-6 rounded-surface shadow-card ' | append: classes
+
+ if variant == 'highlighted'
+ assign classes = classes | append: ' bg-highlighted'
+ else
+ assign classes = classes | append: ' bg-panel'
+ endif
+%}
+<{{ tag }}
+ {% for attribute in attributes %}
+ {{ attribute[0] | html_safe }}="{{ attribute[1] | html_safe }}"
+ {% endfor %}
+ class="{{ classes }}"
+>
+ {% print content %}
+{{ tag }}>
diff --git a/modules/user/public/views/partials/components/atoms/heading.liquid b/modules/user/public/views/partials/components/atoms/heading.liquid
new file mode 100644
index 0000000..0cde244
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/heading.liquid
@@ -0,0 +1,47 @@
+---
+metadata:
+ name: Heading
+ params:
+ tag: ''
+ level:
+ - 1
+ - 2
+ - 3
+ - 4
+ - 5
+ - 6
+ classes: ''
+ content: I'm a heading
+---
+{% liquid
+ assign level = level | default: params.level | default: 2
+ assign defaultTag = 'h' | append: level
+ assign tag = tag | default: params.tag | default: defaultTag
+ assign attributes = attributes | default: params.attributes
+ assign content = content | default: params.content
+
+ assign classes = classes | default: params.classes | append: ' font-bold'
+
+
+ if level == 1
+ assign classes = classes | append: ' text-5xl'
+ elsif level == 2
+ assign classes = classes | append: ' text-3xl'
+ elsif level == 3
+ assign classes = classes | append: ' text-2xl'
+ elsif level == 4
+ assign classes = classes | append: ' text-xl'
+ elsif level == 5
+ assign classes = classes | append: ' text-xl'
+ elsif level == 6
+ assign classes = classes | append: ' text-xl'
+ endif
+%}
+<{{ tag }}
+ class="{{ classes }}"
+ {% for attribute in attributes %}
+ {{ attribute[0] }}="{{ attribute[1] }}"
+ {% endfor %}
+>{% print content %}{{ tag }}>
+
+
diff --git a/modules/user/public/views/partials/components/atoms/icon.liquid b/modules/user/public/views/partials/components/atoms/icon.liquid
new file mode 100644
index 0000000..2c6368e
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/icon.liquid
@@ -0,0 +1,26 @@
+---
+metadata:
+ name: Icon
+ params:
+ name:
+ - plus
+ - checkCircle
+ - ...
+ class: 'w-4 h-4'
+ styleguide:
+ - name: 'all'
+ class: 'w-10 h-10 p-2 m-2 inline-block'
+---
+{% liquid
+ assign name = name | default: params.name
+ assign class = class | default: params.class
+%}
+{% comment %}
+
+ List of icons in SVG format
+
+ Params:
+ - icon name (string)
+ - class (string, optional)
+
+{% endcomment %}
diff --git a/modules/user/public/views/partials/components/atoms/input.liquid b/modules/user/public/views/partials/components/atoms/input.liquid
new file mode 100644
index 0000000..3ca3100
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/input.liquid
@@ -0,0 +1,83 @@
+---
+metadata:
+ name: Input
+ params:
+ variant:
+ - normal
+ - confirmation
+ - error
+ type:
+ - text
+ - textarea
+ - email
+ - password
+ - search
+ - tel
+ - date
+ - number
+ - hidden
+ name: my-input
+ placeholder: Type here
+ value: ''
+ required:
+ - false
+ - true
+ disabled:
+ - false
+ - true
+ classes: ''
+ attributes: {}
+---
+{% liquid
+ assign variant = variant | default: params.variant | default: 'normal'
+ assign type = type | default: params.type | default: 'text'
+ assign name = name | default: params.name
+ assign value = value | default: params.value | default: ''
+ assign required = required | default: params.required | default: false
+ assign disabled = disabled | default: params.disabled | default: false
+ assign placeholder = placeholder | default: params.placeholder
+ assign id = id | default: params.attributes.id | default: name
+ assign attributes = attributes | default: params.attributes
+ assign original_classes = classes | default: params.classes
+ assign classes = 'w-full py-[0.69em] px-[0.44em] inline-block border rounded-input focus:border-interactive-hover bg-input disabled:opacity-40 outline-none text-input-foreground leading-tight transition-colors ' | append: original_classes
+
+ case variant
+ when 'confirmation'
+ assign classes = classes | append: ' border-confirmation'
+ when 'error'
+ assign classes = classes | append: ' border-important'
+ else
+ assign classes = classes | append: ' border-input-border'
+ endcase
+%}
+
+{% if type == 'hcaptcha' %}
+
+
+{% else %}
+
+ {% if type == 'textarea' %}
+
+ {% endif %}
+{% endif %}
+
diff --git a/modules/user/public/views/partials/components/atoms/sidenote.liquid b/modules/user/public/views/partials/components/atoms/sidenote.liquid
new file mode 100644
index 0000000..a5d3b7f
--- /dev/null
+++ b/modules/user/public/views/partials/components/atoms/sidenote.liquid
@@ -0,0 +1,24 @@
+---
+metadata:
+ name: Sidenote
+ params:
+ classes: ''
+ content: I'm a sidenote
+ styleguide:
+ - content: I'm a sidenote
+
+---
+{% liquid
+ assign attributes = attributes | default: params.attributes
+ assign content = content | default: params.content
+ assign classes = classes | default: params.classes | append: ' text-xs text-supplementary'
+%}
+
+ {% print content %}
+
+
diff --git a/modules/user/public/views/partials/components/molecules/formfield.liquid b/modules/user/public/views/partials/components/molecules/formfield.liquid
new file mode 100644
index 0000000..75e4b2f
--- /dev/null
+++ b/modules/user/public/views/partials/components/molecules/formfield.liquid
@@ -0,0 +1,136 @@
+---
+metadata:
+ name: Formfield
+ params:
+ tag: 'fieldset'
+ classes: ''
+ validation:
+ passed:
+ - true
+ - false
+ messages: []
+ input_params:
+ name: 'text-input-with-label-example'
+ placeholder: Type here
+ type:
+ - text
+ - textarea
+ - email
+ - password
+ - search
+ - tel
+ - date
+ - number
+ - hidden
+ - select
+ - hcaptcha
+ label_params:
+ content: Text input with label
+ description_params:
+ content: This is a description
+ icon: This is the icon name
+ multiple:
+ - true
+ - false
+ options:
+ - label: Option 1
+ value: value1
+ - label: Option 2
+ value: value2
+ styleguide:
+ - tag: 'div'
+ classes: ''
+ validation:
+ passed: false
+ messages: ['This is a test error message', 'Another error message']
+ input_params:
+ name: 'text-input-with-label-example'
+ placeholder: Type here
+ label_params:
+ content: Form label
+ description_params:
+ content: This is a FormField description
+ icon: info
+
+---
+{% liquid
+ assign tag = tag | default: params.tag | default: 'fieldset'
+ assign label_params = label_params | default: params.label_params
+ assign classes = classes | default: params.classes
+ assign validation = validation | default: params.validation
+ assign input_params = input_params | default: params.input_params
+ assign attributes = '{}' | parse_json
+ assign input_attributes = input_params.attributes | default: attributes
+
+ assign id = input_attributes.id | default: input_params.name
+
+ hash_assign input_attributes['aria-describedby'] = '' | append: input_params.name | append: '-desc'
+
+ assign input_params = input_params | hash_merge: attributes: input_attributes
+ if validation.passed == false
+ hash_assign input_params['variant'] = 'error'
+ endif
+
+ assign description_params = description_params | default: params.description_params
+%}
+<{{ tag }} class="flex flex-col items-start gap-1 {{ classes }}">
+
+ {% liquid
+ if input_params.type == 'checkbox'
+ theme_render_rc 'components/atoms/checkbox', params: input_params
+ endif
+ %} {{ label_params.content | html_safe }}
+ {% if input_params.required %} * {% endif %}
+
+
+ {% liquid
+ unless input_params.type == 'checkbox'
+ if input_params.type == 'select'
+
+ theme_render_rc 'components/molecules/select', params: input_params
+ else
+ theme_render_rc 'components/atoms/input', params: input_params
+ endif
+ endunless
+ %}
+ {% if description_params.content or validation.messages.size > 0 %}
+
+ {% endif %}
+
+{{ tag }}>
diff --git a/modules/user/public/views/partials/components/molecules/hcaptcha.liquid b/modules/user/public/views/partials/components/molecules/hcaptcha.liquid
new file mode 100644
index 0000000..d0500c8
--- /dev/null
+++ b/modules/user/public/views/partials/components/molecules/hcaptcha.liquid
@@ -0,0 +1,12 @@
+{% if context.constants.VERIFY_HCAPTCHA == "true" %}
+
+
+
+
+ {% #render 'theme/simple/field_error', errors: object.errors.hcaptcha %}
+
+{% elsif context.environment == 'staging' %}
+
+
+
+{% endif %}
diff --git a/modules/user/public/views/partials/components/molecules/pagetitle.liquid b/modules/user/public/views/partials/components/molecules/pagetitle.liquid
new file mode 100644
index 0000000..dd7c982
--- /dev/null
+++ b/modules/user/public/views/partials/components/molecules/pagetitle.liquid
@@ -0,0 +1,13 @@
+---
+metadata:
+ name: Pagetitle
+ params:
+ content: 'Page title'
+ classes: 'text-center'
+---
+{% assign content = content | default: params.content %}
+{% assign classes = classes | default: params.classes %}
+{% assign classes = classes | prepend: 'container ' | strip %}
+
+ {% theme_render_rc 'components/atoms/heading', level: 1, content: content, classes: classes %}
+
diff --git a/modules/user/public/views/partials/components/organisms/login.liquid b/modules/user/public/views/partials/components/organisms/login.liquid
new file mode 100644
index 0000000..9d09132
--- /dev/null
+++ b/modules/user/public/views/partials/components/organisms/login.liquid
@@ -0,0 +1,66 @@
+---
+metadata:
+ name: login form
+ params:
+ action: ''
+ method: 'POST'
+ redirect_to: '/'
+ classes: ''
+ errors:
+ email:
+ - Error message
+ values:
+ email: "random@example.com"
+ email_placeholder: ''
+ submit: 'Submit'
+---
+{% liquid
+ assign action = action | default: params.action
+ assign method = method | default: params.method | default: 'POST'
+ assign errors = errors | default: errors
+ assign redirect_to = redirect_to | default: params.redirect_to | default: '/'
+ assign footer = footer | default: params.footer
+ assign classes = classes | default: params.classes
+ assign email_placeholder = email_placeholder | default: params.email_placeholder
+ assign submit = submit | default: params.submit
+ assign default_submit = 'modules/user/passwords.login' | t
+ assign submit = submit | default: default_submit
+%}
+
+
diff --git a/modules/user/public/views/partials/components/organisms/new-password.liquid b/modules/user/public/views/partials/components/organisms/new-password.liquid
new file mode 100644
index 0000000..f6c1ad2
--- /dev/null
+++ b/modules/user/public/views/partials/components/organisms/new-password.liquid
@@ -0,0 +1,62 @@
+---
+metadata:
+ name: New password form
+ params:
+ context: {}
+ action: '/passwords'
+ redirect_to: '/'
+ errors: {}
+ values: {}
+ submit: 'Submit'
+---
+{% liquid
+ assign context = context | default: params.context
+ assign action = action | default: params.action
+ assign redirect_to = redirect_to | default: params.redirect_to
+ assign errors = errors | default: params.errors
+ assign values = values | default: params.values
+ assign classes = classes | default: params.classes
+ assign submit = submit | default: params.submit
+ assign default_submit = 'modules/user/passwords.password_update' | t
+ assign submit = submit | default: default_submit
+%}
+
diff --git a/modules/user/public/views/partials/components/organisms/register.liquid b/modules/user/public/views/partials/components/organisms/register.liquid
new file mode 100644
index 0000000..ec44cf6
--- /dev/null
+++ b/modules/user/public/views/partials/components/organisms/register.liquid
@@ -0,0 +1,58 @@
+---
+metadata:
+ name: register form
+ params:
+ action: '/users'
+ method: 'POST'
+ redirect_to: '/'
+ registration_fields: []
+ errors:
+ email:
+ - Error message
+ password:
+ - Error message
+ values:
+ email: random@example.com
+ submit: 'Submit'
+ classes: ''
+---
+{% liquid
+ assign action = action | default: params.action
+ assign method = method | default: params.method | default: 'POST'
+ assign errors = errors | default: params.errors
+ assign redirect_to = redirect_to | default: params.redirect_to | default: '/'
+ assign registration_fields = registration_fields | default: params.registration_fields
+ assign classes = classes | default: params.classes
+ assign submit = submit | default: params.submit
+ assign default_submit = 'modules/user/passwords.register' | t
+ assign submit = submit | default: default_submit
+%}
+
+
diff --git a/modules/user/public/views/partials/components/organisms/reset-password.liquid b/modules/user/public/views/partials/components/organisms/reset-password.liquid
new file mode 100644
index 0000000..cbb3257
--- /dev/null
+++ b/modules/user/public/views/partials/components/organisms/reset-password.liquid
@@ -0,0 +1,61 @@
+---
+metadata:
+ name: Reset password form
+ params:
+ context: {}
+ action: '/authentication_links'
+ redirect_to: '/'
+ errors: {}
+ values: {}
+---
+{% liquid
+ assign context = context | default: params.context
+ assign action = action | default: params.action
+ assign redirect_to = redirect_to | default: params.redirect_to
+ assign errors = errors | default: params.errors
+ assign values = values | default: params.values
+ assign classes = classes | default: params.classes
+ assign submit = submit | default: params.submit
+ assign default_submit = 'modules/user/passwords.reset_password' | t
+ assign submit = submit | default: default_submit
+%}
+
diff --git a/modules/user/public/views/partials/components/pages/403.liquid b/modules/user/public/views/partials/components/pages/403.liquid
new file mode 100644
index 0000000..5490df3
--- /dev/null
+++ b/modules/user/public/views/partials/components/pages/403.liquid
@@ -0,0 +1,6 @@
+
+
+ 403 Forbidden
+ You don't have access to this page
+
+
diff --git a/modules/user/public/views/partials/emails/passwords/reset.liquid b/modules/user/public/views/partials/emails/passwords/reset.liquid
new file mode 100644
index 0000000..6e16d0e
--- /dev/null
+++ b/modules/user/public/views/partials/emails/passwords/reset.liquid
@@ -0,0 +1,18 @@
+{{ 'modules/user/emails.passwords.reset.title' | t }}
+
+{{ 'modules/user/emails.passwords.reset.content' | t }}
+{{ 'modules/user/emails.passwords.reset.ignore' | t }}
+
+
diff --git a/modules/user/public/views/partials/passwords/new.liquid b/modules/user/public/views/partials/passwords/new.liquid
new file mode 100644
index 0000000..18fb15c
--- /dev/null
+++ b/modules/user/public/views/partials/passwords/new.liquid
@@ -0,0 +1,22 @@
+---
+metadata:
+ name: New password
+ params:
+ context: {}
+ errors: {}
+---
+{% liquid
+ assign context = context | default: params.context
+ assign errors = errors | default: params.errors
+ assign pageTitle = 'modules/user/passwords.edit' | t
+ theme_render_rc 'components/molecules/pagetitle', content: pageTitle, classes: 'text-center'
+%}
+
+
+ {% capture pwdResetCardContent %}
+ {% theme_render_rc 'components/organisms/new-password', action: '/passwords', context: context, errors: errors, classes: 'form--new-password' %}
+ {% endcapture %}
+
+ {% theme_render_rc 'components/atoms/card', content: pwdResetCardContent, classes: "w-full max-w-lg mx-auto" %}
+
+
diff --git a/modules/user/public/views/partials/passwords/reset.liquid b/modules/user/public/views/partials/passwords/reset.liquid
new file mode 100644
index 0000000..19852e1
--- /dev/null
+++ b/modules/user/public/views/partials/passwords/reset.liquid
@@ -0,0 +1,20 @@
+---
+metadata:
+ name: Reset password
+ params:
+ context: {}
+ errors: []
+---
+{% liquid
+ assign context = context | default: params.context
+ assign errors = errors | default: params.errors
+ assign pageTitle = 'modules/user/passwords.reset_password_title' | t
+ theme_render_rc 'components/molecules/pagetitle', content: pageTitle, classes: 'text-center'
+%}
+{% capture pwdResetCardContent %}
+ {% theme_render_rc 'components/organisms/reset-password', action: '/authentication_links', context: context, errors: errors, classes: 'form--reset-password' %}
+{% endcapture %}
+
+
+ {% theme_render_rc 'components/atoms/card', content: pwdResetCardContent, classes: "w-full max-w-lg mx-auto" %}
+
diff --git a/modules/user/public/views/partials/sessions/new.liquid b/modules/user/public/views/partials/sessions/new.liquid
new file mode 100644
index 0000000..2b6f5e2
--- /dev/null
+++ b/modules/user/public/views/partials/sessions/new.liquid
@@ -0,0 +1,33 @@
+---
+metadata:
+ name: Login
+ params:
+ errors: []
+---
+{% liquid
+ assign errors = errors | default: params.errors
+
+ theme_render_rc 'components/molecules/pagetitle', content: 'Login', classes: 'text-center'
+%}
+
+{% capture loginCardContent %}
+ {% theme_render_rc 'components/organisms/login', action: '/sessions', register_page_url: '/sign-up' errors: errors, classes: 'form--login', email_placeholder: 'Type', submit: 'Log in' %}
+
+ Don't have an account?
+
+ Request to join
+
+ {% # theme_render_rc 'components/atoms/button', content: 'Register', href: '/users/new', tag: 'a' %}
+
+
+ Password lost?
+
+ Reset
+
+ {% # theme_render_rc 'components/atoms/button', content: 'Register', href: '/users/new', tag: 'a' %}
+
+{% endcapture %}
+
+
+ {% theme_render_rc 'components/atoms/card', content: loginCardContent, classes: "w-full max-w-lg mx-auto" %}
+
diff --git a/modules/user/public/views/partials/users/new.liquid b/modules/user/public/views/partials/users/new.liquid
new file mode 100644
index 0000000..db8157f
--- /dev/null
+++ b/modules/user/public/views/partials/users/new.liquid
@@ -0,0 +1,24 @@
+---
+metadata:
+ name: Register
+ params:
+ values: {}
+ errors: []
+ registration_fields: []
+---
+{% liquid
+ assign values = values | default: params.values
+ assign errors = errors | default: params.errors
+ assign values = values | default: params.values
+ assign registration_fields = registration_fields | default: params.registration_fields
+ assign pageTitle = 'modules/user/users.new.create_account' | t
+ theme_render_rc 'components/molecules/pagetitle', content: pageTitle, classes: 'text-center'
+%}
+{% capture registerCardContent %}
+ {% theme_render_rc 'components/organisms/register', action: '/users', errors: errors, values: values, registration_fields: registration_fields, submit: 'SIGN UP', classes: 'form--register' %}
+{% endcapture %}
+
+
+ {% theme_render_rc 'components/atoms/card', content: registerCardContent, classes: "w-full max-w-lg mx-auto" %}
+
+
diff --git a/modules/user/template-values.json b/modules/user/template-values.json
new file mode 100644
index 0000000..92a7622
--- /dev/null
+++ b/modules/user/template-values.json
@@ -0,0 +1,9 @@
+{
+ "name": "User",
+ "machine_name": "user",
+ "type": "module",
+ "version": "3.0.7",
+ "dependencies": {
+ "core": "^1.5.0"
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index aff3ddb..e619fa1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2,5 +2,86 @@
"name": "pos-module-chat",
"lockfileVersion": 3,
"requires": true,
- "packages": {}
+ "packages": {
+ "": {
+ "devDependencies": {
+ "@playwright/test": "^1.49.1",
+ "@types/node": "^22.10.6"
+ }
+ },
+ "node_modules/@playwright/test": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz",
+ "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==",
+ "dev": true,
+ "dependencies": {
+ "playwright": "1.49.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "22.10.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz",
+ "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/playwright": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz",
+ "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==",
+ "dev": true,
+ "dependencies": {
+ "playwright-core": "1.49.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz",
+ "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==",
+ "dev": true,
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true
+ }
+ }
}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e21e80e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,11 @@
+{
+ "scripts": {
+ "pw-tests": "npx playwright test tests --project=test --reporter=list",
+ "test": "playwright test",
+ "install: playwright": "npx playwright install"
+ },
+ "devDependencies": {
+ "@playwright/test": "^1.49.1",
+ "@types/node": "^22.10.6"
+ }
+}
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 0000000..d06ebb0
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,88 @@
+import { defineConfig, devices } from '@playwright/test';
+import process from 'process';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './tests',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 3 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: [
+ ['html', { outputFolder: 'playwright-report', open: 'never' }], // Generates HTML report
+ ],
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ // baseURL: 'http://127.0.0.1:3000',
+ baseURL: process.env.MPKIT_URL,
+
+ testIdAttribute: 'data-tc',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ { name: 'setup', testMatch: /.*\.setup\.ts/ },
+ {
+ name: 'test',
+ use: { ...devices['Desktop Chrome'] },
+ dependencies: ['setup',],
+ testIgnore: [/prepare-env\.spec\.ts/, /example\.spec\.ts/,],
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ // webServer: {
+ // command: 'npm run start',
+ // url: 'http://127.0.0.1:3000',
+ // reuseExistingServer: !process.env.CI,
+ // },
+});
diff --git a/tests/.auth/test1@example.com.json b/tests/.auth/test1@example.com.json
new file mode 100644
index 0000000..25b8902
--- /dev/null
+++ b/tests/.auth/test1@example.com.json
@@ -0,0 +1,25 @@
+{
+ "cookies": [
+ {
+ "name": "_pos_session",
+ "value": "b8e0b1d909cb5f0c9b9a89ef4577fd90",
+ "domain": "dg-template.staging.oregon.platform-os.com",
+ "path": "/",
+ "expires": 1738072783.197026,
+ "httpOnly": true,
+ "secure": true,
+ "sameSite": "Lax"
+ },
+ {
+ "name": "CSRF-TOKEN",
+ "value": "R1RyZXNRecNMNDqxsEDmrneS8C3Td5vTmlJsF_7_nbW093_By2Kj1MaDUPdBJSWyqX6wsyyecbn5996jAYCjdQ",
+ "domain": "dg-template.staging.oregon.platform-os.com",
+ "path": "/",
+ "expires": -1,
+ "httpOnly": false,
+ "secure": true,
+ "sameSite": "Strict"
+ }
+ ],
+ "origins": []
+}
\ No newline at end of file
diff --git a/tests/.auth/test2@example.com.json b/tests/.auth/test2@example.com.json
new file mode 100644
index 0000000..f015d66
--- /dev/null
+++ b/tests/.auth/test2@example.com.json
@@ -0,0 +1,25 @@
+{
+ "cookies": [
+ {
+ "name": "_pos_session",
+ "value": "b48793e47deb94573d507fc64ec0819e",
+ "domain": "dg-template.staging.oregon.platform-os.com",
+ "path": "/",
+ "expires": 1738072783.203775,
+ "httpOnly": true,
+ "secure": true,
+ "sameSite": "Lax"
+ },
+ {
+ "name": "CSRF-TOKEN",
+ "value": "TFUzSsCD_FBh8bBltmNxQjPN8lna9SInDxve2bc3oBcMJkBBpIp9oZsIaYlGC5KCBptjqwFjI0UM1BReRyaKPA",
+ "domain": "dg-template.staging.oregon.platform-os.com",
+ "path": "/",
+ "expires": -1,
+ "httpOnly": false,
+ "secure": true,
+ "sameSite": "Strict"
+ }
+ ],
+ "origins": []
+}
\ No newline at end of file
diff --git a/tests/auth.setup.ts b/tests/auth.setup.ts
new file mode 100644
index 0000000..3b7a94b
--- /dev/null
+++ b/tests/auth.setup.ts
@@ -0,0 +1,29 @@
+import { test as setup } from '@playwright/test';
+import process from 'process';
+import { LogInPage } from './pages/login';
+import { users } from '../tests/data/users';
+
+const PASSWORD = process.env.E2E_TEST_PASSWORD;
+if (!PASSWORD) {
+ throw new Error('E2E_TEST_PASSWORD environment variable is not set');
+}
+
+const usersToAuth = [
+ users.test1,
+ users.test2,
+ users.test3,
+ users.test4,
+ users.test5,
+];
+
+for (const user of usersToAuth) {
+ setup(`authenticate user ${user.email}`, async ({ page }) => {
+ const loginPage = new LogInPage(page);
+ await loginPage.goto();
+ await loginPage.logIn(user.email, PASSWORD);
+
+ await page.waitForURL('/');
+
+ await page.context().storageState({ path: `tests/.auth/${user.email}.json` });
+ });
+}
\ No newline at end of file
diff --git a/tests/data/messages.ts b/tests/data/messages.ts
new file mode 100644
index 0000000..e9fc53f
--- /dev/null
+++ b/tests/data/messages.ts
@@ -0,0 +1,14 @@
+export const messages = {
+ test1: {
+ message1: "Hello Jordan! I want to ask you about something.",
+ },
+ test2: {
+ message1: "Hi Milo! Feel free to ask about anything.",
+ },
+ test3: {
+ message1: "Hey Jordan :) How your day is going today? I hope things are going well"
+ },
+ test4: {
+ message1: "Good morning Jordan, what kind of style do you prefer?"
+ }
+ };
\ No newline at end of file
diff --git a/tests/data/seed/data.zip b/tests/data/seed/data.zip
new file mode 100644
index 0000000..a2a06d9
Binary files /dev/null and b/tests/data/seed/data.zip differ
diff --git a/tests/data/seed/seed.sh b/tests/data/seed/seed.sh
new file mode 100755
index 0000000..0de5048
--- /dev/null
+++ b/tests/data/seed/seed.sh
@@ -0,0 +1,10 @@
+set -eu
+
+DEFAULT_ENV=""
+POS_ENV="${1:-$DEFAULT_ENV}"
+
+pos-cli data clean $POS_ENV --auto-confirm --include-schema
+
+pos-cli deploy $POS_ENV
+
+pos-cli data import --path=./tests/data/seed/data.zip --zip $POS_ENV
\ No newline at end of file
diff --git a/tests/data/users.ts b/tests/data/users.ts
new file mode 100644
index 0000000..34546ed
--- /dev/null
+++ b/tests/data/users.ts
@@ -0,0 +1,32 @@
+export const users = {
+ test1: {
+ email: 'test1@example.com',
+ firstName: 'Aaron',
+ fullName: 'Aaron Lopez',
+ lastName: 'Lopez'
+ },
+ test2: {
+ email: 'test2@example.com',
+ firstName: 'Rhonda',
+ fullName: 'Rhonda Blackwell',
+ lastName: 'Blackwell'
+ },
+ test3: {
+ email: 'test3@example.com',
+ firstName: 'Coleen',
+ fullName: 'Coleen Nguyen',
+ lastName: 'Nguyen'
+ },
+ test4: {
+ email: 'test4@example.com',
+ firstName: 'Emma',
+ fullName: 'Emma Vasquez',
+ lastName: 'Vasquez'
+ },
+ test5: {
+ email: 'test5@example.com',
+ firstName: 'Jonathan',
+ fullName: 'Jonathan Baird',
+ lastName: 'Baird'
+ }
+};
\ No newline at end of file
diff --git a/tests/helper.ts b/tests/helper.ts
new file mode 100644
index 0000000..4500d99
--- /dev/null
+++ b/tests/helper.ts
@@ -0,0 +1,15 @@
+import { Browser, BrowserContext, Page } from 'playwright';
+
+export async function switchContext(
+ currentContext: BrowserContext | null,
+ browser: Browser,
+ storageStatePath: string
+): Promise<{ context: BrowserContext; page: Page }> {
+ if (currentContext) {
+ await currentContext.close();
+ }
+ const newContext = await browser.newContext({ storageState: storageStatePath });
+ const newPage = await newContext.newPage();
+ return { context: newContext, page: newPage };
+}
+
diff --git a/tests/messaging.spec.ts b/tests/messaging.spec.ts
new file mode 100644
index 0000000..f1df492
--- /dev/null
+++ b/tests/messaging.spec.ts
@@ -0,0 +1,100 @@
+import { BrowserContext, expect, Page, test } from '@playwright/test';
+import { InboxPage } from './pages/inbox';
+import { PeoplePage } from './pages/people';
+import { switchContext } from './helper';
+import { messages } from './data/messages';
+import { users } from './data/users';
+
+test.describe('Testing messaging', () => {
+ test('user can send message to other users', async ({ browser }) => {
+ let context: BrowserContext | null = null;
+ let page: Page;
+
+ await test.step(`user 'A' sends message to user 'C' via profile`, async () => {
+ ({ context, page } = await switchContext(context, browser, `tests/.auth/${users.test1.email}.json`));
+ const inboxPage = new InboxPage(page);
+ const peoplePage = new PeoplePage(page);
+
+ await peoplePage.goto();
+ await peoplePage.linkWithText(users.test2.fullName).click();
+
+ await inboxPage.messageInputField.fill(messages.test1.message1);
+ await inboxPage.buttonWithText('Send').click();
+ await context.close();
+ });
+
+ await test.step(`user 'B' sends message to user 'C'`, async () => {
+ ({ context, page } = await switchContext(context, browser, `tests/.auth/${users.test3.email}.json`));
+ const inboxPage = new InboxPage(page);
+ const peoplePage = new PeoplePage(page);
+
+ await peoplePage.goto();
+ await peoplePage.linkWithText(users.test2.fullName).click();
+
+ await inboxPage.messageInputField.fill(messages.test3.message1);
+ await inboxPage.buttonWithText('Send').click();
+ await context.close();
+ });
+
+ await test.step(`user 'D' sends message to user 'C' via profile`, async () => {
+ ({ context, page } = await switchContext(context, browser, `tests/.auth/${users.test4.email}.json`));
+ const inboxPage = new InboxPage(page);
+ const peoplePage = new PeoplePage(page);
+
+ await peoplePage.goto();
+ await peoplePage.linkWithText(users.test2.fullName).click();
+
+ await inboxPage.messageInputField.fill(messages.test4.message1);
+ await inboxPage.buttonWithText('Send').click();
+ await context.close();
+ });
+
+ await test.step(`user 'C' responds to user 'A'`, async () => {
+ ({ context, page } = await switchContext(context, browser, `tests/.auth/${users.test2.email}.json`));
+ const inboxPage = new InboxPage(page);
+
+ await inboxPage.goto();
+ await inboxPage.chatRoom(users.test1.fullName).click();
+ await expect(inboxPage.message(messages.test1.message1)).toBeVisible();
+ await inboxPage.messageInputField.fill(messages.test2.message1);
+ await inboxPage.buttonWithText('Send').click();
+ });
+
+ await test.step(`user 'C' verify there are 3 chatrooms with expected messages`, async () => {
+ const inboxPage = new InboxPage(page);
+
+ const chatRooms = [
+ { name: users.test1.fullName, messagesToBeVisible: [messages.test1.message1, messages.test2.message1], messagesNotToBeVisible: [messages.test3.message1, messages.test4.message1] },
+ { name: users.test3.fullName, messagesToBeVisible: [messages.test3.message1], messagesNotToBeVisible: [messages.test1.message1, messages.test2.message1, messages.test4.message1] },
+ { name: users.test4.fullName, messagesToBeVisible: [messages.test4.message1], messagesNotToBeVisible: [messages.test1.message1, messages.test2.message1, messages.test3.message1] }
+ ];
+
+ await inboxPage.goto();
+
+ for (const chatRoom of chatRooms) {
+ await expect(inboxPage.chatRoom(chatRoom.name)).toBeVisible();
+ await inboxPage.chatRoom(chatRoom.name).click();
+
+ for (const messageToBeVisible of chatRoom.messagesToBeVisible) {
+ await expect(inboxPage.message(messageToBeVisible)).toBeVisible();
+ };
+
+ for (const messageNotToBeVisible of chatRoom.messagesNotToBeVisible) {
+ await expect(inboxPage.message(messageNotToBeVisible)).not.toBeVisible();
+ };
+ };
+ });
+ });
+
+ test(`not involved user has empty inbox`, async ({ browser }) => {
+ const context = await browser.newContext({ storageState: `tests/.auth/${users.test5.email}.json` });
+ const page = await context.newPage();
+ const inboxPage = new InboxPage(page);
+
+ await inboxPage.goto();
+ await expect(inboxPage.chatRoom(users.test1.fullName)).not.toBeVisible();
+ await expect(inboxPage.chatRoom(users.test3.fullName)).not.toBeVisible();
+ await expect(inboxPage.chatRoom(users.test4.fullName)).not.toBeVisible();
+ await expect(inboxPage.elementWithText('You have not started any conversation yet')).toBeVisible();
+ });
+});
\ No newline at end of file
diff --git a/tests/pages/inbox.ts b/tests/pages/inbox.ts
new file mode 100644
index 0000000..bd8e632
--- /dev/null
+++ b/tests/pages/inbox.ts
@@ -0,0 +1,15 @@
+import { type Locator, type Page } from '@playwright/test';
+import { BasePage } from './page';
+
+export class InboxPage extends BasePage {
+ readonly chatRoom: (text: string) => Locator;
+ readonly message: (text: string) => Locator;
+ readonly messageInputField: Locator;
+
+ constructor(page: Page) {
+ super(page, '/inbox');
+ this.chatRoom = (text) => page.locator('[data-tc="chat-room"]').filter( {hasText:text});
+ this.message = (text) => page.locator('#chat-messagesList').getByText(text, { exact: true });
+ this.messageInputField = page.locator('#chat-messageInput');
+ };
+}
diff --git a/tests/pages/login.ts b/tests/pages/login.ts
new file mode 100644
index 0000000..461d843
--- /dev/null
+++ b/tests/pages/login.ts
@@ -0,0 +1,31 @@
+import { type Locator, type Page } from '@playwright/test';
+
+export class LogInPage {
+ readonly page: Page;
+ readonly url: string;
+ readonly emailInputField: Locator;
+ readonly loginButton: Locator;
+ readonly passwordInputField: Locator;
+ readonly resetButton: Locator;
+ readonly elementWithText: (text: string) => Locator;
+
+ constructor(page: Page) {
+ this.page = page;
+ this.url = '/sessions/new';
+ this.elementWithText = (text) => page.getByText(text);
+ this.emailInputField = page.getByRole('textbox', { name: 'Email' });
+ this.loginButton = page.getByRole('button', { name: 'Log in' });
+ this.passwordInputField = page.getByRole('textbox', { name: 'Password' });
+ this.resetButton = page.getByRole('link', { name: 'Reset' });
+ }
+
+ async goto() {
+ await this.page.goto(this.url);
+ }
+
+ async logIn(email: string, password: string) {
+ await this.emailInputField.fill(email);
+ await this.passwordInputField.fill(password);
+ await this.loginButton.click();
+ }
+}
diff --git a/tests/pages/page.ts b/tests/pages/page.ts
new file mode 100644
index 0000000..f628997
--- /dev/null
+++ b/tests/pages/page.ts
@@ -0,0 +1,25 @@
+import { type Locator, type Page, expect } from '@playwright/test';
+
+export class BasePage {
+ readonly page: Page;
+ path: string;
+ readonly buttonWithText: (text: string) => Locator;
+ readonly elementWithText: (text: string) => Locator;
+ readonly headingWithText: (text: string) => Locator;
+ readonly linkWithText: (text: string) => Locator;
+
+ constructor(page: Page, path: string) {
+ this.page = page;
+ this.path = path;
+ this.buttonWithText = (text: string) => page.getByRole('button', { name: text, exact: true });
+ this.elementWithText = (text: string) => page.getByText(text, { exact: true });
+ this.headingWithText = (text: string) => page.getByRole('heading', { name: text });
+ this.linkWithText = (text: string) => page.getByRole('link', { name: text });
+ }
+
+ async goto() {
+ await this.page.goto(this.path);
+ }
+}
+
+
diff --git a/tests/pages/people.ts b/tests/pages/people.ts
new file mode 100644
index 0000000..4584113
--- /dev/null
+++ b/tests/pages/people.ts
@@ -0,0 +1,9 @@
+import { type Locator, type Page } from '@playwright/test';
+import { BasePage } from './page';
+
+export class PeoplePage extends BasePage {
+
+ constructor(page: Page) {
+ super(page, '/');
+ };
+}