@ryanatkn/gro 0.129.4 → 0.129.6
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/package.js +3 -3
- package/package.json +3 -2
- package/src/lib/args.test.ts +59 -0
- package/src/lib/args.ts +169 -0
- package/src/lib/build.task.ts +37 -0
- package/src/lib/changelog.test.ts +138 -0
- package/src/lib/changelog.ts +69 -0
- package/src/lib/changeset.task.ts +206 -0
- package/src/lib/changeset_helpers.ts +13 -0
- package/src/lib/check.task.ts +90 -0
- package/src/lib/clean.task.ts +46 -0
- package/src/lib/clean_fs.ts +54 -0
- package/src/lib/cli.ts +97 -0
- package/src/lib/commit.task.ts +33 -0
- package/src/lib/config.test.ts +71 -0
- package/src/lib/config.ts +161 -0
- package/src/lib/deploy.task.ts +243 -0
- package/src/lib/dev.task.ts +43 -0
- package/src/lib/docs/README.gen.md.ts +63 -0
- package/src/lib/docs/README.md +20 -0
- package/src/lib/docs/build.md +41 -0
- package/src/lib/docs/config.md +213 -0
- package/src/lib/docs/deploy.md +32 -0
- package/src/lib/docs/dev.md +40 -0
- package/src/lib/docs/gen.md +269 -0
- package/src/lib/docs/gro_plugin_sveltekit_app.md +113 -0
- package/src/lib/docs/package_json.md +33 -0
- package/src/lib/docs/plugin.md +50 -0
- package/src/lib/docs/publish.md +137 -0
- package/src/lib/docs/task.md +391 -0
- package/src/lib/docs/tasks.gen.md.ts +90 -0
- package/src/lib/docs/tasks.md +37 -0
- package/src/lib/docs/test.md +52 -0
- package/src/lib/env.ts +75 -0
- package/src/lib/esbuild_helpers.ts +50 -0
- package/src/lib/esbuild_plugin_external_worker.ts +92 -0
- package/src/lib/esbuild_plugin_svelte.test.ts +88 -0
- package/src/lib/esbuild_plugin_svelte.ts +108 -0
- package/src/lib/esbuild_plugin_sveltekit_local_imports.ts +31 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_alias.ts +25 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_app.ts +41 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_env.ts +46 -0
- package/src/lib/format.task.ts +30 -0
- package/src/lib/format_directory.ts +55 -0
- package/src/lib/format_file.test.ts +20 -0
- package/src/lib/format_file.ts +49 -0
- package/src/lib/fs.ts +18 -0
- package/src/lib/gen.task.ts +134 -0
- package/src/lib/gen.test.ts +306 -0
- package/src/lib/gen.ts +360 -0
- package/src/lib/git.test.ts +34 -0
- package/src/lib/git.ts +297 -0
- package/src/lib/github.ts +46 -0
- package/src/lib/gro.config.default.ts +34 -0
- package/src/lib/gro.ts +25 -0
- package/src/lib/gro_helpers.ts +101 -0
- package/src/lib/gro_plugin_gen.ts +95 -0
- package/src/lib/gro_plugin_server.ts +288 -0
- package/src/lib/gro_plugin_sveltekit_app.ts +257 -0
- package/src/lib/gro_plugin_sveltekit_library.ts +74 -0
- package/src/lib/hash.test.ts +33 -0
- package/src/lib/hash.ts +19 -0
- package/src/lib/index.ts +4 -0
- package/src/lib/input_path.test.ts +230 -0
- package/src/lib/input_path.ts +255 -0
- package/src/lib/invoke.ts +27 -0
- package/src/lib/invoke_task.ts +116 -0
- package/src/lib/lint.task.ts +38 -0
- package/src/lib/loader.test.ts +49 -0
- package/src/lib/loader.ts +226 -0
- package/src/lib/module.test.ts +46 -0
- package/src/lib/module.ts +13 -0
- package/src/lib/modules.test.ts +63 -0
- package/src/lib/modules.ts +112 -0
- package/src/lib/package.gen.ts +33 -0
- package/src/lib/package.ts +998 -0
- package/src/lib/package_json.test.ts +101 -0
- package/src/lib/package_json.ts +330 -0
- package/src/lib/package_meta.ts +86 -0
- package/src/lib/path.ts +23 -0
- package/src/lib/path_constants.ts +30 -0
- package/src/lib/paths.test.ts +77 -0
- package/src/lib/paths.ts +101 -0
- package/src/lib/plugin.test.ts +57 -0
- package/src/lib/plugin.ts +113 -0
- package/src/lib/publish.task.ts +194 -0
- package/src/lib/register.ts +3 -0
- package/src/lib/reinstall.task.ts +42 -0
- package/src/lib/release.task.ts +21 -0
- package/src/lib/resolve.task.ts +43 -0
- package/src/lib/resolve_node_specifier.test.ts +31 -0
- package/src/lib/resolve_node_specifier.ts +55 -0
- package/src/lib/resolve_specifier.test.ts +76 -0
- package/src/lib/resolve_specifier.ts +61 -0
- package/src/lib/run.task.ts +41 -0
- package/src/lib/run_gen.test.ts +196 -0
- package/src/lib/run_gen.ts +95 -0
- package/src/lib/run_task.test.ts +86 -0
- package/src/lib/run_task.ts +75 -0
- package/src/lib/search_fs.test.ts +56 -0
- package/src/lib/search_fs.ts +93 -0
- package/src/lib/src_json.test.ts +49 -0
- package/src/lib/src_json.ts +153 -0
- package/src/lib/svelte_helpers.ts +2 -0
- package/src/lib/sveltekit_config.ts +101 -0
- package/src/lib/sveltekit_config_global.ts +6 -0
- package/src/lib/sveltekit_helpers.ts +132 -0
- package/src/lib/sveltekit_shim_app.ts +42 -0
- package/src/lib/sveltekit_shim_app_environment.ts +14 -0
- package/src/lib/sveltekit_shim_app_forms.ts +20 -0
- package/src/lib/sveltekit_shim_app_navigation.ts +23 -0
- package/src/lib/sveltekit_shim_app_paths.ts +16 -0
- package/src/lib/sveltekit_shim_app_stores.ts +25 -0
- package/src/lib/sveltekit_shim_env.ts +45 -0
- package/src/lib/sync.task.ts +47 -0
- package/src/lib/task.test.ts +84 -0
- package/src/lib/task.ts +235 -0
- package/src/lib/task_logging.ts +180 -0
- package/src/lib/test.task.ts +50 -0
- package/src/lib/throttle.test.ts +52 -0
- package/src/lib/throttle.ts +63 -0
- package/src/lib/typecheck.task.ts +57 -0
- package/src/lib/upgrade.task.ts +108 -0
- package/src/lib/watch_dir.ts +88 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {EMPTY_OBJECT} from '@ryanatkn/belt/object.js';
|
|
2
|
+
import {to_array} from '@ryanatkn/belt/array.js';
|
|
3
|
+
import {ensure_end} from '@ryanatkn/belt/string.js';
|
|
4
|
+
import {isAbsolute, join} from 'node:path';
|
|
5
|
+
import {existsSync, readdirSync} from 'node:fs';
|
|
6
|
+
|
|
7
|
+
import type {File_Filter, Resolved_Path, Path_Filter} from './path.js';
|
|
8
|
+
|
|
9
|
+
export interface Search_Fs_Options {
|
|
10
|
+
/**
|
|
11
|
+
* One or more filter functions, any of which can short-circuit the search by returning `false`.
|
|
12
|
+
*/
|
|
13
|
+
filter?: Path_Filter | Path_Filter[];
|
|
14
|
+
/**
|
|
15
|
+
* An array of file suffixes to include.
|
|
16
|
+
*/
|
|
17
|
+
file_filter?: File_Filter | File_Filter[];
|
|
18
|
+
/**
|
|
19
|
+
* Pass `null` or `false` to speed things up at the cost of volatile ordering.
|
|
20
|
+
*/
|
|
21
|
+
sort?: boolean | null | ((a: Resolved_Path, b: Resolved_Path) => number);
|
|
22
|
+
/**
|
|
23
|
+
* Set to `false` to include directories.
|
|
24
|
+
*/
|
|
25
|
+
include_directories?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Sets the cwd for `dir` unless it's an absolute path or `null`.
|
|
28
|
+
*/
|
|
29
|
+
cwd?: string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const search_fs = (
|
|
33
|
+
dir: string,
|
|
34
|
+
options: Search_Fs_Options = EMPTY_OBJECT,
|
|
35
|
+
): Resolved_Path[] => {
|
|
36
|
+
const {
|
|
37
|
+
filter,
|
|
38
|
+
file_filter,
|
|
39
|
+
sort = default_sort,
|
|
40
|
+
include_directories = false,
|
|
41
|
+
cwd = process.cwd(),
|
|
42
|
+
} = options;
|
|
43
|
+
|
|
44
|
+
const final_dir = ensure_end(cwd && !isAbsolute(dir) ? join(cwd, dir) : dir, '/');
|
|
45
|
+
|
|
46
|
+
const filters =
|
|
47
|
+
!filter || (Array.isArray(filter) && !filter.length) ? undefined : to_array(filter);
|
|
48
|
+
const file_filters =
|
|
49
|
+
!file_filter || (Array.isArray(file_filter) && !file_filter.length)
|
|
50
|
+
? undefined
|
|
51
|
+
: to_array(file_filter);
|
|
52
|
+
|
|
53
|
+
if (!existsSync(final_dir)) return [];
|
|
54
|
+
|
|
55
|
+
const paths: Resolved_Path[] = [];
|
|
56
|
+
crawl(final_dir, paths, filters, file_filters, include_directories, null);
|
|
57
|
+
|
|
58
|
+
return sort ? paths.sort(typeof sort === 'boolean' ? default_sort : sort) : paths;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const default_sort = (a: Resolved_Path, b: Resolved_Path): number => a.path.localeCompare(b.path);
|
|
62
|
+
|
|
63
|
+
const crawl = (
|
|
64
|
+
dir: string,
|
|
65
|
+
paths: Resolved_Path[],
|
|
66
|
+
filters: Path_Filter[] | undefined,
|
|
67
|
+
file_filter: File_Filter[] | undefined,
|
|
68
|
+
include_directories: boolean,
|
|
69
|
+
base_dir: string | null,
|
|
70
|
+
): Resolved_Path[] => {
|
|
71
|
+
// This sync version is significantly faster than using the `fs/promises` version -
|
|
72
|
+
// it doesn't parallelize but that's not the common case in Gro.
|
|
73
|
+
const dirents = readdirSync(dir, {withFileTypes: true});
|
|
74
|
+
for (const dirent of dirents) {
|
|
75
|
+
const {name, parentPath} = dirent;
|
|
76
|
+
const is_directory = dirent.isDirectory();
|
|
77
|
+
const id = parentPath + name;
|
|
78
|
+
const include = !filters || filters.every((f) => f(id, is_directory));
|
|
79
|
+
if (include) {
|
|
80
|
+
const path = base_dir === null ? name : base_dir + '/' + name;
|
|
81
|
+
if (is_directory) {
|
|
82
|
+
const dir_id = id + '/';
|
|
83
|
+
if (include_directories) {
|
|
84
|
+
paths.push({path, id: dir_id, is_directory: true});
|
|
85
|
+
}
|
|
86
|
+
crawl(dir_id, paths, filters, file_filter, include_directories, path);
|
|
87
|
+
} else if (!file_filter || file_filter.every((f) => f(id))) {
|
|
88
|
+
paths.push({path, id, is_directory: false});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return paths;
|
|
93
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {test} from 'uvu';
|
|
2
|
+
import * as assert from 'uvu/assert';
|
|
3
|
+
|
|
4
|
+
import {to_src_modules} from './src_json.js';
|
|
5
|
+
import {to_package_exports} from './package_json.js';
|
|
6
|
+
import {paths} from './paths.js';
|
|
7
|
+
|
|
8
|
+
test('to_package_modules', () => {
|
|
9
|
+
assert.equal(
|
|
10
|
+
to_src_modules(
|
|
11
|
+
to_package_exports([
|
|
12
|
+
'fixtures/modules/some_test_css.css',
|
|
13
|
+
'fixtures/modules/Some_Test_Svelte.svelte',
|
|
14
|
+
'fixtures/modules/some_test_ts.ts',
|
|
15
|
+
'fixtures/modules/some_test_json.json',
|
|
16
|
+
]),
|
|
17
|
+
undefined,
|
|
18
|
+
paths.source,
|
|
19
|
+
),
|
|
20
|
+
{
|
|
21
|
+
'./package.json': {path: 'package.json', declarations: []},
|
|
22
|
+
'./fixtures/modules/some_test_css.css': {
|
|
23
|
+
path: 'fixtures/modules/some_test_css.css',
|
|
24
|
+
declarations: [],
|
|
25
|
+
},
|
|
26
|
+
'./fixtures/modules/some_test_json.json': {
|
|
27
|
+
path: 'fixtures/modules/some_test_json.json',
|
|
28
|
+
declarations: [],
|
|
29
|
+
},
|
|
30
|
+
'./fixtures/modules/Some_Test_Svelte.svelte': {
|
|
31
|
+
path: 'fixtures/modules/Some_Test_Svelte.svelte',
|
|
32
|
+
declarations: [],
|
|
33
|
+
},
|
|
34
|
+
'./fixtures/modules/some_test_ts.js': {
|
|
35
|
+
path: 'fixtures/modules/some_test_ts.ts',
|
|
36
|
+
declarations: [
|
|
37
|
+
{name: 'a', kind: 'variable'},
|
|
38
|
+
{name: 'some_test_ts', kind: 'variable'},
|
|
39
|
+
{name: 'some_test_fn', kind: 'function'},
|
|
40
|
+
{name: 'Some_Test_Type', kind: 'type'},
|
|
41
|
+
{name: 'Some_Test_Interface', kind: 'type'},
|
|
42
|
+
{name: 'Some_Test_Class', kind: 'class'},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test.run();
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {z} from 'zod';
|
|
2
|
+
import {join} from 'node:path';
|
|
3
|
+
import {strip_start} from '@ryanatkn/belt/string.js';
|
|
4
|
+
import type {Logger} from '@ryanatkn/belt/log.js';
|
|
5
|
+
import {Project} from 'ts-morph';
|
|
6
|
+
import {existsSync} from 'node:fs';
|
|
7
|
+
|
|
8
|
+
import {paths, replace_extension} from './paths.js';
|
|
9
|
+
import {
|
|
10
|
+
transform_empty_object_to_undefined,
|
|
11
|
+
type Package_Json,
|
|
12
|
+
type Package_Json_Exports,
|
|
13
|
+
} from './package_json.js';
|
|
14
|
+
|
|
15
|
+
export const Src_Module_Declaration = z
|
|
16
|
+
.object({
|
|
17
|
+
name: z.string(), // the export identifier
|
|
18
|
+
// TODO these are poorly named, and they're somewhat redundant with `kind`,
|
|
19
|
+
// they were added to distinguish `VariableDeclaration` functions and non-functions
|
|
20
|
+
kind: z.enum(['type', 'function', 'variable', 'class']).nullable(),
|
|
21
|
+
// code: z.string(), // TODO experiment with `getType().getText()`, some of them return the same as `name`
|
|
22
|
+
})
|
|
23
|
+
.passthrough();
|
|
24
|
+
export type Src_Module_Declaration = z.infer<typeof Src_Module_Declaration>;
|
|
25
|
+
|
|
26
|
+
export const Src_Module = z
|
|
27
|
+
.object({
|
|
28
|
+
path: z.string(),
|
|
29
|
+
declarations: z.array(Src_Module_Declaration),
|
|
30
|
+
})
|
|
31
|
+
.passthrough();
|
|
32
|
+
export type Src_Module = z.infer<typeof Src_Module>;
|
|
33
|
+
|
|
34
|
+
export const Src_Modules = z.record(Src_Module);
|
|
35
|
+
export type Src_Modules = z.infer<typeof Src_Modules>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @see https://github.com/ryanatkn/gro/blob/main/src/lib/docs/gro_plugin_sveltekit_app.md#well-known-src
|
|
39
|
+
*/
|
|
40
|
+
export const Src_Json = z.intersection(
|
|
41
|
+
z.record(z.unknown()), // TODO is this what we want?
|
|
42
|
+
z
|
|
43
|
+
.object({
|
|
44
|
+
name: z.string(), // same as Package_Json
|
|
45
|
+
version: z.string(), // same as Package_Json
|
|
46
|
+
modules: Src_Modules.transform(transform_empty_object_to_undefined).optional(),
|
|
47
|
+
})
|
|
48
|
+
.passthrough(),
|
|
49
|
+
);
|
|
50
|
+
export type Src_Json = z.infer<typeof Src_Json>;
|
|
51
|
+
|
|
52
|
+
export type Map_Src_Json = (src_json: Src_Json) => Src_Json | null | Promise<Src_Json | null>;
|
|
53
|
+
|
|
54
|
+
export const create_src_json = (
|
|
55
|
+
package_json: Package_Json,
|
|
56
|
+
log?: Logger,
|
|
57
|
+
lib_path?: string,
|
|
58
|
+
): Src_Json =>
|
|
59
|
+
Src_Json.parse({
|
|
60
|
+
name: package_json.name,
|
|
61
|
+
version: package_json.version,
|
|
62
|
+
modules: to_src_modules(package_json.exports, log, lib_path),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export const serialize_src_json = (src_json: Src_Json): string => {
|
|
66
|
+
const parsed = Src_Json.parse(src_json); // TODO can parse do the logic that normalize does? see `.transform`
|
|
67
|
+
return JSON.stringify(parsed, null, 2) + '\n';
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const to_src_modules = (
|
|
71
|
+
exports: Package_Json_Exports | undefined,
|
|
72
|
+
log?: Logger,
|
|
73
|
+
lib_path = paths.lib,
|
|
74
|
+
): Src_Modules | undefined => {
|
|
75
|
+
if (!exports) return;
|
|
76
|
+
|
|
77
|
+
const project = new Project();
|
|
78
|
+
project.addSourceFilesAtPaths('src/**/*.ts'); // TODO dir? maybe rewrite with `lib_path`?
|
|
79
|
+
|
|
80
|
+
return Object.fromEntries(
|
|
81
|
+
Object.entries(exports)
|
|
82
|
+
.map(([k, _v]) => {
|
|
83
|
+
// TODO hacky - doesn't handle any but the normal mappings, also add a helper?
|
|
84
|
+
const source_file_path =
|
|
85
|
+
k === '.' || k === './'
|
|
86
|
+
? 'index.ts'
|
|
87
|
+
: strip_start(k.endsWith('.js') ? replace_extension(k, '.ts') : k, './');
|
|
88
|
+
if (!source_file_path.endsWith('.ts')) {
|
|
89
|
+
// TODO support more than just TypeScript - maybe use @sveltejs/language-tools,
|
|
90
|
+
// see how @sveltejs/package generates types, or maybe use its generated declaration files with ts-morph
|
|
91
|
+
const src_module: Src_Module = {path: source_file_path, declarations: []};
|
|
92
|
+
return [k, src_module];
|
|
93
|
+
}
|
|
94
|
+
const source_file_id = join(lib_path, source_file_path);
|
|
95
|
+
if (!existsSync(source_file_id)) {
|
|
96
|
+
log?.warn(
|
|
97
|
+
'failed to infer source file from export path',
|
|
98
|
+
k,
|
|
99
|
+
'- the inferred file',
|
|
100
|
+
source_file_id,
|
|
101
|
+
'does not exist',
|
|
102
|
+
);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const declarations: Src_Module_Declaration[] = [];
|
|
107
|
+
|
|
108
|
+
const source_file = project.getSourceFile((f) =>
|
|
109
|
+
f.getFilePath().endsWith(source_file_path),
|
|
110
|
+
); // TODO expected this to work without the callback, according to my read of the docs it is, but `project.getSourceFile(source_file_path)` fails
|
|
111
|
+
if (source_file) {
|
|
112
|
+
for (const [name, decls] of source_file.getExportedDeclarations()) {
|
|
113
|
+
// TODO how to correctly handle multiples?
|
|
114
|
+
for (const decl of decls) {
|
|
115
|
+
// TODO helper
|
|
116
|
+
const decl_type = decl.getType();
|
|
117
|
+
const k = decl.getKindName();
|
|
118
|
+
const kind =
|
|
119
|
+
k === 'InterfaceDeclaration' || k === 'TypeAliasDeclaration'
|
|
120
|
+
? 'type'
|
|
121
|
+
: k === 'ClassDeclaration'
|
|
122
|
+
? 'class'
|
|
123
|
+
: k === 'VariableDeclaration'
|
|
124
|
+
? decl_type.getCallSignatures().length
|
|
125
|
+
? 'function'
|
|
126
|
+
: 'variable' // TODO name?
|
|
127
|
+
: null;
|
|
128
|
+
// TODO
|
|
129
|
+
// const code =
|
|
130
|
+
// k === 'InterfaceDeclaration' || k === 'TypeAliasDeclaration'
|
|
131
|
+
// ? decl_type.getText(source_file) // TODO
|
|
132
|
+
// : decl_type.getText(source_file);
|
|
133
|
+
const found = declarations.find((d) => d.name === name);
|
|
134
|
+
if (found) {
|
|
135
|
+
// TODO hacky, this only was added to prevent `TypeAliasDeclaration` from overriding `VariableDeclaration`
|
|
136
|
+
if (found.kind === 'type') {
|
|
137
|
+
found.kind = kind;
|
|
138
|
+
// found.code = code;
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
// TODO more
|
|
142
|
+
declarations.push({name, kind}); // code
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const src_module: Src_Module = {path: source_file_path, declarations};
|
|
149
|
+
return [k, src_module];
|
|
150
|
+
})
|
|
151
|
+
.filter((v) => v !== null),
|
|
152
|
+
);
|
|
153
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type {Config as SveltekitConfig} from '@sveltejs/kit';
|
|
2
|
+
import type {CompileOptions, PreprocessorGroup, ModuleCompileOptions} from 'svelte/compiler';
|
|
3
|
+
import {join} from 'node:path';
|
|
4
|
+
|
|
5
|
+
import {SVELTEKIT_CONFIG_FILENAME} from './path_constants.js';
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
|
|
9
|
+
This module is intended to have minimal dependencies to avoid over-imports in the CLI.
|
|
10
|
+
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Loads a SvelteKit config at `dir`.
|
|
15
|
+
* @returns `null` if no config is found
|
|
16
|
+
*/
|
|
17
|
+
export const load_sveltekit_config = async (
|
|
18
|
+
dir: string = process.cwd(),
|
|
19
|
+
): Promise<SveltekitConfig | null> => {
|
|
20
|
+
try {
|
|
21
|
+
return (await import(join(dir, SVELTEKIT_CONFIG_FILENAME))).default;
|
|
22
|
+
} catch (_err) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A subset of SvelteKit's config in a form that Gro uses
|
|
29
|
+
* because SvelteKit doesn't expose its config resolver.
|
|
30
|
+
* Flattens things out to keep them simple and easy to pass around,
|
|
31
|
+
* and doesn't deal with most properties.
|
|
32
|
+
* The `base` and `assets` in particular are renamed for clarity with Gro's internal systems,
|
|
33
|
+
* so these properties become first-class vocabulary inside Gro.
|
|
34
|
+
*/
|
|
35
|
+
export interface Parsed_Sveltekit_Config {
|
|
36
|
+
// TODO probably fill these out with defaults
|
|
37
|
+
sveltekit_config: SveltekitConfig | null;
|
|
38
|
+
alias: Record<string, string> | undefined;
|
|
39
|
+
base_url: '' | `/${string}` | undefined;
|
|
40
|
+
assets_url: '' | `http://${string}` | `https://${string}` | undefined;
|
|
41
|
+
|
|
42
|
+
// TODO others, but maybe replace with a Zod schema? https://kit.svelte.dev/docs/configuration
|
|
43
|
+
assets_path: string;
|
|
44
|
+
lib_path: string;
|
|
45
|
+
routes_path: string;
|
|
46
|
+
|
|
47
|
+
env_dir: string | undefined;
|
|
48
|
+
private_prefix: string | undefined;
|
|
49
|
+
public_prefix: string | undefined;
|
|
50
|
+
svelte_compile_options: CompileOptions;
|
|
51
|
+
svelte_compile_module_options: ModuleCompileOptions;
|
|
52
|
+
svelte_preprocessors: PreprocessorGroup | PreprocessorGroup[] | undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// TODO currently incomplete and hack - maybe rethink
|
|
56
|
+
/**
|
|
57
|
+
* Returns Gro-relevant properties of a SvelteKit config
|
|
58
|
+
* as a convenience wrapper around `load_sveltekit_config`.
|
|
59
|
+
* Needed because SvelteKit doesn't expose its config resolver.
|
|
60
|
+
*/
|
|
61
|
+
export const init_sveltekit_config = async (
|
|
62
|
+
dir_or_config: string | SveltekitConfig = process.cwd(),
|
|
63
|
+
): Promise<Parsed_Sveltekit_Config> => {
|
|
64
|
+
const sveltekit_config =
|
|
65
|
+
typeof dir_or_config === 'string' ? await load_sveltekit_config(dir_or_config) : dir_or_config;
|
|
66
|
+
const kit = sveltekit_config?.kit;
|
|
67
|
+
|
|
68
|
+
const alias = kit?.alias;
|
|
69
|
+
|
|
70
|
+
const base_url = kit?.paths?.base;
|
|
71
|
+
const assets_url = kit?.paths?.assets;
|
|
72
|
+
|
|
73
|
+
// TODO probably a Zod schema instead
|
|
74
|
+
const assets_path = kit?.files?.assets ?? 'static';
|
|
75
|
+
const lib_path = kit?.files?.lib ?? 'src/lib';
|
|
76
|
+
const routes_path = kit?.files?.routes ?? 'src/routes';
|
|
77
|
+
|
|
78
|
+
const env_dir = kit?.env?.dir;
|
|
79
|
+
const private_prefix = kit?.env?.privatePrefix;
|
|
80
|
+
const public_prefix = kit?.env?.publicPrefix;
|
|
81
|
+
|
|
82
|
+
const svelte_compile_options = sveltekit_config?.compilerOptions ?? {};
|
|
83
|
+
const svelte_compile_module_options = {}; // TODO from `kit`? or subset of `svelte_compile_options`?
|
|
84
|
+
const svelte_preprocessors = sveltekit_config?.preprocess;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
sveltekit_config,
|
|
88
|
+
alias,
|
|
89
|
+
base_url,
|
|
90
|
+
assets_url,
|
|
91
|
+
assets_path,
|
|
92
|
+
lib_path,
|
|
93
|
+
routes_path,
|
|
94
|
+
env_dir,
|
|
95
|
+
private_prefix,
|
|
96
|
+
public_prefix,
|
|
97
|
+
svelte_compile_options,
|
|
98
|
+
svelte_compile_module_options,
|
|
99
|
+
svelte_preprocessors,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {init_sveltekit_config} from './sveltekit_config.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The parsed SvelteKit config for the cwd, cached globally at the module level.
|
|
5
|
+
*/
|
|
6
|
+
export const sveltekit_config_global = await init_sveltekit_config(); // always load it to keep things simple ahead
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type {Result} from '@ryanatkn/belt/result.js';
|
|
2
|
+
import {existsSync} from 'node:fs';
|
|
3
|
+
|
|
4
|
+
import {Package_Json, load_package_json} from './package_json.js';
|
|
5
|
+
import {sveltekit_config_global} from './sveltekit_config_global.js';
|
|
6
|
+
import type {Parsed_Sveltekit_Config} from './sveltekit_config.js';
|
|
7
|
+
import {SVELTEKIT_CONFIG_FILENAME, SVELTEKIT_DEV_DIRNAME} from './path_constants.js';
|
|
8
|
+
import {find_cli, spawn_cli, to_cli_name, type Cli} from './cli.js';
|
|
9
|
+
import {Task_Error} from './task.js';
|
|
10
|
+
|
|
11
|
+
export const SVELTEKIT_CLI = 'svelte-kit';
|
|
12
|
+
|
|
13
|
+
export const SVELTE_CHECK_CLI = 'svelte-check';
|
|
14
|
+
|
|
15
|
+
export const SVELTE_PACKAGE_CLI = 'svelte-package';
|
|
16
|
+
export const SVELTE_PACKAGE_DEP_NAME = '@sveltejs/package';
|
|
17
|
+
|
|
18
|
+
export const VITE_CLI = 'vite';
|
|
19
|
+
|
|
20
|
+
export const has_sveltekit_app = (): Result<object, {message: string}> => {
|
|
21
|
+
if (!existsSync(SVELTEKIT_CONFIG_FILENAME)) {
|
|
22
|
+
return {ok: false, message: `no SvelteKit config found at ${SVELTEKIT_CONFIG_FILENAME}`};
|
|
23
|
+
}
|
|
24
|
+
// TODO check for routes?
|
|
25
|
+
return {ok: true};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const has_sveltekit_library = (
|
|
29
|
+
package_json?: Package_Json,
|
|
30
|
+
sveltekit_config: Parsed_Sveltekit_Config = sveltekit_config_global,
|
|
31
|
+
): Result<object, {message: string}> => {
|
|
32
|
+
const has_sveltekit_app_result = has_sveltekit_app();
|
|
33
|
+
if (!has_sveltekit_app_result.ok) {
|
|
34
|
+
return has_sveltekit_app_result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!existsSync(sveltekit_config.lib_path)) {
|
|
38
|
+
return {ok: false, message: `no SvelteKit lib directory found at ${sveltekit_config.lib_path}`};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const pkg = package_json ?? load_package_json();
|
|
42
|
+
if (
|
|
43
|
+
!(pkg.devDependencies?.[SVELTE_PACKAGE_DEP_NAME] || pkg.dependencies?.[SVELTE_PACKAGE_DEP_NAME])
|
|
44
|
+
) {
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
message: `no dependency found in package.json for ${SVELTE_PACKAGE_DEP_NAME}, install it with \`npm i -D ${SVELTE_PACKAGE_DEP_NAME}\``,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {ok: true};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const sveltekit_sync = async (
|
|
55
|
+
sveltekit_cli: string | Cli = SVELTEKIT_CLI,
|
|
56
|
+
): Promise<void> => {
|
|
57
|
+
const result = await spawn_cli(sveltekit_cli, ['sync']);
|
|
58
|
+
if (!result) {
|
|
59
|
+
throw new Task_Error(
|
|
60
|
+
`Failed to find SvelteKit CLI \`${to_cli_name(sveltekit_cli)}\`, do you need to run \`npm i\`?`,
|
|
61
|
+
);
|
|
62
|
+
} else if (!result.ok) {
|
|
63
|
+
throw new Task_Error(`Failed ${to_cli_name(sveltekit_cli)} sync`);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* If the SvelteKit CLI is found and its `.svelte-kit` directory is not, run `svelte-kit sync`.
|
|
69
|
+
*/
|
|
70
|
+
export const sveltekit_sync_if_obviously_needed = async (
|
|
71
|
+
sveltekit_cli: string | Cli = SVELTEKIT_CLI,
|
|
72
|
+
): Promise<void> => {
|
|
73
|
+
if (existsSync(SVELTEKIT_DEV_DIRNAME)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const found_sveltekit_cli =
|
|
77
|
+
typeof sveltekit_cli === 'string' ? find_cli(sveltekit_cli) : sveltekit_cli;
|
|
78
|
+
if (!found_sveltekit_cli) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
return sveltekit_sync(found_sveltekit_cli);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Options to the SvelteKit packaging CLI.
|
|
86
|
+
* @see https://kit.svelte.dev/docs/packaging#options
|
|
87
|
+
*/
|
|
88
|
+
export interface Svelte_Package_Options {
|
|
89
|
+
/**
|
|
90
|
+
* Watch files in src/lib for changes and rebuild the package
|
|
91
|
+
*/
|
|
92
|
+
watch?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Alias for `watch`.
|
|
95
|
+
*/
|
|
96
|
+
w?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* The input directory which contains all the files of the package.
|
|
99
|
+
* Defaults to src/lib
|
|
100
|
+
*/
|
|
101
|
+
input?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Alias for `input`.
|
|
104
|
+
*/
|
|
105
|
+
i?: string;
|
|
106
|
+
/**
|
|
107
|
+
* The output directory where the processed files are written to.
|
|
108
|
+
* Your package.json's exports should point to files inside there,
|
|
109
|
+
* and the files array should include that folder.
|
|
110
|
+
* Defaults to dist
|
|
111
|
+
*/
|
|
112
|
+
output?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Alias for `output`.
|
|
115
|
+
*/
|
|
116
|
+
o?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Whether or not to create type definitions (d.ts files).
|
|
119
|
+
* We strongly recommend doing this as it fosters ecosystem library quality.
|
|
120
|
+
* Defaults to true
|
|
121
|
+
*/
|
|
122
|
+
types?: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Alias for `types`.
|
|
125
|
+
*/
|
|
126
|
+
t?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* The path to a tsconfig or jsconfig.
|
|
129
|
+
* When not provided, searches for the next upper tsconfig/jsconfig in the workspace path.
|
|
130
|
+
*/
|
|
131
|
+
tsconfig?: string;
|
|
132
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type {Parsed_Sveltekit_Config} from './sveltekit_config.js';
|
|
2
|
+
|
|
3
|
+
export const SVELTEKIT_SHIM_APP_PATHS_MATCHER = /\/util\/sveltekit_shim_app_paths\.js$/u;
|
|
4
|
+
export const SVELTEKIT_SHIM_APP_ENVIRONMENT_MATCHER =
|
|
5
|
+
/\/util\/sveltekit_shim_app_environment\.js$/u;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Maps SvelteKit `$app` specifiers to their Gro shims.
|
|
9
|
+
* @see https://kit.svelte.dev/docs/modules
|
|
10
|
+
*/
|
|
11
|
+
export const sveltekit_shim_app_specifiers = new Map([
|
|
12
|
+
['$app/environment', '@ryanatkn/gro/sveltekit_shim_app_environment.js'],
|
|
13
|
+
['$app/forms', '@ryanatkn/gro/sveltekit_shim_app_forms.js'],
|
|
14
|
+
['$app/navigation', '@ryanatkn/gro/sveltekit_shim_app_navigation.js'],
|
|
15
|
+
['$app/paths', '@ryanatkn/gro/sveltekit_shim_app_paths.js'],
|
|
16
|
+
['$app/stores', '@ryanatkn/gro/sveltekit_shim_app_stores.js'],
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export const render_sveltekit_shim_app_paths = (
|
|
20
|
+
base_url: Parsed_Sveltekit_Config['base_url'] = '',
|
|
21
|
+
assets_url: Parsed_Sveltekit_Config['assets_url'] = '',
|
|
22
|
+
): string => `// shim for $app/paths
|
|
23
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
24
|
+
|
|
25
|
+
export const assets = ${JSON.stringify(assets_url)};
|
|
26
|
+
export const base = ${JSON.stringify(base_url)};
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
// TODO improve support
|
|
30
|
+
// `dev` is not guaranteed to be the same as `MODE` - https://kit.svelte.dev/docs/modules#$app-environment-dev
|
|
31
|
+
// `version` is `config.kit.version.name` but I couldn't see how to load a SvelteKit `ValidatedConfig`
|
|
32
|
+
// `building` is just being hardcoded, might be better (but still not correct) to be `!dev`
|
|
33
|
+
export const render_sveltekit_shim_app_environment = (
|
|
34
|
+
dev: boolean,
|
|
35
|
+
): string => `// shim for $app/environment
|
|
36
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
37
|
+
|
|
38
|
+
export const browser = false;
|
|
39
|
+
export const building = false;
|
|
40
|
+
export const dev = ${JSON.stringify(dev)};
|
|
41
|
+
export const version = 'TODO';
|
|
42
|
+
`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// shim for $app/environment
|
|
2
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This file is created dynamically by `render_sveltekit_shim_app_environment`
|
|
6
|
+
* but exists here for the sake of the Node loader.
|
|
7
|
+
* There may be a cleaner workaround but I couldn't find it.
|
|
8
|
+
* @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const browser = false;
|
|
12
|
+
export const building = false;
|
|
13
|
+
export const dev = true;
|
|
14
|
+
export const version = 'TODO';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// shim for $app/forms
|
|
2
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
applyAction as base_applyAction,
|
|
6
|
+
deserialize as base_deserialize,
|
|
7
|
+
enhance as base_enhance,
|
|
8
|
+
} from '$app/forms';
|
|
9
|
+
import {noop, noop_async} from '@ryanatkn/belt/function.js';
|
|
10
|
+
import * as devalue from 'devalue';
|
|
11
|
+
|
|
12
|
+
export const applyAction: typeof base_applyAction = noop_async;
|
|
13
|
+
export const deserialize: typeof base_deserialize = (result) => {
|
|
14
|
+
const parsed = JSON.parse(result);
|
|
15
|
+
if (parsed.data) {
|
|
16
|
+
parsed.data = devalue.parse(parsed.data);
|
|
17
|
+
}
|
|
18
|
+
return parsed;
|
|
19
|
+
};
|
|
20
|
+
export const enhance: typeof base_enhance = () => ({destroy: noop});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// shim for $app/navigation
|
|
2
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
afterNavigate as base_afterNavigate,
|
|
6
|
+
beforeNavigate as base_beforeNavigate,
|
|
7
|
+
disableScrollHandling as base_disableScrollHandling,
|
|
8
|
+
goto as base_goto,
|
|
9
|
+
invalidate as base_invalidate,
|
|
10
|
+
invalidateAll as base_invalidateAll,
|
|
11
|
+
preloadCode as base_preloadCode,
|
|
12
|
+
preloadData as base_preloadData,
|
|
13
|
+
} from '$app/navigation';
|
|
14
|
+
import {noop, noop_async} from '@ryanatkn/belt/function.js';
|
|
15
|
+
|
|
16
|
+
export const afterNavigate: typeof base_afterNavigate = noop;
|
|
17
|
+
export const beforeNavigate: typeof base_beforeNavigate = noop;
|
|
18
|
+
export const disableScrollHandling: typeof base_disableScrollHandling = noop;
|
|
19
|
+
export const goto: typeof base_goto = noop_async;
|
|
20
|
+
export const invalidate: typeof base_invalidate = noop_async;
|
|
21
|
+
export const invalidateAll: typeof base_invalidateAll = noop_async;
|
|
22
|
+
export const preloadCode: typeof base_preloadCode = noop_async;
|
|
23
|
+
export const preloadData: typeof base_preloadData = noop_async;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// shim for $app/paths
|
|
2
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This file is created dynamically by `render_sveltekit_shim_app_paths`
|
|
6
|
+
* but exists here for the sake of the Node loader.
|
|
7
|
+
* There may be a cleaner workaround but I couldn't find it.
|
|
8
|
+
* @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {resolveRoute as base_resolveRoute} from '$app/paths';
|
|
12
|
+
import {noop} from '@ryanatkn/belt/function.js';
|
|
13
|
+
|
|
14
|
+
export const assets = '';
|
|
15
|
+
export const base = '';
|
|
16
|
+
export const resolveRoute: typeof base_resolveRoute = noop;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// shim for $app/stores
|
|
2
|
+
// @see https://github.com/sveltejs/kit/issues/1485
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
getStores as base_getStores,
|
|
6
|
+
navigating as base_navigating,
|
|
7
|
+
page as base_page,
|
|
8
|
+
updated as base_updated,
|
|
9
|
+
} from '$app/stores';
|
|
10
|
+
import {readable} from 'svelte/store';
|
|
11
|
+
|
|
12
|
+
export const getStores: typeof base_getStores = () => ({navigating, page, updated}) as const;
|
|
13
|
+
export const navigating: typeof base_navigating = readable(null);
|
|
14
|
+
export const page: typeof base_page = readable({
|
|
15
|
+
url: new URL('https://gro.ryanatkn.com/TODO'),
|
|
16
|
+
params: {},
|
|
17
|
+
route: {id: 'RouteId'},
|
|
18
|
+
status: 200,
|
|
19
|
+
error: null,
|
|
20
|
+
data: {},
|
|
21
|
+
state: {},
|
|
22
|
+
form: {},
|
|
23
|
+
});
|
|
24
|
+
export const updated: typeof base_updated = readable(true) as any;
|
|
25
|
+
updated.check = () => Promise.resolve(true);
|