sb-mig 5.6.0-beta.1 → 5.6.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -19
- package/dist/api/assets/assets.js +2 -15
- package/dist/api/auth/auth.types.d.ts +1 -1
- package/dist/api/components/components.js +2 -1
- package/dist/api/components/components.sync.d.ts +8 -0
- package/dist/api/components/components.sync.js +193 -0
- package/dist/api/data-migration/component-data-migration.js +2 -2
- package/dist/api/datasources/datasource-entries.js +4 -5
- package/dist/api/datasources/datasources.d.ts +5 -2
- package/dist/api/datasources/datasources.js +42 -35
- package/dist/api/datasources/datasources.sync.d.ts +2 -0
- package/dist/api/datasources/datasources.sync.js +11 -0
- package/dist/api/datasources/datasources.types.d.ts +1 -1
- package/dist/api/datasources/index.d.ts +2 -1
- package/dist/api/datasources/index.js +2 -1
- package/dist/api/managementApi.d.ts +2 -2
- package/dist/api/migrate.d.ts +1 -1
- package/dist/api/migrate.js +3 -48
- package/dist/api/plugins/index.d.ts +2 -1
- package/dist/api/plugins/index.js +2 -1
- package/dist/api/plugins/plugins.d.ts +7 -2
- package/dist/api/plugins/plugins.js +28 -15
- package/dist/api/plugins/plugins.sync.d.ts +2 -0
- package/dist/api/plugins/plugins.sync.js +11 -0
- package/dist/api/roles/index.d.ts +2 -1
- package/dist/api/roles/index.js +2 -1
- package/dist/api/roles/roles.d.ts +5 -2
- package/dist/api/roles/roles.js +34 -11
- package/dist/api/roles/roles.sync.d.ts +2 -0
- package/dist/api/roles/roles.sync.js +6 -0
- package/dist/api/roles/roles.types.d.ts +1 -1
- package/dist/api/stories/stories.js +3 -11
- package/dist/api/sync/sync.types.d.ts +30 -0
- package/dist/api/sync/sync.types.js +1 -0
- package/dist/api/testApi.d.ts +2 -2
- package/dist/api/utils/helper-functions.d.ts +5 -1
- package/dist/api/utils/helper-functions.js +6 -1
- package/dist/api/utils/request.d.ts +1 -1
- package/dist/api/utils/request.js +11 -2
- package/dist/api/utils/resolverTransformations.js +2 -57
- package/dist/api-v2/assets/index.d.ts +13 -0
- package/dist/api-v2/assets/index.js +25 -0
- package/dist/api-v2/auth/index.d.ts +3 -0
- package/dist/api-v2/auth/index.js +8 -0
- package/dist/api-v2/client.d.ts +13 -0
- package/dist/api-v2/client.js +17 -0
- package/dist/api-v2/components/index.d.ts +10 -0
- package/dist/api-v2/components/index.js +29 -0
- package/dist/api-v2/datasources/index.d.ts +8 -0
- package/dist/api-v2/datasources/index.js +58 -0
- package/dist/api-v2/discover/discover.d.ts +47 -0
- package/dist/api-v2/discover/discover.js +328 -0
- package/dist/api-v2/discover/index.d.ts +2 -0
- package/dist/api-v2/discover/index.js +1 -0
- package/dist/api-v2/index.d.ts +19 -0
- package/dist/api-v2/index.js +21 -0
- package/dist/api-v2/plugins/index.d.ts +9 -0
- package/dist/api-v2/plugins/index.js +42 -0
- package/dist/api-v2/precompile/index.d.ts +2 -0
- package/dist/api-v2/precompile/index.js +1 -0
- package/dist/api-v2/precompile/precompile.d.ts +65 -0
- package/dist/api-v2/precompile/precompile.js +127 -0
- package/dist/api-v2/presets/index.d.ts +13 -0
- package/dist/api-v2/presets/index.js +25 -0
- package/dist/api-v2/requestConfig.d.ts +5 -0
- package/dist/api-v2/requestConfig.js +34 -0
- package/dist/api-v2/roles/index.d.ts +5 -0
- package/dist/api-v2/roles/index.js +35 -0
- package/dist/api-v2/spaces/index.d.ts +7 -0
- package/dist/api-v2/spaces/index.js +11 -0
- package/dist/api-v2/stories/index.d.ts +34 -0
- package/dist/api-v2/stories/index.js +172 -0
- package/dist/api-v2/stories/types.d.ts +28 -0
- package/dist/api-v2/stories/types.js +1 -0
- package/dist/api-v2/sync/index.d.ts +24 -0
- package/dist/api-v2/sync/index.js +109 -0
- package/dist/api-v2/sync/types.d.ts +1 -0
- package/dist/api-v2/sync/types.js +1 -0
- package/dist/api-v2/test.d.ts +15 -0
- package/dist/api-v2/test.js +21 -0
- package/dist/cli/commands/backup.js +7 -3
- package/dist/cli/commands/copy.js +2 -2
- package/dist/cli/commands/migrate.js +1 -2
- package/dist/cli/commands/migrations.js +2 -2
- package/dist/cli/commands/remove.js +1 -1
- package/dist/cli/commands/revert.js +2 -2
- package/dist/cli/commands/sync.js +1 -2
- package/dist/cli/index.js +1 -1
- package/dist/cli/utils/cli-utils.d.ts +69 -0
- package/dist/cli/utils/cli-utils.js +100 -0
- package/dist/cli/utils/discover.d.ts +3 -22
- package/dist/cli/utils/discover.js +53 -100
- package/dist/config/config.d.ts +2 -39
- package/dist/config/config.types.d.ts +40 -0
- package/dist/config/config.types.js +1 -0
- package/dist/config/defaultConfig.d.ts +1 -1
- package/dist/config/defaultConfig.js +2 -2
- package/dist/utils/array-utils.d.ts +20 -0
- package/dist/utils/array-utils.js +20 -0
- package/dist/utils/async-utils.d.ts +13 -0
- package/dist/utils/async-utils.js +13 -0
- package/dist/utils/date-utils.d.ts +14 -0
- package/dist/utils/date-utils.js +21 -0
- package/dist/utils/files.d.ts +35 -0
- package/dist/utils/files.js +57 -2
- package/dist/utils/main.d.ts +8 -18
- package/dist/utils/main.js +12 -104
- package/dist/utils/migrations.d.ts +9 -3
- package/dist/utils/object-utils.d.ts +46 -0
- package/dist/utils/object-utils.js +71 -0
- package/dist/utils/others.d.ts +6 -9
- package/dist/utils/others.js +8 -15
- package/dist/utils/path-utils.d.ts +89 -0
- package/dist/utils/path-utils.js +106 -0
- package/dist/utils/pkg.d.ts +16 -2
- package/dist/utils/pkg.js +16 -3
- package/dist/utils/string-utils.d.ts +33 -0
- package/dist/utils/string-utils.js +45 -0
- package/dist/utils/transform-utils.d.ts +62 -0
- package/dist/utils/transform-utils.js +113 -0
- package/dist-cjs/api/auth/auth.js +28 -0
- package/dist-cjs/api/auth/auth.types.js +2 -0
- package/dist-cjs/api/components/components.js +202 -0
- package/dist-cjs/api/components/components.sync.js +199 -0
- package/dist-cjs/api/components/components.types.js +2 -0
- package/dist-cjs/api/datasources/datasource-entries.js +166 -0
- package/dist-cjs/api/datasources/datasources.js +166 -0
- package/dist-cjs/api/datasources/datasources.types.js +2 -0
- package/dist-cjs/api/plugins/plugins.js +132 -0
- package/dist-cjs/api/plugins/plugins.types.js +2 -0
- package/dist-cjs/api/presets/componentPresets.js +25 -0
- package/dist-cjs/api/presets/presets.js +92 -0
- package/dist-cjs/api/presets/presets.types.js +2 -0
- package/dist-cjs/api/presets/resolvePresets.js +49 -0
- package/dist-cjs/api/roles/roles.js +131 -0
- package/dist-cjs/api/roles/roles.types.js +2 -0
- package/dist-cjs/api/spaces/spaces.js +34 -0
- package/dist-cjs/api/spaces/spaces.types.js +2 -0
- package/dist-cjs/api/stories/stories.js +214 -0
- package/dist-cjs/api/stories/stories.types.js +2 -0
- package/dist-cjs/api/sync/sync.types.js +2 -0
- package/dist-cjs/api/utils/request.js +48 -0
- package/dist-cjs/api/utils/resolvers.types.js +2 -0
- package/dist-cjs/api-v2/assets/index.js +30 -0
- package/dist-cjs/api-v2/auth/index.js +12 -0
- package/dist-cjs/api-v2/client.js +23 -0
- package/dist-cjs/api-v2/components/index.js +40 -0
- package/dist-cjs/api-v2/datasources/index.js +64 -0
- package/dist-cjs/api-v2/discover/discover.js +368 -0
- package/dist-cjs/api-v2/discover/index.js +9 -0
- package/dist-cjs/api-v2/index.js +60 -0
- package/dist-cjs/api-v2/plugins/index.js +49 -0
- package/dist-cjs/api-v2/precompile/index.js +7 -0
- package/dist-cjs/api-v2/precompile/precompile.js +136 -0
- package/dist-cjs/api-v2/presets/index.js +33 -0
- package/dist-cjs/api-v2/requestConfig.js +37 -0
- package/dist-cjs/api-v2/roles/index.js +41 -0
- package/dist-cjs/api-v2/spaces/index.js +16 -0
- package/dist-cjs/api-v2/stories/index.js +180 -0
- package/dist-cjs/api-v2/stories/types.js +2 -0
- package/dist-cjs/api-v2/sync/index.js +115 -0
- package/dist-cjs/api-v2/sync/types.js +2 -0
- package/dist-cjs/api-v2/test.js +25 -0
- package/dist-cjs/config/config.types.js +2 -0
- package/dist-cjs/config/constants.js +29 -0
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/utils/array-utils.js +24 -0
- package/dist-cjs/utils/logger.js +32 -0
- package/dist-cjs/utils/object-utils.js +77 -0
- package/dist-cjs/utils/path-utils.js +115 -0
- package/package.json +43 -27
- package/dist/utils/pkg-require.d.ts +0 -2
- package/dist/utils/pkg-require.js +0 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createComponent as apiCreateComponent, getAllComponents as apiGetAllComponents, getComponent as apiGetComponent, getAllComponentsGroups as apiGetAllComponentsGroups, createComponentsGroup as apiCreateComponentsGroup, getComponentsGroup as apiGetComponentsGroup, removeComponent as apiRemoveComponent, removeComponentGroup as apiRemoveComponentGroup, updateComponent as apiUpdateComponent, } from "../../api/components/components.js";
|
|
2
|
+
import { toRequestConfig } from "../requestConfig.js";
|
|
3
|
+
export async function getAllComponents(client) {
|
|
4
|
+
return await apiGetAllComponents(toRequestConfig(client));
|
|
5
|
+
}
|
|
6
|
+
export async function getComponent(client, componentName) {
|
|
7
|
+
return await apiGetComponent(componentName, toRequestConfig(client));
|
|
8
|
+
}
|
|
9
|
+
export async function getAllComponentsGroups(client) {
|
|
10
|
+
return await apiGetAllComponentsGroups(toRequestConfig(client));
|
|
11
|
+
}
|
|
12
|
+
export async function getComponentsGroup(client, groupName) {
|
|
13
|
+
return await apiGetComponentsGroup(groupName, toRequestConfig(client));
|
|
14
|
+
}
|
|
15
|
+
export async function createComponentsGroup(client, groupName) {
|
|
16
|
+
return await apiCreateComponentsGroup(groupName, toRequestConfig(client));
|
|
17
|
+
}
|
|
18
|
+
export async function removeComponentGroup(client, componentGroup) {
|
|
19
|
+
return await apiRemoveComponentGroup(componentGroup, toRequestConfig(client));
|
|
20
|
+
}
|
|
21
|
+
export async function removeComponent(client, component) {
|
|
22
|
+
return await apiRemoveComponent(component, toRequestConfig(client));
|
|
23
|
+
}
|
|
24
|
+
export async function createComponent(client, component, presets = false) {
|
|
25
|
+
return await apiCreateComponent(component, presets, toRequestConfig(client));
|
|
26
|
+
}
|
|
27
|
+
export async function updateComponent(client, component, presets = false) {
|
|
28
|
+
return await apiUpdateComponent(component, presets, toRequestConfig(client));
|
|
29
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ApiClient } from "../client.js";
|
|
2
|
+
export declare function getAllDatasources(client: ApiClient): Promise<any>;
|
|
3
|
+
export declare function getDatasource(client: ApiClient, datasourceName: string): Promise<any>;
|
|
4
|
+
export declare function createDatasource(client: ApiClient, datasource: any): Promise<any>;
|
|
5
|
+
export declare function updateDatasource(client: ApiClient, args: {
|
|
6
|
+
datasource: any;
|
|
7
|
+
datasourceToBeUpdated: any;
|
|
8
|
+
}): Promise<any>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getAllItemsWithPagination } from "../../api/utils/request.js";
|
|
2
|
+
export async function getAllDatasources(client) {
|
|
3
|
+
const spaceId = client.spaceId;
|
|
4
|
+
return getAllItemsWithPagination({
|
|
5
|
+
apiFn: ({ per_page, page }) => client.sbApi.get(`spaces/${spaceId}/datasources/`, {
|
|
6
|
+
per_page,
|
|
7
|
+
page,
|
|
8
|
+
}),
|
|
9
|
+
params: { spaceId },
|
|
10
|
+
itemsKey: "datasources",
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export async function getDatasource(client, datasourceName) {
|
|
14
|
+
const datasources = await getAllDatasources(client);
|
|
15
|
+
const match = datasources.filter((d) => d.name === datasourceName);
|
|
16
|
+
if (Array.isArray(match) && match.length === 0)
|
|
17
|
+
return false;
|
|
18
|
+
return match;
|
|
19
|
+
}
|
|
20
|
+
export async function createDatasource(client, datasource) {
|
|
21
|
+
const spaceId = client.spaceId;
|
|
22
|
+
const finalDatasource = {
|
|
23
|
+
name: datasource.name,
|
|
24
|
+
slug: datasource.slug,
|
|
25
|
+
dimensions: [...(datasource.dimensions ?? [])],
|
|
26
|
+
dimensions_attributes: [...(datasource.dimensions ?? [])],
|
|
27
|
+
};
|
|
28
|
+
return client.sbApi
|
|
29
|
+
.post(`spaces/${spaceId}/datasources/`, {
|
|
30
|
+
datasource: finalDatasource,
|
|
31
|
+
})
|
|
32
|
+
.then((res) => res.data);
|
|
33
|
+
}
|
|
34
|
+
export async function updateDatasource(client, args) {
|
|
35
|
+
const spaceId = client.spaceId;
|
|
36
|
+
const { datasource, datasourceToBeUpdated } = args;
|
|
37
|
+
const dimensionsToCreate = (datasource.dimensions ?? []).filter((dimension) => {
|
|
38
|
+
const isDimensionInRemoteDatasource = datasourceToBeUpdated.dimensions?.find((d) => dimension.name === d.name);
|
|
39
|
+
return !isDimensionInRemoteDatasource;
|
|
40
|
+
});
|
|
41
|
+
return client.sbApi
|
|
42
|
+
.put(`spaces/${spaceId}/datasources/${datasourceToBeUpdated.id}`, {
|
|
43
|
+
datasource: {
|
|
44
|
+
id: datasourceToBeUpdated.id,
|
|
45
|
+
name: datasource.name,
|
|
46
|
+
slug: datasource.slug,
|
|
47
|
+
dimensions: [
|
|
48
|
+
...(datasourceToBeUpdated.dimensions ?? []),
|
|
49
|
+
...dimensionsToCreate,
|
|
50
|
+
],
|
|
51
|
+
dimensions_attributes: [
|
|
52
|
+
...(datasourceToBeUpdated.dimensions ?? []),
|
|
53
|
+
...dimensionsToCreate,
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
.then((res) => res.data);
|
|
58
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface DiscoveredResource {
|
|
2
|
+
name: string;
|
|
3
|
+
filePath: string;
|
|
4
|
+
type: "local" | "external";
|
|
5
|
+
}
|
|
6
|
+
export interface LoadedResource {
|
|
7
|
+
name: string;
|
|
8
|
+
filePath: string;
|
|
9
|
+
data: any;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Load the content of a resource file (.sb.js, .datasource.js, etc.)
|
|
14
|
+
* Uses dynamic import to load ES modules and CommonJS
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadResourceContent(filePath: string): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Load multiple resources by file path
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadResources(filePaths: string[]): Promise<LoadedResource[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Options for component discovery
|
|
23
|
+
*/
|
|
24
|
+
export interface DiscoverComponentsOptions {
|
|
25
|
+
/** File extensions to search for (default: [".sb.ts", ".sb.cjs"]) */
|
|
26
|
+
extensions?: string[];
|
|
27
|
+
/** Whether to include external (node_modules) components (default: true) */
|
|
28
|
+
includeExternal?: boolean;
|
|
29
|
+
/** Maximum depth to scan (default: 20, prevents runaway scanning) */
|
|
30
|
+
maxDepth?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Discover components in the working directory
|
|
34
|
+
* Prefers .ts for local files and .cjs for external (node_modules) files
|
|
35
|
+
* to avoid duplicates when both ESM and CJS versions exist
|
|
36
|
+
*
|
|
37
|
+
* Security: Stays within project bounds and doesn't follow symlinks outside
|
|
38
|
+
*/
|
|
39
|
+
export declare function discoverComponents(workingDir: string, options?: DiscoverComponentsOptions): Promise<DiscoveredResource[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Discover datasources in the working directory
|
|
42
|
+
*/
|
|
43
|
+
export declare function discoverDatasources(workingDir: string): Promise<DiscoveredResource[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Discover roles in the working directory
|
|
46
|
+
*/
|
|
47
|
+
export declare function discoverRoles(workingDir: string): Promise<DiscoveredResource[]>;
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { readdir, stat, readFile, realpath } from "fs/promises";
|
|
2
|
+
import { join, resolve } from "path";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
/**
|
|
5
|
+
* Load the content of a resource file (.sb.js, .datasource.js, etc.)
|
|
6
|
+
* Uses dynamic import to load ES modules and CommonJS
|
|
7
|
+
*/
|
|
8
|
+
export async function loadResourceContent(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
// Use dynamic import which works for both ESM and CJS
|
|
11
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
12
|
+
const module = await import(fileUrl);
|
|
13
|
+
return module.default || module;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw new Error(`Failed to load ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Load multiple resources by file path
|
|
21
|
+
*/
|
|
22
|
+
export async function loadResources(filePaths) {
|
|
23
|
+
const results = [];
|
|
24
|
+
for (const filePath of filePaths) {
|
|
25
|
+
const name = filePath
|
|
26
|
+
.split("/")
|
|
27
|
+
.pop()
|
|
28
|
+
?.replace(/\.sb\.(js|cjs|mjs|ts)$/, "")
|
|
29
|
+
.replace(/\.(datasource|roles)\.(js|cjs|ts)$/, "")
|
|
30
|
+
.replace(/\.sb\.(datasource|roles)\.(js|cjs|ts)$/, "") ||
|
|
31
|
+
"unknown";
|
|
32
|
+
try {
|
|
33
|
+
const data = await loadResourceContent(filePath);
|
|
34
|
+
results.push({ name, filePath, data });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
results.push({
|
|
38
|
+
name,
|
|
39
|
+
filePath,
|
|
40
|
+
data: null,
|
|
41
|
+
error: error instanceof Error ? error.message : String(error),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read componentsDirectories from storyblok.config.js if it exists
|
|
49
|
+
*/
|
|
50
|
+
async function readComponentDirectories(workingDir) {
|
|
51
|
+
const configFiles = [
|
|
52
|
+
"storyblok.config.js",
|
|
53
|
+
"storyblok.config.cjs",
|
|
54
|
+
"storyblok.config.mjs",
|
|
55
|
+
];
|
|
56
|
+
for (const configFile of configFiles) {
|
|
57
|
+
try {
|
|
58
|
+
const configPath = join(workingDir, configFile);
|
|
59
|
+
const configContent = await readFile(configPath, "utf-8");
|
|
60
|
+
const match = configContent.match(/componentsDirectories\s*:\s*\[([\s\S]*?)\]/);
|
|
61
|
+
if (match && match[1]) {
|
|
62
|
+
const dirsMatch = match[1].match(/['"]([^'"]+)['"]/g);
|
|
63
|
+
if (dirsMatch) {
|
|
64
|
+
return dirsMatch.map((d) => d.replace(/['"]/g, ""));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Config file doesn't exist, continue
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return ["src", "components", "storyblok"];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if a path is within the project directory
|
|
77
|
+
* Resolves symlinks and ensures we don't escape the project bounds
|
|
78
|
+
*/
|
|
79
|
+
async function isWithinProject(targetPath, projectRoot) {
|
|
80
|
+
try {
|
|
81
|
+
// Resolve both paths to handle symlinks
|
|
82
|
+
const resolvedTarget = await realpath(targetPath);
|
|
83
|
+
const resolvedRoot = await realpath(projectRoot);
|
|
84
|
+
// Check if target is within project root
|
|
85
|
+
return (resolvedTarget.startsWith(resolvedRoot + "/") ||
|
|
86
|
+
resolvedTarget === resolvedRoot);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// If we can't resolve the path, assume it's not safe
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Discover components in the working directory
|
|
95
|
+
* Prefers .ts for local files and .cjs for external (node_modules) files
|
|
96
|
+
* to avoid duplicates when both ESM and CJS versions exist
|
|
97
|
+
*
|
|
98
|
+
* Security: Stays within project bounds and doesn't follow symlinks outside
|
|
99
|
+
*/
|
|
100
|
+
export async function discoverComponents(workingDir, options) {
|
|
101
|
+
const components = [];
|
|
102
|
+
// Priority order: .ts first (local), then .cjs (for node_modules)
|
|
103
|
+
// Skip .js and .mjs to avoid duplicates
|
|
104
|
+
const extensions = options?.extensions ?? [".sb.ts", ".sb.cjs"];
|
|
105
|
+
const includeExternal = options?.includeExternal ?? true;
|
|
106
|
+
const maxDepth = options?.maxDepth ?? 20;
|
|
107
|
+
// Resolve the project root for security checks
|
|
108
|
+
const projectRoot = resolve(workingDir);
|
|
109
|
+
const componentDirs = await readComponentDirectories(workingDir);
|
|
110
|
+
const scanDir = async (dir, isExternal, depth) => {
|
|
111
|
+
// Prevent excessive depth
|
|
112
|
+
if (depth > maxDepth) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Security: Ensure we're still within project bounds
|
|
116
|
+
if (!(await isWithinProject(dir, projectRoot))) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
121
|
+
for (const entry of entries) {
|
|
122
|
+
const fullPath = join(dir, entry.name);
|
|
123
|
+
if (entry.isDirectory()) {
|
|
124
|
+
// Skip common non-source directories
|
|
125
|
+
if (entry.name === ".git" ||
|
|
126
|
+
entry.name === ".next" ||
|
|
127
|
+
entry.name === "dist" ||
|
|
128
|
+
entry.name === ".cache" ||
|
|
129
|
+
entry.name === "coverage") {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// Skip node_modules entirely if not including external
|
|
133
|
+
if (entry.name === "node_modules" && !includeExternal) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const isNowExternal = isExternal || entry.name === "node_modules";
|
|
137
|
+
await scanDir(fullPath, isNowExternal, depth + 1);
|
|
138
|
+
}
|
|
139
|
+
else if (entry.isFile()) {
|
|
140
|
+
// Skip external files if not including them
|
|
141
|
+
if (isExternal && !includeExternal) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
for (const ext of extensions) {
|
|
145
|
+
if (entry.name.endsWith(ext) &&
|
|
146
|
+
!entry.name.startsWith("_")) {
|
|
147
|
+
const componentName = entry.name.replace(ext, "");
|
|
148
|
+
components.push({
|
|
149
|
+
name: componentName,
|
|
150
|
+
filePath: fullPath,
|
|
151
|
+
type: isExternal ? "external" : "local",
|
|
152
|
+
});
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Directory doesn't exist or can't be read
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
for (const dir of componentDirs) {
|
|
164
|
+
const fullDir = join(workingDir, dir);
|
|
165
|
+
// Skip if the directory path includes node_modules and we're not including external
|
|
166
|
+
if (dir.includes("node_modules") && !includeExternal) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const dirStat = await stat(fullDir);
|
|
171
|
+
if (dirStat.isDirectory()) {
|
|
172
|
+
await scanDir(fullDir, dir.includes("node_modules"), 0);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Directory doesn't exist
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Also scan root
|
|
180
|
+
try {
|
|
181
|
+
const rootEntries = await readdir(workingDir, { withFileTypes: true });
|
|
182
|
+
for (const entry of rootEntries) {
|
|
183
|
+
if (entry.isFile()) {
|
|
184
|
+
for (const ext of extensions) {
|
|
185
|
+
if (entry.name.endsWith(ext) &&
|
|
186
|
+
!entry.name.startsWith("_")) {
|
|
187
|
+
const componentName = entry.name.replace(ext, "");
|
|
188
|
+
if (!components.find((c) => c.name === componentName)) {
|
|
189
|
+
components.push({
|
|
190
|
+
name: componentName,
|
|
191
|
+
filePath: join(workingDir, entry.name),
|
|
192
|
+
type: "local",
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Ignore
|
|
203
|
+
}
|
|
204
|
+
// Deduplicate: prefer .ts over .cjs for same component name
|
|
205
|
+
const seen = new Map();
|
|
206
|
+
for (const component of components) {
|
|
207
|
+
const existing = seen.get(component.name);
|
|
208
|
+
if (!existing) {
|
|
209
|
+
seen.set(component.name, component);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Prefer .ts files over .cjs
|
|
213
|
+
if (component.filePath.endsWith(".ts") &&
|
|
214
|
+
!existing.filePath.endsWith(".ts")) {
|
|
215
|
+
seen.set(component.name, component);
|
|
216
|
+
}
|
|
217
|
+
// Prefer local over external
|
|
218
|
+
else if (component.type === "local" &&
|
|
219
|
+
existing.type === "external") {
|
|
220
|
+
seen.set(component.name, component);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const deduplicated = Array.from(seen.values());
|
|
225
|
+
// Sort: local first, then by name
|
|
226
|
+
deduplicated.sort((a, b) => {
|
|
227
|
+
if (a.type !== b.type) {
|
|
228
|
+
return a.type === "local" ? -1 : 1;
|
|
229
|
+
}
|
|
230
|
+
return a.name.localeCompare(b.name);
|
|
231
|
+
});
|
|
232
|
+
return deduplicated;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Discover datasources in the working directory
|
|
236
|
+
*/
|
|
237
|
+
export async function discoverDatasources(workingDir) {
|
|
238
|
+
const datasources = [];
|
|
239
|
+
const extensions = [
|
|
240
|
+
".datasource.js",
|
|
241
|
+
".datasource.cjs",
|
|
242
|
+
".sb.datasource.js",
|
|
243
|
+
".sb.datasource.cjs",
|
|
244
|
+
];
|
|
245
|
+
const scanDir = async (dir) => {
|
|
246
|
+
try {
|
|
247
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
248
|
+
for (const entry of entries) {
|
|
249
|
+
const fullPath = join(dir, entry.name);
|
|
250
|
+
if (entry.isDirectory()) {
|
|
251
|
+
if (entry.name === ".git" ||
|
|
252
|
+
entry.name === ".next" ||
|
|
253
|
+
entry.name === "dist" ||
|
|
254
|
+
entry.name === "node_modules") {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
await scanDir(fullPath);
|
|
258
|
+
}
|
|
259
|
+
else if (entry.isFile()) {
|
|
260
|
+
for (const ext of extensions) {
|
|
261
|
+
if (entry.name.endsWith(ext) &&
|
|
262
|
+
!entry.name.startsWith("_")) {
|
|
263
|
+
const name = entry.name
|
|
264
|
+
.replace(ext, "")
|
|
265
|
+
.replace(".sb", "");
|
|
266
|
+
datasources.push({
|
|
267
|
+
name,
|
|
268
|
+
filePath: fullPath,
|
|
269
|
+
type: "local",
|
|
270
|
+
});
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Skip
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
await scanDir(workingDir);
|
|
282
|
+
datasources.sort((a, b) => a.name.localeCompare(b.name));
|
|
283
|
+
return datasources;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Discover roles in the working directory
|
|
287
|
+
*/
|
|
288
|
+
export async function discoverRoles(workingDir) {
|
|
289
|
+
const roles = [];
|
|
290
|
+
const extensions = [".sb.roles.js", ".sb.roles.cjs", ".sb.roles.ts"];
|
|
291
|
+
const scanDir = async (dir) => {
|
|
292
|
+
try {
|
|
293
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
294
|
+
for (const entry of entries) {
|
|
295
|
+
const fullPath = join(dir, entry.name);
|
|
296
|
+
if (entry.isDirectory()) {
|
|
297
|
+
if (entry.name === ".git" ||
|
|
298
|
+
entry.name === ".next" ||
|
|
299
|
+
entry.name === "dist" ||
|
|
300
|
+
entry.name === "node_modules") {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
await scanDir(fullPath);
|
|
304
|
+
}
|
|
305
|
+
else if (entry.isFile()) {
|
|
306
|
+
for (const ext of extensions) {
|
|
307
|
+
if (entry.name.endsWith(ext) &&
|
|
308
|
+
!entry.name.startsWith("_")) {
|
|
309
|
+
const name = entry.name.replace(ext, "");
|
|
310
|
+
roles.push({
|
|
311
|
+
name,
|
|
312
|
+
filePath: fullPath,
|
|
313
|
+
type: "local",
|
|
314
|
+
});
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
// Skip
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
await scanDir(workingDir);
|
|
326
|
+
roles.sort((a, b) => a.name.localeCompare(b.name));
|
|
327
|
+
return roles;
|
|
328
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { discoverComponents, discoverDatasources, discoverRoles, loadResourceContent, loadResources, } from "./discover.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { testConnection, testAsyncConnection } from "./test.js";
|
|
2
|
+
export { createClient } from "./client.js";
|
|
3
|
+
export type { ClientConfig, ApiClient } from "./client.js";
|
|
4
|
+
export * as stories from "./stories/index.js";
|
|
5
|
+
export type { CopyProgress, CopyResult, StoryTreeNode, FetchStoriesResult, } from "./stories/types.js";
|
|
6
|
+
export * as assets from "./assets/index.js";
|
|
7
|
+
export * as auth from "./auth/index.js";
|
|
8
|
+
export * as components from "./components/index.js";
|
|
9
|
+
export * as datasources from "./datasources/index.js";
|
|
10
|
+
export * as plugins from "./plugins/index.js";
|
|
11
|
+
export * as presets from "./presets/index.js";
|
|
12
|
+
export * as roles from "./roles/index.js";
|
|
13
|
+
export * as spaces from "./spaces/index.js";
|
|
14
|
+
export * as sync from "./sync/index.js";
|
|
15
|
+
export type { SyncResult, SyncError, SyncProgressEvent, SyncProgressCallback, } from "./sync/types.js";
|
|
16
|
+
export * as discover from "./discover/index.js";
|
|
17
|
+
export type { DiscoveredResource } from "./discover/index.js";
|
|
18
|
+
export * as precompile from "./precompile/index.js";
|
|
19
|
+
export type { PrecompileOptions, PrecompileResult, } from "./precompile/index.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Test functions for ESM/CJS interop testing
|
|
2
|
+
export { testConnection, testAsyncConnection } from "./test.js";
|
|
3
|
+
// Client
|
|
4
|
+
export { createClient } from "./client.js";
|
|
5
|
+
// Stories
|
|
6
|
+
export * as stories from "./stories/index.js";
|
|
7
|
+
// Resources (thin wrappers)
|
|
8
|
+
export * as assets from "./assets/index.js";
|
|
9
|
+
export * as auth from "./auth/index.js";
|
|
10
|
+
export * as components from "./components/index.js";
|
|
11
|
+
export * as datasources from "./datasources/index.js";
|
|
12
|
+
export * as plugins from "./plugins/index.js";
|
|
13
|
+
export * as presets from "./presets/index.js";
|
|
14
|
+
export * as roles from "./roles/index.js";
|
|
15
|
+
export * as spaces from "./spaces/index.js";
|
|
16
|
+
// Sync (data-only)
|
|
17
|
+
export * as sync from "./sync/index.js";
|
|
18
|
+
// Discovery
|
|
19
|
+
export * as discover from "./discover/index.js";
|
|
20
|
+
// Precompile (TypeScript to JS using Rollup + SWC)
|
|
21
|
+
export * as precompile from "./precompile/index.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ApiClient } from "../client.js";
|
|
2
|
+
export declare function getAllPlugins(client: ApiClient): Promise<any>;
|
|
3
|
+
export declare function getPlugin(client: ApiClient, pluginName: string): Promise<any>;
|
|
4
|
+
export declare function getPluginDetails(client: ApiClient, plugin: any): Promise<any>;
|
|
5
|
+
export declare function updatePlugin(client: ApiClient, args: {
|
|
6
|
+
plugin: any;
|
|
7
|
+
body: string;
|
|
8
|
+
}): Promise<any>;
|
|
9
|
+
export declare function createPlugin(client: ApiClient, pluginName: string): Promise<any>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getAllItemsWithPagination } from "../../api/utils/request.js";
|
|
2
|
+
export async function getAllPlugins(client) {
|
|
3
|
+
return getAllItemsWithPagination({
|
|
4
|
+
apiFn: ({ per_page, page }) => client.sbApi.get("field_types", { per_page, page }),
|
|
5
|
+
params: {},
|
|
6
|
+
itemsKey: "field_types",
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export async function getPlugin(client, pluginName) {
|
|
10
|
+
const plugins = await getAllPlugins(client);
|
|
11
|
+
const plugin = plugins.find((p) => p.name === pluginName);
|
|
12
|
+
if (!plugin)
|
|
13
|
+
return false;
|
|
14
|
+
return await getPluginDetails(client, plugin);
|
|
15
|
+
}
|
|
16
|
+
export async function getPluginDetails(client, plugin) {
|
|
17
|
+
return client.sbApi
|
|
18
|
+
.get(`field_types/${plugin.id}`)
|
|
19
|
+
.then((res) => res.data);
|
|
20
|
+
}
|
|
21
|
+
export async function updatePlugin(client, args) {
|
|
22
|
+
const { plugin, body } = args;
|
|
23
|
+
return client.sbApi
|
|
24
|
+
.put(`field_types/${plugin.id}`, {
|
|
25
|
+
publish: true,
|
|
26
|
+
field_type: {
|
|
27
|
+
body,
|
|
28
|
+
compiled_body: "",
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
.then((res) => res.data);
|
|
32
|
+
}
|
|
33
|
+
export async function createPlugin(client, pluginName) {
|
|
34
|
+
return client.sbApi
|
|
35
|
+
.post("field_types", {
|
|
36
|
+
publish: true,
|
|
37
|
+
field_type: {
|
|
38
|
+
name: pluginName,
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
.then((res) => res.data);
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { precompile, extractComponentName, getCompiledPath, } from "./precompile.js";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for precompiling TypeScript schema files
|
|
3
|
+
*/
|
|
4
|
+
export interface PrecompileOptions {
|
|
5
|
+
/** Directory to store compiled files (defaults to .sb-mig-cache) */
|
|
6
|
+
cacheDir?: string;
|
|
7
|
+
/** Whether to clear cache before compiling (defaults to true) */
|
|
8
|
+
flushCache?: boolean;
|
|
9
|
+
/** Project directory (defaults to process.cwd()) */
|
|
10
|
+
projectDir?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of precompiling files
|
|
14
|
+
*/
|
|
15
|
+
export interface PrecompileResult {
|
|
16
|
+
/** Successfully compiled files with their output paths */
|
|
17
|
+
compiled: Array<{
|
|
18
|
+
input: string;
|
|
19
|
+
outputCjs: string;
|
|
20
|
+
outputEsm: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Files that failed to compile */
|
|
23
|
+
errors: Array<{
|
|
24
|
+
input: string;
|
|
25
|
+
error: string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extract the component name from a file path
|
|
30
|
+
* e.g., "/path/to/my-component.sb.ts" -> "my-component.sb"
|
|
31
|
+
*/
|
|
32
|
+
export declare const extractComponentName: (filePath: string) => string;
|
|
33
|
+
/**
|
|
34
|
+
* Precompile TypeScript schema files to JavaScript
|
|
35
|
+
*
|
|
36
|
+
* This uses Rollup with SWC for fast transpilation, producing
|
|
37
|
+
* both CommonJS (.cjs) and ESM (.js) outputs.
|
|
38
|
+
*
|
|
39
|
+
* @param files - Array of TypeScript file paths to compile
|
|
40
|
+
* @param options - Precompile options
|
|
41
|
+
* @returns Result with compiled files and any errors
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const result = await precompile([
|
|
46
|
+
* '/path/to/hero.sb.ts',
|
|
47
|
+
* '/path/to/card.sb.ts',
|
|
48
|
+
* ], { cacheDir: '.cache/sb-mig' });
|
|
49
|
+
*
|
|
50
|
+
* // Use compiled CJS files
|
|
51
|
+
* for (const compiled of result.compiled) {
|
|
52
|
+
* const content = require(compiled.outputCjs);
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function precompile(files: string[], options?: PrecompileOptions): Promise<PrecompileResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Get the compiled file path for a TypeScript source file
|
|
59
|
+
*
|
|
60
|
+
* @param tsFilePath - Original .ts file path
|
|
61
|
+
* @param options - Options with cacheDir and projectDir
|
|
62
|
+
* @param format - Output format ('cjs' or 'esm')
|
|
63
|
+
* @returns Path to the compiled file
|
|
64
|
+
*/
|
|
65
|
+
export declare function getCompiledPath(tsFilePath: string, options?: PrecompileOptions, format?: "cjs" | "esm"): string;
|