create-lapis-lazuli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +71 -0
- package/dist/lib.js +267 -0
- package/dist/templates.js +95 -0
- package/package.json +25 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { buildProject, bundleProject, createProject, validateManifest } from "./lib.js";
|
|
4
|
+
function usage() {
|
|
5
|
+
throw new Error([
|
|
6
|
+
"Usage:",
|
|
7
|
+
" create-lapis-lazuli <directory> [display-name] [engine]",
|
|
8
|
+
" lapis create <directory> [display-name] [engine]",
|
|
9
|
+
" lapis validate <directory>",
|
|
10
|
+
" lapis bundle <directory> [output-directory]",
|
|
11
|
+
" lapis build <directory>",
|
|
12
|
+
"",
|
|
13
|
+
"Supported engines: js, python",
|
|
14
|
+
].join("\n"));
|
|
15
|
+
}
|
|
16
|
+
async function main() {
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const executable = basename(process.argv[1] ?? "");
|
|
19
|
+
const knownCommands = new Set(["create", "validate", "build", "bundle"]);
|
|
20
|
+
let [command, firstArg, secondArg, thirdArg] = args;
|
|
21
|
+
if (executable === "create-lapis-lazuli" && (!command || !knownCommands.has(command))) {
|
|
22
|
+
thirdArg = secondArg;
|
|
23
|
+
secondArg = firstArg;
|
|
24
|
+
firstArg = command;
|
|
25
|
+
command = "create";
|
|
26
|
+
}
|
|
27
|
+
if (!command) {
|
|
28
|
+
usage();
|
|
29
|
+
}
|
|
30
|
+
switch (command) {
|
|
31
|
+
case "create": {
|
|
32
|
+
if (!firstArg) {
|
|
33
|
+
usage();
|
|
34
|
+
}
|
|
35
|
+
const result = await createProject(firstArg, secondArg, thirdArg);
|
|
36
|
+
console.log(`Created ${result.projectDir}`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
case "validate":
|
|
40
|
+
{
|
|
41
|
+
if (!firstArg) {
|
|
42
|
+
usage();
|
|
43
|
+
}
|
|
44
|
+
const result = await validateManifest(firstArg);
|
|
45
|
+
console.log(`Validated ${result.manifest.id} -> ${result.entrypoint}`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
case "build": {
|
|
49
|
+
if (!firstArg) {
|
|
50
|
+
usage();
|
|
51
|
+
}
|
|
52
|
+
const result = await buildProject(firstArg);
|
|
53
|
+
console.log(`Built ${result.manifest.id} -> ${result.buildDir}`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
case "bundle": {
|
|
57
|
+
if (!firstArg) {
|
|
58
|
+
usage();
|
|
59
|
+
}
|
|
60
|
+
const result = await bundleProject(firstArg, secondArg);
|
|
61
|
+
console.log(`Bundled ${result.bundleDir}`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
default:
|
|
65
|
+
usage();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
main().catch((error) => {
|
|
69
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
});
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { copyFile, lstat, mkdir, mkdtemp, readFile, readdir, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { renderManifest, renderPackageJson, renderPythonPyproject, renderSource, GITIGNORE } from "./templates.js";
|
|
6
|
+
const LOCAL_SDK_DIR = fileURLToPath(new URL("../../../sdks/typescript", import.meta.url));
|
|
7
|
+
const LOCAL_PYTHON_SDK_DIR = fileURLToPath(new URL("../../../sdks/python/src/lapis_lazuli", import.meta.url));
|
|
8
|
+
const SUPPORTED_ENGINES = new Set(["js", "python"]);
|
|
9
|
+
const PYTHON_BUNDLE_IGNORED_DIRECTORIES = new Set([
|
|
10
|
+
".git",
|
|
11
|
+
".lapis",
|
|
12
|
+
"__pycache__",
|
|
13
|
+
".mypy_cache",
|
|
14
|
+
".pytest_cache",
|
|
15
|
+
".ruff_cache",
|
|
16
|
+
".venv",
|
|
17
|
+
"dist",
|
|
18
|
+
"node_modules",
|
|
19
|
+
"venv",
|
|
20
|
+
]);
|
|
21
|
+
const PYTHON_BUNDLE_IGNORED_FILES = new Set([
|
|
22
|
+
".DS_Store",
|
|
23
|
+
]);
|
|
24
|
+
function assertString(value, field) {
|
|
25
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
26
|
+
throw new Error(`Manifest field "${field}" must be a non-empty string.`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
export async function readManifest(projectDir) {
|
|
31
|
+
const manifestPath = join(resolve(projectDir), "lapis-plugin.json");
|
|
32
|
+
const manifestText = await readFile(manifestPath, "utf8");
|
|
33
|
+
const raw = JSON.parse(manifestText);
|
|
34
|
+
return {
|
|
35
|
+
id: assertString(raw.id, "id"),
|
|
36
|
+
name: assertString(raw.name, "name"),
|
|
37
|
+
version: assertString(raw.version, "version"),
|
|
38
|
+
engine: assertString(raw.engine, "engine"),
|
|
39
|
+
main: assertString(raw.main, "main"),
|
|
40
|
+
apiVersion: assertString(raw.apiVersion, "apiVersion"),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function validateManifest(projectDir) {
|
|
44
|
+
const manifest = await readManifest(projectDir);
|
|
45
|
+
const entrypoint = resolve(projectDir, manifest.main);
|
|
46
|
+
const entrypointStats = await stat(entrypoint).catch(() => null);
|
|
47
|
+
if (!entrypointStats?.isFile()) {
|
|
48
|
+
throw new Error(`Entrypoint "${manifest.main}" does not exist.`);
|
|
49
|
+
}
|
|
50
|
+
assertSupportedEngine(manifest.engine);
|
|
51
|
+
return {
|
|
52
|
+
manifest,
|
|
53
|
+
entrypoint,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export async function buildProject(projectDir) {
|
|
57
|
+
const { manifest, entrypoint } = await validateManifest(projectDir);
|
|
58
|
+
const buildDir = resolve(projectDir, ".lapis/build");
|
|
59
|
+
await rm(buildDir, { recursive: true, force: true });
|
|
60
|
+
await mkdir(buildDir, { recursive: true });
|
|
61
|
+
if (manifest.engine === "js") {
|
|
62
|
+
const cleanupLocalSdkLink = await ensureLocalSdkLink(projectDir);
|
|
63
|
+
const preparedEntrypoint = await prepareEntrypointForBuild(entrypoint);
|
|
64
|
+
try {
|
|
65
|
+
const result = await Bun.build({
|
|
66
|
+
entrypoints: [preparedEntrypoint.entrypoint],
|
|
67
|
+
root: resolve(projectDir),
|
|
68
|
+
outdir: buildDir,
|
|
69
|
+
target: "node",
|
|
70
|
+
format: "cjs",
|
|
71
|
+
sourcemap: "external",
|
|
72
|
+
minify: false,
|
|
73
|
+
splitting: false,
|
|
74
|
+
});
|
|
75
|
+
if (!result.success) {
|
|
76
|
+
const logs = result.logs.map((log) => log.message).join("\n");
|
|
77
|
+
throw new Error(`Build failed.\n${logs}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await preparedEntrypoint.cleanup?.();
|
|
82
|
+
await cleanupLocalSdkLink?.();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
await stagePythonProject(projectDir, buildDir);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
buildDir,
|
|
90
|
+
manifest,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export async function bundleProject(projectDir, outputDir) {
|
|
94
|
+
const { buildDir, manifest } = await buildProject(projectDir);
|
|
95
|
+
const bundleDir = resolve(outputDir ?? join(projectDir, "dist", manifest.id));
|
|
96
|
+
const bundledMain = manifest.engine === "js" ? "main.js" : normalizeBundlePath(manifest.main);
|
|
97
|
+
const mainPath = join(bundleDir, bundledMain);
|
|
98
|
+
const manifestPath = join(bundleDir, "lapis-plugin.json");
|
|
99
|
+
await rm(bundleDir, { recursive: true, force: true });
|
|
100
|
+
await mkdir(bundleDir, { recursive: true });
|
|
101
|
+
if (manifest.engine === "js") {
|
|
102
|
+
const builtMain = await findBuiltEntrypoint(buildDir);
|
|
103
|
+
if (!builtMain) {
|
|
104
|
+
throw new Error("Bundled output did not contain a JavaScript entrypoint.");
|
|
105
|
+
}
|
|
106
|
+
const builtContents = await readFile(builtMain, "utf8");
|
|
107
|
+
await mkdir(dirname(mainPath), { recursive: true });
|
|
108
|
+
await writeFile(mainPath, builtContents, "utf8");
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
await copyDirectoryContents(buildDir, bundleDir);
|
|
112
|
+
}
|
|
113
|
+
await writeFile(manifestPath, JSON.stringify({
|
|
114
|
+
...manifest,
|
|
115
|
+
main: bundledMain,
|
|
116
|
+
}, null, 2), "utf8");
|
|
117
|
+
return {
|
|
118
|
+
bundleDir,
|
|
119
|
+
manifestPath,
|
|
120
|
+
mainPath,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export async function createProject(destination, displayName, engine = "js") {
|
|
124
|
+
const projectDir = resolve(destination);
|
|
125
|
+
const id = basename(projectDir);
|
|
126
|
+
const supportedEngine = assertSupportedEngine(engine);
|
|
127
|
+
const pluginName = displayName ?? id
|
|
128
|
+
.split(/[-_]/g)
|
|
129
|
+
.filter(Boolean)
|
|
130
|
+
.map((part) => part[0].toUpperCase() + part.slice(1))
|
|
131
|
+
.join(" ");
|
|
132
|
+
await mkdir(join(projectDir, "src"), { recursive: true });
|
|
133
|
+
if (supportedEngine === "js") {
|
|
134
|
+
await writeFile(join(projectDir, "package.json"), renderPackageJson(id), "utf8");
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
await writeFile(join(projectDir, "pyproject.toml"), renderPythonPyproject(id), "utf8");
|
|
138
|
+
}
|
|
139
|
+
await writeFile(join(projectDir, "lapis-plugin.json"), renderManifest(id, pluginName, supportedEngine), "utf8");
|
|
140
|
+
await writeFile(join(projectDir, "src", supportedEngine === "js" ? "index.ts" : "main.py"), renderSource(pluginName, supportedEngine), "utf8");
|
|
141
|
+
await writeFile(join(projectDir, ".gitignore"), GITIGNORE, "utf8");
|
|
142
|
+
return { projectDir };
|
|
143
|
+
}
|
|
144
|
+
export async function createTempProject(prefix = "lapis-cli-test-") {
|
|
145
|
+
return mkdtemp(join(tmpdir(), prefix));
|
|
146
|
+
}
|
|
147
|
+
export async function cleanupTempProject(projectDir) {
|
|
148
|
+
await rm(resolve(projectDir), { recursive: true, force: true });
|
|
149
|
+
}
|
|
150
|
+
export async function ensureDirectory(path) {
|
|
151
|
+
await mkdir(resolve(path), { recursive: true });
|
|
152
|
+
}
|
|
153
|
+
export async function writeTextFile(path, contents) {
|
|
154
|
+
await ensureDirectory(dirname(path));
|
|
155
|
+
await writeFile(path, contents, "utf8");
|
|
156
|
+
}
|
|
157
|
+
async function ensureLocalSdkLink(projectDir) {
|
|
158
|
+
const linkPath = join(resolve(projectDir), "node_modules", "lapis-lazuli");
|
|
159
|
+
const existing = await lstat(linkPath).catch(() => null);
|
|
160
|
+
if (existing) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const localSdkExists = await stat(LOCAL_SDK_DIR).catch(() => null);
|
|
164
|
+
if (!localSdkExists?.isDirectory()) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
await mkdir(dirname(linkPath), { recursive: true });
|
|
168
|
+
await symlink(LOCAL_SDK_DIR, linkPath, "dir");
|
|
169
|
+
return async () => {
|
|
170
|
+
await rm(linkPath, { recursive: true, force: true });
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function prepareEntrypointForBuild(entrypoint) {
|
|
174
|
+
const source = await readFile(entrypoint, "utf8");
|
|
175
|
+
const localSdkEntry = join(LOCAL_SDK_DIR, "src", "index.ts");
|
|
176
|
+
const localSdkExists = await stat(localSdkEntry).catch(() => null);
|
|
177
|
+
if (!localSdkExists?.isFile() || !source.includes("lapis-lazuli")) {
|
|
178
|
+
return { entrypoint };
|
|
179
|
+
}
|
|
180
|
+
const rewrittenImportPath = normalizeImportPath(relative(dirname(entrypoint), localSdkEntry));
|
|
181
|
+
const rewrittenSource = source.replace(/(["'])lapis-lazuli\1/g, (_match, quote) => `${quote}${rewrittenImportPath}${quote}`);
|
|
182
|
+
const rewrittenEntrypoint = join(dirname(entrypoint), `.lapis-${basename(entrypoint)}`);
|
|
183
|
+
await writeFile(rewrittenEntrypoint, rewrittenSource, "utf8");
|
|
184
|
+
return {
|
|
185
|
+
entrypoint: rewrittenEntrypoint,
|
|
186
|
+
cleanup: async () => {
|
|
187
|
+
await rm(rewrittenEntrypoint, { force: true });
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function normalizeImportPath(importPath) {
|
|
192
|
+
const normalized = importPath.replaceAll("\\", "/");
|
|
193
|
+
return normalized.startsWith(".") ? normalized : `./${normalized}`;
|
|
194
|
+
}
|
|
195
|
+
async function findBuiltEntrypoint(buildDir) {
|
|
196
|
+
const entries = await readdir(buildDir, { withFileTypes: true });
|
|
197
|
+
for (const entry of entries) {
|
|
198
|
+
const absolutePath = join(buildDir, entry.name);
|
|
199
|
+
if (entry.isDirectory()) {
|
|
200
|
+
const nested = await findBuiltEntrypoint(absolutePath);
|
|
201
|
+
if (nested) {
|
|
202
|
+
return nested;
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (entry.isFile() && entry.name.endsWith(".js") && !entry.name.endsWith(".js.map")) {
|
|
207
|
+
return absolutePath;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
function assertSupportedEngine(engine) {
|
|
213
|
+
if (!SUPPORTED_ENGINES.has(engine)) {
|
|
214
|
+
throw new Error(`Unsupported engine "${engine}". Supported engines: ${Array.from(SUPPORTED_ENGINES).map((value) => `"${value}"`).join(", ")}.`);
|
|
215
|
+
}
|
|
216
|
+
return engine;
|
|
217
|
+
}
|
|
218
|
+
function normalizeBundlePath(path) {
|
|
219
|
+
return path.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
220
|
+
}
|
|
221
|
+
async function stagePythonProject(projectDir, buildDir) {
|
|
222
|
+
await copyDirectoryContents(resolve(projectDir), buildDir, shouldIncludePythonBundlePath);
|
|
223
|
+
await ensureLocalPythonSdk(buildDir);
|
|
224
|
+
}
|
|
225
|
+
function shouldIncludePythonBundlePath(relativePath, entry) {
|
|
226
|
+
void relativePath;
|
|
227
|
+
if (entry.isDirectory()) {
|
|
228
|
+
return !PYTHON_BUNDLE_IGNORED_DIRECTORIES.has(entry.name);
|
|
229
|
+
}
|
|
230
|
+
return !PYTHON_BUNDLE_IGNORED_FILES.has(entry.name);
|
|
231
|
+
}
|
|
232
|
+
async function copyDirectoryContents(sourceDir, targetDir, shouldInclude = () => true) {
|
|
233
|
+
async function visit(currentSourceDir) {
|
|
234
|
+
const entries = await readdir(currentSourceDir, { withFileTypes: true });
|
|
235
|
+
for (const entry of entries) {
|
|
236
|
+
const sourcePath = join(currentSourceDir, entry.name);
|
|
237
|
+
const relativePath = normalizeBundlePath(relative(sourceDir, sourcePath));
|
|
238
|
+
if (!shouldInclude(relativePath, entry)) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const targetPath = join(targetDir, relativePath);
|
|
242
|
+
if (entry.isDirectory()) {
|
|
243
|
+
await mkdir(targetPath, { recursive: true });
|
|
244
|
+
await visit(sourcePath);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (entry.isFile()) {
|
|
248
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
249
|
+
await copyFile(sourcePath, targetPath);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
await visit(sourceDir);
|
|
254
|
+
}
|
|
255
|
+
async function ensureLocalPythonSdk(buildDir) {
|
|
256
|
+
const localSdkExists = await stat(LOCAL_PYTHON_SDK_DIR).catch(() => null);
|
|
257
|
+
if (!localSdkExists?.isDirectory()) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const targetDir = join(buildDir, "lapis_lazuli");
|
|
261
|
+
const existingTarget = await stat(targetDir).catch(() => null);
|
|
262
|
+
if (existingTarget?.isDirectory()) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
await mkdir(targetDir, { recursive: true });
|
|
266
|
+
await copyDirectoryContents(LOCAL_PYTHON_SDK_DIR, targetDir);
|
|
267
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export function renderPackageJson(name) {
|
|
2
|
+
return JSON.stringify({
|
|
3
|
+
name,
|
|
4
|
+
private: true,
|
|
5
|
+
type: "module",
|
|
6
|
+
scripts: {
|
|
7
|
+
build: "lapis build .",
|
|
8
|
+
bundle: "lapis bundle .",
|
|
9
|
+
},
|
|
10
|
+
dependencies: {
|
|
11
|
+
"lapis-lazuli": "^0.1.0",
|
|
12
|
+
},
|
|
13
|
+
}, null, 2);
|
|
14
|
+
}
|
|
15
|
+
export function renderPythonPyproject(name) {
|
|
16
|
+
return [
|
|
17
|
+
"[project]",
|
|
18
|
+
`name = "${name}"`,
|
|
19
|
+
'version = "0.1.0"',
|
|
20
|
+
'description = "Lapis Lazuli Python plugin"',
|
|
21
|
+
'requires-python = ">=3.11"',
|
|
22
|
+
"dependencies = [",
|
|
23
|
+
' "lapis-lazuli-sdk>=0.1.0",',
|
|
24
|
+
"]",
|
|
25
|
+
"",
|
|
26
|
+
].join("\n");
|
|
27
|
+
}
|
|
28
|
+
export function renderManifest(id, displayName, engine = "js") {
|
|
29
|
+
return JSON.stringify({
|
|
30
|
+
id,
|
|
31
|
+
name: displayName,
|
|
32
|
+
version: "0.1.0",
|
|
33
|
+
engine,
|
|
34
|
+
main: engine === "js" ? "./src/index.ts" : "./src/main.py",
|
|
35
|
+
apiVersion: "1.0",
|
|
36
|
+
}, null, 2);
|
|
37
|
+
}
|
|
38
|
+
export function renderSource(displayName, engine = "js") {
|
|
39
|
+
if (engine === "python") {
|
|
40
|
+
return `from lapis_lazuli import Plugin
|
|
41
|
+
|
|
42
|
+
plugin = Plugin("${displayName}", version="0.1.0")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@plugin.startup
|
|
46
|
+
def on_enable(context):
|
|
47
|
+
context.app.log.info("${displayName} enabled.")
|
|
48
|
+
|
|
49
|
+
def execute(command):
|
|
50
|
+
command.sender.send_message("Hello from ${displayName}.")
|
|
51
|
+
|
|
52
|
+
context.commands.register(
|
|
53
|
+
"hello",
|
|
54
|
+
execute,
|
|
55
|
+
description="Send a hello message from ${displayName}.",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@plugin.shutdown
|
|
60
|
+
def on_disable(context):
|
|
61
|
+
context.app.log.info("${displayName} disabled.")
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
return `import { definePlugin } from "lapis-lazuli";
|
|
65
|
+
|
|
66
|
+
export default definePlugin({
|
|
67
|
+
name: "${displayName}",
|
|
68
|
+
version: "0.1.0",
|
|
69
|
+
onEnable(context) {
|
|
70
|
+
context.app.log.info("${displayName} enabled.");
|
|
71
|
+
|
|
72
|
+
context.commands.register({
|
|
73
|
+
name: "hello",
|
|
74
|
+
description: "Send a hello message from ${displayName}.",
|
|
75
|
+
execute({ sender }) {
|
|
76
|
+
sender.sendMessage("Hello from ${displayName}.");
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
onDisable(context) {
|
|
81
|
+
context.app.log.info("${displayName} disabled.");
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
export const GITIGNORE = `dist
|
|
87
|
+
.lapis
|
|
88
|
+
node_modules
|
|
89
|
+
.venv
|
|
90
|
+
venv
|
|
91
|
+
__pycache__
|
|
92
|
+
.mypy_cache
|
|
93
|
+
.pytest_cache
|
|
94
|
+
.ruff_cache
|
|
95
|
+
`;
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-lapis-lazuli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-lapis-lazuli": "./dist/index.js",
|
|
8
|
+
"lapis": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.build.json",
|
|
18
|
+
"prepublishOnly": "bun run build",
|
|
19
|
+
"test": "bun test"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^24.5.2",
|
|
23
|
+
"typescript": "^5.9.3"
|
|
24
|
+
}
|
|
25
|
+
}
|