@leaddreamer/inventorylogic 0.0.3-beta.79 → 0.0.3-beta.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +16 -20
  2. package/business/Utilities/index.js +1 -0
  3. package/business/Utilities/other.js +1 -3
  4. package/business/Utilities/promise-queue/index.js +183 -150
  5. package/business/Utilities/promise-queue/new.js +231 -0
  6. package/dist/InventoryLogic.0ac93278.js +35 -0
  7. package/dist/InventoryLogic.0ac93278.js.map +1 -0
  8. package/dist/InventoryLogic.31f6d549.js +152 -0
  9. package/dist/InventoryLogic.31f6d549.js.map +1 -0
  10. package/dist/InventoryLogic.35827495.js +285 -0
  11. package/dist/InventoryLogic.35827495.js.map +1 -0
  12. package/dist/InventoryLogic.37dfff3e.js +72 -0
  13. package/dist/InventoryLogic.37dfff3e.js.map +1 -0
  14. package/dist/InventoryLogic.4206cb15.js +213 -0
  15. package/dist/InventoryLogic.4206cb15.js.map +1 -0
  16. package/dist/InventoryLogic.44193a77.js +35 -0
  17. package/dist/InventoryLogic.44193a77.js.map +1 -0
  18. package/dist/InventoryLogic.46ca6768.js +131 -0
  19. package/dist/InventoryLogic.46ca6768.js.map +1 -0
  20. package/dist/InventoryLogic.4d012935.js +151 -0
  21. package/dist/InventoryLogic.4d012935.js.map +1 -0
  22. package/dist/InventoryLogic.57f24f5f.js +155 -0
  23. package/dist/InventoryLogic.57f24f5f.js.map +1 -0
  24. package/dist/InventoryLogic.59be76a4.js +184 -0
  25. package/dist/InventoryLogic.59be76a4.js.map +1 -0
  26. package/dist/InventoryLogic.70925a32.js +375 -0
  27. package/dist/InventoryLogic.70925a32.js.map +1 -0
  28. package/dist/InventoryLogic.72fcf301.js +6 -0
  29. package/dist/InventoryLogic.72fcf301.js.map +1 -0
  30. package/dist/InventoryLogic.7741caec.js +375 -0
  31. package/dist/InventoryLogic.7741caec.js.map +1 -0
  32. package/dist/InventoryLogic.78480e5e.js +152 -0
  33. package/dist/InventoryLogic.78480e5e.js.map +1 -0
  34. package/dist/InventoryLogic.80d0e568.js +135 -0
  35. package/dist/InventoryLogic.80d0e568.js.map +1 -0
  36. package/dist/InventoryLogic.8a273d2e.js +110 -0
  37. package/dist/InventoryLogic.8a273d2e.js.map +1 -0
  38. package/dist/InventoryLogic.8addb055.js +202 -0
  39. package/dist/InventoryLogic.8addb055.js.map +1 -0
  40. package/dist/InventoryLogic.9dee46ea.js +6 -0
  41. package/dist/InventoryLogic.9dee46ea.js.map +1 -0
  42. package/dist/InventoryLogic.b90f66ea.js +124 -0
  43. package/dist/InventoryLogic.b90f66ea.js.map +1 -0
  44. package/dist/InventoryLogic.bb447b4c.js +39 -0
  45. package/dist/InventoryLogic.bb447b4c.js.map +1 -0
  46. package/dist/InventoryLogic.d27e84a7.js +75 -0
  47. package/dist/InventoryLogic.d27e84a7.js.map +1 -0
  48. package/dist/InventoryLogic.d69ad127.js +217 -0
  49. package/dist/InventoryLogic.d69ad127.js.map +1 -0
  50. package/dist/InventoryLogic.e03e6b07.js +245 -0
  51. package/dist/InventoryLogic.e03e6b07.js.map +1 -0
  52. package/dist/InventoryLogic.f276f76c.js +213 -0
  53. package/dist/InventoryLogic.f276f76c.js.map +1 -0
  54. package/dist/InventoryLogic.f4627c8a.js +160 -0
  55. package/dist/InventoryLogic.f4627c8a.js.map +1 -0
  56. package/dist/index.js +23 -0
  57. package/dist/index.js.map +1 -0
  58. package/index.js +1 -2
  59. package/package.json +7 -3
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["business/BusinessData/index.js"],"sourcesContent":["/**\n * Functions for managing (potentially)private data for an organization.\n * Unified structure as a sub-record of organization, or CityManager accounts\n * @module BusinessData\n */\nimport {\n fetchRecord,\n writeRecord,\n typedWrite,\n writeBack,\n deleteRecordByRefPath,\n} from \"@leaddreamer/firebase-wrapper\";\nimport { Forms, fillForm } from \"@leaddreamer/staticforms\";\nimport {\n BUSINESS,\n BUSINESSDATA,\n BUSINESS_TYPE,\n ADDRESSES,\n USER,\n MCC,\n} from \"../boilerplate/index.js\";\nimport { fetchAddresses } from \"../Addresses/index.js\";\n\n//////////////////////////////////////////////////////////////////////\n// definitions\n\n/**\n * @external AddressType\n */\n/**\n * @typedef {object} contact\n * @property {?string} contact.Id\n * @property {!string} contact.first_name\n * @property {!string} contact.last_name\n * @property {!string} contact.tel\n * @property {?string} contact.email - must be filled in to make profile public\n */\n/**\n * @typedef {object} BusinessData\n * @property {?string} email - must be filled in to make profile public\n * @property {contact} contact\n * @property {!string} tel\n * @property {string} business_type\n * @property {AddressType} business_address\n * @property {AddressType} mailing_address\n * @property {AddressType} billing_address\n */\n/**\n * @constant\n * @type {BusinessData}\n * @default\n */\nconst BusinessDefault = {\n Id: null,\n email: null,\n business_type: null,\n contact: null,\n business_address: null,\n mailing_address: null,\n billing_address: null,\n tel: null,\n mcc: null,\n tax_rate: null,\n //tax_id: null,\n openIssues: false,\n};\n\n/**\n * @constant\n * @type {BusinessData}\n * @default\n */\nconst BusinessAccountForm = {\n refPath: \"hidden:text\",\n email: \"email\",\n business_type: `lookup:${BUSINESS_TYPE}`,\n contact: `object:${USER}`,\n business_address: `lookupLink:${ADDRESSES}`,\n mailing_address: `lookupLink:${ADDRESSES}`,\n billing_address: `lookupLink:${ADDRESSES}`,\n tel: \"tel\",\n mcc: `lookup:${MCC}`,\n};\n\nForms.Base[BUSINESSDATA] = BusinessDefault;\nForms.BaseForm[BUSINESSDATA] = BusinessAccountForm;\nForms.AccountForm[BUSINESSDATA] = BusinessAccountForm;\n\n//////////////////////////////////////////////////////////////////////\n// Utilities\n\n/**\n * Fetches a fulll object representation of an account, including BusinessData\n * @param {AccountType} account\n * @returns {Promise.AccountType}\n */\nexport async function fetchFullAccount(account) {\n const BusinessData = await fetchBusinessData(account);\n\n account.business = BusinessData;\n\n return account;\n}\n\n/**\n * Fetches the BusinessData (corporate, addresses, etc) for an account\n * @param {AccountType} account\n * @returns {Promise.BusinessData}\n */\nexport async function fetchBusinessData(account) {\n let addresses = [];\n try {\n addresses = await fetchAddresses(account);\n } catch (err) {}\n const addressMap = new Map();\n if (addresses.length) {\n addresses.forEach((address) => {\n addressMap.set(address.Id, address);\n });\n }\n\n const BusinessData = await fetchRecord(\n BUSINESSDATA,\n account.Id,\n account.refPath,\n );\n\n let addressEntries = {};\n [\"business_address\", \"billing_address\", \"mailing_address\"].forEach(\n (entry) => {\n const isLink =\n entry && BusinessData[entry] && !BusinessData[entry]?.address_line_1;\n if (isLink) {\n addressEntries[entry] = {\n ...addressMap.get(BusinessData[entry]),\n };\n }\n },\n ); //hacky way to repeat same effort\n\n return {\n ...BusinessData,\n ...addressEntries,\n };\n}\n\n/**\n * Composes a URL for an \"account page\" from the account, and passed base URL\n * @param {!AccountType} account\n * @param {!string} origin base URL for the application\n * @returns {string} full URL for business accouont\n */\nexport function accountPage(account, origin) {\n return `${origin}/${BUSINESS}/Account`; //Leads to LOGGED IN organization account page\n}\n\n/**\n * @external WriteBatch\n * @typedef {WriteBatch|Transaction|void} ChainType\n */\n\n/**\n * @async\n * @function\n * @static\n * Creates the Business information document\n * @param {AccountType} account\n * @param {?ChainType} batch - batching object. Transaction will be added to the batch\n * @returns {Promise<ChainType>} WriteBatch, Transaction or Void\n */\nexport async function createBusinessData(account, batch = null) {\n return typedWrite(\n {\n ...Forms.Base[BUSINESSDATA], //base fields with defaults\n ...fillForm(account, BUSINESSDATA), //sanitize passed data\n }, //data\n account, //parent\n BUSINESSDATA, //type\n batch,\n );\n}\n\n/**\n * Writes the \"Business\" data to the database\n * @param {BusinessData} businessData\n * @returns {Promise<BusinessData>}\n */\nexport async function saveBusinessData(businessData, batch = null) {\n return writeBack(businessData, batch);\n}\n\n/**\n * Deletes a BusinessData record (rarely used if ever)\n * @param {BusinessData} businessData\n * @param {!string} businessData.refPath\n * @returns {Promise<void>}\n */\nexport async function deleteBusinessData(businessData, batch = null) {\n return deleteRecordByRefPath(businessData.refPath, batch);\n}\n\n/**\n * creates the \"base path\" (refPath) to store addresses based on an account (refPath)\n * @param {Record} account\n * @param {!string} account.refPath\n * @returns {string}\n */\nexport function businessDataPath(account) {\n return `${account.refPath}/${BUSINESSDATA}/${account.Id}`;\n}\n\n/**\n * verifies that all needed information has been filled in\n * @param {AccountType} account\n * @param {BusinessData} businessData record\n * @returns {Boolean}\n */\nexport function profileComplete(account, businessData) {\n if (!businessData?.business_address) return false;\n if (!businessData?.billing_address) return false;\n if (!businessData?.mailing_address) return false;\n if (!businessData?.email) return false;\n if (!businessData?.tel) return false;\n if (!account?.website) return false;\n if (!(account?.name || account?.corporate)) return false;\n return true;\n}\n\n/**\n * verifies that all needed information has been filled in\n * @param {AccountType} account\n * @param {BusinessData} businessData record\n * @returns {string|null}\n */\nexport function profileIncomplete(account, businessData) {\n let problem_string = \"\";\n if (!businessData?.business_address) {\n problem_string = problem_string.concat(`=> Business Address Missing\\n`);\n }\n if (!businessData?.billing_address) {\n problem_string = problem_string.concat(`=> Billing Address Missing\\n`);\n }\n if (!businessData?.mailing_address) {\n problem_string = problem_string.concat(`=> Mailing Address Missing\\n`);\n }\n if (!businessData?.email) {\n problem_string = problem_string.concat(`=> Business Email Missing\\n`);\n }\n if (!businessData?.tel) {\n problem_string = problem_string.concat(`=> Business Telephone Missing\\n`);\n }\n if (!account?.website) {\n problem_string = problem_string.concat(`=> Business Website Missing\\n`);\n }\n if (!(account?.name || account?.corporate)) {\n problem_string = problem_string.concat(\n `=> Business and/or Corporate Name Missing\\n`,\n );\n }\n return problem_string.length ? problem_string : null;\n}\n\n/**\n * Sets the \"openIssues\" flag in an account's BUSINESSDATA record\n * The account's refPath is attached to the Payment system's record, and\n * used here to find the Payment Account\n * @param {BusinessData} businessData\n * @returns {Promise.boolean}\n */\nexport async function setOpenIssues(businessData) {\n return writeRecord(\n BUSINESSDATA,\n {\n ...businessData,\n openIssues: true,\n },\n businessData.refPath,\n null,\n true,\n );\n}\n\n/**\n * Clears the \"openIssues\" flag in an account's BUSINESSDATA record\n * The account's refPath is attached to the Payment system's record, and\n * used here to find the Payment Account\n * @param {BusinessData} businessData\n * @returns {Promise.boolean}\n */\nexport async function clearOpenIssues(businessData) {\n return writeRecord(\n BUSINESSDATA,\n {\n ...businessData,\n openIssues: false,\n },\n businessData.refPath,\n null,\n true,\n );\n}\n"],"names":[],"version":3,"file":"InventoryLogic.57f24f5f.js.map"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Typedefs, constants, support functions and database operations related to Promise getQueueSize
3
+ * Thes are useful for scheduling large serial asynchronous operations
4
+ * @module PromiseQueue
5
+ */ /**
6
+ * Creates a new rate limited queue. The queue is created with stopped state, i.e. you have to call start() to run jobs.
7
+ * @class
8
+ */ class $d403d40112d3687c$export$e869d3bcedcd9592 {
9
+ /**
10
+ * @param {number} maxCallsPerSecond - The rate limit of this queue in maximum calls per seconds which may be executed at any time. Pass values less than 1 to have less than one call per second, e.g. 1/3 for 3 one call in three seconds at maximum.
11
+ * @param {callback} logger optional logger function for errors
12
+ * @constructor
13
+ */ constructor(maxCallsPerSecond = 1, logger){
14
+ /**
15
+ * The rate limit of this queue in maximum calls per seconds
16
+ * which may be executed at any time. Pass values less than 1
17
+ * to have less than one call per second, e.g. 1/3 for 3 one
18
+ * call in three seconds at maximum.
19
+ * @type {float}
20
+ */ this.maxCallsPerSecond = typeof maxCallsPerSecond === "undefined" ? 1 : maxCallsPerSecond;
21
+ /**
22
+ * optional logger function for errors
23
+ * @type {callback}
24
+ */ this.logger = logger;
25
+ /**
26
+ * lists of tasks to be processed, in order, in the queue
27
+ * @type {Array.callback}
28
+ */ this.tasks = [];
29
+ /**
30
+ * flag to indicate queue processing is active
31
+ * @type {boolean}
32
+ */ this.isActive = false;
33
+ /**
34
+ * pacing for queue processing / rate limiting
35
+ * @type {float}
36
+ */ this.jobIntervalMillis = 1000 / maxCallsPerSecond;
37
+ /**
38
+ * timestamp of start of last task
39
+ * @type {time}
40
+ */ this.lastTaskTimestamp = null;
41
+ /**
42
+ * @type {string}
43
+ */ this.currentTaskTimeoutId = null;
44
+ }
45
+ /**
46
+ * Processes the next task and returns the id of the time used to wait for the next invocation of this method.
47
+ * @private
48
+ */ updateTaskSchedule() {
49
+ if (this.logger && this.logger.debug) this.logger.debug("PromiseQueue.updateTaskSchedule");
50
+ if (this.isEmpty() || this.isStopped()) return;
51
+ const queue = this;
52
+ function processNextTask() {
53
+ if (queue.logger && queue.logger.debug) queue.logger.debug("PromiseQueue.processNextTask", queue.tasks.length);
54
+ var nextTaskItem = queue.tasks.shift();
55
+ if (nextTaskItem) try {
56
+ const result = nextTaskItem.task.call();
57
+ if (queue.logger && queue.logger.debug) queue.logger.debug("Resolving queued promise", result, result instanceof Promise);
58
+ nextTaskItem.resolve(result);
59
+ } catch (e) {
60
+ queue.logger.info("rejecting queued promise result", e);
61
+ nextTaskItem.reject(e);
62
+ }
63
+ }
64
+ function scheduleNext(timeoutMillisOverride) {
65
+ if (queue.logger && queue.logger.debug) queue.logger.debug("PromiseQueue.scheduleNext", timeoutMillisOverride);
66
+ if (queue.isEmpty()) {
67
+ queue.currentTaskTimeoutId = null;
68
+ return;
69
+ }
70
+ queue.currentTaskTimeoutId = setTimeout(function() {
71
+ queue.lastTaskTimestamp = Date.now();
72
+ processNextTask();
73
+ scheduleNext(queue.jobIntervalMillis);
74
+ }, timeoutMillisOverride);
75
+ }
76
+ if (this.currentTaskTimeoutId == null) {
77
+ if (this.lastTaskTimestamp) {
78
+ let passedTime = Date.now() - this.lastTaskTimestamp;
79
+ if (passedTime > this.jobIntervalMillis) scheduleNext(this.jobIntervalMillis);
80
+ else scheduleNext(Math.max(0, this.jobIntervalMillis - passedTime));
81
+ } else scheduleNext(0);
82
+ }
83
+ }
84
+ /**
85
+ * Starts the task processing of this queue.
86
+ *
87
+ * If it is already started, then false will be returned.
88
+ * If it is not yet started then the first task will be processed in the background and true will be returned.
89
+ *
90
+ * @return {boolean} true if this queue wasn't started before and now started to process tasks.
91
+ */ start() {
92
+ if (this.isActive) return false;
93
+ this.isActive = true;
94
+ this.updateTaskSchedule();
95
+ return true;
96
+ }
97
+ /**
98
+ * Stops the processing of this queue.
99
+ * @return true if the queue was started and is now stopped. false if it was already stopped.
100
+ */ stop() {
101
+ if (this.isActive) {
102
+ this.isActive = false;
103
+ if (this.currentTaskTimeoutId) {
104
+ clearInterval(this.currentTaskTimeoutId);
105
+ this.currentTaskTimeoutId = null;
106
+ this.lastTaskTimestamp = null;
107
+ }
108
+ }
109
+ }
110
+ getMaxCallsPerSecond() {
111
+ return this.maxCallsPerSecond;
112
+ }
113
+ isStarted() {
114
+ return this.isActive;
115
+ }
116
+ isStopped() {
117
+ return !this.isStarted();
118
+ }
119
+ /**
120
+ * @returns {boolean} true if this queue is currently empty, i.e. if it has no tasks in the queue.
121
+ */ isEmpty() {
122
+ return this.tasks.length === 0;
123
+ }
124
+ /**
125
+ * @returns {boolean} true if this queue has one or more entries.
126
+ */ isNotEmpty() {
127
+ return !this.isEmpty();
128
+ }
129
+ /**
130
+ * @param {function} task - The task to add.
131
+ * @param {boolean} append - if the task should be appended or prepended to the list of queued tasks
132
+ * @return {Promise} A promise which is resolved/rejected when the task was executed by the queue.
133
+ */ async add(task, append) {
134
+ var self = this;
135
+ var promise = new Promise(function(resolve, reject) {
136
+ var newTaskItem = {
137
+ task: task,
138
+ resolve: resolve,
139
+ reject: reject
140
+ };
141
+ if (self.isEmpty() || append) self.tasks.push(newTaskItem);
142
+ else self.tasks.unshift(newTaskItem);
143
+ });
144
+ self.updateTaskSchedule();
145
+ return promise;
146
+ }
147
+ /**
148
+ * Appends a new task at the end of the queue.
149
+ * @param {function} task - The task to perform. This function will be called with no arguments.
150
+ * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue
151
+ */ async append(task) {
152
+ return this.add(task, true);
153
+ }
154
+ /**
155
+ * Adds a new task as first item in the queue.
156
+ * @param task
157
+ * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue
158
+ */ async prepend(task) {
159
+ return this.add(task, false);
160
+ }
161
+ /**
162
+ * Removes the task from the qeueue. If the task is contained more than one time then all occurrences will be removed.
163
+ * @param {function} task - The task to remove.
164
+ * @return {number} - The number of items which were removed.
165
+ */ remove(task) {
166
+ if (this.isEmpty()) return 0;
167
+ var removedItems = 0;
168
+ for(var i = this.tasks.length - 1; i >= 0; i--)if (this.tasks[i].task === task) {
169
+ this.tasks.splice(i, 1);
170
+ removedItems++;
171
+ }
172
+ return removedItems;
173
+ }
174
+ /**
175
+ * @returns {Number} - The number of queued/waiting tasks in the queue.
176
+ */ getQueueSize() {
177
+ return this.tasks.length;
178
+ }
179
+ }
180
+ var $d403d40112d3687c$export$2e2bcd8739ae039 = PromiseQueue = new $d403d40112d3687c$export$e869d3bcedcd9592(1, null);
181
+
182
+
183
+ export {$d403d40112d3687c$export$e869d3bcedcd9592 as PromiseQueueClass, $d403d40112d3687c$export$2e2bcd8739ae039 as default};
184
+ //# sourceMappingURL=InventoryLogic.59be76a4.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["business/Utilities/promise-queue/index.js"],"sourcesContent":["/**\n * Typedefs, constants, support functions and database operations related to Promise getQueueSize\n * Thes are useful for scheduling large serial asynchronous operations\n * @module PromiseQueue\n */\n/**\n * Creates a new rate limited queue. The queue is created with stopped state, i.e. you have to call start() to run jobs.\n * @class\n */\nexport class PromiseQueueClass {\n /**\n * @param {number} maxCallsPerSecond - The rate limit of this queue in maximum calls per seconds which may be executed at any time. Pass values less than 1 to have less than one call per second, e.g. 1/3 for 3 one call in three seconds at maximum.\n * @param {callback} logger optional logger function for errors\n * @constructor\n */\n constructor(maxCallsPerSecond=1, logger) {\n /**\n * The rate limit of this queue in maximum calls per seconds\n * which may be executed at any time. Pass values less than 1\n * to have less than one call per second, e.g. 1/3 for 3 one\n * call in three seconds at maximum.\n * @type {float}\n */\n this.maxCallsPerSecond =\n typeof maxCallsPerSecond === \"undefined\" ? 1 : maxCallsPerSecond;\n /**\n * optional logger function for errors\n * @type {callback}\n */\n this.logger = logger;\n\n /**\n * lists of tasks to be processed, in order, in the queue\n * @type {Array.callback}\n */\n this.tasks = [];\n /**\n * flag to indicate queue processing is active\n * @type {boolean}\n */\n this.isActive = false;\n /**\n * pacing for queue processing / rate limiting\n * @type {float}\n */\n this.jobIntervalMillis = 1000 / maxCallsPerSecond;\n /**\n * timestamp of start of last task\n * @type {time}\n */\n this.lastTaskTimestamp = null;\n /**\n * @type {string}\n */\n this.currentTaskTimeoutId = null;\n }\n\n /**\n * Processes the next task and returns the id of the time used to wait for the next invocation of this method.\n * @private\n */\n updateTaskSchedule() {\n if (this.logger && this.logger.debug) {\n this.logger.debug(\"PromiseQueue.updateTaskSchedule\");\n }\n\n if (this.isEmpty() || this.isStopped()) {\n return;\n }\n\n const queue = this;\n\n function processNextTask() {\n if (queue.logger && queue.logger.debug) {\n queue.logger.debug(\"PromiseQueue.processNextTask\", queue.tasks.length);\n }\n\n var nextTaskItem = queue.tasks.shift();\n if (nextTaskItem) {\n try {\n const result = nextTaskItem.task.call();\n\n if (queue.logger && queue.logger.debug) {\n queue.logger.debug(\n \"Resolving queued promise\",\n result,\n result instanceof Promise\n );\n }\n\n nextTaskItem.resolve(result);\n } catch (e) {\n queue.logger.info(\"rejecting queued promise result\", e);\n nextTaskItem.reject(e);\n }\n }\n }\n\n function scheduleNext(timeoutMillisOverride) {\n if (queue.logger && queue.logger.debug) {\n queue.logger.debug(\"PromiseQueue.scheduleNext\", timeoutMillisOverride);\n }\n\n if (queue.isEmpty()) {\n queue.currentTaskTimeoutId = null;\n return;\n }\n\n queue.currentTaskTimeoutId = setTimeout(function () {\n queue.lastTaskTimestamp = Date.now();\n processNextTask();\n\n scheduleNext(queue.jobIntervalMillis);\n }, timeoutMillisOverride);\n }\n\n if (this.currentTaskTimeoutId == null) {\n if (this.lastTaskTimestamp) {\n let passedTime = Date.now() - this.lastTaskTimestamp;\n if (passedTime > this.jobIntervalMillis) {\n scheduleNext(this.jobIntervalMillis);\n } else {\n scheduleNext(Math.max(0, this.jobIntervalMillis - passedTime));\n }\n } else {\n scheduleNext(0);\n }\n }\n };\n\n /**\n * Starts the task processing of this queue.\n *\n * If it is already started, then false will be returned.\n * If it is not yet started then the first task will be processed in the background and true will be returned.\n *\n * @return {boolean} true if this queue wasn't started before and now started to process tasks.\n */\n start() {\n if (this.isActive) {\n return false;\n }\n\n this.isActive = true;\n\n this.updateTaskSchedule();\n\n return true;\n };\n\n /**\n * Stops the processing of this queue.\n * @return true if the queue was started and is now stopped. false if it was already stopped.\n */\n stop() {\n if (this.isActive) {\n this.isActive = false;\n\n if (this.currentTaskTimeoutId) {\n clearInterval(this.currentTaskTimeoutId);\n this.currentTaskTimeoutId = null;\n this.lastTaskTimestamp = null;\n }\n }\n };\n\n getMaxCallsPerSecond() {\n return this.maxCallsPerSecond;\n };\n\n isStarted() {\n return this.isActive;\n };\n\n isStopped() {\n return !this.isStarted();\n };\n\n /**\n * @returns {boolean} true if this queue is currently empty, i.e. if it has no tasks in the queue.\n */\n isEmpty() {\n return this.tasks.length === 0;\n };\n\n /**\n * @returns {boolean} true if this queue has one or more entries.\n */\n isNotEmpty() {\n return !this.isEmpty();\n };\n\n /**\n * @param {function} task - The task to add.\n * @param {boolean} append - if the task should be appended or prepended to the list of queued tasks\n * @return {Promise} A promise which is resolved/rejected when the task was executed by the queue.\n */\n async add(task, append) {\n var self = this;\n\n var promise = new Promise(function (resolve, reject) {\n var newTaskItem = { task: task, resolve: resolve, reject: reject };\n\n if (self.isEmpty() || append) {\n self.tasks.push(newTaskItem);\n } else {\n self.tasks.unshift(newTaskItem);\n }\n });\n\n self.updateTaskSchedule();\n\n return promise;\n };\n\n /**\n * Appends a new task at the end of the queue.\n * @param {function} task - The task to perform. This function will be called with no arguments.\n * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue\n */\n async append(task) {\n return this.add(task, true);\n };\n\n /**\n * Adds a new task as first item in the queue.\n * @param task\n * @return {Promise} A promise which is resolved/rejected When the task was executed by the queue\n */\n async prepend(task) {\n return this.add(task, false);\n };\n\n /**\n * Removes the task from the qeueue. If the task is contained more than one time then all occurrences will be removed.\n * @param {function} task - The task to remove.\n * @return {number} - The number of items which were removed.\n */\n remove(task) {\n if (this.isEmpty()) {\n return 0;\n }\n\n var removedItems = 0;\n for (var i = this.tasks.length - 1; i >= 0; i--) {\n if (this.tasks[i].task === task) {\n this.tasks.splice(i, 1);\n removedItems++;\n }\n }\n\n return removedItems;\n };\n\n /**\n * @returns {Number} - The number of queued/waiting tasks in the queue.\n */\n getQueueSize() {\n return this.tasks.length;\n };\n\n};\n\nexport default PromiseQueue = new PromiseQueueClass(1, null);\n"],"names":[],"version":3,"file":"InventoryLogic.59be76a4.js.map"}
@@ -0,0 +1,375 @@
1
+ import {ISBN_LENGTH as $fefa9c41cb73ae0b$export$dbb3cd0a4caa6254, MARKUPS as $fefa9c41cb73ae0b$export$1bfdae073fb20e6c, PRODUCT as $fefa9c41cb73ae0b$export$e36553b0ff5db35a} from "./InventoryLogic.d27e84a7.js";
2
+ import {typedRecordFromChild as $9ab66828811feaa2$export$9536a88c96a1be48} from "./InventoryLogic.31f6d549.js";
3
+ import {GoogleAPIProductMap as $e409a6a48e9bf1c0$export$4059922dac929494} from "./InventoryLogic.b90f66ea.js";
4
+ import {JSONProductFeedToItemMapping as $63eb266a363bf697$export$8f68ab01093b41d6, squarespaceFeedTest as $63eb266a363bf697$export$c736243f342fb27b} from "./InventoryLogic.e03e6b07.js";
5
+ import {updateRecord as $lRpTb$updateRecord} from "@leaddreamer/firebase-wrapper";
6
+ import {Forms as $lRpTb$Forms, fillForm as $lRpTb$fillForm} from "@leaddreamer/staticforms";
7
+
8
+ /**
9
+ * Typedefs, constants, support functions and database operations related to Products
10
+ * @module Product
11
+ */
12
+
13
+
14
+
15
+
16
+
17
+ //////////////////////////////////////////////////////////////////////
18
+ // Constants
19
+ /**
20
+ * "recipe" related values - build-stage markups, product/project Flag, created/modified dates
21
+ * @typedef {object} Recipe_Data
22
+ * @property {module:Markups~Stage} markups
23
+ * @property {boolean} projectQ flag for product/project
24
+ * @property {dateTime} created
25
+ * @property {dateTime} modified
26
+ */ /**
27
+ * A list of attributes for a product
28
+ * @typedef {Array.String} AttributeList
29
+ */ /**
30
+ * Array of attribute name/value pairs
31
+ * @typedef {object} AttributeValue
32
+ * @property {string} attibuteName attribute name from attribute list
33
+ * @property {string} value value for the particular attribute
34
+ */ /**
35
+ * @typedef
36
+ */ /**
37
+ * Image Descriptor
38
+ * @typedef {object} ProductImage
39
+ * @property {string} altText alt text for the image - SEO etc
40
+ * @property {Array.string} availableFormats Available image sizes.
41
+ * @property {string} id unique id for this productImage
42
+ * @property {integer} orderIndex Position of the image in the product's image list.
43
+ * @property {object} originalSize Image size when first uploaded.
44
+ * @property {MetaData} seoOptions
45
+ * @property {string} URL Absolute URL of the hosted image.
46
+ */ /**
47
+ * a Brand Object
48
+ * @typedef {object} BrandObject
49
+ * @property {?string} Id Database Id of document (redundant for convenience)
50
+ * @property {?string} refPath if from database, full path to document
51
+ * @property {?AggregateRatingsValue} aggregateRating
52
+ * @property {?URL|ImageObject} logo
53
+ * @property {ReviewObject} review A review of the item. Supersedes reviews
54
+ * @property {text} slogan A slogan or motto associated with the item.
55
+ * @property {Name} name The name of the brand.
56
+ */ /**
57
+ * Currency Description ISO 4217 currency code
58
+ * @typedef {object} CurrencyDescription
59
+ * @property {string} currencyCode
60
+ * @property {integer} defaultFractionDigits
61
+ * @property {string} displayName
62
+ * @property {string} numericCodeAsString
63
+ * @property {string} symbol
64
+ */ /**
65
+ * Monetary Value Specification
66
+ * @typedef {object} MonetaryValue
67
+ * @property {CurrencyDescription} currencyDescription
68
+ * @property {decimal} value Decimal monetary value
69
+ * @property {Date} effectiveDate
70
+ */ /**
71
+ * Pricing Object
72
+ * @typedef {object} FullProductPricing
73
+ * @property {MonetaryValue} basePrice
74
+ * @property {boolean} onSale
75
+ * @property {MonetaryValue} salePrice
76
+ */ /**
77
+ * Dimensions Object
78
+ * @typedef {object} ProductDimensions
79
+ * @property {float} height
80
+ * @property {float} width
81
+ * @property {float} length
82
+ * @property {text} unit //​ProductDimensionsUnit
83
+ */ /**
84
+ * Price Object
85
+ * @typedef {object} PriceObject
86
+ *
87
+ */ /**
88
+ * Weight Object
89
+ * @typedef {object} ProductWeight
90
+ * @property {text} unit //​ProductWeightUnitEnum
91
+ * @property {float} value
92
+ */ /**
93
+ * Measurements of the variant when it's shipped. Present for PHYSICAL products only.
94
+ * @typedef {object} ProductMeasurements
95
+ * @property {ProductDimensions} dimensions
96
+ * @property {ProductWeight} weight
97
+ */ /**
98
+ * @typedef {object} QuantitativeValue
99
+ * @property {Boolean | Number | text | StructuredValue} value
100
+ * The value of a QuantitativeValue (including Observation) or property value node.
101
+ * * For QuantitativeValue and MonetaryAmount, the recommended type for values is 'Number'.
102
+ * * For PropertyValue, it can be 'Text', 'Number', 'Boolean', or 'StructuredValue'.
103
+ * * Use values from 0123456789 (Unicode 'DIGIT ZERO' (U+0030) to 'DIGIT NINE' (U+0039)) rather than superficially similar Unicode symbols.
104
+ * * Use '.' (Unicode 'FULL STOP' (U+002E)) rather than ',' to indicate a decimal point. Avoid using these symbols as a readability separator.
105
+ * @property {number} maxValue The upper value of some characteristic or property.
106
+ * @property {number} minValue The lower value of some characteristic or property.
107
+ * @property {?Text} unitText A string or text indicating the unit of measurement. Useful if you cannot provide a standard unit code for unitCode
108
+ * @property {?Text | URL} unitCode
109
+ * The unit of measurement given using the UN/CEFACT Common Code (3 characters) or a URL. Other codes than the UN/CEFACT Common Code may be used with a prefix followed by a colon
110
+ *
111
+ */ /**
112
+ * @typedef {object} SizeSpecification
113
+ * @property {Text} type "SizeSpecification"
114
+ * @property {QuantitativeValue} hasMeasurement
115
+ * @property {Array.SizeGroupEnumeration|SizeGroupEnumeration|Text} sizeGroup
116
+ * The size group (also known as "size type") for a product's size. Size groups are common in the fashion industry to define size
117
+ * segments and suggested audiences for wearable products. Multiple values can be combined, for example "men's big and tall", "petite maternity" or "regular".
118
+ * @property {Array.SizeSystemEnumeration|SizeSystemEnumeration|Text} sizeSystem
119
+ * The size system used to identify a product's size. Typically either a standard (for example, "GS1" or "ISO-EN13402"), country
120
+ * code (for example "US" or "JP"), or a measuring system (for example "Metric" or "Imperial").
121
+ * @property {QuantitativeValue} suggestedAge The age or age range for the intended audience or user, for example 3-12 months for infants, 1-5 years for toddlers.
122
+ * @property {GenderType|Text} suggestedGender The suggested gender of the intended user or audience, for example "male", "female", or "unisex".
123
+ * @property {QuantitativeValue} suggestedMeasurement A suggested range of body measurements for the intended audience or user, for example inseam between 32 and 34 inches or
124
+ * height between 170 and 190 cm. Typically found on a size chart for wearable products.
125
+ */ /**
126
+ * Available stock for the variant. Present for PHYSICAL products only.
127
+ * @typedef {object} ProductStock
128
+ * @property {integer} quantity
129
+ * @property {boolean} unlimited
130
+ */ /**
131
+ * Meta Information for SEO
132
+ * @typedef {object} MetaData
133
+ * @property {string} title
134
+ * @property {string} description
135
+ */ /**
136
+ * @typedef {"newborn" | "infant" | "toddler" | "kids" | "adult"} AgeGroupEnum
137
+ * @typedef {"male" | "female" | "unisex"} GenderEnum
138
+ */ /**
139
+ * Demographics characteristics
140
+ * @typedef {object} Demographics
141
+ * @property {boolean} adultOriented
142
+ * @property {AgeGroupEnum} age_group
143
+ * @property {GenderEnum} gender
144
+ */ /**
145
+ * List of product ID's for various platforms
146
+ * @typedef {object} PlatformIDs
147
+ * @property {Text} squarespaceId
148
+ * @property {Text} googleMerchantId
149
+ * @property {Text} shopifyId
150
+ */ /**
151
+ * Squarespace Specific Data
152
+ * @typedef {object} SquarespaceDataObject
153
+ * @property {Text} storePageId
154
+ */ /**
155
+ * List of Platform Specific Data
156
+ * @typedef {object} PlatformData
157
+ * @property {SquarespaceDataObject} squarespaceData
158
+ */ /**
159
+ * @typedef {object} AttributeValueObject
160
+ * @property {Text} condition
161
+ * @property {Array.Text} tags
162
+ * @property {Array.Text} colors
163
+ * @property {Array.Text} materials
164
+ * @property {Array.Text} patterns
165
+ * @property {string} custom_label_0
166
+ * @property {string} custom_label_1
167
+ * @property {string} custom_label_2
168
+ * @property {string} custom_label_3
169
+ * @property {string} custom_label_4
170
+ */ /**
171
+ * @typedef {object} VideoImage
172
+ * @property {URL} video_link
173
+ */ /**
174
+ * @typedef {object} VirtualModel
175
+ * @property {URL} virtual_model_link
176
+ */ /**
177
+ * Media Related Data
178
+ * @typedef {object} MediaObject
179
+ * @property {Array.ProductImage} images
180
+ * @property {VideoImage} video_image
181
+ * @property {VirtualModel} virtual_model
182
+ */ /**
183
+ * variant record (including inventory and pricing)
184
+ * @typedef {object} PhysicalProductVariant
185
+ * @property {PlatformIDs} platformIds
186
+ * @property {string} sku
187
+ * @property {ProductImage} image Image associated with this variant
188
+ * @property {FullProductPricing} pricing
189
+ * @property {ProductStock} stock
190
+ * @property {Array.AttributeValue} attributes array of attribute/value pairs for a variant
191
+ * @property {ProductMeasurements} shippingMeasurements
192
+ * @property {string} gtin Global Trade Item Number
193
+ * @property {string} mpn manufacturer part number
194
+ * @property {ProductMeasurements} productMeasurements
195
+ * @property {SizeSpecification} sizeSpecification
196
+ * @property {"in_stock"|"out_of_stock"|"preorder"|"backorder"} availability
197
+ * Accurately submit the product's availability and match the availability
198
+ * from your landing page, checkout pages, and structured data (for
199
+ * example, “in_stock” or “out_of_stock” in your Schema.org markup).
200
+ * If an item is out of stock, the price must still be clearly visible
201
+ * on the landing page.
202
+ * Provide the availability date [availability_date] attribute if you
203
+ * submit preorder [preorder] or backorder [backorder] as the availability value.
204
+ * @property {string|ISO8601} availability_date
205
+ * Use this attribute if your product's availability is set to preorder.
206
+ * Provide a value up to one year in the future.
207
+ * The availability date should also be added to the product’s landing
208
+ * page and be clear to your customers (for example, “May 6, 2023”).
209
+ * If an exact date can’t be provided, you can use an estimated date
210
+ * (for example, “May 2023”).
211
+ */ /**
212
+ * a product record
213
+ * @typedef {object} Product
214
+ * @property {?string} Id Database Id of document (redundant for convenience)
215
+ * @property {?string} refPath if from database, full path to document
216
+ * @property {PlatformIDs} platformIds
217
+ * @property {PlatformData} platformData
218
+ * @property {string} name name for the Product
219
+ * @property {string} short_name name for the Product
220
+ * @property {string} description Basic description of the product
221
+ * @property {string} short_description
222
+ * @property {string} google_product_category
223
+ * @property {?string} product_type "casual google_product_category"
224
+ * @property {Text|BrandObject} brand
225
+ * The brand(s) associated with a product or service, or the brand(s) maintained by an organization or business user.
226
+ * @property {Demographics} demographics
227
+ * @property {AttributeValueObject} attributes array of attribute/value pairs for a product
228
+ * @property {Recipe_Data} recipe pricing and fabrication data
229
+ * @property {MediaObject} mediaObject
230
+ * @property {MobileInfo} mobileInfo
231
+ * @property {boolean} isVisible
232
+ * @property {MetaData} seoOptions
233
+ * @property {string} URL
234
+ * @property {string} urlSlug
235
+ * @property {Array.string} variantAttributes
236
+ * @property {Array.PhysicalProductVariant} variants
237
+ */ /**
238
+ * @readonly
239
+ * @constant
240
+ * @type {Product}
241
+ * @default
242
+ */ const $e615241e8e7f6b5a$var$ProductDefault = {
243
+ platformIds: {
244
+ squarespaceId: null,
245
+ googleMerchantId: null,
246
+ shopifyId: null
247
+ },
248
+ platformData: {
249
+ squarespaceData: {
250
+ storePageId: null
251
+ }
252
+ },
253
+ name: null,
254
+ short_name: null,
255
+ description: null,
256
+ short_description: null,
257
+ google_product_category: null,
258
+ product_type: null,
259
+ brand: {
260
+ aggregate_rating: null,
261
+ logo: null,
262
+ review: {},
263
+ slogan: null,
264
+ name: null
265
+ },
266
+ demographics: {
267
+ adultOriented: false,
268
+ age_group: null,
269
+ gender: null
270
+ },
271
+ attributes: [],
272
+ recipe: {
273
+ markups: null,
274
+ projectQ: false,
275
+ created: null,
276
+ modified: null
277
+ },
278
+ mediaObject: {
279
+ images: [],
280
+ video_image: null,
281
+ virtual_model: null
282
+ },
283
+ mobileInfo: null,
284
+ isVisible: true,
285
+ type: "PHYSICAL",
286
+ seoOptions: {
287
+ title: null,
288
+ description: null
289
+ },
290
+ tags: [
291
+ ""
292
+ ],
293
+ materials: [
294
+ ""
295
+ ],
296
+ patterns: [
297
+ ""
298
+ ],
299
+ URL: null,
300
+ urlSlug: null,
301
+ variantAttributes: [],
302
+ variants: []
303
+ };
304
+ /**
305
+ * Form to create test data
306
+ * @readonly
307
+ * @constant
308
+ * @type {Product}
309
+ * @default
310
+ */ const $e615241e8e7f6b5a$var$ProductDataForm = {
311
+ Id: `string.uuid`,
312
+ refPath: null,
313
+ name: `commerce.product`,
314
+ description: `commerce.productDescription`,
315
+ sku: `commerce.isbn:${(0, $fefa9c41cb73ae0b$export$dbb3cd0a4caa6254)}`,
316
+ markups: `subrecord:${(0, $fefa9c41cb73ae0b$export$1bfdae073fb20e6c)}`,
317
+ projectQ: `checkbox`
318
+ };
319
+ /**
320
+ * Form to enter MINIMAL product data to start creation
321
+ * @readonly
322
+ * @constant
323
+ * @type {Product}
324
+ * @default
325
+ */ const $e615241e8e7f6b5a$var$ProductDefaultForm = {
326
+ Id: `hidden`,
327
+ refPath: `hidden`,
328
+ name: "text",
329
+ description: "textarea",
330
+ sku: "text"
331
+ };
332
+ (0, $lRpTb$Forms).Base[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$ProductDefault;
333
+ (0, $lRpTb$Forms).BaseForm[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$ProductDefaultForm;
334
+ (0, $lRpTb$Forms).CreateForm[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$ProductDefaultForm;
335
+ (0, $lRpTb$Forms).Data[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$ProductDataForm;
336
+ (0, $lRpTb$Forms).Summarize[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$summarizeProduct;
337
+ (0, $lRpTb$Forms).Save[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = $e615241e8e7f6b5a$var$updateProduct;
338
+ (0, $lRpTb$Forms).SearchBy[0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a] = "name";
339
+ async function $e615241e8e7f6b5a$export$9c734a715e6666d0() {
340
+ //get a blank Product Record
341
+ //write it to database, saving reference
342
+ //copy user stages to product stages
343
+ //We return the product information - but most applications will use database listeners
344
+ }
345
+ //////////////////////////////////////////////////////////////////////
346
+ // record operations
347
+ /**
348
+ * writes record back to database. Assumes only Id is valid
349
+ * @param {Product} product a partially-populated product record for updates
350
+ * @param {User} user minimal record of user this product belongs to
351
+ * @returns {promise.LineItem} a copy of the data written
352
+ */ async function $e615241e8e7f6b5a$var$updateProduct(product, user = null) {
353
+ if (!(product?.refPath || user?.refPath)) {
354
+ console.log("no product specified to save LineItem");
355
+ //no root products
356
+ return null;
357
+ }
358
+ return (0, $lRpTb$updateRecord)((0, $lRpTb$fillForm)(product, (0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a)), user, (0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a));
359
+ }
360
+ //////////////////////////////////////////////////////////////////////
361
+ // utilities
362
+ /**
363
+ * Returns a standardized formatted name string
364
+ * @param {Unit}
365
+ * @returns {string} formatted name string
366
+ */ function $e615241e8e7f6b5a$var$summarizeProduct(product) {
367
+ return `${product.name} ${product.description}`;
368
+ }
369
+ function $e615241e8e7f6b5a$export$d4a471daa895146b(child) {
370
+ return (0, $9ab66828811feaa2$export$9536a88c96a1be48)(child, (0, $fefa9c41cb73ae0b$export$e36553b0ff5db35a));
371
+ }
372
+
373
+
374
+ export {$e615241e8e7f6b5a$export$9c734a715e6666d0 as createProduct, $e615241e8e7f6b5a$export$d4a471daa895146b as makeProductFromChild, $e409a6a48e9bf1c0$export$4059922dac929494 as GoogleAPIProductMap, $63eb266a363bf697$export$8f68ab01093b41d6 as JSONProductFeedToItemMapping, $63eb266a363bf697$export$c736243f342fb27b as squarespaceFeedTest};
375
+ //# sourceMappingURL=InventoryLogic.70925a32.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["business/Product/index.js"],"sourcesContent":["/**\n * Typedefs, constants, support functions and database operations related to Products\n * @module Product\n */\nimport { updateRecord } from \"@leaddreamer/firebase-wrapper\";\nimport { Forms, fillForm } from \"@leaddreamer/staticforms\";\n\nimport { PRODUCT, MARKUPS, ISBN_LENGTH } from \"../boilerplate/index.js\";\nimport { typedRecordFromChild } from \"../Utilities/index.js\"\n\n//////////////////////////////////////////////////////////////////////\n// Constants\n\n/**\n * \"recipe\" related values - build-stage markups, product/project Flag, created/modified dates\n * @typedef {object} Recipe_Data\n * @property {module:Markups~Stage} markups\n * @property {boolean} projectQ flag for product/project\n * @property {dateTime} created\n * @property {dateTime} modified\n */\n\n/**\n * A list of attributes for a product\n * @typedef {Array.String} AttributeList\n */\n\n/**\n * Array of attribute name/value pairs\n * @typedef {object} AttributeValue\n * @property {string} attibuteName attribute name from attribute list\n * @property {string} value value for the particular attribute\n */\n\n/**\n * @typedef\n */\n\n/**\n * Image Descriptor\n * @typedef {object} ProductImage\n * @property {string} altText alt text for the image - SEO etc\n * @property {Array.string} availableFormats Available image sizes.\n * @property {string} id unique id for this productImage\n * @property {integer} orderIndex Position of the image in the product's image list.\n * @property {object} originalSize Image size when first uploaded.\n * @property {MetaData} seoOptions\n * @property {string} URL Absolute URL of the hosted image.\n */\n\n/**\n * a Brand Object\n * @typedef {object} BrandObject\n * @property {?string} Id Database Id of document (redundant for convenience)\n * @property {?string} refPath if from database, full path to document\n * @property {?AggregateRatingsValue} aggregateRating\n * @property {?URL|ImageObject} logo\n * @property {ReviewObject} review A review of the item. Supersedes reviews\n * @property {text} slogan A slogan or motto associated with the item.\n * @property {Name} name The name of the brand.\n */\n\n/**\n * Currency Description ISO 4217 currency code\n * @typedef {object} CurrencyDescription\n * @property {string} currencyCode\n * @property {integer} defaultFractionDigits\n * @property {string} displayName\n * @property {string} numericCodeAsString\n * @property {string} symbol\n */\n\n/**\n * Monetary Value Specification\n * @typedef {object} MonetaryValue\n * @property {CurrencyDescription} currencyDescription\n * @property {decimal} value Decimal monetary value\n * @property {Date} effectiveDate\n */\n\n/**\n * Pricing Object\n * @typedef {object} FullProductPricing\n * @property {MonetaryValue} basePrice\n * @property {boolean} onSale\n * @property {MonetaryValue} salePrice\n */\n\n/**\n * Dimensions Object\n * @typedef {object} ProductDimensions\n * @property {float} height \n * @property {float} width \n * @property {float} length \n * @property {text} unit //​ProductDimensionsUnit\n */\n\n/**\n * Price Object\n * @typedef {object} PriceObject\n * \n */\n\n/**\n * Weight Object\n * @typedef {object} ProductWeight\n * @property {text} unit //​ProductWeightUnitEnum\n * @property {float} value\n */\n\n/**\n * Measurements of the variant when it's shipped. Present for PHYSICAL products only.\n * @typedef {object} ProductMeasurements\n * @property {ProductDimensions} dimensions\n * @property {ProductWeight} weight\n */\n\n/**\n * @typedef {object} QuantitativeValue\n * @property {Boolean | Number | text | StructuredValue} value\n * The value of a QuantitativeValue (including Observation) or property value node.\n * * For QuantitativeValue and MonetaryAmount, the recommended type for values is 'Number'.\n * * For PropertyValue, it can be 'Text', 'Number', 'Boolean', or 'StructuredValue'.\n * * Use values from 0123456789 (Unicode 'DIGIT ZERO' (U+0030) to 'DIGIT NINE' (U+0039)) rather than superficially similar Unicode symbols.\n * * Use '.' (Unicode 'FULL STOP' (U+002E)) rather than ',' to indicate a decimal point. Avoid using these symbols as a readability separator.\n * @property {number} maxValue The upper value of some characteristic or property.\n * @property {number} minValue The lower value of some characteristic or property.\n * @property {?Text} unitText A string or text indicating the unit of measurement. Useful if you cannot provide a standard unit code for unitCode\n * @property {?Text | URL} unitCode \n * The unit of measurement given using the UN/CEFACT Common Code (3 characters) or a URL. Other codes than the UN/CEFACT Common Code may be used with a prefix followed by a colon\n * \n */\n\n/**\n * @typedef {object} SizeSpecification\n * @property {Text} type \"SizeSpecification\"\n * @property {QuantitativeValue} hasMeasurement\n * @property {Array.SizeGroupEnumeration|SizeGroupEnumeration|Text} sizeGroup\n * The size group (also known as \"size type\") for a product's size. Size groups are common in the fashion industry to define size\n * segments and suggested audiences for wearable products. Multiple values can be combined, for example \"men's big and tall\", \"petite maternity\" or \"regular\".\n * @property {Array.SizeSystemEnumeration|SizeSystemEnumeration|Text} sizeSystem\n * The size system used to identify a product's size. Typically either a standard (for example, \"GS1\" or \"ISO-EN13402\"), country\n * code (for example \"US\" or \"JP\"), or a measuring system (for example \"Metric\" or \"Imperial\").\n * @property {QuantitativeValue} suggestedAge The age or age range for the intended audience or user, for example 3-12 months for infants, 1-5 years for toddlers.\n * @property {GenderType|Text} suggestedGender The suggested gender of the intended user or audience, for example \"male\", \"female\", or \"unisex\".\n * @property {QuantitativeValue} suggestedMeasurement A suggested range of body measurements for the intended audience or user, for example inseam between 32 and 34 inches or\n * height between 170 and 190 cm. Typically found on a size chart for wearable products.\n */\n\n/**\n * Available stock for the variant. Present for PHYSICAL products only.\n * @typedef {object} ProductStock\n * @property {integer} quantity\n * @property {boolean} unlimited\n */\n\n/**\n * Meta Information for SEO\n * @typedef {object} MetaData\n * @property {string} title\n * @property {string} description\n */\n\n/**\n * @typedef {\"newborn\" | \"infant\" | \"toddler\" | \"kids\" | \"adult\"} AgeGroupEnum\n * @typedef {\"male\" | \"female\" | \"unisex\"} GenderEnum\n */\n\n/**\n * Demographics characteristics\n * @typedef {object} Demographics\n * @property {boolean} adultOriented\n * @property {AgeGroupEnum} age_group\n * @property {GenderEnum} gender\n */\n\n/**\n * List of product ID's for various platforms\n * @typedef {object} PlatformIDs\n * @property {Text} squarespaceId\n * @property {Text} googleMerchantId\n * @property {Text} shopifyId\n */\n\n/**\n * Squarespace Specific Data\n * @typedef {object} SquarespaceDataObject\n * @property {Text} storePageId\n */\n\n/**\n * List of Platform Specific Data\n * @typedef {object} PlatformData\n * @property {SquarespaceDataObject} squarespaceData\n */\n\n/**\n * @typedef {object} AttributeValueObject\n * @property {Text} condition\n * @property {Array.Text} tags\n * @property {Array.Text} colors\n * @property {Array.Text} materials\n * @property {Array.Text} patterns\n * @property {string} custom_label_0\n * @property {string} custom_label_1\n * @property {string} custom_label_2\n * @property {string} custom_label_3\n * @property {string} custom_label_4\n */\n\n/**\n * @typedef {object} VideoImage\n * @property {URL} video_link\n */\n\n/**\n * @typedef {object} VirtualModel\n * @property {URL} virtual_model_link\n */\n\n/**\n * Media Related Data\n * @typedef {object} MediaObject\n * @property {Array.ProductImage} images\n * @property {VideoImage} video_image\n * @property {VirtualModel} virtual_model \n */\n\n/**\n * variant record (including inventory and pricing)\n * @typedef {object} PhysicalProductVariant\n * @property {PlatformIDs} platformIds\n * @property {string} sku\n * @property {ProductImage} image Image associated with this variant\n * @property {FullProductPricing} pricing\n * @property {ProductStock} stock\n * @property {Array.AttributeValue} attributes array of attribute/value pairs for a variant\n * @property {ProductMeasurements} shippingMeasurements\n * @property {string} gtin Global Trade Item Number\n * @property {string} mpn manufacturer part number\n * @property {ProductMeasurements} productMeasurements\n * @property {SizeSpecification} sizeSpecification\n * @property {\"in_stock\"|\"out_of_stock\"|\"preorder\"|\"backorder\"} availability\n * Accurately submit the product's availability and match the availability\n * from your landing page, checkout pages, and structured data (for\n * example, “in_stock” or “out_of_stock” in your Schema.org markup).\n * If an item is out of stock, the price must still be clearly visible\n * on the landing page.\n * Provide the availability date [availability_date] attribute if you\n * submit preorder [preorder] or backorder [backorder] as the availability value.\n * @property {string|ISO8601} availability_date\n * Use this attribute if your product's availability is set to preorder.\n * Provide a value up to one year in the future.\n * The availability date should also be added to the product’s landing\n * page and be clear to your customers (for example, “May 6, 2023”).\n * If an exact date can’t be provided, you can use an estimated date\n * (for example, “May 2023”).\n */\n\n/**\n * a product record\n * @typedef {object} Product\n * @property {?string} Id Database Id of document (redundant for convenience)\n * @property {?string} refPath if from database, full path to document\n * @property {PlatformIDs} platformIds\n * @property {PlatformData} platformData\n * @property {string} name name for the Product\n * @property {string} short_name name for the Product\n * @property {string} description Basic description of the product\n * @property {string} short_description\n * @property {string} google_product_category\n * @property {?string} product_type \"casual google_product_category\"\n * @property {Text|BrandObject} brand\n * The brand(s) associated with a product or service, or the brand(s) maintained by an organization or business user.\n * @property {Demographics} demographics\n * @property {AttributeValueObject} attributes array of attribute/value pairs for a product\n * @property {Recipe_Data} recipe pricing and fabrication data\n * @property {MediaObject} mediaObject\n * @property {MobileInfo} mobileInfo\n * @property {boolean} isVisible\n * @property {MetaData} seoOptions\n * @property {string} URL\n * @property {string} urlSlug\n * @property {Array.string} variantAttributes\n * @property {Array.PhysicalProductVariant} variants\n */\n\n/**\n * @readonly\n * @constant\n * @type {Product}\n * @default\n */\nconst ProductDefault = {\n platformIds: {\n squarespaceId: null,\n googleMerchantId: null,\n shopifyId: null\n },\n platformData: {\n squarespaceData: {\n storePageId: null\n }\n },\n name: null,\n short_name: null,\n description: null,\n short_description: null,\n google_product_category: null,\n product_type: null,\n brand: {\n aggregate_rating: null,\n logo: null,\n review: {},\n slogan: null,\n name: null\n },\n demographics: {\n adultOriented: false,\n age_group: null,\n gender: null\n },\n attributes: [],\n recipe: {\n markups: null,\n projectQ: false,\n created: null,\n modified: null,\n },\n mediaObject: {\n images: [],\n video_image: null,\n virtual_model: null\n },\n mobileInfo: null,\n isVisible: true,\n type: \"PHYSICAL\",\n seoOptions: {\n title: null,\n description: null,\n },\n tags: [\"\"],\n materials: [\"\"],\n patterns: [\"\"],\n URL: null,\n urlSlug: null,\n variantAttributes: [],\n variants: []\n};\n\n/**\n * Form to create test data\n * @readonly\n * @constant\n * @type {Product}\n * @default\n */\nconst ProductDataForm = {\n Id: `string.uuid`,\n refPath: null,\n name: `commerce.product`,\n description: `commerce.productDescription`,\n sku: `commerce.isbn:${ISBN_LENGTH}`,\n markups: `subrecord:${MARKUPS}`,\n projectQ: `checkbox`\n};\n\n/**\n * Form to enter MINIMAL product data to start creation\n * @readonly\n * @constant\n * @type {Product}\n * @default\n */\nconst ProductDefaultForm = {\n Id: `hidden`,\n refPath: `hidden`,\n name: \"text\",\n description: \"textarea\",\n sku: \"text\",\n};\n\nForms.Base[PRODUCT] = ProductDefault;\nForms.BaseForm[PRODUCT] = ProductDefaultForm;\nForms.CreateForm[PRODUCT] = ProductDefaultForm;\nForms.Data[PRODUCT] = ProductDataForm;\nForms.Summarize[PRODUCT] = summarizeProduct;\nForms.Save[PRODUCT] = updateProduct;\nForms.SearchBy[PRODUCT] = \"name\";\n\n//////////////////////////////////////////////////////////////////////\n// business operations\n\n/**\n * Creates a new Blank Product\n * @param {UserObject} user minimal record of user this commodity belongs to (if any)\n * @returns {Promise<void>}\n */\n\nexport async function createProduct() {\n //get a blank Product Record\n //write it to database, saving reference\n //copy user stages to product stages\n //We return the product information - but most applications will use database listeners\n};\n\n\n//////////////////////////////////////////////////////////////////////\n// record operations\n\n/**\n * writes record back to database. Assumes only Id is valid\n * @param {Product} product a partially-populated product record for updates\n * @param {User} user minimal record of user this product belongs to\n * @returns {promise.LineItem} a copy of the data written\n */\nasync function updateProduct(product, user = null) {\n if (!(product?.refPath || user?.refPath)) {\n console.log(\"no product specified to save LineItem\");\n //no root products\n return null;\n };\n\n return updateRecord(\n fillForm(product, PRODUCT), //saves only APPROPRIATE fields -does NOT populate missing fields\n user,\n PRODUCT\n );\n}\n\n//////////////////////////////////////////////////////////////////////\n// utilities\n\n/**\n * Returns a standardized formatted name string\n * @param {Unit}\n * @returns {string} formatted name string\n */\nfunction summarizeProduct(product) {\n return `${product.name} ${product.description}`;\n}\n/**\n * @param {Record} child a record assumed to be a leaf/child\n * @returns {Record}\n */\nexport function makeProductFromChild(child) {\n return typedRecordFromChild(child, PRODUCT);\n}\n\nexport * from \"./GoogleMerchantAPI.js\";\nexport * from \"./Squarespace.js\"\n"],"names":[],"version":3,"file":"InventoryLogic.70925a32.js.map"}