@ryanatkn/gro 0.112.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 +21 -0
- package/README.md +257 -0
- package/dist/args.d.ts +59 -0
- package/dist/args.js +132 -0
- package/dist/args.test.d.ts +1 -0
- package/dist/args.test.js +43 -0
- package/dist/build.task.d.ts +11 -0
- package/dist/build.task.js +24 -0
- package/dist/changelog.d.ts +8 -0
- package/dist/changelog.js +47 -0
- package/dist/changelog.test.d.ts +1 -0
- package/dist/changelog.test.js +118 -0
- package/dist/changeset.task.d.ts +49 -0
- package/dist/changeset.task.js +141 -0
- package/dist/check.task.d.ts +47 -0
- package/dist/check.task.js +77 -0
- package/dist/clean.task.d.ts +26 -0
- package/dist/clean.task.js +41 -0
- package/dist/clean_fs.d.ts +9 -0
- package/dist/clean_fs.js +27 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +25 -0
- package/dist/commit.task.d.ts +11 -0
- package/dist/commit.task.js +22 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.js +42 -0
- package/dist/config.test.d.ts +1 -0
- package/dist/config.test.js +8 -0
- package/dist/deploy.task.d.ts +47 -0
- package/dist/deploy.task.js +198 -0
- package/dist/dev.task.d.ts +22 -0
- package/dist/dev.task.js +32 -0
- package/dist/docs/README.gen.md.d.ts +5 -0
- package/dist/docs/README.gen.md.js +53 -0
- package/dist/docs/README.md +20 -0
- package/dist/docs/build.md +41 -0
- package/dist/docs/config.md +162 -0
- package/dist/docs/deploy.md +32 -0
- package/dist/docs/dev.md +40 -0
- package/dist/docs/gen.md +241 -0
- package/dist/docs/gro_plugin_sveltekit_frontend.md +97 -0
- package/dist/docs/package_json.md +29 -0
- package/dist/docs/plugin.md +50 -0
- package/dist/docs/publish.md +144 -0
- package/dist/docs/task.md +377 -0
- package/dist/docs/tasks.gen.md.d.ts +2 -0
- package/dist/docs/tasks.gen.md.js +60 -0
- package/dist/docs/tasks.md +35 -0
- package/dist/docs/test.md +52 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.js +47 -0
- package/dist/esbuild_helpers.d.ts +14 -0
- package/dist/esbuild_helpers.js +36 -0
- package/dist/esbuild_plugin_external_worker.d.ts +22 -0
- package/dist/esbuild_plugin_external_worker.js +49 -0
- package/dist/esbuild_plugin_svelte.d.ts +9 -0
- package/dist/esbuild_plugin_svelte.js +49 -0
- package/dist/esbuild_plugin_sveltekit_local_imports.d.ts +7 -0
- package/dist/esbuild_plugin_sveltekit_local_imports.js +30 -0
- package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts +6 -0
- package/dist/esbuild_plugin_sveltekit_shim_alias.js +16 -0
- package/dist/esbuild_plugin_sveltekit_shim_app.d.ts +8 -0
- package/dist/esbuild_plugin_sveltekit_shim_app.js +23 -0
- package/dist/esbuild_plugin_sveltekit_shim_env.d.ts +10 -0
- package/dist/esbuild_plugin_sveltekit_shim_env.js +18 -0
- package/dist/format.task.d.ts +11 -0
- package/dist/format.task.js +24 -0
- package/dist/format_directory.d.ts +2 -0
- package/dist/format_directory.js +27 -0
- package/dist/format_file.d.ts +8 -0
- package/dist/format_file.js +42 -0
- package/dist/format_file.test.d.ts +1 -0
- package/dist/format_file.test.js +16 -0
- package/dist/fs.d.ts +7 -0
- package/dist/fs.js +19 -0
- package/dist/fs.test.d.ts +1 -0
- package/dist/fs.test.js +16 -0
- package/dist/gen.d.ts +57 -0
- package/dist/gen.js +81 -0
- package/dist/gen.task.d.ts +14 -0
- package/dist/gen.task.js +103 -0
- package/dist/gen.test.d.ts +1 -0
- package/dist/gen.test.js +239 -0
- package/dist/gen_module.d.ts +46 -0
- package/dist/gen_module.js +54 -0
- package/dist/gen_module.test.d.ts +1 -0
- package/dist/gen_module.test.js +30 -0
- package/dist/git.d.ts +76 -0
- package/dist/git.js +200 -0
- package/dist/git.test.d.ts +1 -0
- package/dist/git.test.js +18 -0
- package/dist/github.d.ts +35 -0
- package/dist/github.js +32 -0
- package/dist/gro.config.default.d.ts +12 -0
- package/dist/gro.config.default.js +31 -0
- package/dist/gro.d.ts +2 -0
- package/dist/gro.js +19 -0
- package/dist/gro_helpers.d.ts +43 -0
- package/dist/gro_helpers.js +79 -0
- package/dist/gro_plugin_gen.d.ts +6 -0
- package/dist/gro_plugin_gen.js +80 -0
- package/dist/gro_plugin_server.d.ts +77 -0
- package/dist/gro_plugin_server.js +152 -0
- package/dist/gro_plugin_sveltekit_app.d.ts +27 -0
- package/dist/gro_plugin_sveltekit_app.js +180 -0
- package/dist/gro_plugin_sveltekit_library.d.ts +4 -0
- package/dist/gro_plugin_sveltekit_library.js +42 -0
- package/dist/hash.d.ts +5 -0
- package/dist/hash.js +14 -0
- package/dist/hash.test.d.ts +1 -0
- package/dist/hash.test.js +25 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/input_path.d.ts +48 -0
- package/dist/input_path.js +161 -0
- package/dist/input_path.test.d.ts +1 -0
- package/dist/input_path.test.js +106 -0
- package/dist/invoke.d.ts +1 -0
- package/dist/invoke.js +18 -0
- package/dist/invoke_task.d.ts +20 -0
- package/dist/invoke_task.js +140 -0
- package/dist/lint.task.d.ts +11 -0
- package/dist/lint.task.js +29 -0
- package/dist/loader.d.ts +4 -0
- package/dist/loader.js +153 -0
- package/dist/module.d.ts +3 -0
- package/dist/module.js +6 -0
- package/dist/module.test.d.ts +1 -0
- package/dist/module.test.js +41 -0
- package/dist/modules.d.ts +60 -0
- package/dist/modules.js +103 -0
- package/dist/modules.test.d.ts +1 -0
- package/dist/modules.test.js +182 -0
- package/dist/package.d.ts +939 -0
- package/dist/package.gen.d.ts +7 -0
- package/dist/package.gen.js +26 -0
- package/dist/package.js +887 -0
- package/dist/package_json.d.ts +342 -0
- package/dist/package_json.js +212 -0
- package/dist/package_json.test.d.ts +1 -0
- package/dist/package_json.test.js +77 -0
- package/dist/path.d.ts +12 -0
- package/dist/path.js +8 -0
- package/dist/paths.d.ts +60 -0
- package/dist/paths.js +128 -0
- package/dist/paths.test.d.ts +1 -0
- package/dist/paths.test.js +49 -0
- package/dist/plugin.d.ts +36 -0
- package/dist/plugin.js +80 -0
- package/dist/plugin.test.d.ts +1 -0
- package/dist/plugin.test.js +54 -0
- package/dist/print_task.d.ts +4 -0
- package/dist/print_task.js +124 -0
- package/dist/publish.task.d.ts +32 -0
- package/dist/publish.task.js +125 -0
- package/dist/release.task.d.ts +5 -0
- package/dist/release.task.js +18 -0
- package/dist/resolve_node_specifier.d.ts +8 -0
- package/dist/resolve_node_specifier.js +39 -0
- package/dist/resolve_node_specifier.test.d.ts +1 -0
- package/dist/resolve_node_specifier.test.js +21 -0
- package/dist/resolve_specifier.d.ts +15 -0
- package/dist/resolve_specifier.js +51 -0
- package/dist/resolve_specifier.test.d.ts +1 -0
- package/dist/resolve_specifier.test.js +66 -0
- package/dist/run.task.d.ts +11 -0
- package/dist/run.task.js +31 -0
- package/dist/run_gen.d.ts +6 -0
- package/dist/run_gen.js +74 -0
- package/dist/run_gen.test.d.ts +1 -0
- package/dist/run_gen.test.js +182 -0
- package/dist/run_task.d.ts +13 -0
- package/dist/run_task.js +44 -0
- package/dist/run_task.test.d.ts +1 -0
- package/dist/run_task.test.js +63 -0
- package/dist/search_fs.d.ts +11 -0
- package/dist/search_fs.js +22 -0
- package/dist/search_fs.test.d.ts +1 -0
- package/dist/search_fs.test.js +46 -0
- package/dist/src_json.d.ts +256 -0
- package/dist/src_json.js +110 -0
- package/dist/src_json.test.d.ts +1 -0
- package/dist/src_json.test.js +52 -0
- package/dist/sveltekit_config.d.ts +36 -0
- package/dist/sveltekit_config.js +51 -0
- package/dist/sveltekit_shim_app.d.ts +10 -0
- package/dist/sveltekit_shim_app.js +31 -0
- package/dist/sveltekit_shim_app_environment.d.ts +10 -0
- package/dist/sveltekit_shim_app_environment.js +12 -0
- package/dist/sveltekit_shim_app_forms.d.ts +5 -0
- package/dist/sveltekit_shim_app_forms.js +13 -0
- package/dist/sveltekit_shim_app_navigation.d.ts +10 -0
- package/dist/sveltekit_shim_app_navigation.js +11 -0
- package/dist/sveltekit_shim_app_paths.d.ts +11 -0
- package/dist/sveltekit_shim_app_paths.js +6 -0
- package/dist/sveltekit_shim_app_stores.d.ts +6 -0
- package/dist/sveltekit_shim_app_stores.js +17 -0
- package/dist/sveltekit_shim_env.d.ts +4 -0
- package/dist/sveltekit_shim_env.js +23 -0
- package/dist/sync.task.d.ts +30 -0
- package/dist/sync.task.js +45 -0
- package/dist/task.d.ts +29 -0
- package/dist/task.js +17 -0
- package/dist/task.test.d.ts +1 -0
- package/dist/task.test.js +22 -0
- package/dist/task_module.d.ts +14 -0
- package/dist/task_module.js +19 -0
- package/dist/task_module.test.d.ts +1 -0
- package/dist/task_module.test.js +70 -0
- package/dist/test.task.d.ts +20 -0
- package/dist/test.task.js +43 -0
- package/dist/throttle.d.ts +16 -0
- package/dist/throttle.js +59 -0
- package/dist/throttle.test.d.ts +1 -0
- package/dist/throttle.test.js +49 -0
- package/dist/typecheck.task.d.ts +5 -0
- package/dist/typecheck.task.js +38 -0
- package/dist/upgrade.task.d.ts +14 -0
- package/dist/upgrade.task.js +37 -0
- package/dist/watch_dir.d.ts +30 -0
- package/dist/watch_dir.js +59 -0
- package/package.json +422 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { suite } from 'uvu';
|
|
2
|
+
import * as assert from 'uvu/assert';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { validate_task_module, load_task_module, load_task_modules } from './task_module.js';
|
|
5
|
+
import * as actual_test_task_module from './test.task.js';
|
|
6
|
+
// TODO if we import directly, svelte-package generates types in `src/fixtures`
|
|
7
|
+
/* eslint-disable no-useless-concat */
|
|
8
|
+
const test_task_module = await import('../fixtures/' + 'test_task_module.task_fixture');
|
|
9
|
+
const test_invalid_task_module = await import('../fixtures/' + 'test_invalid_task_module.js');
|
|
10
|
+
/* test__validate_task_module */
|
|
11
|
+
const test__validate_task_module = suite('validate_task_module');
|
|
12
|
+
test__validate_task_module('basic behavior', () => {
|
|
13
|
+
assert.ok(validate_task_module(test_task_module));
|
|
14
|
+
assert.ok(!validate_task_module(test_invalid_task_module));
|
|
15
|
+
assert.ok(!validate_task_module({ task: { run: {} } }));
|
|
16
|
+
});
|
|
17
|
+
test__validate_task_module.run();
|
|
18
|
+
/* test__validate_task_module */
|
|
19
|
+
/* test__load_task_module */
|
|
20
|
+
const test__load_task_module = suite('load_task_module');
|
|
21
|
+
test__load_task_module('basic behavior', async () => {
|
|
22
|
+
const name = 'fixtures/test_task_module.task_fixture.js';
|
|
23
|
+
const id = resolve('src/' + name);
|
|
24
|
+
const result = await load_task_module(id);
|
|
25
|
+
assert.ok(result.ok);
|
|
26
|
+
assert.is(result.mod.id, id);
|
|
27
|
+
assert.is(result.mod.id, id);
|
|
28
|
+
assert.is(result.mod.name, id); // TODO was `name` but changed after scoping to lib, but we want to relax that restriction
|
|
29
|
+
assert.is(result.mod.mod, test_task_module);
|
|
30
|
+
});
|
|
31
|
+
test__load_task_module('invalid module', async () => {
|
|
32
|
+
const id = resolve('src/fixtures/test_invalid_task_module.js');
|
|
33
|
+
const result = await load_task_module(id);
|
|
34
|
+
assert.ok(!result.ok);
|
|
35
|
+
if (result.type === 'invalid') {
|
|
36
|
+
assert.is(result.id, id);
|
|
37
|
+
assert.is(result.mod, test_invalid_task_module);
|
|
38
|
+
assert.is(result.validation, 'validate_task_module');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
throw Error('should be invalid');
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
test__load_task_module('failing module', async () => {
|
|
45
|
+
const id = resolve('src/fixtures/test_failing_task_module.js');
|
|
46
|
+
const result = await load_task_module(id);
|
|
47
|
+
assert.ok(!result.ok);
|
|
48
|
+
if (result.type === 'importFailed') {
|
|
49
|
+
assert.is(result.id, id);
|
|
50
|
+
assert.ok(result.error);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
throw Error('should have failed');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
test__load_task_module.run();
|
|
57
|
+
/* test__load_task_module */
|
|
58
|
+
/* test__load_task_modules */
|
|
59
|
+
const test__load_task_modules = suite('load_task_modules');
|
|
60
|
+
test__load_task_modules('basic behavior', async () => {
|
|
61
|
+
const result = await load_task_modules([
|
|
62
|
+
resolve('src/lib/test'),
|
|
63
|
+
resolve('src/lib/test.task.ts'),
|
|
64
|
+
]);
|
|
65
|
+
assert.ok(result.ok);
|
|
66
|
+
assert.is(result.modules.length, 1);
|
|
67
|
+
assert.is(result.modules[0].mod, actual_test_task_module);
|
|
68
|
+
});
|
|
69
|
+
test__load_task_modules.run();
|
|
70
|
+
/* test__load_task_modules */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type Task } from './task.js';
|
|
3
|
+
export declare const Args: z.ZodObject<{
|
|
4
|
+
_: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
5
|
+
bail: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
7
|
+
ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
|
+
}, "strict", z.ZodTypeAny, {
|
|
9
|
+
_: string[];
|
|
10
|
+
bail: boolean;
|
|
11
|
+
cwd?: string | undefined;
|
|
12
|
+
ignore?: string | string[] | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
_?: string[] | undefined;
|
|
15
|
+
bail?: boolean | undefined;
|
|
16
|
+
cwd?: string | undefined;
|
|
17
|
+
ignore?: string | string[] | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
export type Args = z.infer<typeof Args>;
|
|
20
|
+
export declare const task: Task<Args>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { yellow } from 'kleur/colors';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Task_Error } from './task.js';
|
|
4
|
+
import { paths } from './paths.js';
|
|
5
|
+
import { find_cli } from './cli.js';
|
|
6
|
+
export const Args = z
|
|
7
|
+
.object({
|
|
8
|
+
_: z.array(z.string(), { description: 'file patterns to test' }).default([`\\.test\\.ts$`]), // TODO maybe use uvu's default instead of being restrictive?
|
|
9
|
+
bail: z
|
|
10
|
+
.boolean({ description: 'the bail option to uvu run, exit immediately on failure' })
|
|
11
|
+
.default(false),
|
|
12
|
+
cwd: z.string({ description: 'the cwd option to uvu parse' }).optional(),
|
|
13
|
+
ignore: z
|
|
14
|
+
.union([z.string(), z.array(z.string())], { description: 'the ignore option to uvu parse' })
|
|
15
|
+
.optional(),
|
|
16
|
+
})
|
|
17
|
+
.strict();
|
|
18
|
+
export const task = {
|
|
19
|
+
summary: 'run tests with uvu',
|
|
20
|
+
Args,
|
|
21
|
+
run: async ({ args, log }) => {
|
|
22
|
+
const { _: patterns, bail, cwd, ignore } = args;
|
|
23
|
+
if (!(await find_cli('uvu'))) {
|
|
24
|
+
log.warn(yellow('uvu is not installed, skipping tests'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const { run } = await import('uvu/run');
|
|
28
|
+
const { parse } = await import('uvu/parse');
|
|
29
|
+
// uvu doesn't work with esm loaders and TypeScript files,
|
|
30
|
+
// so we use its `parse` and `run` APIs directly instead of its CLI.
|
|
31
|
+
// To avoid surprises, we allow any number of patterns in the rest args,
|
|
32
|
+
// so we call `parse` multiple times because it supports only one.
|
|
33
|
+
const suites = [];
|
|
34
|
+
for (const pattern of patterns) {
|
|
35
|
+
const parsed = await parse(paths.source, pattern, { cwd, ignore }); // eslint-disable-line no-await-in-loop
|
|
36
|
+
suites.push(...parsed.suites);
|
|
37
|
+
}
|
|
38
|
+
await run(suites, { bail });
|
|
39
|
+
if (process.exitCode) {
|
|
40
|
+
throw new Task_Error('Tests failed.');
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throttles calls to a callback that returns a void promise.
|
|
3
|
+
* Immediately invokes the callback on the first call.
|
|
4
|
+
* If the throttled function is called while the promise is already pending,
|
|
5
|
+
* the call is queued to run after the pending promise completes plus `delay`,
|
|
6
|
+
* and only the last call is invoked.
|
|
7
|
+
* In other words, all calls and their args are discarded
|
|
8
|
+
* during the pending window except for the most recent.
|
|
9
|
+
* Unlike debouncing, this calls the throttled callback
|
|
10
|
+
* both on the leading and trailing edges of the delay window.
|
|
11
|
+
* It also differs from a queue where every call to the throttled callback eventually runs.
|
|
12
|
+
* @param cb - any function that returns a void promise
|
|
13
|
+
* @param delay - delay this many milliseconds between the pending call finishing and the next starting
|
|
14
|
+
* @returns same as `cb`
|
|
15
|
+
*/
|
|
16
|
+
export declare const throttle: <T extends (...args: any[]) => Promise<void>>(cb: T, delay?: number) => T;
|
package/dist/throttle.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { wait } from '@ryanatkn/belt/async.js';
|
|
2
|
+
// TODO maybe support non-promise return values?
|
|
3
|
+
/**
|
|
4
|
+
* Throttles calls to a callback that returns a void promise.
|
|
5
|
+
* Immediately invokes the callback on the first call.
|
|
6
|
+
* If the throttled function is called while the promise is already pending,
|
|
7
|
+
* the call is queued to run after the pending promise completes plus `delay`,
|
|
8
|
+
* and only the last call is invoked.
|
|
9
|
+
* In other words, all calls and their args are discarded
|
|
10
|
+
* during the pending window except for the most recent.
|
|
11
|
+
* Unlike debouncing, this calls the throttled callback
|
|
12
|
+
* both on the leading and trailing edges of the delay window.
|
|
13
|
+
* It also differs from a queue where every call to the throttled callback eventually runs.
|
|
14
|
+
* @param cb - any function that returns a void promise
|
|
15
|
+
* @param delay - delay this many milliseconds between the pending call finishing and the next starting
|
|
16
|
+
* @returns same as `cb`
|
|
17
|
+
*/
|
|
18
|
+
export const throttle = (cb, delay = 0) => {
|
|
19
|
+
let pending_promise = null;
|
|
20
|
+
let next_args = null;
|
|
21
|
+
let next_promise = null;
|
|
22
|
+
let next_promise_resolve = null;
|
|
23
|
+
const defer = (args) => {
|
|
24
|
+
next_args = args;
|
|
25
|
+
if (!next_promise) {
|
|
26
|
+
next_promise = new Promise((resolve) => {
|
|
27
|
+
next_promise_resolve = resolve;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return next_promise;
|
|
31
|
+
};
|
|
32
|
+
const flush = async () => {
|
|
33
|
+
if (!next_promise_resolve)
|
|
34
|
+
return;
|
|
35
|
+
const result = await call(next_args);
|
|
36
|
+
next_args = null;
|
|
37
|
+
next_promise = null;
|
|
38
|
+
const resolve = next_promise_resolve;
|
|
39
|
+
next_promise_resolve = null;
|
|
40
|
+
resolve(result); // resolve last to prevent synchronous call issues
|
|
41
|
+
};
|
|
42
|
+
const call = (args) => {
|
|
43
|
+
pending_promise = cb(...args);
|
|
44
|
+
void pending_promise.then(async () => {
|
|
45
|
+
await wait(delay);
|
|
46
|
+
pending_promise = null;
|
|
47
|
+
await flush();
|
|
48
|
+
});
|
|
49
|
+
return pending_promise;
|
|
50
|
+
};
|
|
51
|
+
return ((...args) => {
|
|
52
|
+
if (pending_promise) {
|
|
53
|
+
return defer(args);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return call(args);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { wait } from '@ryanatkn/belt/async.js';
|
|
2
|
+
import { test } from 'uvu';
|
|
3
|
+
import * as assert from 'uvu/assert';
|
|
4
|
+
import { throttle } from './throttle.js';
|
|
5
|
+
test('throttles calls to a function', async () => {
|
|
6
|
+
const results = [];
|
|
7
|
+
const fn = throttle(async (name) => {
|
|
8
|
+
results.push(name + '_run');
|
|
9
|
+
await wait();
|
|
10
|
+
results.push(name + '_done');
|
|
11
|
+
});
|
|
12
|
+
const promise_a = fn('a');
|
|
13
|
+
const promise_b = fn('b'); // discarded
|
|
14
|
+
const promise_c = fn('c'); // discarded
|
|
15
|
+
const promise_d = fn('d');
|
|
16
|
+
assert.ok(promise_a !== promise_b);
|
|
17
|
+
assert.is(promise_b, promise_c);
|
|
18
|
+
assert.is(promise_b, promise_d);
|
|
19
|
+
assert.equal(results, ['a_run']);
|
|
20
|
+
await promise_a;
|
|
21
|
+
assert.equal(results, ['a_run', 'a_done']);
|
|
22
|
+
await promise_b;
|
|
23
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done']);
|
|
24
|
+
const promise_e = fn('e'); // discarded
|
|
25
|
+
const promise_f = fn('f');
|
|
26
|
+
assert.ok(promise_d !== promise_e);
|
|
27
|
+
assert.is(promise_e, promise_f);
|
|
28
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done']); // delayed
|
|
29
|
+
await wait();
|
|
30
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done', 'f_run']);
|
|
31
|
+
await promise_e;
|
|
32
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done', 'f_run', 'f_done']);
|
|
33
|
+
const promise_g = fn('g');
|
|
34
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done', 'f_run', 'f_done']); // delayed
|
|
35
|
+
await wait();
|
|
36
|
+
assert.equal(results, ['a_run', 'a_done', 'd_run', 'd_done', 'f_run', 'f_done', 'g_run']);
|
|
37
|
+
await promise_g;
|
|
38
|
+
assert.equal(results, [
|
|
39
|
+
'a_run',
|
|
40
|
+
'a_done',
|
|
41
|
+
'd_run',
|
|
42
|
+
'd_done',
|
|
43
|
+
'f_run',
|
|
44
|
+
'f_done',
|
|
45
|
+
'g_run',
|
|
46
|
+
'g_done',
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
test.run();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { print_spawn_result } from '@ryanatkn/belt/process.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Task_Error } from './task.js';
|
|
4
|
+
import { print_command_args, serialize_args, to_forwarded_args } from './args.js';
|
|
5
|
+
import { find_cli, spawn_cli } from './cli.js';
|
|
6
|
+
import { sveltekit_sync } from './sync.task.js';
|
|
7
|
+
export const Args = z.object({}).strict();
|
|
8
|
+
export const task = {
|
|
9
|
+
summary: 'run tsc on the project without emitting any files',
|
|
10
|
+
Args,
|
|
11
|
+
run: async ({ log }) => {
|
|
12
|
+
await sveltekit_sync();
|
|
13
|
+
if (await find_cli('svelte-check')) {
|
|
14
|
+
// svelte-check
|
|
15
|
+
const serialized = serialize_args(to_forwarded_args('svelte-check'));
|
|
16
|
+
log.info(print_command_args(['svelte-check'].concat(serialized)));
|
|
17
|
+
const svelte_check_result = await spawn_cli('svelte-check', serialized);
|
|
18
|
+
if (!svelte_check_result?.ok) {
|
|
19
|
+
throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result)}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (await find_cli('tsc')) {
|
|
23
|
+
// tsc
|
|
24
|
+
const forwarded = to_forwarded_args('tsc');
|
|
25
|
+
if (!forwarded.noEmit)
|
|
26
|
+
forwarded.noEmit = true;
|
|
27
|
+
const serialized = serialize_args(forwarded);
|
|
28
|
+
log.info(print_command_args(['tsc'].concat(serialized)));
|
|
29
|
+
const svelte_check_result = await spawn_cli('tsc', serialized);
|
|
30
|
+
if (!svelte_check_result?.ok) {
|
|
31
|
+
throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Task_Error(`Failed to typecheck because neither tsc nor svelte-check was found`);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Task } from './task.js';
|
|
3
|
+
export declare const Args: z.ZodObject<{
|
|
4
|
+
_: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
5
|
+
dry: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
}, "strict", z.ZodTypeAny, {
|
|
7
|
+
_: string[];
|
|
8
|
+
dry: boolean;
|
|
9
|
+
}, {
|
|
10
|
+
_?: string[] | undefined;
|
|
11
|
+
dry?: boolean | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export type Args = z.infer<typeof Args>;
|
|
14
|
+
export declare const task: Task<Args>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { spawn } from '@ryanatkn/belt/process.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { load_package_json } from './package_json.js';
|
|
4
|
+
export const Args = z
|
|
5
|
+
.object({
|
|
6
|
+
_: z.array(z.string(), { description: 'names of deps to exclude from the upgrade' }).default([]),
|
|
7
|
+
dry: z.boolean({ description: 'if true, print out the planned upgrades' }).default(false),
|
|
8
|
+
})
|
|
9
|
+
.strict();
|
|
10
|
+
export const task = {
|
|
11
|
+
summary: 'upgrade deps',
|
|
12
|
+
Args,
|
|
13
|
+
run: async ({ args, log, invoke_task }) => {
|
|
14
|
+
const { _, dry } = args;
|
|
15
|
+
const package_json = await load_package_json();
|
|
16
|
+
const deps = to_deps(package_json).filter((d) => !_.includes(d.key));
|
|
17
|
+
const upgrade_items = to_upgrade_items(deps);
|
|
18
|
+
if (dry) {
|
|
19
|
+
log.info(`deps`, deps);
|
|
20
|
+
log.info(`upgrade_items`, upgrade_items);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
log.info(`upgrading:`, upgrade_items.join(' '));
|
|
24
|
+
await spawn('npm', ['i'].concat(upgrade_items));
|
|
25
|
+
await invoke_task('sync');
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const to_deps = (package_json) => {
|
|
29
|
+
const prod_deps = package_json.dependencies
|
|
30
|
+
? Object.entries(package_json.dependencies).map(([key, value]) => ({ key, value }))
|
|
31
|
+
: [];
|
|
32
|
+
const dev_deps = package_json.devDependencies
|
|
33
|
+
? Object.entries(package_json.devDependencies).map(([key, value]) => ({ key, value }))
|
|
34
|
+
: [];
|
|
35
|
+
return prod_deps.concat(dev_deps);
|
|
36
|
+
};
|
|
37
|
+
const to_upgrade_items = (deps) => deps.map((dep) => dep.key + (dep.value.includes('-next.') ? '@next' : '@latest'));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type WatchOptions } from 'chokidar';
|
|
2
|
+
import type { Path_Stats, Path_Filter } from './path.js';
|
|
3
|
+
export interface Watch_Node_Fs {
|
|
4
|
+
init: () => Promise<void>;
|
|
5
|
+
close: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export interface Watcher_Change {
|
|
8
|
+
type: Watcher_Change_Type;
|
|
9
|
+
path: string;
|
|
10
|
+
stats: Path_Stats;
|
|
11
|
+
}
|
|
12
|
+
export type Watcher_Change_Type = 'create' | 'update' | 'delete';
|
|
13
|
+
export interface Watcher_Change_Callback {
|
|
14
|
+
(change: Watcher_Change): void;
|
|
15
|
+
}
|
|
16
|
+
export interface Options {
|
|
17
|
+
dir: string;
|
|
18
|
+
on_change: Watcher_Change_Callback;
|
|
19
|
+
filter?: Path_Filter | null | undefined;
|
|
20
|
+
chokidar?: WatchOptions;
|
|
21
|
+
/**
|
|
22
|
+
* When `false`, returns the `path` relative to `dir`.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
absolute?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Watch for changes on the filesystem using chokidar.
|
|
29
|
+
*/
|
|
30
|
+
export declare const watch_dir: ({ dir, on_change, filter, absolute, chokidar: chokidar_options, }: Options) => Watch_Node_Fs;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import chokidar, {} from 'chokidar';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { relative } from 'node:path';
|
|
4
|
+
const FILE_STATS = { isDirectory: () => false };
|
|
5
|
+
const DIR_STATS = { isDirectory: () => true };
|
|
6
|
+
/**
|
|
7
|
+
* Watch for changes on the filesystem using chokidar.
|
|
8
|
+
*/
|
|
9
|
+
export const watch_dir = ({ dir, on_change, filter, absolute = true, chokidar: chokidar_options, }) => {
|
|
10
|
+
let watcher;
|
|
11
|
+
return {
|
|
12
|
+
init: async () => {
|
|
13
|
+
watcher = chokidar.watch(dir, chokidar_options);
|
|
14
|
+
watcher.on('add', async (path, s) => {
|
|
15
|
+
const stats = s || (await stat(path));
|
|
16
|
+
const final_path = absolute ? path : relative(dir, path);
|
|
17
|
+
if (filter && !filter(final_path, stats))
|
|
18
|
+
return;
|
|
19
|
+
on_change({ type: 'create', path: final_path, stats });
|
|
20
|
+
});
|
|
21
|
+
watcher.on('addDir', async (path, s) => {
|
|
22
|
+
const stats = s || (await stat(path));
|
|
23
|
+
const final_path = absolute ? path : relative(dir, path);
|
|
24
|
+
if (filter && !filter(final_path, stats))
|
|
25
|
+
return;
|
|
26
|
+
on_change({ type: 'create', path: final_path, stats });
|
|
27
|
+
});
|
|
28
|
+
watcher.on('change', async (path, s) => {
|
|
29
|
+
const stats = s || (await stat(path));
|
|
30
|
+
const final_path = absolute ? path : relative(dir, path);
|
|
31
|
+
if (filter && !filter(final_path, stats))
|
|
32
|
+
return;
|
|
33
|
+
on_change({ type: 'update', path: final_path, stats });
|
|
34
|
+
});
|
|
35
|
+
watcher.on('unlink', (path) => {
|
|
36
|
+
const final_path = absolute ? path : relative(dir, path);
|
|
37
|
+
if (filter && !filter(final_path, FILE_STATS))
|
|
38
|
+
return;
|
|
39
|
+
on_change({ type: 'delete', path: final_path, stats: FILE_STATS });
|
|
40
|
+
});
|
|
41
|
+
watcher.on('unlinkDir', (path) => {
|
|
42
|
+
const final_path = absolute ? path : relative(dir, path);
|
|
43
|
+
if (filter && !filter(final_path, DIR_STATS))
|
|
44
|
+
return;
|
|
45
|
+
on_change({ type: 'delete', path: final_path, stats: DIR_STATS });
|
|
46
|
+
});
|
|
47
|
+
// wait until ready
|
|
48
|
+
let resolve;
|
|
49
|
+
const promise = new Promise((r) => (resolve = r));
|
|
50
|
+
watcher.once('ready', () => resolve());
|
|
51
|
+
await promise;
|
|
52
|
+
},
|
|
53
|
+
close: async () => {
|
|
54
|
+
if (!watcher)
|
|
55
|
+
return;
|
|
56
|
+
await watcher.close();
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|