🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

@inlang/sdk

Package Overview
Dependencies
Maintainers
2
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@inlang/sdk - npm Package Compare versions

Comparing version

to
0.19.0

dist/migrations/migrateToDirectory.d.ts

31

dist/adapter/solidAdapter.test.js

@@ -75,6 +75,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */

const fs = createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config));
const project = solidAdapter(await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -100,6 +100,6 @@ _import: $import,

const fs = createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config));
const project = solidAdapter(await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -154,6 +154,6 @@ _import: $import,

const mockImport = async () => ({ default: mockPlugin });
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(mockConfig));
await fs.mkdir("/user/project.inlang.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(mockConfig));
const project = solidAdapter(await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang.inlang",
nodeishFs: fs,

@@ -176,6 +176,6 @@ _import: mockImport,

const fs = createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config));
await fs.mkdir("/user/project.inlang.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(config));
const project = solidAdapter(await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang.inlang",
nodeishFs: fs,

@@ -223,5 +223,6 @@ _import: $import,

const fs = createNodeishMemoryFs();
await fs.writeFile("./project.config.json", JSON.stringify(config));
await fs.mkdir("./project.inlang", { recursive: true });
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(config));
const project = solidAdapter(await loadProject({
settingsFilePath: "./project.config.json",
projectPath: "./project.inlang",
nodeishFs: fs,

@@ -253,3 +254,3 @@ _import: $import,

const project = solidAdapter(await loadProject({
settingsFilePath: "./project.config.json",
projectPath: "./project.config.json",
nodeishFs: fs,

@@ -256,0 +257,0 @@ _import: $import,

@@ -6,8 +6,8 @@ import type { NodeishFilesystemSubset } from "@inlang/plugin";

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/
export declare const createNodeishFsWithAbsolutePaths: (args: {
settingsFilePath: string;
projectPath: string;
nodeishFs: NodeishFilesystemSubset;
}) => NodeishFilesystemSubset;
//# sourceMappingURL=createNodeishFsWithAbsolutePaths.d.ts.map

@@ -7,11 +7,11 @@ import { normalizePath } from "@lix-js/fs";

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/
export const createNodeishFsWithAbsolutePaths = (args) => {
if (!isAbsolutePath(args.settingsFilePath)) {
throw new Error(`Expected an absolute path but received "${args.settingsFilePath}".`);
if (!isAbsolutePath(args.projectPath)) {
throw new Error(`Expected an absolute path but received "${args.projectPath}".`);
}
// get the base path of the settings file by
// removing the file name from the path
const basePath = normalizePath(args.settingsFilePath).split("/").slice(0, -1).join("/");
const basePath = normalizePath(args.projectPath).split("/").slice(0, -1).join("/");
const makeAbsolute = (path) => {

@@ -18,0 +18,0 @@ if (isAbsolutePath(path)) {

import { it, expect, vi } from "vitest";
import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js";
it("throws an error if settingsFilePath is not an absolute path", () => {
it("throws an error if projectPath is not an absolute path", () => {
const relativePath = "relative/path";
expect(() => createNodeishFsWithAbsolutePaths({ settingsFilePath: relativePath, nodeishFs: {} })).toThrow();
expect(() => createNodeishFsWithAbsolutePaths({ projectPath: relativePath, nodeishFs: {} })).toThrow();
});
it("intercepts paths correctly for readFile", async () => {
const settingsFilePath = `/Users/samuel/Documents/paraglide/example/project.inlang.json`;
const projectPath = `/Users/samuel/Documents/paraglide/example/project.inlang`;
const filePaths = [

@@ -26,3 +26,3 @@ ["file.txt", `/Users/samuel/Documents/paraglide/example/file.txt`],

const interceptedFs = createNodeishFsWithAbsolutePaths({
settingsFilePath,
projectPath,
nodeishFs: mockNodeishFs,

@@ -29,0 +29,0 @@ });

@@ -6,3 +6,3 @@ import type { NodeishFilesystemSubset } from "@inlang/plugin";

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/

@@ -9,0 +9,0 @@ export declare const createNodeishFsWithWatcher: (args: {

@@ -5,3 +5,3 @@ /**

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/

@@ -18,5 +18,7 @@ export const createNodeishFsWithWatcher = (args) => {

});
//eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const event of watcher) {
args.updateMessages();
if (watcher) {
//eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const event of watcher) {
args.updateMessages();
}
}

@@ -23,0 +25,0 @@ }

@@ -11,3 +11,3 @@ import { assert, describe, it } from "vitest";

assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"));
assert.isTrue(isAbsolutePath("C:/Users/user/project/project.inlang.json"));
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"));
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"));

@@ -14,0 +14,0 @@ });

import type { InlangProject, Subscribable } from "./api.js";
import { type ImportFunction } from "./resolve-modules/index.js";
import { type NodeishFilesystemSubset } from "./versionedInterfaces.js";
import { type NodeishFilesystem } from "@lix-js/fs";
/**
* Creates an inlang instance.
*
* @param settingsFilePath - Absolute path to the inlang settings file.
* @param projectPath - Absolute path to the inlang settings file.
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.

@@ -15,4 +15,4 @@ * @param _import - Use `_import` to pass a custom import function for testing,

export declare const loadProject: (args: {
settingsFilePath: string;
nodeishFs: NodeishFilesystemSubset;
projectPath: string;
nodeishFs: NodeishFilesystem;
_import?: ImportFunction | undefined;

@@ -19,0 +19,0 @@ _capture?: ((id: string, props: Record<string, unknown>) => void) | undefined;

@@ -15,2 +15,3 @@ import { resolveModules } from "./resolve-modules/index.js";

import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
import { maybeMigrateToDirectory } from "./migrations/migrateToDirectory.js";
const settingsCompiler = TypeCompiler.Compile(ProjectSettings);

@@ -20,3 +21,3 @@ /**

*
* @param settingsFilePath - Absolute path to the inlang settings file.
* @param projectPath - Absolute path to the inlang settings file.
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.

@@ -29,10 +30,15 @@ * @param _import - Use `_import` to pass a custom import function for testing,

export const loadProject = async (args) => {
const projectPath = normalizePath(args.projectPath);
// -- migrate if outdated ------------------------------------------------
await maybeMigrateToDirectory({ nodeishFs: args.nodeishFs, projectPath });
// -- validation --------------------------------------------------------
//! the only place where throwing is acceptable because the project
//! won't even be loaded. do not throw anywhere else. otherwise, apps
//! can't handle errors gracefully.
if (!isAbsolutePath(args.settingsFilePath)) {
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.settingsFilePath}".`, { argument: "settingsFilePath" });
// the only place where throwing is acceptable because the project
// won't even be loaded. do not throw anywhere else. otherwise, apps
// can't handle errors gracefully.
if (!isAbsolutePath(args.projectPath)) {
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.projectPath}".`, { argument: "projectPath" });
}
const settingsFilePath = normalizePath(args.settingsFilePath);
else if (/[^\\/]+\.inlang$/.test(projectPath) === false) {
throw new LoadProjectInvalidArgument(`Expected a path ending in "{name}.inlang" but received "${projectPath}".\n\nValid examples: \n- "/path/to/micky-mouse.inlang"\n- "/path/to/green-elephant.inlang\n`, { argument: "projectPath" });
}
// -- load project ------------------------------------------------------

@@ -42,3 +48,3 @@ return await createRoot(async () => {

const nodeishFs = createNodeishFsWithAbsolutePaths({
settingsFilePath,
projectPath,
nodeishFs: args.nodeishFs,

@@ -49,3 +55,3 @@ });

createEffect(() => {
loadSettings({ settingsFilePath, nodeishFs })
loadSettings({ settingsFilePath: projectPath + "/settings.json", nodeishFs })
.then((settings) => {

@@ -62,3 +68,3 @@ setSettings(settings);

// TODO: create FS watcher and update settings on change
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings }));
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings, projectPath }));
const setSettings = (settings) => {

@@ -167,8 +173,8 @@ try {

}
// if (
// newMessages.length !== 0 &&
// JSON.stringify(newMessages) !== JSON.stringify(messages())
// ) {
// setMessages(newMessages)
// }
const abortController = new AbortController();
if (newMessages.length !== 0 &&
JSON.stringify(newMessages) !== JSON.stringify(messages()) &&
nodeishFs.watch("/", { signal: abortController.signal }) === undefined) {
setMessages(newMessages);
}
}, { atBegin: false }));

@@ -250,3 +256,3 @@ createEffect(() => {

}
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile("./project.inlang.json", serializedSettings));
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile(args.projectPath + "/settings.json", serializedSettings));
if (writeSettingsError) {

@@ -253,0 +259,0 @@ throw writeSettingsError;

@@ -83,7 +83,38 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */

// ------------------------------------------------------------------------------------------------
/**
* Dear Developers,
*
* Inlang projects (folders) are not like .vscode, .git, or .github folders. Treat em
* like files: they can be renamed and moved around.
*/
it("should throw if a project (path) does not have a name", async () => {
const fs = createNodeishMemoryFs();
const project = await tryCatch(() => loadProject({
projectPath: "/source-code/.inlang",
nodeishFs: fs,
_import,
}));
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
});
it("should throw if a project path does not end with .inlang", async () => {
const fs = createNodeishMemoryFs();
const invalidPaths = [
"/source-code/frontend.inlang/settings",
"/source-code/frontend.inlang/settings.json",
"/source-code/frontend.inlang.md",
];
for (const invalidPath of invalidPaths) {
const project = await tryCatch(() => loadProject({
projectPath: invalidPath,
nodeishFs: fs,
_import,
}));
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
}
});
describe("initialization", () => {
it("should throw if settingsFilePath is not an absolute path", async () => {
it("should throw if projectPath is not an absolute path", async () => {
const fs = createNodeishMemoryFs();
const result = await tryCatch(() => loadProject({
settingsFilePath: "relative/path",
projectPath: "relative/path",
nodeishFs: fs,

@@ -97,6 +128,6 @@ _import,

const fs = createNodeishMemoryFs();
fs.mkdir("C:\\Users\\user\\project", { recursive: true });
fs.writeFile("C:\\Users\\user\\project\\project.inlang.json", JSON.stringify(settings));
fs.mkdir("C:\\Users\\user\\project.inlang", { recursive: true });
fs.writeFile("C:\\Users\\user\\project.inlang\\settings.json", JSON.stringify(settings));
const result = await tryCatch(() => loadProject({
settingsFilePath: "C:\\Users\\user\\project\\project.inlang.json",
projectPath: "C:\\Users\\user\\project.inlang",
nodeishFs: fs,

@@ -113,3 +144,3 @@ _import,

const project = await loadProject({
settingsFilePath: "/user/project/test.json",
projectPath: "/user/non-existend-project.inlang",
nodeishFs: fs,

@@ -122,6 +153,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", "invalid json");
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", "invalid json");
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -134,6 +165,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify({}));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({}));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -146,6 +177,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -159,10 +190,10 @@ _import,

const settingsWithDeifferentFormatting = JSON.stringify(settings, undefined, 4);
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", settingsWithDeifferentFormatting);
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", settingsWithDeifferentFormatting);
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,
_import,
});
const settingsOnDisk = await fs.readFile("/user/project/project.inlang.json", {
const settingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
encoding: "utf-8",

@@ -174,3 +205,3 @@ });

await new Promise((resolve) => setTimeout(resolve, 0));
const newsettingsOnDisk = await fs.readFile("/user/project/project.inlang.json", {
const newsettingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
encoding: "utf-8",

@@ -187,6 +218,6 @@ });

const fs = createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -216,6 +247,6 @@ _import: $badImport,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -228,6 +259,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -249,8 +280,8 @@ _import,

describe("setSettings", () => {
it("should fail if settings is not valid", async () => {
it("should fail if settings are not valid", async () => {
const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -265,3 +296,3 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.mkdir("/user/project.inlang", { recursive: true });
const settings = {

@@ -272,5 +303,5 @@ sourceLanguageTag: "en",

};
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -284,17 +315,17 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,
_import,
});
const before = await fs.readFile("/user/project/project.inlang.json", { encoding: "utf-8" });
const before = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" });
expect(before).toBeDefined();
const result = project.setSettings({ ...settings, languageTags: ["en"] });
const result = project.setSettings({ ...settings, languageTags: ["en", "nl", "de"] });
expect(result.data).toBeUndefined();
expect(result.error).toBeUndefined();
// TODO: how to wait for fs.writeFile to finish?
await new Promise((resolve) => setTimeout(resolve, 0));
const after = await fs.readFile("/user/project/project.inlang.json", { encoding: "utf-8" });
await new Promise((resolve) => setTimeout(resolve, 50));
const after = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" });
expect(after).toBeDefined();

@@ -312,6 +343,6 @@ expect(after).not.toBe(before);

};
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -341,6 +372,6 @@ _import,

};
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -373,4 +404,4 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify({
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({
sourceLanguageTag: "en",

@@ -386,3 +417,3 @@ languageTags: ["en"],

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -417,4 +448,4 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify({
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({
sourceLanguageTag: "en",

@@ -430,3 +461,3 @@ languageTags: ["en"],

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -442,6 +473,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -458,6 +489,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -474,6 +505,6 @@ _import,

const fs = await createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -496,4 +527,4 @@ _import,

};
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
await fs.mkdir("./resources");

@@ -514,3 +545,3 @@ const mockSaveFn = vi.fn();

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -660,3 +691,4 @@ _import,

};
await fs.writeFile("./project.inlang.json", JSON.stringify(settings));
await fs.mkdir("./project.inlang", { recursive: true });
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
const mockSaveFn = vi.fn();

@@ -680,3 +712,3 @@ const _mockPlugin = {

const project = await loadProject({
settingsFilePath: "/project.inlang.json",
projectPath: "/project.inlang",
nodeishFs: fs,

@@ -697,3 +729,3 @@ _import,

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project/project.inlang.json",
nodeishFs: fs,

@@ -718,6 +750,6 @@ _import,

const fs = createNodeishMemoryFs();
await fs.mkdir("/user/project", { recursive: true });
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
await fs.mkdir("/user/project.inlang", { recursive: true });
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -776,6 +808,7 @@ _import: async () => ({

};
await fs.writeFile("./project.inlang.json", JSON.stringify(settings));
await fs.mkdir("./project.inlang", { recursive: true });
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
// establish watcher
const project = await loadProject({
settingsFilePath: normalizePath("/project.inlang.json"),
projectPath: normalizePath("/project.inlang"),
nodeishFs: fs,

@@ -782,0 +815,0 @@ _import: async () => ({

/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { expect, test } from "vitest";
import { Plugin, MessageLintRule } from "@inlang/sdk";
import { Plugin, MessageLintRule } from "../index.js";
// import { createNodeishMemoryFs } from "@lix-js/fs"

@@ -5,0 +5,0 @@ import { Type } from "@sinclair/typebox";

{
"name": "@inlang/sdk",
"type": "module",
"version": "0.18.0",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"exports": {
".": "./dist/index.js",
"./test-utilities": "./dist/test-utilities/index.js",
"./lint": "./dist/lint/index.js",
"./messages": "./dist/messages/index.js"
},
"files": [
"./dist",
"./src"
],
"scripts": {
"build": "tsc --build",
"dev": "tsc --watch",
"test": "tsc --noEmit && vitest run --passWithNoTests --coverage",
"lint": "eslint ./src --fix",
"format": "prettier ./src --write",
"clean": "rm -rf ./dist ./node_modules"
},
"engines": {
"node": ">=18.0.0"
},
"dependencies": {
"@inlang/json-types": "*",
"@inlang/translatable": "*",
"@inlang/message-lint-rule": "*",
"@inlang/module": "*",
"@inlang/language-tag": "*",
"@inlang/message": "*",
"@inlang/plugin": "*",
"@inlang/project-settings": "*",
"@inlang/result": "*",
"@lix-js/fs": "*",
"@sinclair/typebox": "^0.31.17",
"deepmerge-ts": "^5.1.0",
"solid-js": "1.6.12",
"throttle-debounce": "5.0.0",
"dedent": "1.5.1"
},
"devDependencies": {
"@lix-js/fs": "*",
"@types/throttle-debounce": "5.0.0",
"@vitest/coverage-v8": "^0.33.0",
"jsdom": "22.1.0",
"patch-package": "6.5.1",
"tsd": "^0.25.0",
"typescript": "5.2.2",
"vitest": "^0.33.0"
}
}
"name": "@inlang/sdk",
"type": "module",
"version": "0.19.0",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"exports": {
".": "./dist/index.js",
"./test-utilities": "./dist/test-utilities/index.js",
"./lint": "./dist/lint/index.js",
"./messages": "./dist/messages/index.js"
},
"files": [
"./dist",
"./src"
],
"engines": {
"node": ">=18.0.0"
},
"dependencies": {
"@sinclair/typebox": "^0.31.17",
"deepmerge-ts": "^5.1.0",
"solid-js": "1.6.12",
"throttle-debounce": "5.0.0",
"dedent": "1.5.1",
"@inlang/json-types": "1.1.0",
"@inlang/message-lint-rule": "1.4.0",
"@inlang/translatable": "1.2.0",
"@inlang/module": "1.2.0",
"@inlang/language-tag": "1.2.0",
"@inlang/message": "2.0.0",
"@inlang/plugin": "2.4.0",
"@inlang/result": "1.1.0",
"@inlang/project-settings": "2.2.0",
"@lix-js/fs": "0.4.0"
},
"devDependencies": {
"@types/throttle-debounce": "5.0.0",
"@vitest/coverage-v8": "^0.33.0",
"jsdom": "22.1.0",
"patch-package": "6.5.1",
"tsd": "^0.25.0",
"typescript": "5.2.2",
"vitest": "^0.33.0",
"@lix-js/fs": "0.4.0"
},
"scripts": {
"build": "tsc --build",
"dev": "tsc --watch",
"test": "tsc --noEmit && vitest run --passWithNoTests --coverage",
"lint": "eslint ./src --fix",
"format": "prettier ./src --write",
"clean": "rm -rf ./dist ./node_modules"
}
}

@@ -93,7 +93,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */

const fs = createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config))
const project = solidAdapter(
await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -127,7 +127,7 @@ _import: $import,

const fs = createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config))
const project = solidAdapter(
await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -193,7 +193,7 @@ _import: $import,

await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(mockConfig))
await fs.mkdir("/user/project.inlang.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(mockConfig))
const project = solidAdapter(
await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang.inlang",
nodeishFs: fs,

@@ -224,7 +224,7 @@ _import: mockImport,

const fs = createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
await fs.mkdir("/user/project.inlang.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(config))
const project = solidAdapter(
await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang.inlang",
nodeishFs: fs,

@@ -287,6 +287,7 @@ _import: $import,

const fs = createNodeishMemoryFs()
await fs.writeFile("./project.config.json", JSON.stringify(config))
await fs.mkdir("./project.inlang", { recursive: true })
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(config))
const project = solidAdapter(
await loadProject({
settingsFilePath: "./project.config.json",
projectPath: "./project.inlang",
nodeishFs: fs,

@@ -329,3 +330,3 @@ _import: $import,

await loadProject({
settingsFilePath: "./project.config.json",
projectPath: "./project.config.json",
nodeishFs: fs,

@@ -332,0 +333,0 @@ _import: $import,

@@ -5,7 +5,7 @@ import { it, expect, vi } from "vitest"

it("throws an error if settingsFilePath is not an absolute path", () => {
it("throws an error if projectPath is not an absolute path", () => {
const relativePath = "relative/path"
expect(() =>
createNodeishFsWithAbsolutePaths({ settingsFilePath: relativePath, nodeishFs: {} as any })
createNodeishFsWithAbsolutePaths({ projectPath: relativePath, nodeishFs: {} as any })
).toThrow()

@@ -15,3 +15,3 @@ })

it("intercepts paths correctly for readFile", async () => {
const settingsFilePath = `/Users/samuel/Documents/paraglide/example/project.inlang.json`
const projectPath = `/Users/samuel/Documents/paraglide/example/project.inlang`

@@ -37,3 +37,3 @@ const filePaths = [

const interceptedFs = createNodeishFsWithAbsolutePaths({
settingsFilePath,
projectPath,
nodeishFs: mockNodeishFs,

@@ -40,0 +40,0 @@ })

@@ -9,10 +9,10 @@ import type { NodeishFilesystemSubset } from "@inlang/plugin"

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/
export const createNodeishFsWithAbsolutePaths = (args: {
settingsFilePath: string
projectPath: string
nodeishFs: NodeishFilesystemSubset
}): NodeishFilesystemSubset => {
if (!isAbsolutePath(args.settingsFilePath)) {
throw new Error(`Expected an absolute path but received "${args.settingsFilePath}".`)
if (!isAbsolutePath(args.projectPath)) {
throw new Error(`Expected an absolute path but received "${args.projectPath}".`)
}

@@ -22,3 +22,3 @@

// removing the file name from the path
const basePath = normalizePath(args.settingsFilePath).split("/").slice(0, -1).join("/")
const basePath = normalizePath(args.projectPath).split("/").slice(0, -1).join("/")

@@ -25,0 +25,0 @@ const makeAbsolute = (path: string) => {

@@ -7,3 +7,3 @@ import type { NodeishFilesystemSubset } from "@inlang/plugin"

*
* The paths are resolved from the `settingsFilePath` argument.
* The paths are resolved from the `projectPath` argument.
*/

@@ -24,5 +24,7 @@ export const createNodeishFsWithWatcher = (args: {

})
//eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const event of watcher) {
args.updateMessages()
if (watcher) {
//eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const event of watcher) {
args.updateMessages()
}
}

@@ -29,0 +31,0 @@ } catch (err: any) {

@@ -13,3 +13,3 @@ import { assert, describe, it } from "vitest"

assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"))
assert.isTrue(isAbsolutePath("C:/Users/user/project/project.inlang.json"))
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"))
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"))

@@ -16,0 +16,0 @@ })

@@ -108,4 +108,43 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */

/**
* Dear Developers,
*
* Inlang projects (folders) are not like .vscode, .git, or .github folders. Treat em
* like files: they can be renamed and moved around.
*/
it("should throw if a project (path) does not have a name", async () => {
const fs = createNodeishMemoryFs()
const project = await tryCatch(() =>
loadProject({
projectPath: "/source-code/.inlang",
nodeishFs: fs,
_import,
})
)
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument)
})
it("should throw if a project path does not end with .inlang", async () => {
const fs = createNodeishMemoryFs()
const invalidPaths = [
"/source-code/frontend.inlang/settings",
"/source-code/frontend.inlang/settings.json",
"/source-code/frontend.inlang.md",
]
for (const invalidPath of invalidPaths) {
const project = await tryCatch(() =>
loadProject({
projectPath: invalidPath,
nodeishFs: fs,
_import,
})
)
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument)
}
})
describe("initialization", () => {
it("should throw if settingsFilePath is not an absolute path", async () => {
it("should throw if projectPath is not an absolute path", async () => {
const fs = createNodeishMemoryFs()

@@ -115,3 +154,3 @@

loadProject({
settingsFilePath: "relative/path",
projectPath: "relative/path",
nodeishFs: fs,

@@ -127,8 +166,8 @@ _import,

const fs = createNodeishMemoryFs()
fs.mkdir("C:\\Users\\user\\project", { recursive: true })
fs.writeFile("C:\\Users\\user\\project\\project.inlang.json", JSON.stringify(settings))
fs.mkdir("C:\\Users\\user\\project.inlang", { recursive: true })
fs.writeFile("C:\\Users\\user\\project.inlang\\settings.json", JSON.stringify(settings))
const result = await tryCatch(() =>
loadProject({
settingsFilePath: "C:\\Users\\user\\project\\project.inlang.json",
projectPath: "C:\\Users\\user\\project.inlang",
nodeishFs: fs,

@@ -149,3 +188,3 @@ _import,

const project = await loadProject({
settingsFilePath: "/user/project/test.json",
projectPath: "/user/non-existend-project.inlang",
nodeishFs: fs,

@@ -160,7 +199,7 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", "invalid json")
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", "invalid json")
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -175,7 +214,7 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify({}))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({}))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -190,6 +229,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -205,7 +244,7 @@ _import,

const settingsWithDeifferentFormatting = JSON.stringify(settings, undefined, 4)
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", settingsWithDeifferentFormatting)
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", settingsWithDeifferentFormatting)
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -215,3 +254,3 @@ _import,

const settingsOnDisk = await fs.readFile("/user/project/project.inlang.json", {
const settingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
encoding: "utf-8",

@@ -225,3 +264,3 @@ })

const newsettingsOnDisk = await fs.readFile("/user/project/project.inlang.json", {
const newsettingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
encoding: "utf-8",

@@ -241,7 +280,7 @@ })

const fs = createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -275,6 +314,6 @@ _import: $badImport,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -289,6 +328,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -314,8 +353,8 @@ _import,

describe("setSettings", () => {
it("should fail if settings is not valid", async () => {
it("should fail if settings are not valid", async () => {
const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -332,3 +371,3 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.mkdir("/user/project.inlang", { recursive: true })

@@ -341,6 +380,6 @@ const settings: ProjectSettings = {

await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -356,6 +395,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -365,6 +404,6 @@ _import,

const before = await fs.readFile("/user/project/project.inlang.json", { encoding: "utf-8" })
const before = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" })
expect(before).toBeDefined()
const result = project.setSettings({ ...settings, languageTags: ["en"] })
const result = project.setSettings({ ...settings, languageTags: ["en", "nl", "de"] })
expect(result.data).toBeUndefined()

@@ -374,5 +413,5 @@ expect(result.error).toBeUndefined()

// TODO: how to wait for fs.writeFile to finish?
await new Promise((resolve) => setTimeout(resolve, 0))
await new Promise((resolve) => setTimeout(resolve, 50))
const after = await fs.readFile("/user/project/project.inlang.json", { encoding: "utf-8" })
const after = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" })
expect(after).toBeDefined()

@@ -391,6 +430,6 @@ expect(after).not.toBe(before)

}
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -425,7 +464,7 @@ _import,

await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -461,5 +500,5 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile(
"/user/project/project.inlang.json",
"/user/project.inlang/settings.json",
JSON.stringify({

@@ -478,3 +517,3 @@ sourceLanguageTag: "en",

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -514,5 +553,5 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile(
"/user/project/project.inlang.json",
"/user/project.inlang/settings.json",
JSON.stringify({

@@ -531,3 +570,3 @@ sourceLanguageTag: "en",

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -548,6 +587,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -565,6 +604,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -583,6 +622,6 @@ _import,

const fs = await createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -609,4 +648,4 @@ _import,

await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))

@@ -633,3 +672,3 @@ await fs.mkdir("./resources")

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -789,3 +828,4 @@ _import,

await fs.writeFile("./project.inlang.json", JSON.stringify(settings))
await fs.mkdir("./project.inlang", { recursive: true })
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings))

@@ -814,3 +854,3 @@ const mockSaveFn = vi.fn()

const project = await loadProject({
settingsFilePath: "/project.inlang.json",
projectPath: "/project.inlang",
nodeishFs: fs,

@@ -835,3 +875,3 @@ _import,

const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project/project.inlang.json",
nodeishFs: fs,

@@ -855,6 +895,6 @@ _import,

const fs = createNodeishMemoryFs()
await fs.mkdir("/user/project", { recursive: true })
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
await fs.mkdir("/user/project.inlang", { recursive: true })
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
const project = await loadProject({
settingsFilePath: "/user/project/project.inlang.json",
projectPath: "/user/project.inlang",
nodeishFs: fs,

@@ -921,7 +961,8 @@ _import: async () => ({

await fs.writeFile("./project.inlang.json", JSON.stringify(settings))
await fs.mkdir("./project.inlang", { recursive: true })
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings))
// establish watcher
const project = await loadProject({
settingsFilePath: normalizePath("/project.inlang.json"),
projectPath: normalizePath("/project.inlang"),
nodeishFs: fs,

@@ -928,0 +969,0 @@ _import: async () => ({

@@ -26,5 +26,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */

import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js"
import { normalizePath } from "@lix-js/fs"
import { normalizePath, type NodeishFilesystem } from "@lix-js/fs"
import { isAbsolutePath } from "./isAbsolutePath.js"
import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js"
import { maybeMigrateToDirectory } from "./migrations/migrateToDirectory.js"

@@ -36,3 +37,3 @@ const settingsCompiler = TypeCompiler.Compile(ProjectSettings)

*
* @param settingsFilePath - Absolute path to the inlang settings file.
* @param projectPath - Absolute path to the inlang settings file.
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.

@@ -45,20 +46,30 @@ * @param _import - Use `_import` to pass a custom import function for testing,

export const loadProject = async (args: {
settingsFilePath: string
nodeishFs: NodeishFilesystemSubset
projectPath: string
nodeishFs: NodeishFilesystem
_import?: ImportFunction
_capture?: (id: string, props: Record<string, unknown>) => void
}): Promise<InlangProject> => {
const projectPath = normalizePath(args.projectPath)
// -- migrate if outdated ------------------------------------------------
await maybeMigrateToDirectory({ nodeishFs: args.nodeishFs, projectPath })
// -- validation --------------------------------------------------------
//! the only place where throwing is acceptable because the project
//! won't even be loaded. do not throw anywhere else. otherwise, apps
//! can't handle errors gracefully.
if (!isAbsolutePath(args.settingsFilePath)) {
// the only place where throwing is acceptable because the project
// won't even be loaded. do not throw anywhere else. otherwise, apps
// can't handle errors gracefully.
if (!isAbsolutePath(args.projectPath)) {
throw new LoadProjectInvalidArgument(
`Expected an absolute path but received "${args.settingsFilePath}".`,
{ argument: "settingsFilePath" }
`Expected an absolute path but received "${args.projectPath}".`,
{ argument: "projectPath" }
)
} else if (/[^\\/]+\.inlang$/.test(projectPath) === false) {
throw new LoadProjectInvalidArgument(
`Expected a path ending in "{name}.inlang" but received "${projectPath}".\n\nValid examples: \n- "/path/to/micky-mouse.inlang"\n- "/path/to/green-elephant.inlang\n`,
{ argument: "projectPath" }
)
}
const settingsFilePath = normalizePath(args.settingsFilePath)
// -- load project ------------------------------------------------------

@@ -68,3 +79,3 @@ return await createRoot(async () => {

const nodeishFs = createNodeishFsWithAbsolutePaths({
settingsFilePath,
projectPath,
nodeishFs: args.nodeishFs,

@@ -77,3 +88,3 @@ })

createEffect(() => {
loadSettings({ settingsFilePath, nodeishFs })
loadSettings({ settingsFilePath: projectPath + "/settings.json", nodeishFs })
.then((settings) => {

@@ -92,3 +103,3 @@ setSettings(settings)

const writeSettingsToDisk = skipFirst((settings: ProjectSettings) =>
_writeSettingsToDisk({ nodeishFs, settings })
_writeSettingsToDisk({ nodeishFs, settings, projectPath })
)

@@ -232,8 +243,10 @@

}
// if (
// newMessages.length !== 0 &&
// JSON.stringify(newMessages) !== JSON.stringify(messages())
// ) {
// setMessages(newMessages)
// }
const abortController = new AbortController()
if (
newMessages.length !== 0 &&
JSON.stringify(newMessages) !== JSON.stringify(messages()) &&
nodeishFs.watch("/", { signal: abortController.signal }) === undefined
) {
setMessages(newMessages)
}
},

@@ -330,2 +343,3 @@ { atBegin: false }

const _writeSettingsToDisk = async (args: {
projectPath: string
nodeishFs: NodeishFilesystemSubset

@@ -343,3 +357,3 @@ settings: ProjectSettings

const { error: writeSettingsError } = await tryCatch(async () =>
args.nodeishFs.writeFile("./project.inlang.json", serializedSettings)
args.nodeishFs.writeFile(args.projectPath + "/settings.json", serializedSettings)
)

@@ -346,0 +360,0 @@

/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { expect, test } from "vitest"
import { Plugin, MessageLintRule } from "@inlang/sdk"
import { Plugin, MessageLintRule } from "../index.js"
// import { createNodeishMemoryFs } from "@lix-js/fs"

@@ -5,0 +5,0 @@ import { Type } from "@sinclair/typebox"

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet