@ericminassian/plat 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/dist/api-types.d.ts +7 -0
- package/dist/api-types.js +3 -0
- package/dist/api-types.js.map +1 -0
- package/dist/api.d.ts +123 -0
- package/dist/api.js +271 -0
- package/dist/api.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/build.d.ts +45 -0
- package/dist/build.js +188 -0
- package/dist/build.js.map +1 -0
- package/dist/commands/account.d.ts +2 -0
- package/dist/commands/account.js +45 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/apps.d.ts +2 -0
- package/dist/commands/apps.js +75 -0
- package/dist/commands/apps.js.map +1 -0
- package/dist/commands/common.d.ts +19 -0
- package/dist/commands/common.js +43 -0
- package/dist/commands/common.js.map +1 -0
- package/dist/commands/lifecycle.d.ts +3 -0
- package/dist/commands/lifecycle.js +105 -0
- package/dist/commands/lifecycle.js.map +1 -0
- package/dist/commands/manage.d.ts +2 -0
- package/dist/commands/manage.js +103 -0
- package/dist/commands/manage.js.map +1 -0
- package/dist/commands/observe.d.ts +8 -0
- package/dist/commands/observe.js +195 -0
- package/dist/commands/observe.js.map +1 -0
- package/dist/credentials.d.ts +13 -0
- package/dist/credentials.js +42 -0
- package/dist/credentials.js.map +1 -0
- package/dist/deploy.d.ts +23 -0
- package/dist/deploy.js +100 -0
- package/dist/deploy.js.map +1 -0
- package/dist/dev/crons.d.ts +16 -0
- package/dist/dev/crons.js +47 -0
- package/dist/dev/crons.js.map +1 -0
- package/dist/dev/entries.d.ts +6 -0
- package/dist/dev/entries.js +21 -0
- package/dist/dev/entries.js.map +1 -0
- package/dist/dev/index.d.ts +33 -0
- package/dist/dev/index.js +262 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/local-stage.d.ts +46 -0
- package/dist/dev/local-stage.js +116 -0
- package/dist/dev/local-stage.js.map +1 -0
- package/dist/dev/pretty.d.ts +16 -0
- package/dist/dev/pretty.js +91 -0
- package/dist/dev/pretty.js.map +1 -0
- package/dist/dev/proc.d.ts +7 -0
- package/dist/dev/proc.js +16 -0
- package/dist/dev/proc.js.map +1 -0
- package/dist/dev/router.d.ts +67 -0
- package/dist/dev/router.js +184 -0
- package/dist/dev/router.js.map +1 -0
- package/dist/dev/server-entry.d.ts +1 -0
- package/dist/dev/server-entry.js +28 -0
- package/dist/dev/server-entry.js.map +1 -0
- package/dist/dev/test.d.ts +10 -0
- package/dist/dev/test.js +62 -0
- package/dist/dev/test.js.map +1 -0
- package/dist/dev/worker-host.d.ts +1 -0
- package/dist/dev/worker-host.js +67 -0
- package/dist/dev/worker-host.js.map +1 -0
- package/dist/dev/worker.d.ts +57 -0
- package/dist/dev/worker.js +216 -0
- package/dist/dev/worker.js.map +1 -0
- package/dist/github.d.ts +39 -0
- package/dist/github.js +108 -0
- package/dist/github.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +23 -0
- package/dist/init.js +102 -0
- package/dist/init.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.js +24 -0
- package/dist/main.js.map +1 -0
- package/dist/project.d.ts +22 -0
- package/dist/project.js +81 -0
- package/dist/project.js.map +1 -0
- package/dist/util/net.d.ts +4 -0
- package/dist/util/net.js +33 -0
- package/dist/util/net.js.map +1 -0
- package/dist/util/output.d.ts +42 -0
- package/dist/util/output.js +105 -0
- package/dist/util/output.js.map +1 -0
- package/dist/util/prompt.d.ts +3 -0
- package/dist/util/prompt.js +22 -0
- package/dist/util/prompt.js.map +1 -0
- package/dist/util/time.d.ts +11 -0
- package/dist/util/time.js +29 -0
- package/dist/util/time.js.map +1 -0
- package/dist/util/zip.d.ts +10 -0
- package/dist/util/zip.js +45 -0
- package/dist/util/zip.js.map +1 -0
- package/package.json +50 -3
- package/src/api-types.ts +8 -0
- package/src/api.ts +341 -0
- package/src/bin.ts +4 -0
- package/src/build.ts +255 -0
- package/src/commands/account.ts +62 -0
- package/src/commands/apps.ts +102 -0
- package/src/commands/common.ts +51 -0
- package/src/commands/lifecycle.ts +139 -0
- package/src/commands/manage.ts +169 -0
- package/src/commands/observe.ts +276 -0
- package/src/credentials.ts +50 -0
- package/src/deploy.ts +138 -0
- package/src/dev/crons.ts +70 -0
- package/src/dev/entries.ts +23 -0
- package/src/dev/index.ts +281 -0
- package/src/dev/local-stage.ts +176 -0
- package/src/dev/pretty.ts +90 -0
- package/src/dev/proc.ts +15 -0
- package/src/dev/router.ts +246 -0
- package/src/dev/server-entry.ts +21 -0
- package/src/dev/test.ts +68 -0
- package/src/dev/worker-host.ts +62 -0
- package/src/dev/worker.ts +332 -0
- package/src/github.ts +121 -0
- package/src/index.ts +20 -0
- package/src/init.ts +123 -0
- package/src/main.ts +28 -0
- package/src/project.ts +89 -0
- package/src/util/net.ts +33 -0
- package/src/util/output.ts +117 -0
- package/src/util/prompt.ts +20 -0
- package/src/util/time.ts +32 -0
- package/src/util/zip.ts +46 -0
- package/template/.github/workflows/platform.yml +24 -0
- package/template/AGENTS.md +134 -0
- package/template/CLAUDE.md +1 -0
- package/template/README.md +13 -0
- package/template/_gitignore +8 -0
- package/template/package.json +31 -0
- package/template/platform.json +18 -0
- package/template/src/server.ts +100 -0
- package/template/src/types.ts +21 -0
- package/template/src/worker.ts +32 -0
- package/template/test/server.test.ts +120 -0
- package/template/test/todos.integration.test.ts +30 -0
- package/template/tsconfig.json +18 -0
- package/template/vitest.config.ts +9 -0
- package/template/vitest.integration.config.ts +10 -0
- package/template/web/index.html +12 -0
- package/template/web/src/App.tsx +102 -0
- package/template/web/src/api.ts +11 -0
- package/template/web/src/main.tsx +10 -0
- package/template/web/src/styles.css +102 -0
- package/template/web/tsconfig.json +18 -0
- package/template/web/vite.config.ts +19 -0
- package/README.md +0 -3
package/dist/project.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { ManifestError, parseManifest } from '@ericminassian/platform-core';
|
|
6
|
+
import { CliError, EXIT } from './util/output.js';
|
|
7
|
+
export const MANIFEST_FILE = 'platform.json';
|
|
8
|
+
/** Walk up from `cwd` to the nearest platform.json. */
|
|
9
|
+
export function findProjectRoot(cwd) {
|
|
10
|
+
let dir = resolve(cwd);
|
|
11
|
+
for (;;) {
|
|
12
|
+
if (existsSync(join(dir, MANIFEST_FILE)))
|
|
13
|
+
return dir;
|
|
14
|
+
const parent = dirname(dir);
|
|
15
|
+
if (parent === dir)
|
|
16
|
+
return null;
|
|
17
|
+
dir = parent;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function loadProject(cwd) {
|
|
21
|
+
const root = findProjectRoot(cwd);
|
|
22
|
+
if (!root) {
|
|
23
|
+
throw new CliError(`no ${MANIFEST_FILE} found in ${cwd} or its parents`, {
|
|
24
|
+
hint: 'run this inside an app, or create one with `plat init <dir> --name <app>`',
|
|
25
|
+
exitCode: EXIT.usage,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
let raw;
|
|
29
|
+
try {
|
|
30
|
+
raw = JSON.parse(readFileSync(join(root, MANIFEST_FILE), 'utf8'));
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
throw new CliError(`${MANIFEST_FILE} is not valid JSON: ${err.message}`, {
|
|
34
|
+
exitCode: EXIT.usage,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
return { root, raw, manifest: parseManifest(raw) };
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof ManifestError)
|
|
42
|
+
throw new CliError(err.message, { exitCode: EXIT.usage });
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** App name from `--app`, else the nearest platform.json. */
|
|
47
|
+
export function resolveAppName(opt, cwd = process.cwd()) {
|
|
48
|
+
if (opt)
|
|
49
|
+
return opt;
|
|
50
|
+
const root = findProjectRoot(cwd);
|
|
51
|
+
if (!root) {
|
|
52
|
+
throw new CliError('no app given', {
|
|
53
|
+
hint: 'pass --app <name> or run inside an app directory',
|
|
54
|
+
exitCode: EXIT.usage,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return loadProject(root).manifest.name;
|
|
58
|
+
}
|
|
59
|
+
export function cliVersion() {
|
|
60
|
+
return cliPackageJson().version ?? '0.0.0';
|
|
61
|
+
}
|
|
62
|
+
export function cliPackageRoot() {
|
|
63
|
+
return fileURLToPath(new URL('..', import.meta.url));
|
|
64
|
+
}
|
|
65
|
+
function cliPackageJson() {
|
|
66
|
+
return JSON.parse(readFileSync(join(cliPackageRoot(), 'package.json'), 'utf8'));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve a module the way the *app* would (its own node_modules first), so
|
|
70
|
+
* the server wrapper and app code share one copy of the SDK. Falls back to the
|
|
71
|
+
* CLI's own dependency.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveFromApp(appRoot, specifier) {
|
|
74
|
+
try {
|
|
75
|
+
return createRequire(join(appRoot, 'package.json')).resolve(specifier);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return createRequire(import.meta.url).resolve(specifier);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
package/dist/util/net.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createServer } from 'node:net';
|
|
2
|
+
/** A free TCP port on 127.0.0.1. */
|
|
3
|
+
export function freePort() {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const srv = createServer();
|
|
6
|
+
srv.once('error', reject);
|
|
7
|
+
srv.listen(0, '127.0.0.1', () => {
|
|
8
|
+
const addr = srv.address();
|
|
9
|
+
const port = typeof addr === 'object' && addr ? addr.port : 0;
|
|
10
|
+
srv.close(() => resolve(port));
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** Resolves once something accepts TCP connections on host:port. */
|
|
15
|
+
export async function waitForPort(port, host = '127.0.0.1', timeoutMs = 30_000) {
|
|
16
|
+
const { connect } = await import('node:net');
|
|
17
|
+
const deadline = Date.now() + timeoutMs;
|
|
18
|
+
while (Date.now() < deadline) {
|
|
19
|
+
const ok = await new Promise((resolve) => {
|
|
20
|
+
const s = connect(port, host);
|
|
21
|
+
s.once('connect', () => {
|
|
22
|
+
s.end();
|
|
23
|
+
resolve(true);
|
|
24
|
+
});
|
|
25
|
+
s.once('error', () => resolve(false));
|
|
26
|
+
});
|
|
27
|
+
if (ok)
|
|
28
|
+
return;
|
|
29
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`nothing listening on ${host}:${port} after ${timeoutMs}ms`);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=net.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net.js","sourceRoot":"","sources":["../../src/util/net.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,oCAAoC;AACpC,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,IAAI,GAAG,WAAW,EAAE,SAAS,GAAG,MAAM;IACpF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YAChD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBACrB,CAAC,CAAC,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QACH,IAAI,EAAE;YAAE,OAAO;QACf,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,IAAI,IAAI,UAAU,SAAS,IAAI,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output conventions: human-readable by default, `--json` prints exactly one
|
|
3
|
+
* JSON document on stdout (progress goes to stderr) so agents can parse it.
|
|
4
|
+
*/
|
|
5
|
+
export declare class CliError extends Error {
|
|
6
|
+
readonly hint?: string;
|
|
7
|
+
readonly exitCode: number;
|
|
8
|
+
constructor(message: string, opts?: {
|
|
9
|
+
hint?: string;
|
|
10
|
+
exitCode?: number;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export declare const EXIT: {
|
|
14
|
+
readonly ok: 0;
|
|
15
|
+
readonly error: 1;
|
|
16
|
+
readonly usage: 2;
|
|
17
|
+
readonly auth: 3;
|
|
18
|
+
readonly notFound: 4;
|
|
19
|
+
readonly deployFailed: 5;
|
|
20
|
+
};
|
|
21
|
+
export interface OutputOptions {
|
|
22
|
+
json?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function setJsonMode(on: boolean): void;
|
|
25
|
+
export declare function isJsonMode(): boolean;
|
|
26
|
+
/** Progress/status lines; stderr so `--json` stdout stays clean. */
|
|
27
|
+
export declare function info(msg: string): void;
|
|
28
|
+
export declare function step(msg: string): void;
|
|
29
|
+
export declare function success(msg: string): void;
|
|
30
|
+
export declare function warn(msg: string): void;
|
|
31
|
+
/** Prints the command result: JSON in `--json` mode, else via `human`. */
|
|
32
|
+
export declare function result<T>(value: T, human: (v: T) => string | undefined): void;
|
|
33
|
+
export declare function formatError(err: unknown): {
|
|
34
|
+
message: string;
|
|
35
|
+
hint?: string;
|
|
36
|
+
exitCode: number;
|
|
37
|
+
};
|
|
38
|
+
export declare function reportError(err: unknown): number;
|
|
39
|
+
/** Plain-text table with padded columns. */
|
|
40
|
+
export declare function table(rows: Array<Record<string, unknown>>, columns?: string[]): string;
|
|
41
|
+
/** Unicode sparkline; nulls render as spaces. */
|
|
42
|
+
export declare function sparkline(values: Array<number | null>): string;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
/**
|
|
3
|
+
* Output conventions: human-readable by default, `--json` prints exactly one
|
|
4
|
+
* JSON document on stdout (progress goes to stderr) so agents can parse it.
|
|
5
|
+
*/
|
|
6
|
+
export class CliError extends Error {
|
|
7
|
+
hint;
|
|
8
|
+
exitCode;
|
|
9
|
+
constructor(message, opts = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.hint = opts.hint;
|
|
12
|
+
this.exitCode = opts.exitCode ?? 1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export const EXIT = {
|
|
16
|
+
ok: 0,
|
|
17
|
+
error: 1,
|
|
18
|
+
usage: 2,
|
|
19
|
+
auth: 3,
|
|
20
|
+
notFound: 4,
|
|
21
|
+
deployFailed: 5,
|
|
22
|
+
};
|
|
23
|
+
let jsonMode = false;
|
|
24
|
+
export function setJsonMode(on) {
|
|
25
|
+
jsonMode = on;
|
|
26
|
+
}
|
|
27
|
+
export function isJsonMode() {
|
|
28
|
+
return jsonMode;
|
|
29
|
+
}
|
|
30
|
+
/** Progress/status lines; stderr so `--json` stdout stays clean. */
|
|
31
|
+
export function info(msg) {
|
|
32
|
+
process.stderr.write(`${msg}\n`);
|
|
33
|
+
}
|
|
34
|
+
export function step(msg) {
|
|
35
|
+
info(`${pc.cyan('›')} ${msg}`);
|
|
36
|
+
}
|
|
37
|
+
export function success(msg) {
|
|
38
|
+
info(`${pc.green('✓')} ${msg}`);
|
|
39
|
+
}
|
|
40
|
+
export function warn(msg) {
|
|
41
|
+
info(`${pc.yellow('!')} ${msg}`);
|
|
42
|
+
}
|
|
43
|
+
/** Prints the command result: JSON in `--json` mode, else via `human`. */
|
|
44
|
+
export function result(value, human) {
|
|
45
|
+
if (jsonMode) {
|
|
46
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const text = human(value);
|
|
50
|
+
if (text)
|
|
51
|
+
process.stdout.write(`${text}\n`);
|
|
52
|
+
}
|
|
53
|
+
export function formatError(err) {
|
|
54
|
+
if (err instanceof CliError)
|
|
55
|
+
return { message: err.message, hint: err.hint, exitCode: err.exitCode };
|
|
56
|
+
if (err instanceof Error)
|
|
57
|
+
return { message: err.message, exitCode: EXIT.error };
|
|
58
|
+
return { message: String(err), exitCode: EXIT.error };
|
|
59
|
+
}
|
|
60
|
+
export function reportError(err) {
|
|
61
|
+
const { message, hint, exitCode } = formatError(err);
|
|
62
|
+
if (jsonMode) {
|
|
63
|
+
process.stdout.write(`${JSON.stringify({ error: { message, hint, exitCode } }, null, 2)}\n`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
info(`${pc.red('✗')} ${message}`);
|
|
67
|
+
if (hint)
|
|
68
|
+
info(` ${pc.dim(hint)}`);
|
|
69
|
+
}
|
|
70
|
+
return exitCode;
|
|
71
|
+
}
|
|
72
|
+
/** Plain-text table with padded columns. */
|
|
73
|
+
export function table(rows, columns) {
|
|
74
|
+
if (rows.length === 0)
|
|
75
|
+
return pc.dim('(none)');
|
|
76
|
+
const cols = columns ?? Object.keys(rows[0]);
|
|
77
|
+
const cell = (v) => v === undefined || v === null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
78
|
+
const widths = cols.map((c) => Math.max(c.length, ...rows.map((r) => visibleLength(cell(r[c])))));
|
|
79
|
+
const line = (vals) => vals.map((v, i) => v + ' '.repeat(widths[i] - visibleLength(v))).join(' ');
|
|
80
|
+
return [pc.bold(line(cols)), ...rows.map((r) => line(cols.map((c) => cell(r[c]))))].join('\n');
|
|
81
|
+
}
|
|
82
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: matching ANSI escape codes is the point
|
|
83
|
+
const ANSI = /\x1b\[[0-9;]*m/g;
|
|
84
|
+
function visibleLength(s) {
|
|
85
|
+
return s.replace(ANSI, '').length;
|
|
86
|
+
}
|
|
87
|
+
const SPARKS = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
|
|
88
|
+
/** Unicode sparkline; nulls render as spaces. */
|
|
89
|
+
export function sparkline(values) {
|
|
90
|
+
const nums = values.filter((v) => v !== null && Number.isFinite(v));
|
|
91
|
+
if (nums.length === 0)
|
|
92
|
+
return '';
|
|
93
|
+
const min = Math.min(...nums);
|
|
94
|
+
const max = Math.max(...nums);
|
|
95
|
+
return values
|
|
96
|
+
.map((v) => {
|
|
97
|
+
if (v === null || !Number.isFinite(v))
|
|
98
|
+
return ' ';
|
|
99
|
+
if (max === min)
|
|
100
|
+
return v === 0 ? SPARKS[0] : SPARKS[3];
|
|
101
|
+
return SPARKS[Math.round(((v - min) / (max - min)) * (SPARKS.length - 1))];
|
|
102
|
+
})
|
|
103
|
+
.join('');
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/util/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function prompt(question: string): Promise<string>;
|
|
2
|
+
/** Ask the user to type `expected` back; `--yes` skips it, and non-interactive runs must pass it. */
|
|
3
|
+
export declare function confirmByTyping(question: string, expected: string, yes?: boolean): Promise<void>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline/promises';
|
|
2
|
+
import { CliError, EXIT } from './output.js';
|
|
3
|
+
export async function prompt(question) {
|
|
4
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
5
|
+
try {
|
|
6
|
+
return await rl.question(question);
|
|
7
|
+
}
|
|
8
|
+
finally {
|
|
9
|
+
rl.close();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Ask the user to type `expected` back; `--yes` skips it, and non-interactive runs must pass it. */
|
|
13
|
+
export async function confirmByTyping(question, expected, yes) {
|
|
14
|
+
if (yes)
|
|
15
|
+
return;
|
|
16
|
+
if (!process.stdin.isTTY)
|
|
17
|
+
throw new CliError('confirmation needed', { hint: 'pass --yes', exitCode: EXIT.usage });
|
|
18
|
+
const answer = await prompt(`${question} type ${expected} to confirm: `);
|
|
19
|
+
if (answer.trim() !== expected)
|
|
20
|
+
throw new CliError('aborted', { exitCode: EXIT.usage });
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/util/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAgB;IAC3C,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,QAAgB,EAAE,GAAa;IACrF,IAAI,GAAG;QAAE,OAAO;IAChB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QACtB,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,QAAQ,SAAS,QAAQ,eAAe,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,QAAQ;QAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Resolution } from '@ericminassian/platform-core';
|
|
2
|
+
/** `"90s" | "15m" | "6h" | "7d" | "2w"` → milliseconds. */
|
|
3
|
+
export declare function parseDuration(input: string): number;
|
|
4
|
+
/** Pick a rollup resolution that yields a readable number of points. */
|
|
5
|
+
export declare function resolutionFor(rangeMs: number): Resolution;
|
|
6
|
+
export declare function sinceRange(since: string, now?: number): {
|
|
7
|
+
from: number;
|
|
8
|
+
to: number;
|
|
9
|
+
res: Resolution;
|
|
10
|
+
};
|
|
11
|
+
export declare function shortTime(iso: string | number): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CliError, EXIT } from './output.js';
|
|
2
|
+
const UNITS = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 };
|
|
3
|
+
/** `"90s" | "15m" | "6h" | "7d" | "2w"` → milliseconds. */
|
|
4
|
+
export function parseDuration(input) {
|
|
5
|
+
const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/.exec(input.trim());
|
|
6
|
+
if (!m)
|
|
7
|
+
throw new CliError(`invalid duration "${input}"`, { hint: 'use e.g. 30m, 6h, 7d', exitCode: EXIT.usage });
|
|
8
|
+
return Number(m[1]) * UNITS[m[2]];
|
|
9
|
+
}
|
|
10
|
+
/** Pick a rollup resolution that yields a readable number of points. */
|
|
11
|
+
export function resolutionFor(rangeMs) {
|
|
12
|
+
if (rangeMs <= 6 * UNITS.h)
|
|
13
|
+
return '1m';
|
|
14
|
+
if (rangeMs <= 14 * UNITS.d)
|
|
15
|
+
return '1h';
|
|
16
|
+
return '1d';
|
|
17
|
+
}
|
|
18
|
+
export function sinceRange(since, now = Date.now()) {
|
|
19
|
+
const ms = parseDuration(since);
|
|
20
|
+
return { from: now - ms, to: now, res: resolutionFor(ms) };
|
|
21
|
+
}
|
|
22
|
+
export function shortTime(iso) {
|
|
23
|
+
const d = new Date(iso);
|
|
24
|
+
return d
|
|
25
|
+
.toISOString()
|
|
26
|
+
.replace('T', ' ')
|
|
27
|
+
.replace(/\.\d+Z$/, 'Z');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,KAAK,GAA2B,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;AAE3G,2DAA2D;AAC3D,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC,CAAC;QACJ,MAAM,IAAI,QAAQ,CAAC,qBAAqB,KAAK,GAAG,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5G,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAE,CAAE,CAAC;AACtC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,CAAE;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,OAAO,IAAI,EAAE,GAAG,KAAK,CAAC,CAAE;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACxD,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAoB;IAC5C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,CAAC;SACL,WAAW,EAAE;SACb,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;SACjB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Every file under `dir`, as zip paths (forward slashes) → absolute paths. */
|
|
2
|
+
export declare function listFiles(dir: string): Array<{
|
|
3
|
+
zipPath: string;
|
|
4
|
+
absPath: string;
|
|
5
|
+
}>;
|
|
6
|
+
/** Zip a directory. Timestamps are fixed so identical inputs produce identical zips. */
|
|
7
|
+
export declare function zipDirectory(dir: string): Uint8Array;
|
|
8
|
+
export declare function zipEntries(entries: Record<string, Uint8Array | string>): Uint8Array;
|
|
9
|
+
export declare function zipFileNames(zip: Uint8Array): string[];
|
|
10
|
+
export declare function dirExists(path: string): boolean;
|
package/dist/util/zip.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative, sep } from 'node:path';
|
|
3
|
+
import { unzipSync, zipSync } from 'fflate';
|
|
4
|
+
/** Every file under `dir`, as zip paths (forward slashes) → absolute paths. */
|
|
5
|
+
export function listFiles(dir) {
|
|
6
|
+
const out = [];
|
|
7
|
+
const walk = (d) => {
|
|
8
|
+
for (const entry of readdirSync(d, { withFileTypes: true })) {
|
|
9
|
+
const abs = join(d, entry.name);
|
|
10
|
+
if (entry.isDirectory())
|
|
11
|
+
walk(abs);
|
|
12
|
+
else if (entry.isFile())
|
|
13
|
+
out.push({ zipPath: relative(dir, abs).split(sep).join('/'), absPath: abs });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
walk(dir);
|
|
17
|
+
return out.sort((a, b) => a.zipPath.localeCompare(b.zipPath));
|
|
18
|
+
}
|
|
19
|
+
/** Zip a directory. Timestamps are fixed so identical inputs produce identical zips. */
|
|
20
|
+
export function zipDirectory(dir) {
|
|
21
|
+
const files = {};
|
|
22
|
+
for (const f of listFiles(dir))
|
|
23
|
+
files[f.zipPath] = [readFileSync(f.absPath), { mtime: FIXED_MTIME }];
|
|
24
|
+
return zipSync(files, { level: 6 });
|
|
25
|
+
}
|
|
26
|
+
export function zipEntries(entries) {
|
|
27
|
+
const files = {};
|
|
28
|
+
for (const [name, data] of Object.entries(entries)) {
|
|
29
|
+
files[name] = [typeof data === 'string' ? new TextEncoder().encode(data) : data, { mtime: FIXED_MTIME }];
|
|
30
|
+
}
|
|
31
|
+
return zipSync(files, { level: 6 });
|
|
32
|
+
}
|
|
33
|
+
export function zipFileNames(zip) {
|
|
34
|
+
return Object.keys(unzipSync(zip)).sort();
|
|
35
|
+
}
|
|
36
|
+
export function dirExists(path) {
|
|
37
|
+
try {
|
|
38
|
+
return statSync(path).isDirectory();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const FIXED_MTIME = new Date('2020-01-01T00:00:00Z');
|
|
45
|
+
//# sourceMappingURL=zip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/util/zip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,SAAS,EAAiB,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE3D,+EAA+E;AAC/E,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,GAAG,GAAgD,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;QACzB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,GAAG,CAAC,CAAC;iBAC9B,IAAI,KAAK,CAAC,MAAM,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACxG,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC;QAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACrG,OAAO,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAA4C;IACrE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAe;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,sBAAsB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ericminassian/plat",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for the platform: init, dev (AWS Emulator), build, deploy, logs, metrics, errors, data.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/eric-minassian/platform.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"plat": "./dist/bin.js"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"src",
|
|
27
|
+
"template"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.1169.0",
|
|
31
|
+
"@aws-sdk/client-cognito-identity-provider": "^3.1169.0",
|
|
32
|
+
"@aws-sdk/client-eventbridge": "^3.1169.0",
|
|
33
|
+
"@aws-sdk/client-lambda": "^3.1169.0",
|
|
34
|
+
"@aws-sdk/client-s3": "^3.1169.0",
|
|
35
|
+
"@aws-sdk/client-sqs": "^3.1169.0",
|
|
36
|
+
"@aws-sdk/client-ssm": "^3.1169.0",
|
|
37
|
+
"@ericminassian/platform": "0.1.0",
|
|
38
|
+
"@ericminassian/platform-core": "0.1.0",
|
|
39
|
+
"@ericminassian/platform-engine": "0.1.0",
|
|
40
|
+
"commander": "^15.1.0",
|
|
41
|
+
"cron-parser": "^5.10.6",
|
|
42
|
+
"esbuild": "^0.28.2",
|
|
43
|
+
"fflate": "^0.8.3",
|
|
44
|
+
"picocolors": "^1.1.1",
|
|
45
|
+
"tsx": "^4.23.15"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -p tsconfig.build.json && node scripts/copy-template.ts",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:integration": "vitest run --config vitest.integration.config.ts"
|
|
52
|
+
}
|
|
6
53
|
}
|