@substrio/cli 0.0.0-stage → 0.1.0
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.
- package/LICENSE +177 -0
- package/README.md +66 -2
- package/bin/substrio.mjs +91 -0
- package/package.json +44 -4
- package/src/api.mjs +107 -0
- package/src/apply.mjs +204 -0
- package/src/blobs.mjs +102 -0
- package/src/cli.mjs +405 -0
- package/src/collections.mjs +701 -0
- package/src/command-table.mjs +436 -0
- package/src/commands/bundle.mjs +369 -0
- package/src/commands/count.mjs +39 -0
- package/src/commands/deploy.mjs +488 -0
- package/src/commands/dev.mjs +246 -0
- package/src/commands/env.mjs +115 -0
- package/src/commands/files.mjs +172 -0
- package/src/commands/git.mjs +195 -0
- package/src/commands/groups-runtime.mjs +227 -0
- package/src/commands/groups.mjs +417 -0
- package/src/commands/history.mjs +374 -0
- package/src/commands/import.mjs +506 -0
- package/src/commands/init.mjs +175 -0
- package/src/commands/key.mjs +172 -0
- package/src/commands/login.mjs +167 -0
- package/src/commands/logs.mjs +285 -0
- package/src/commands/mcp-config.mjs +102 -0
- package/src/commands/op.mjs +265 -0
- package/src/commands/open.mjs +35 -0
- package/src/commands/push.mjs +199 -0
- package/src/commands/signup.mjs +164 -0
- package/src/commands/site.mjs +129 -0
- package/src/commands/skills.mjs +177 -0
- package/src/commands/status.mjs +78 -0
- package/src/commands/tenants.mjs +172 -0
- package/src/commands/test.mjs +167 -0
- package/src/commands/tools.mjs +63 -0
- package/src/commands/versions.mjs +293 -0
- package/src/config.mjs +569 -0
- package/src/documents.mjs +139 -0
- package/src/function-build.mjs +273 -0
- package/src/identity.mjs +248 -0
- package/src/jsonfile.mjs +22 -0
- package/src/live-move.mjs +267 -0
- package/src/local/args.mjs +58 -0
- package/src/local/reload.mjs +408 -0
- package/src/local/server.mjs +291 -0
- package/src/local/watch.mjs +175 -0
- package/src/manifest.mjs +591 -0
- package/src/ops.mjs +265 -0
- package/src/readers.mjs +416 -0
- package/src/sdk.mjs +26 -0
- package/src/settings.mjs +117 -0
- package/src/testing/app.mjs +507 -0
- package/src/testing/env.mjs +35 -0
- package/src/testing/index.mjs +11 -0
- package/src/testing/types.mjs +55 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract between `substrio test` and the test files it runs: the server to
|
|
3
|
+
* use and the app to apply. The master key is never in the environment (a child
|
|
4
|
+
* process's environment is readable); it is in a 0600 file this names.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { TestError, TestErrorCode } from './types.mjs';
|
|
8
|
+
|
|
9
|
+
/** The environment variables of the contract. */
|
|
10
|
+
export const TestEnv = Object.freeze({
|
|
11
|
+
URL: 'SUBSTRIO_TEST_URL',
|
|
12
|
+
KEY_FILE: 'SUBSTRIO_TEST_KEY_FILE',
|
|
13
|
+
APP_DIR: 'SUBSTRIO_TEST_APP_DIR',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/** Reads the contract from `env`; a TestError outside `substrio test`. Returns {url, keyFile, appDir}. */
|
|
17
|
+
export function readTestEnv(env = process.env) {
|
|
18
|
+
const missing = Object.values(TestEnv).filter((name) => !env[name]);
|
|
19
|
+
if (missing.length > 0) {
|
|
20
|
+
throw new TestError(`startApp() works under \`substrio test\`, which sets ${missing.join(', ')}; run this file with \`substrio test\``, TestErrorCode.NOT_UNDER_SUBSTRIO_TEST);
|
|
21
|
+
}
|
|
22
|
+
return { url: env[TestEnv.URL], keyFile: env[TestEnv.KEY_FILE], appDir: env[TestEnv.APP_DIR] };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set by a node test runner in every process it starts. `substrio test` starts a run
|
|
27
|
+
* of its own, which with it inherited would skip every file as a nested run.
|
|
28
|
+
*/
|
|
29
|
+
const NODE_TEST_CONTEXT = 'NODE_TEST_CONTEXT';
|
|
30
|
+
|
|
31
|
+
/** The environment a `substrio test` child gets: `base` without a parent run's context, plus the contract. */
|
|
32
|
+
export function testEnvFor({ url, keyFile, appDir }, base = process.env) {
|
|
33
|
+
const { [NODE_TEST_CONTEXT]: _parentRun, ...own } = base;
|
|
34
|
+
return { ...own, [TestEnv.URL]: url, [TestEnv.KEY_FILE]: keyFile, [TestEnv.APP_DIR]: appDir };
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @substrio/cli/test: what a test file of an app imports.
|
|
3
|
+
*
|
|
4
|
+
* import { startApp, fixture, Level } from '@substrio/cli/test';
|
|
5
|
+
*
|
|
6
|
+
* Run the files with `substrio test`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { startApp, fixture, Fixture, TestApp, Run, FunctionRef, TestCollection, TestDb, TestLogs, FetchStubs, FetchCall, TestTenantClock } from './app.mjs';
|
|
10
|
+
export { TestEnv } from './env.mjs';
|
|
11
|
+
export { CallOutcome, ClockMode, HttpMethod, Level, PathMatch, RunOutcome, TestError, TestErrorCode, TriggerKind } from './types.mjs';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed sets of the test API (`@substrio/cli/test`) as frozen enums, and
|
|
3
|
+
* the typed error of a misused harness. Strings exist only on the wire; a test
|
|
4
|
+
* names a level, a method, a trigger kind by these.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** A function log line's level (function.logs). */
|
|
8
|
+
export const Level = Object.freeze({
|
|
9
|
+
TRACE: 'trace', DEBUG: 'debug', INFO: 'info', WARN: 'warn', ERROR: 'error', FATAL: 'fatal',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
/** How a call to a function ended. */
|
|
13
|
+
export const RunOutcome = Object.freeze({ OK: 'ok', ERROR: 'error' });
|
|
14
|
+
|
|
15
|
+
/** The change a collection trigger fires on. */
|
|
16
|
+
export const TriggerKind = Object.freeze({ INSERT: 'insert', UPDATE: 'update', DELETE: 'delete' });
|
|
17
|
+
|
|
18
|
+
/** A request method a stub answers or a test sends. */
|
|
19
|
+
export const HttpMethod = Object.freeze({
|
|
20
|
+
GET: 'GET', POST: 'POST', PUT: 'PUT', DELETE: 'DELETE', PATCH: 'PATCH', OPTIONS: 'OPTIONS', HEAD: 'HEAD',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/** How a stub's path matches: the path alone, or it and everything below it. */
|
|
24
|
+
export const PathMatch = Object.freeze({ EXACT: 'exact', PREFIX: 'prefix' });
|
|
25
|
+
|
|
26
|
+
/** What became of a recorded fetch. */
|
|
27
|
+
export const CallOutcome = Object.freeze({ STUBBED: 'stubbed', UNMATCHED: 'unmatched' });
|
|
28
|
+
|
|
29
|
+
/** How a test tenant's clock runs. */
|
|
30
|
+
export const ClockMode = Object.freeze({ REAL: 'real', FROZEN: 'frozen', OFFSET: 'offset' });
|
|
31
|
+
|
|
32
|
+
/** What went wrong with the harness itself, not with the app under test. */
|
|
33
|
+
export const TestErrorCode = Object.freeze({
|
|
34
|
+
NOT_UNDER_SUBSTRIO_TEST: 'NOT_UNDER_SUBSTRIO_TEST', // startApp outside `substrio test`
|
|
35
|
+
UNKNOWN_FUNCTION: 'UNKNOWN_FUNCTION', // a name the app does not deploy
|
|
36
|
+
NO_SCHEDULE: 'NO_SCHEDULE', // cron() of a function with no [[cron]]
|
|
37
|
+
INVALID_FIXTURE: 'INVALID_FIXTURE',
|
|
38
|
+
INVALID_ARGUMENT: 'INVALID_ARGUMENT', // a value outside its enum, a bad stub
|
|
39
|
+
TIMEOUT: 'TIMEOUT',
|
|
40
|
+
APP_FAILED: 'APP_FAILED', // the app could not be applied to the test tenant
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export class TestError extends Error {
|
|
44
|
+
constructor(message, code) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = 'TestError';
|
|
47
|
+
this.code = code;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** `value` when it is a member of the frozen enum `set`, else a typed TestError naming the members. */
|
|
52
|
+
export function member(set, value, what) {
|
|
53
|
+
if (Object.values(set).includes(value)) return value;
|
|
54
|
+
throw new TestError(`${what} must be one of ${Object.values(set).join(', ')}, not ${JSON.stringify(value)}`, TestErrorCode.INVALID_ARGUMENT);
|
|
55
|
+
}
|