apps-script-utils (Українська) 2.1.1 Help

Середовище виконання Apps Script

Бібліотека одна, але її функції працюють не в тих самих місцях. Від того, по який бік межі стоїть функція, залежить, чи вдасться покрити її модульним тестом і чи коштує вона звернення до сервісу.

Два роди функцій

Незалежні від середовища функції — це звичайний JavaScript. Вони приймають значення, повертають значення й ніколи не лізуть у глобальні об'єкти. До цього роду належить усе в lang, net, json, html, time та exception, а також ті частини appsscript, які лише перетворюють рядки й прості об'єкти: розбірники нотації A1, конвертери літер стовпців і порівняння GridRange.

Прив'язані до сервісів функції самі звертаються до глобального сервісу. Вони працюють лише всередині скрипта з виданими правами і в Node не працюють зовсім. Сьогодні це весь список:

Функція

До якого глобального об'єкта звертається

isAdmin

Session.getActiveUser, AdminDirectory.Users

checkMultipleAccount

Session.getEffectiveUser

getSheetById

SpreadsheetApp.getActiveSpreadsheet, якщо таблицю не передано

getSheetByIndex

SpreadsheetApp.getActiveSpreadsheet, якщо таблицю не передано

highlightHtml

SpreadsheetApp.newTextStyle, SpreadsheetApp.newRichTextValue

convertRichTextToHtml

Utilities.formatString

Усе інше в appsscript приймає об'єкт сервісу аргументом: appendRows пише в той Sheet, який ви йому дали, а requireSheet розглядає передане значення, а не здобуває його сам. Таким функціям живий об'єкт сервісу потрібен, щоб принести користь, але шукати його вони не йдуть — саме це й дозволяє підмінити їх у тесті.

Пакетність на межі

Кожне звернення до сервісу — це похід туди й назад, і Apps Script зараховує його до ліміту часу виконання. Помічники для запису існують саме тому: appendRows робить один виклик незалежно від кількості рядків, а цикл із appendRow — по виклику на рядок.

// Один виклик сервісу. appendRows(sheet, rows); // По виклику на рядок; годиться хіба що для одного запису. for (const row of rows) { appendRow(sheet, row); }

Те саме міркування слушне й для перевірок. Перевіряйте форму даних до того, як вони дійдуть до сервісу, а не після:

import { IllegalArgumentException, appendRows, isConsistent2DArray } from "apps-script-utils"; if (!isConsistent2DArray(rows)) { throw new IllegalArgumentException("every row must have the same number of columns"); } appendRows(sheet, rows);

Range.setValues() відхиляє рваний масив, але збій надходить від сервісу, не повідомляючи, який рядок винен. Перевірка заздалегідь перетворює це на помилку, якою ви керуєте.

Квоти

Apps Script стежить за квотами на скрипт і на акаунт: час виконання, виклики кожного сервісу, тригери, запити URL та інше. Бібліотека їх не підвищує й не рахує — вона лише зменшує кількість звернень. Два наслідки, які варто тримати в голові:

  • Функція, що не залежить від середовища, не коштує нічого, крім процесорного часу. Переносьте перевірки й перетворення на цей бік межі всюди, де можете.

  • Функція, прив'язана до сервісу, може впасти з причин, не пов'язаних з аргументами. Якщо isAdmin кидає AdminDirectoryException, це означає, що розширений сервіс Admin SDK не увімкнено в проєкті, а не що користувач не адміністратор.

Чинні ліміти опубліковано в Quotas for Google Services.

Тестування

Набір тестів працює на Vitest у Node, де глобальних об'єктів Apps Script немає зовсім. Саме тому поділ і важливий:

  • Незалежні від середовища функції покрито модульними тестами напряму. Їх більшість у test/, імпорт іде через аліас @/.

  • Прив'язані до сервісів — ні. Виклик у Node падає з ReferenceError на SpreadsheetApp чи іншому глобальному об'єкті, тому їх перевіряють руками на справжньому проєкті скрипта. Функції, які просто приймають Sheet, стоять посередині: їх можна прогнати з об'єктом-заглушкою тієї самої форми, що й клас сервісу.

npm test # прогнати набір один раз npm run dev # режим спостереження

Коли додаєте функцію, перше питання до її будови таке: чи може вона приймати об'єкт сервісу параметром замість того, щоб здобувати його? Якщо може — вона стає тестованою, а код, що викликає, зберігає контроль над кількістю звернень до сервісу.

Як писати для обох боків

Бібліотека розрахована на середовище V8. Дві звички тримають код робочим по обидва боки межі:

  • Приймайте об'єкти сервісів аргументами. appendRows(sheet, rows) працює всюди, звідки б не прийшов Sheet; функція, яка всередині кличе SpreadsheetApp.getActiveSpreadsheet(), працює лише у прив'язаному скрипті.

  • Відокремлюйте розбір від здобування. parseA1Notation — чиста робота з рядками, вона запускається в Node і тому покрита тестами; getSheetById — той самий пошук, але виражений через активну таблицю, і тестами не покритий. Явна передача таблиці — getSheetById(id, spreadsheet) — повертає його назад за межу.

23 September 2026

Цю документацію згенеровано нейромережею (Claude) на основі вихідного коду бібліотеки.