@liquidmetal-ai/raindrop 0.0.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/README.md +777 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +6 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/dist/base-command.d.ts +27 -0
- package/dist/base-command.d.ts.map +1 -0
- package/dist/base-command.js +69 -0
- package/dist/build.d.ts +13 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +86 -0
- package/dist/build.test.d.ts +2 -0
- package/dist/build.test.d.ts.map +1 -0
- package/dist/build.test.js +41 -0
- package/dist/codegen.d.ts +32 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +212 -0
- package/dist/codegen.test.d.ts +2 -0
- package/dist/codegen.test.d.ts.map +1 -0
- package/dist/codegen.test.js +97 -0
- package/dist/commands/auth/list.d.ts +10 -0
- package/dist/commands/auth/list.d.ts.map +1 -0
- package/dist/commands/auth/list.js +55 -0
- package/dist/commands/auth/login.d.ts +10 -0
- package/dist/commands/auth/login.d.ts.map +1 -0
- package/dist/commands/auth/login.js +69 -0
- package/dist/commands/auth/logout.d.ts +8 -0
- package/dist/commands/auth/logout.d.ts.map +1 -0
- package/dist/commands/auth/logout.js +15 -0
- package/dist/commands/auth/select.d.ts +10 -0
- package/dist/commands/auth/select.d.ts.map +1 -0
- package/dist/commands/auth/select.js +39 -0
- package/dist/commands/build/branch.d.ts +16 -0
- package/dist/commands/build/branch.d.ts.map +1 -0
- package/dist/commands/build/branch.js +81 -0
- package/dist/commands/build/delete.d.ts +19 -0
- package/dist/commands/build/delete.d.ts.map +1 -0
- package/dist/commands/build/delete.js +99 -0
- package/dist/commands/build/deploy.d.ts +18 -0
- package/dist/commands/build/deploy.d.ts.map +1 -0
- package/dist/commands/build/deploy.js +144 -0
- package/dist/commands/build/env/get.d.ts +19 -0
- package/dist/commands/build/env/get.d.ts.map +1 -0
- package/dist/commands/build/env/get.js +101 -0
- package/dist/commands/build/env/set.d.ts +20 -0
- package/dist/commands/build/env/set.d.ts.map +1 -0
- package/dist/commands/build/env/set.js +115 -0
- package/dist/commands/build/find.d.ts +24 -0
- package/dist/commands/build/find.d.ts.map +1 -0
- package/dist/commands/build/find.js +110 -0
- package/dist/commands/build/generate.d.ts +13 -0
- package/dist/commands/build/generate.d.ts.map +1 -0
- package/dist/commands/build/generate.js +38 -0
- package/dist/commands/build/init.d.ts +15 -0
- package/dist/commands/build/init.d.ts.map +1 -0
- package/dist/commands/build/init.js +57 -0
- package/dist/commands/build/list.d.ts +17 -0
- package/dist/commands/build/list.d.ts.map +1 -0
- package/dist/commands/build/list.js +100 -0
- package/dist/commands/build/start.d.ts +16 -0
- package/dist/commands/build/start.d.ts.map +1 -0
- package/dist/commands/build/start.js +71 -0
- package/dist/commands/build/stop.d.ts +15 -0
- package/dist/commands/build/stop.d.ts.map +1 -0
- package/dist/commands/build/stop.js +67 -0
- package/dist/commands/build/token.d.ts +9 -0
- package/dist/commands/build/token.d.ts.map +1 -0
- package/dist/commands/build/token.js +42 -0
- package/dist/commands/build/upload.d.ts +17 -0
- package/dist/commands/build/upload.d.ts.map +1 -0
- package/dist/commands/build/upload.js +75 -0
- package/dist/commands/build/validate.d.ts +13 -0
- package/dist/commands/build/validate.d.ts.map +1 -0
- package/dist/commands/build/validate.js +26 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +34 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +24 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +140 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/oclif.manifest.json +1208 -0
- package/package.json +107 -0
package/bin/dev.cmd
ADDED
package/bin/dev.js
ADDED
package/bin/run.cmd
ADDED
package/bin/run.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PromiseClient } from '@connectrpc/connect';
|
|
2
|
+
import { Application } from '@liquidmetal-ai/drizzle/appify/build';
|
|
3
|
+
import { CatalogService } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/catalog_connect';
|
|
4
|
+
import { Command, Interfaces } from '@oclif/core';
|
|
5
|
+
import { Config } from './config.js';
|
|
6
|
+
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
|
|
7
|
+
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
8
|
+
export declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
9
|
+
static baseFlags: {};
|
|
10
|
+
protected flags: Flags<T>;
|
|
11
|
+
protected args: Args<T>;
|
|
12
|
+
protected raindropConfig?: Config;
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
protected catch(err: Error & {
|
|
15
|
+
exitCode?: number;
|
|
16
|
+
}): Promise<any>;
|
|
17
|
+
protected finally(_: Error | undefined): Promise<any>;
|
|
18
|
+
protected loadConfig(): Promise<Config>;
|
|
19
|
+
protected saveConfig(config: Config): Promise<void>;
|
|
20
|
+
protected loadManifest(): Promise<Application[]>;
|
|
21
|
+
protected catalogService(): Promise<{
|
|
22
|
+
client: PromiseClient<typeof CatalogService>;
|
|
23
|
+
userId: string;
|
|
24
|
+
organizationId: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=base-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-command.d.ts","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAE9F,OAAO,EAAE,OAAO,EAAS,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,MAAM,EAA0B,MAAM,aAAa,CAAC;AAG7D,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,OAAO,OAAO,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC,OAAO,WAAW,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACvH,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,OAAO,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEhF,8BAAsB,WAAW,CAAC,CAAC,SAAS,OAAO,OAAO,CAAE,SAAQ,OAAO;IACzE,MAAM,CAAC,SAAS,KAAM;IAEtB,SAAS,CAAC,KAAK,EAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,SAAS,CAAC,IAAI,EAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEzB,SAAS,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;cAclB,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;cAKvD,OAAO,CAAC,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;cAI3C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;cAK7B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cAIzC,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;cAwBtC,cAAc,IAAI,OAAO,CAAC;QACxC,MAAM,EAAE,aAAa,CAAC,OAAO,cAAc,CAAC,CAAC;QAC7C,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CAIH"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { manifestFromString } from '@liquidmetal-ai/drizzle/appify/index';
|
|
2
|
+
import { CatalogService } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/catalog_connect';
|
|
3
|
+
import { RainbowAuthService } from '@liquidmetal-ai/drizzle/liquidmetal/v1alpha1/rainbow_auth_connect';
|
|
4
|
+
import { Command } from '@oclif/core';
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { loadConfig, saveConfig } from './config.js';
|
|
8
|
+
import { createAuthenticatingClient, useClient } from './index.js';
|
|
9
|
+
export class BaseCommand extends Command {
|
|
10
|
+
static baseFlags = {};
|
|
11
|
+
flags;
|
|
12
|
+
args;
|
|
13
|
+
raindropConfig;
|
|
14
|
+
async init() {
|
|
15
|
+
await super.init();
|
|
16
|
+
const { args, flags } = await this.parse({
|
|
17
|
+
flags: this.ctor.flags,
|
|
18
|
+
baseFlags: super.ctor.baseFlags,
|
|
19
|
+
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
20
|
+
args: this.ctor.args,
|
|
21
|
+
strict: this.ctor.strict,
|
|
22
|
+
});
|
|
23
|
+
this.flags = flags;
|
|
24
|
+
this.args = args;
|
|
25
|
+
}
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
async catch(err) {
|
|
28
|
+
return super.catch(err);
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
async finally(_) {
|
|
32
|
+
return super.finally(_);
|
|
33
|
+
}
|
|
34
|
+
async loadConfig() {
|
|
35
|
+
this.raindropConfig = await loadConfig(this.flags.config);
|
|
36
|
+
return this.raindropConfig;
|
|
37
|
+
}
|
|
38
|
+
async saveConfig(config) {
|
|
39
|
+
await saveConfig(this.flags.config, config);
|
|
40
|
+
}
|
|
41
|
+
async loadManifest() {
|
|
42
|
+
let manifestPath = this.flags.manifest;
|
|
43
|
+
if (this.flags.root) {
|
|
44
|
+
manifestPath = path.isAbsolute(this.flags.manifest)
|
|
45
|
+
? this.flags.manifest
|
|
46
|
+
: path.join(this.flags.root, this.flags.manifest);
|
|
47
|
+
}
|
|
48
|
+
const contents = await fs.readFile(manifestPath, 'utf-8');
|
|
49
|
+
const [apps, errors] = await manifestFromString(contents);
|
|
50
|
+
const allErrors = errors.some((e) => "severity" in e && e.severity !== 'warning');
|
|
51
|
+
for (const error of errors) {
|
|
52
|
+
this.log(`${this.flags.manifest}:${error.line}:${error.column} - ${error.message}`);
|
|
53
|
+
}
|
|
54
|
+
if (allErrors && errors.length > 0) {
|
|
55
|
+
this.error('Manifest loaded with errors', { exit: 1 });
|
|
56
|
+
}
|
|
57
|
+
else if (errors.length > 0) {
|
|
58
|
+
this.warn('Manifest loaded with warnings');
|
|
59
|
+
}
|
|
60
|
+
if (apps.length === 0) {
|
|
61
|
+
this.error('No applications found in manifest', { exit: 1 });
|
|
62
|
+
}
|
|
63
|
+
return apps;
|
|
64
|
+
}
|
|
65
|
+
async catalogService() {
|
|
66
|
+
const rainbowAuth = useClient(RainbowAuthService, this.flags.rainbowAuthService);
|
|
67
|
+
return await createAuthenticatingClient(CatalogService, this.config.configDir, rainbowAuth);
|
|
68
|
+
}
|
|
69
|
+
}
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Application } from '@liquidmetal-ai/drizzle/appify/build';
|
|
2
|
+
import * as esbuild from 'esbuild';
|
|
3
|
+
export default function build(options: {
|
|
4
|
+
root: string;
|
|
5
|
+
entryPoints: string[];
|
|
6
|
+
outdir: string;
|
|
7
|
+
}): Promise<esbuild.BuildResult>;
|
|
8
|
+
interface Cmd {
|
|
9
|
+
log: (message?: string, ...args: any[]) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function buildHandlers(cmd: Cmd, apps: Application[], buildDir: string, root: string): Promise<void>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAW,MAAM,sCAAsC,CAAC;AAC5E,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,wBAA8B,KAAK,CAAC,OAAO,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAuD/B;AAED,UAAU,GAAG;IAGX,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CACjD;AAGD,wBAAsB,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,iBAwChG"}
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
|
|
2
|
+
import * as esbuild from 'esbuild';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { HANDLERS_DIR } from './codegen.js';
|
|
6
|
+
export default async function build(options) {
|
|
7
|
+
// Customize outbase so that even when only one entryPoint is provided,
|
|
8
|
+
// the output file is placed in the same directory as it would if
|
|
9
|
+
// another entryPoint were provided later.
|
|
10
|
+
let outbase;
|
|
11
|
+
if (options.entryPoints.length === 1) {
|
|
12
|
+
outbase = path.join(options.root, HANDLERS_DIR);
|
|
13
|
+
}
|
|
14
|
+
const buildResult = await esbuild.build({
|
|
15
|
+
entryPoints: options.entryPoints,
|
|
16
|
+
external: ['cloudflare:workers', 'crypto'],
|
|
17
|
+
bundle: true,
|
|
18
|
+
outdir: options.outdir,
|
|
19
|
+
outbase,
|
|
20
|
+
tsconfig: `${options.root}/tsconfig.json`,
|
|
21
|
+
// TODO [bosgood] Add support for middleware/code injection from wrangler
|
|
22
|
+
inject: [],
|
|
23
|
+
format: 'esm', // Only ES6 module format will be supported
|
|
24
|
+
sourcemap: true,
|
|
25
|
+
sourceRoot: options.outdir,
|
|
26
|
+
// Experiment: let's see how far we can get without minification because:
|
|
27
|
+
// 1) It should be slightly faster to build
|
|
28
|
+
// 2) It should be easier to debug
|
|
29
|
+
minify: false,
|
|
30
|
+
metafile: true,
|
|
31
|
+
// From wrangler:
|
|
32
|
+
target: 'es2022',
|
|
33
|
+
loader: { '.js': 'jsx', '.mjs': 'jsx', '.cjs': 'jsx' },
|
|
34
|
+
// Wrangler uses the browser platform for all builds by default,
|
|
35
|
+
// even when node_compat is enabled.
|
|
36
|
+
platform: 'browser',
|
|
37
|
+
// TODO [bosgood] Inlined from wrangler
|
|
38
|
+
// build conditions used by esbuild, and when resolving custom `import` calls
|
|
39
|
+
conditions: ['workerd', 'worker', 'browser'],
|
|
40
|
+
define: {
|
|
41
|
+
'navigator.userAgent': `"Cloudflare-Workers"`,
|
|
42
|
+
// TODO [bosgood] wrangler also optionally defines overrides for process.env.NODE_ENV
|
|
43
|
+
},
|
|
44
|
+
// The default logLevel is "warning". So that we can rewrite errors before
|
|
45
|
+
// logging, we disable esbuild's default logging, and log build failures
|
|
46
|
+
// ourselves.
|
|
47
|
+
logLevel: 'silent',
|
|
48
|
+
});
|
|
49
|
+
return buildResult;
|
|
50
|
+
}
|
|
51
|
+
// Builds the handlers for the given manifest
|
|
52
|
+
export async function buildHandlers(cmd, apps, buildDir, root) {
|
|
53
|
+
// Wipe out the output directory then rebuild
|
|
54
|
+
await fs.rm(buildDir, { force: true, recursive: true });
|
|
55
|
+
cmd.log(`Building to ${buildDir}`);
|
|
56
|
+
// Discover entrypoints from manifest
|
|
57
|
+
let entryPoints = [];
|
|
58
|
+
for (const app of apps) {
|
|
59
|
+
entryPoints = entryPoints.concat(app.handlers().map((handler) => path.join(root, HANDLERS_DIR, valueOf(handler.name), 'index.ts')));
|
|
60
|
+
}
|
|
61
|
+
if (entryPoints.length === 0) {
|
|
62
|
+
cmd.log('Nothing to build');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
cmd.log(`Building entry points:\n${entryPoints.join('\n')}`);
|
|
66
|
+
const buildResult = await build({
|
|
67
|
+
root: root,
|
|
68
|
+
entryPoints,
|
|
69
|
+
outdir: buildDir,
|
|
70
|
+
});
|
|
71
|
+
if (buildResult.errors.length > 0 || buildResult.warnings.length > 0) {
|
|
72
|
+
cmd.log('Build results');
|
|
73
|
+
}
|
|
74
|
+
if (buildResult.errors.length > 0) {
|
|
75
|
+
cmd.log(buildResult.errors.map((e) => e.text).join('\n'));
|
|
76
|
+
}
|
|
77
|
+
if (buildResult.warnings.length > 0) {
|
|
78
|
+
cmd.log(buildResult.warnings.map((w) => w.text).join('\n'));
|
|
79
|
+
}
|
|
80
|
+
if (buildResult.errors.length === 0) {
|
|
81
|
+
cmd.log('Build successful');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
cmd.log('Build failed', { exit: 1 });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.test.d.ts","sourceRoot":"","sources":["../src/build.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { expect, test } from 'vitest';
|
|
5
|
+
import build from './build.js';
|
|
6
|
+
const ENTRY_POINT = `
|
|
7
|
+
console.log('Hello, world!');
|
|
8
|
+
`;
|
|
9
|
+
const TSCONFIG = `
|
|
10
|
+
{
|
|
11
|
+
"compilerOptions": {
|
|
12
|
+
"target": "ESNext",
|
|
13
|
+
"module": "ESNext",
|
|
14
|
+
"moduleResolution": "Node",
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
|
18
|
+
"strict": true,
|
|
19
|
+
"isolatedModules": true,
|
|
20
|
+
"allowSyntheticDefaultImports": true,
|
|
21
|
+
"resolveJsonModule": true,
|
|
22
|
+
"jsx": "react-jsx",
|
|
23
|
+
"outDir": "dist",
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
test('build', async () => {
|
|
28
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'build-test'));
|
|
29
|
+
const srcDir = path.join(root, 'src');
|
|
30
|
+
await fs.mkdir(srcDir);
|
|
31
|
+
const tsconfig = path.join(root, 'tsconfig.json');
|
|
32
|
+
const entryPoint = path.join(root, 'src', 'index.ts');
|
|
33
|
+
await fs.writeFile(entryPoint, ENTRY_POINT);
|
|
34
|
+
await fs.writeFile(tsconfig, TSCONFIG);
|
|
35
|
+
await build({
|
|
36
|
+
root,
|
|
37
|
+
entryPoints: [entryPoint],
|
|
38
|
+
outdir: path.join(root, 'dist'),
|
|
39
|
+
});
|
|
40
|
+
expect(await fs.readdir(path.join(root, 'dist'))).toContain('index.js');
|
|
41
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Actor, Application, Observer, Service } from '@liquidmetal-ai/drizzle/appify/build';
|
|
2
|
+
export declare const TOOL_NAME = "raindrop build";
|
|
3
|
+
export declare const TEMPLATES_DIR: string;
|
|
4
|
+
export declare const TEMPLATE_INIT = "init";
|
|
5
|
+
export declare const GENERATED_EXTENSION = ".gen";
|
|
6
|
+
export declare const HANDLERS_DIR = "src";
|
|
7
|
+
export declare const RAINDROP_TYPES_FILENAME = "raindrop.gen.ts";
|
|
8
|
+
export declare function trimTemplateSuffix(filename: string): string;
|
|
9
|
+
type TemplateContext = Record<string, string | number>;
|
|
10
|
+
export declare function renderTemplateFromString(template: string, context: TemplateContext): string;
|
|
11
|
+
export declare function renderTemplateFromFile(templatePath: string, context: TemplateContext): Promise<string>;
|
|
12
|
+
export declare function renderTemplatesFromDirectory(templatePath: string, outPath: string, context: TemplateContext, opts: CodegenOptions): Promise<void>;
|
|
13
|
+
export declare function shouldWriteTemplate(opts: CodegenOptions, relPath: string): boolean;
|
|
14
|
+
export type CodegenOptions = {
|
|
15
|
+
renderScaffoldingCode?: boolean;
|
|
16
|
+
renderUserModifiableCode?: boolean;
|
|
17
|
+
renderNonUserModifiableCode?: boolean;
|
|
18
|
+
overwrite?: boolean;
|
|
19
|
+
} | undefined;
|
|
20
|
+
export declare function renderCodegenPlan(plan: CodegenPlan, outPath: string | undefined, opts: CodegenOptions, context?: TemplateContext): Promise<void>;
|
|
21
|
+
export type CodegenPlan = {
|
|
22
|
+
templateName: string;
|
|
23
|
+
outPath: string;
|
|
24
|
+
context?: TemplateContext;
|
|
25
|
+
}[];
|
|
26
|
+
export declare function codegenPlan(apps: Application[]): CodegenPlan;
|
|
27
|
+
export declare function gatherEnvForHandler(handler: Actor | Service | Observer, app: Application): string;
|
|
28
|
+
export declare function fileExists(path: string): Promise<boolean>;
|
|
29
|
+
export type DirWalkCallback = (relPath: string) => void | Promise<void>;
|
|
30
|
+
export declare function dirWalk(dir: string, visitFn: DirWalkCallback): Promise<void>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=codegen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAW,MAAM,sCAAsC,CAAC;AAKtG,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,eAAO,MAAM,aAAa,QAA6E,CAAC;AACxG,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,eAAO,MAAM,YAAY,QAAQ,CAAC;AAClC,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AAYzD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAG3F;AAED,wBAAsB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5G;AAED,wBAAsB,4BAA4B,CAChD,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAqBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAYlF;AAED,MAAM,MAAM,cAAc,GACtB;IACA,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACC,SAAS,CAAC;AAEd,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,MAAM,GAAG,SAAqB,EACvC,IAAI,EAAE,cAAc,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B,EAAE,CAAC;AAGJ,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,CAsC5D;AAeD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAoDjG;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAGxE,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAalF"}
|
package/dist/codegen.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { valueOf } from '@liquidmetal-ai/drizzle/appify/build';
|
|
2
|
+
import Handlebars from 'handlebars';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
export const TOOL_NAME = 'raindrop build';
|
|
7
|
+
export const TEMPLATES_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'templates');
|
|
8
|
+
export const TEMPLATE_INIT = 'init';
|
|
9
|
+
export const GENERATED_EXTENSION = '.gen';
|
|
10
|
+
export const HANDLERS_DIR = 'src';
|
|
11
|
+
export const RAINDROP_TYPES_FILENAME = 'raindrop.gen.ts';
|
|
12
|
+
const TEMPLATE_R2_EVENT_NOTIFICATION = path.join('handlers', 'r2-event-notification');
|
|
13
|
+
const TEMPLATE_QUEUE_CONSUMER = path.join('handlers', 'queue-consumer');
|
|
14
|
+
const TEMPLATE_HTTP_SERVICE = path.join('handlers', 'http-service');
|
|
15
|
+
const TEMPLATE_ACTOR = path.join('handlers', 'actor');
|
|
16
|
+
const TEMPLATE_EXTENSION = '.hbs';
|
|
17
|
+
const SCAFFOLDING_PREFIX = '__';
|
|
18
|
+
const HANDLEBARS_RENDER_OPTS = {
|
|
19
|
+
strict: true, // Fail on missing variables
|
|
20
|
+
noEscape: true, // Do not escape HTML
|
|
21
|
+
};
|
|
22
|
+
export function trimTemplateSuffix(filename) {
|
|
23
|
+
return filename.replace(new RegExp(`${TEMPLATE_EXTENSION}$`), '');
|
|
24
|
+
}
|
|
25
|
+
export function renderTemplateFromString(template, context) {
|
|
26
|
+
const compiledTemplate = Handlebars.compile(template, HANDLEBARS_RENDER_OPTS);
|
|
27
|
+
return compiledTemplate(context);
|
|
28
|
+
}
|
|
29
|
+
export async function renderTemplateFromFile(templatePath, context) {
|
|
30
|
+
const template = await fs.readFile(templatePath, 'utf-8');
|
|
31
|
+
return renderTemplateFromString(template, context);
|
|
32
|
+
}
|
|
33
|
+
export async function renderTemplatesFromDirectory(templatePath, outPath, context, opts) {
|
|
34
|
+
const visit = async (relPath) => {
|
|
35
|
+
if (!shouldWriteTemplate(opts, relPath)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const rawContent = await fs.readFile(path.join(templatePath, relPath), 'utf-8');
|
|
39
|
+
// Templates are rendered, other files are copied
|
|
40
|
+
const content = relPath.endsWith(TEMPLATE_EXTENSION)
|
|
41
|
+
? await renderTemplateFromFile(path.join(templatePath, relPath), context)
|
|
42
|
+
: rawContent;
|
|
43
|
+
const outputFilename = trimTemplateSuffix(relPath);
|
|
44
|
+
await fs.mkdir(path.join(outPath, path.dirname(outputFilename)), { recursive: true });
|
|
45
|
+
const outputFilePath = path.join(outPath, outputFilename);
|
|
46
|
+
const alreadyExists = await fileExists(outputFilePath);
|
|
47
|
+
if (alreadyExists && !opts?.overwrite) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
await fs.writeFile(outputFilePath, content);
|
|
51
|
+
};
|
|
52
|
+
return await dirWalk(templatePath, visit);
|
|
53
|
+
}
|
|
54
|
+
function templateType(relPath) {
|
|
55
|
+
if (path.basename(relPath).startsWith(SCAFFOLDING_PREFIX)) {
|
|
56
|
+
return 'scaffolding';
|
|
57
|
+
}
|
|
58
|
+
if (path.basename(relPath).includes(GENERATED_EXTENSION)) {
|
|
59
|
+
return 'non-user-modifiable';
|
|
60
|
+
}
|
|
61
|
+
return 'user-modifiable';
|
|
62
|
+
}
|
|
63
|
+
export function shouldWriteTemplate(opts, relPath) {
|
|
64
|
+
const type = templateType(relPath);
|
|
65
|
+
if (type == 'scaffolding' && !opts?.renderScaffoldingCode) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (type == 'non-user-modifiable' && !opts?.renderNonUserModifiableCode) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (!['scaffolding', 'non-user-modifiable'].includes(type) && !opts?.renderUserModifiableCode) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
export async function renderCodegenPlan(plan, outPath = undefined, opts, context = {}) {
|
|
77
|
+
const templateContext = {
|
|
78
|
+
...context,
|
|
79
|
+
toolName: TOOL_NAME,
|
|
80
|
+
};
|
|
81
|
+
for (const task of plan) {
|
|
82
|
+
await renderTemplatesFromDirectory(task.templateName, outPath ? path.join(outPath, task.outPath) : task.outPath, { ...templateContext, ...task.context }, opts);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Creates a list of codegen tasks based on the app configuration
|
|
86
|
+
export function codegenPlan(apps) {
|
|
87
|
+
const plan = [];
|
|
88
|
+
// Initialization template is always included
|
|
89
|
+
plan.push({
|
|
90
|
+
templateName: path.join(TEMPLATES_DIR, TEMPLATE_INIT),
|
|
91
|
+
outPath: '',
|
|
92
|
+
});
|
|
93
|
+
for (const app of apps) {
|
|
94
|
+
for (const observer of app.observer) {
|
|
95
|
+
// Technically HCL is allowing multiple sources. This may or may not be something we want to support
|
|
96
|
+
// for raindrop build, but for now let's codegen only on the first available source
|
|
97
|
+
const primeSource = observer.source[0];
|
|
98
|
+
const templateName = primeSource?.bucket ? TEMPLATE_R2_EVENT_NOTIFICATION : TEMPLATE_QUEUE_CONSUMER;
|
|
99
|
+
plan.push({
|
|
100
|
+
templateName: path.join(TEMPLATES_DIR, templateName),
|
|
101
|
+
outPath: path.join(HANDLERS_DIR, valueOf(observer.name)),
|
|
102
|
+
context: { observerName: valueOf(observer.name) },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
for (const service of app.service) {
|
|
106
|
+
plan.push({
|
|
107
|
+
templateName: path.join(TEMPLATES_DIR, TEMPLATE_HTTP_SERVICE),
|
|
108
|
+
outPath: path.join(HANDLERS_DIR, valueOf(service.name)),
|
|
109
|
+
context: { serviceName: valueOf(service.name) },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
for (const actor of app.actor) {
|
|
113
|
+
plan.push({
|
|
114
|
+
templateName: path.join(TEMPLATES_DIR, TEMPLATE_ACTOR),
|
|
115
|
+
outPath: path.join(HANDLERS_DIR, valueOf(actor.name)),
|
|
116
|
+
context: { actorClassName: kebabCaseToCamelCase(valueOf(actor.name)) },
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return plan;
|
|
121
|
+
}
|
|
122
|
+
const TYPE_DEFINITIONS_TEMPLATE = Handlebars.compile(`// Code generated by {{ toolName }}, DO NOT EDIT.
|
|
123
|
+
export interface Env {
|
|
124
|
+
{{#each resources}}
|
|
125
|
+
{{this.name}}: {{{this.type}}};
|
|
126
|
+
{{/each}}
|
|
127
|
+
}
|
|
128
|
+
`, HANDLEBARS_RENDER_OPTS);
|
|
129
|
+
// gatherEnvForHandler gathers up the entire environment mapping for
|
|
130
|
+
// the Env object on the handler.
|
|
131
|
+
export function gatherEnvForHandler(handler, app) {
|
|
132
|
+
const bindings = {};
|
|
133
|
+
// Iterate over the entire app and gather all the bindings.
|
|
134
|
+
for (const appService of app.service) {
|
|
135
|
+
if (appService !== handler) {
|
|
136
|
+
bindings[kebabCaseToConstantCase(valueOf(appService.name))] = `import('../${valueOf(appService.name)}').default`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const appActor of app.actor) {
|
|
140
|
+
const actorName = valueOf(appActor.name);
|
|
141
|
+
const actorClass = kebabCaseToCamelCase(actorName);
|
|
142
|
+
if (appActor === handler) {
|
|
143
|
+
bindings[kebabCaseToConstantCase(valueOf(appActor.name))] = `DurableObjectNamespace<import('./index.js').${actorClass}>`;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
bindings[kebabCaseToConstantCase(valueOf(appActor.name))] = `DurableObjectNamespace<import('../${actorName}').${actorClass}>`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const appObserver of app.observer) {
|
|
150
|
+
// Don't allow self-queueing.
|
|
151
|
+
if (appObserver === handler) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
for (const source of appObserver.source) {
|
|
155
|
+
// Only bind queue sources, not bucket sources.
|
|
156
|
+
if (source.queue) {
|
|
157
|
+
bindings[kebabCaseToConstantCase(valueOf(source.queue))] = `Queue<import('../${valueOf(appObserver.name)}').Body>`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const appBucket of app.bucket) {
|
|
162
|
+
bindings[kebabCaseToConstantCase(valueOf(appBucket.name))] = 'R2Bucket';
|
|
163
|
+
}
|
|
164
|
+
for (const appSqlDatabase of app.sqlDatabase) {
|
|
165
|
+
bindings[kebabCaseToConstantCase(valueOf(appSqlDatabase.name))] = 'D1Database';
|
|
166
|
+
}
|
|
167
|
+
for (const appVectorizeIndex of app.vectorIndex) {
|
|
168
|
+
bindings[kebabCaseToConstantCase(valueOf(appVectorizeIndex.name))] = 'VectorizeIndex';
|
|
169
|
+
}
|
|
170
|
+
for (const env of app.env) {
|
|
171
|
+
bindings[kebabCaseToConstantCase(valueOf(env.name))] = 'string';
|
|
172
|
+
}
|
|
173
|
+
for (const env of handler.env) {
|
|
174
|
+
bindings[kebabCaseToConstantCase(valueOf(env.name))] = 'string';
|
|
175
|
+
}
|
|
176
|
+
bindings['AI'] = 'Ai';
|
|
177
|
+
return TYPE_DEFINITIONS_TEMPLATE({
|
|
178
|
+
toolName: TOOL_NAME,
|
|
179
|
+
resources: Object.entries(bindings)
|
|
180
|
+
.map(([name, type]) => ({ name, type }))
|
|
181
|
+
.sort((a, b) => a.name.localeCompare(b.name)),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
export async function fileExists(path) {
|
|
185
|
+
try {
|
|
186
|
+
await fs.lstat(path);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// dirWalk walks a directory tree and calls the callback for each file it encounters
|
|
194
|
+
export async function dirWalk(dir, visitFn) {
|
|
195
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
196
|
+
const tasks = entries.map(async (entry) => {
|
|
197
|
+
if (entry.isDirectory()) {
|
|
198
|
+
await dirWalk(path.join(dir, entry.name), visitFn);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Process encountered file
|
|
202
|
+
await visitFn(entry.name);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
await Promise.all(tasks);
|
|
206
|
+
}
|
|
207
|
+
function kebabCaseToConstantCase(s) {
|
|
208
|
+
return s.toUpperCase().replace(/-/g, '_');
|
|
209
|
+
}
|
|
210
|
+
function kebabCaseToCamelCase(s) {
|
|
211
|
+
return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
212
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.test.d.ts","sourceRoot":"","sources":["../src/codegen.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mustManifestFromString } from '@liquidmetal-ai/drizzle/appify/index';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { expect, test } from 'vitest';
|
|
6
|
+
import { codegenPlan, renderTemplatesFromDirectory, shouldWriteTemplate, trimTemplateSuffix, } from './codegen.js';
|
|
7
|
+
test('trims handlebars suffix', async () => {
|
|
8
|
+
expect(trimTemplateSuffix('index.ts.hbs')).toEqual('index.ts');
|
|
9
|
+
});
|
|
10
|
+
test('codegens from blank app', async () => {
|
|
11
|
+
const apps = await mustManifestFromString(`
|
|
12
|
+
application "ingest" {}
|
|
13
|
+
`);
|
|
14
|
+
const plan = codegenPlan(apps);
|
|
15
|
+
expect(Object.keys(plan)).toHaveLength(1);
|
|
16
|
+
expect(plan[0]?.templateName).toMatch('templates/init');
|
|
17
|
+
expect(plan[0]?.outPath).toEqual('');
|
|
18
|
+
});
|
|
19
|
+
test('codegens from app with observer', async () => {
|
|
20
|
+
const apps = await mustManifestFromString(`
|
|
21
|
+
application "ingest" {
|
|
22
|
+
bucket "bucket" {}
|
|
23
|
+
|
|
24
|
+
observer "process" {
|
|
25
|
+
source {
|
|
26
|
+
bucket = "bucket"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`);
|
|
31
|
+
const plan = codegenPlan(apps);
|
|
32
|
+
expect(Object.keys(plan)).toHaveLength(2);
|
|
33
|
+
expect(plan[1]?.templateName).toMatch('templates/handlers/r2-event-notification');
|
|
34
|
+
expect(plan[1]?.outPath).toEqual('src/process');
|
|
35
|
+
});
|
|
36
|
+
test('codegens from app with service', async () => {
|
|
37
|
+
const apps = await mustManifestFromString(`
|
|
38
|
+
application "ingest" {
|
|
39
|
+
bucket "bucket" {}
|
|
40
|
+
|
|
41
|
+
service "ingester" {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`);
|
|
45
|
+
const plan = codegenPlan(apps);
|
|
46
|
+
expect(Object.keys(plan)).toHaveLength(2);
|
|
47
|
+
expect(plan[1]?.templateName).toMatch('templates/handlers/http-service');
|
|
48
|
+
expect(plan[1]?.outPath).toEqual('src/ingester');
|
|
49
|
+
});
|
|
50
|
+
test('codegens from app with durable object', async () => {
|
|
51
|
+
const apps = await mustManifestFromString(`
|
|
52
|
+
application "ingest" {
|
|
53
|
+
actor "ingest-object" {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`);
|
|
57
|
+
const plan = codegenPlan(apps);
|
|
58
|
+
expect(Object.keys(plan)).toHaveLength(2);
|
|
59
|
+
expect(plan[1]?.templateName).toMatch('templates/handlers/actor');
|
|
60
|
+
expect(plan[1]?.outPath).toEqual('src/ingest-object');
|
|
61
|
+
});
|
|
62
|
+
test('only codegens scaffolding when enabled', () => {
|
|
63
|
+
expect(shouldWriteTemplate({
|
|
64
|
+
renderScaffoldingCode: true,
|
|
65
|
+
}, 'src/handlers/something/__index.ts')).toBe(true);
|
|
66
|
+
expect(shouldWriteTemplate({
|
|
67
|
+
renderScaffoldingCode: false,
|
|
68
|
+
}, 'src/handlers/something/__index.ts')).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
test('only codegens user modifiable code when enabled', () => {
|
|
71
|
+
expect(shouldWriteTemplate({
|
|
72
|
+
renderUserModifiableCode: true,
|
|
73
|
+
}, 'src/handlers/something/index.ts')).toBe(true);
|
|
74
|
+
expect(shouldWriteTemplate({
|
|
75
|
+
renderUserModifiableCode: false,
|
|
76
|
+
}, 'src/handlers/something/index.ts')).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
test('only codegens non-user modifiable code when enabled', () => {
|
|
79
|
+
expect(shouldWriteTemplate({
|
|
80
|
+
renderNonUserModifiableCode: true,
|
|
81
|
+
}, 'src/handlers/something/env.gen.d.ts')).toBe(true);
|
|
82
|
+
expect(shouldWriteTemplate({
|
|
83
|
+
renderNonUserModifiableCode: false,
|
|
84
|
+
}, 'src/handlers/something/env.gen.d.ts')).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
test('codegens template files', async () => {
|
|
87
|
+
const templatePath = path.join(__dirname, '..', 'templates', 'init');
|
|
88
|
+
const outPath = await fs.mkdtemp(path.join(os.tmpdir(), 'codegen-test'));
|
|
89
|
+
await renderTemplatesFromDirectory(templatePath, outPath, {
|
|
90
|
+
toolName: 'raindrop',
|
|
91
|
+
applicationName: 'test-app',
|
|
92
|
+
}, {
|
|
93
|
+
renderScaffoldingCode: true,
|
|
94
|
+
renderUserModifiableCode: true,
|
|
95
|
+
renderNonUserModifiableCode: true,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class List extends BaseCommand<typeof List> {
|
|
3
|
+
static args: {};
|
|
4
|
+
static description: string;
|
|
5
|
+
static flags: {
|
|
6
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,WAAW,CAAC,OAAO,IAAI,CAAC;IACxD,MAAM,CAAC,IAAI,KAAM;IAEjB,MAAM,CAAC,WAAW,SAA0B;IAE5C,MAAM,CAAC,KAAK;;MAOV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAmD3B"}
|