Develop and implement the 'gas-fakes' project, emulating Google Apps Script (GAS) functionality using Node.js.
This skill enables the agent to assist in the development of the gas-fakes project. The primary objective is to emulate Google Apps Script (GAS) behavior using Node.js and Google APIs, allowing Apps Script code to run in a local Node.js environment.
Before implementing, verify the specifications of the target Google Apps Script classes and methods. Ensure that the functionality you are about to build aligns with real GAS behavior.
Generate Node.js code that maps GAS methods to the corresponding Google Cloud APIs.
src/ directory to understand the current architecture.You must verify your implementation by writing and executing test scripts.
test/ directory.Whenever you create a new test script (e.g., test/testnewfeature.js) or significantly modify an existing one:
test/test.js. This includes adding the import statement and the test call within the testFakes() function..agents/workflows/ directory (specifically test.md) to ensure you are following the latest project-specific procedures.[CRITICAL INSTRUCTION]
The gas-fakes project is complex, and bridging Node.js with GAS involves many hidden constraints, specific architectural patterns, and potential errors. You are required to continuously learn and autonomously evolve this SKILL.
SKILL.md file (by adding, deleting, or modifying content) to document the newly acquired knowledge. If necessary, also create or update sample scripts, helper templates, or explanatory Markdown files in the project.Jdbc.getCloudSqlConnection() for PostgreSQL in Apps Script; it only works for MySQL. You MUST use standard Jdbc.getConnection().https://www.gstatic.com/ipranges/goog.json) in your Cloud SQL instance's Authorized Networks to allow connection.Jdbc.getConnection() has strict requirements for Postgres when hosted on Google Cloud:
ssl=true as a query parameter (e.g., jdbc:postgresql://<IP>:<PORT>/<DB>?ssl=true). The Java driver on Apps Script throws The following connection properties are unsupported: ssl.Jdbc.getConnection("jdbc:postgresql://<IP>:<PORT>/<DB>", rawUser, rawPass).Jdbc.getCloudSqlConnection(url, user, password) for MySQL on Google Cloud using the specific protocol format jdbc:google:mysql://[INSTANCE_CONNECTION_NAME]/[DATABASE_NAME].mysql2 driver cannot directly resolve Google Cloud SQL instance names containing colons (e.g. project:region:instance). To emulate Jdbc.getCloudSqlConnection locally without the Cloud SQL Auth Proxy, you must:
gcloud sql instances describe [INSTANCE_NAME] command to dynamically resolve the instance's public IP address.new URL()), as it will fail. Ensure the string is formatted as [protocol://]user:pass@host/db or parse the parameters manually.JdbcResultSet.getBigDecimal() returns a JdbcBigDecimal object on live GAS. This is a Java proxy that may NOT expose standard Java methods like doubleValue(). To get a numeric value safely across all platforms, use Number(val) or parseFloat(val.toString()).JdbcResultSet methods (e.g., getString()) support both 1-indexed integers and string column labels. Ensure the fake implementation resolves both using findColumn.;) in strings passed to prepareStatement. Some drivers (e.g., MySQL on GAS) may fail to recognize ? placeholders if a semicolon is present.Jdbc.getCloudSqlConnection.Jdbc.getConnection.Jdbc.getConnection.prepareStatement method may fail with Parameter index out of range (1 > 0) because the older GAS driver cannot parse placeholders in modern MySQL 8+ protocols.
try/catch fallback to standard Statement.execute() with manually escaped values if prepareStatement fails for MySQL backends.TextDecoder, TextEncoder, fetch, setTimeout, and ReadableStream.const str = Utilities.newBlob(bytes).getDataAsString();
https://www.gstatic.com/ipranges/goog.json) in your Cloud SQL instance's Authorized Networks to allow connection.if (ScriptApp.isFake).if (ScriptApp.isFake) blocks. Whenever possible, verify behaviors and expected return values using the Public API.
__fakeObjectType === 'JdbcBlob', simply call blob.length() or blob.getBytes(). If these work, the object is implicitly of the correct type.if (ScriptApp.isFake) makes the test suite harder to maintain and reduces confidence that the same test is actually verifying the same behavior on both platforms.getBlob() requires an OID large object column — not BYTEA: Calling rs.getBlob(n) on a TEXT or BYTEA column throws "Bad value for type long : <value>" because the PostgreSQL JDBC driver's getBlob() internally calls getLong() to retrieve a PostgreSQL large object OID from pg_largeobject. For inline binary data, use getBytes() / getBinaryStream() instead. MySQL's BLOB type maps directly and works with getBlob(). In practice: never test getBlob() against a PostgreSQL/CockroachDB backend in a parity test.createStatement() returns FORWARD_ONLY: Plain conn.createStatement() returns a forward-only cursor. Navigation methods last(), first(), absolute(), relative(), previous(), beforeFirst(), afterLast() all throw "Operation requires a scrollable ResultSet". Use conn.createStatement(1004, 1007) (TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY) to get a scrollable cursor. In the fake, these parameters are accepted but advisory — results are already buffered.getFloat() is 32-bit: GAS rs.getFloat() returns an IEEE 754 single-precision float. 1.1 becomes 1.100000023841858. Always compare with Math.fround(expected). The fake applies Math.fround() accordingly.getDouble() is 64-bit: Unlike the above, rs.getDouble() returns a full 64-bit double.gcloud, Google Cloud IAM may take several seconds to propagate changes. Subsequent commands referencing the new entity may fail with "not found" errors if executed too quickly.gcloud iam commands that depend on recently created resources. A simple busy-wait or execSync to a sleep command can be used in a synchronous CLI environment to ensure portability.while (Date.now() - start < delay)) is often more reliable than depending on OS-specific sleep or timeout commands when running inside a CLI tool.SKILL.md when new knowledge is extracted and crystallized.37:["$","$L41",null,{"content":"$42","frontMatter":{"name":"gas-fakes-dev","description":"Develop and implement the 'gas-fakes' project, emulating Google Apps Script (GAS) functionality using Node.js."}}]