sb-mig 5.6.0-beta.1 → 5.6.0-beta.2
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 +1 -14
- 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 +36 -0
- package/dist/api-v2/discover/discover.js +281 -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 +4 -51
- 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 +321 -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 +37 -20
- package/dist/utils/pkg-require.d.ts +0 -2
- package/dist/utils/pkg-require.js +0 -4
|
@@ -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,36 @@
|
|
|
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
|
+
* Discover components in the working directory
|
|
23
|
+
* Prefers .ts for local files and .cjs for external (node_modules) files
|
|
24
|
+
* to avoid duplicates when both ESM and CJS versions exist
|
|
25
|
+
*/
|
|
26
|
+
export declare function discoverComponents(workingDir: string, options?: {
|
|
27
|
+
extensions?: string[];
|
|
28
|
+
}): Promise<DiscoveredResource[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Discover datasources in the working directory
|
|
31
|
+
*/
|
|
32
|
+
export declare function discoverDatasources(workingDir: string): Promise<DiscoveredResource[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Discover roles in the working directory
|
|
35
|
+
*/
|
|
36
|
+
export declare function discoverRoles(workingDir: string): Promise<DiscoveredResource[]>;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { readdir, stat, readFile } from "fs/promises";
|
|
2
|
+
import { join } 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
|
+
* Discover components in the working directory
|
|
77
|
+
* Prefers .ts for local files and .cjs for external (node_modules) files
|
|
78
|
+
* to avoid duplicates when both ESM and CJS versions exist
|
|
79
|
+
*/
|
|
80
|
+
export async function discoverComponents(workingDir, options) {
|
|
81
|
+
const components = [];
|
|
82
|
+
// Priority order: .ts first (local), then .cjs (for node_modules)
|
|
83
|
+
// Skip .js and .mjs to avoid duplicates
|
|
84
|
+
const extensions = options?.extensions ?? [".sb.ts", ".sb.cjs"];
|
|
85
|
+
const componentDirs = await readComponentDirectories(workingDir);
|
|
86
|
+
const scanDir = async (dir, isExternal) => {
|
|
87
|
+
try {
|
|
88
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
const fullPath = join(dir, entry.name);
|
|
91
|
+
if (entry.isDirectory()) {
|
|
92
|
+
if (entry.name === ".git" ||
|
|
93
|
+
entry.name === ".next" ||
|
|
94
|
+
entry.name === "dist") {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const isNowExternal = isExternal || entry.name === "node_modules";
|
|
98
|
+
await scanDir(fullPath, isNowExternal);
|
|
99
|
+
}
|
|
100
|
+
else if (entry.isFile()) {
|
|
101
|
+
for (const ext of extensions) {
|
|
102
|
+
if (entry.name.endsWith(ext) &&
|
|
103
|
+
!entry.name.startsWith("_")) {
|
|
104
|
+
const componentName = entry.name.replace(ext, "");
|
|
105
|
+
components.push({
|
|
106
|
+
name: componentName,
|
|
107
|
+
filePath: fullPath,
|
|
108
|
+
type: isExternal ? "external" : "local",
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Directory doesn't exist or can't be read
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
for (const dir of componentDirs) {
|
|
121
|
+
const fullDir = join(workingDir, dir);
|
|
122
|
+
try {
|
|
123
|
+
const dirStat = await stat(fullDir);
|
|
124
|
+
if (dirStat.isDirectory()) {
|
|
125
|
+
await scanDir(fullDir, dir.includes("node_modules"));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Directory doesn't exist
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Also scan root
|
|
133
|
+
try {
|
|
134
|
+
const rootEntries = await readdir(workingDir, { withFileTypes: true });
|
|
135
|
+
for (const entry of rootEntries) {
|
|
136
|
+
if (entry.isFile()) {
|
|
137
|
+
for (const ext of extensions) {
|
|
138
|
+
if (entry.name.endsWith(ext) &&
|
|
139
|
+
!entry.name.startsWith("_")) {
|
|
140
|
+
const componentName = entry.name.replace(ext, "");
|
|
141
|
+
if (!components.find((c) => c.name === componentName)) {
|
|
142
|
+
components.push({
|
|
143
|
+
name: componentName,
|
|
144
|
+
filePath: join(workingDir, entry.name),
|
|
145
|
+
type: "local",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Ignore
|
|
156
|
+
}
|
|
157
|
+
// Deduplicate: prefer .ts over .cjs for same component name
|
|
158
|
+
const seen = new Map();
|
|
159
|
+
for (const component of components) {
|
|
160
|
+
const existing = seen.get(component.name);
|
|
161
|
+
if (!existing) {
|
|
162
|
+
seen.set(component.name, component);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Prefer .ts files over .cjs
|
|
166
|
+
if (component.filePath.endsWith(".ts") &&
|
|
167
|
+
!existing.filePath.endsWith(".ts")) {
|
|
168
|
+
seen.set(component.name, component);
|
|
169
|
+
}
|
|
170
|
+
// Prefer local over external
|
|
171
|
+
else if (component.type === "local" &&
|
|
172
|
+
existing.type === "external") {
|
|
173
|
+
seen.set(component.name, component);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const deduplicated = Array.from(seen.values());
|
|
178
|
+
// Sort: local first, then by name
|
|
179
|
+
deduplicated.sort((a, b) => {
|
|
180
|
+
if (a.type !== b.type) {
|
|
181
|
+
return a.type === "local" ? -1 : 1;
|
|
182
|
+
}
|
|
183
|
+
return a.name.localeCompare(b.name);
|
|
184
|
+
});
|
|
185
|
+
return deduplicated;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Discover datasources in the working directory
|
|
189
|
+
*/
|
|
190
|
+
export async function discoverDatasources(workingDir) {
|
|
191
|
+
const datasources = [];
|
|
192
|
+
const extensions = [
|
|
193
|
+
".datasource.js",
|
|
194
|
+
".datasource.cjs",
|
|
195
|
+
".sb.datasource.js",
|
|
196
|
+
".sb.datasource.cjs",
|
|
197
|
+
];
|
|
198
|
+
const scanDir = async (dir) => {
|
|
199
|
+
try {
|
|
200
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
201
|
+
for (const entry of entries) {
|
|
202
|
+
const fullPath = join(dir, entry.name);
|
|
203
|
+
if (entry.isDirectory()) {
|
|
204
|
+
if (entry.name === ".git" ||
|
|
205
|
+
entry.name === ".next" ||
|
|
206
|
+
entry.name === "dist" ||
|
|
207
|
+
entry.name === "node_modules") {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
await scanDir(fullPath);
|
|
211
|
+
}
|
|
212
|
+
else if (entry.isFile()) {
|
|
213
|
+
for (const ext of extensions) {
|
|
214
|
+
if (entry.name.endsWith(ext) &&
|
|
215
|
+
!entry.name.startsWith("_")) {
|
|
216
|
+
const name = entry.name
|
|
217
|
+
.replace(ext, "")
|
|
218
|
+
.replace(".sb", "");
|
|
219
|
+
datasources.push({
|
|
220
|
+
name,
|
|
221
|
+
filePath: fullPath,
|
|
222
|
+
type: "local",
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Skip
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
await scanDir(workingDir);
|
|
235
|
+
datasources.sort((a, b) => a.name.localeCompare(b.name));
|
|
236
|
+
return datasources;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Discover roles in the working directory
|
|
240
|
+
*/
|
|
241
|
+
export async function discoverRoles(workingDir) {
|
|
242
|
+
const roles = [];
|
|
243
|
+
const extensions = [".sb.roles.js", ".sb.roles.cjs", ".sb.roles.ts"];
|
|
244
|
+
const scanDir = async (dir) => {
|
|
245
|
+
try {
|
|
246
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
247
|
+
for (const entry of entries) {
|
|
248
|
+
const fullPath = join(dir, entry.name);
|
|
249
|
+
if (entry.isDirectory()) {
|
|
250
|
+
if (entry.name === ".git" ||
|
|
251
|
+
entry.name === ".next" ||
|
|
252
|
+
entry.name === "dist" ||
|
|
253
|
+
entry.name === "node_modules") {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
await scanDir(fullPath);
|
|
257
|
+
}
|
|
258
|
+
else if (entry.isFile()) {
|
|
259
|
+
for (const ext of extensions) {
|
|
260
|
+
if (entry.name.endsWith(ext) &&
|
|
261
|
+
!entry.name.startsWith("_")) {
|
|
262
|
+
const name = entry.name.replace(ext, "");
|
|
263
|
+
roles.push({
|
|
264
|
+
name,
|
|
265
|
+
filePath: fullPath,
|
|
266
|
+
type: "local",
|
|
267
|
+
});
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// Skip
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
await scanDir(workingDir);
|
|
279
|
+
roles.sort((a, b) => a.name.localeCompare(b.name));
|
|
280
|
+
return roles;
|
|
281
|
+
}
|
|
@@ -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;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { mkdir, rm } from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { rollup } from "rollup";
|
|
4
|
+
import ts from "rollup-plugin-ts";
|
|
5
|
+
/**
|
|
6
|
+
* Extract the component name from a file path
|
|
7
|
+
* e.g., "/path/to/my-component.sb.ts" -> "my-component.sb"
|
|
8
|
+
*/
|
|
9
|
+
export const extractComponentName = (filePath) => {
|
|
10
|
+
const separator = "/";
|
|
11
|
+
const parts = filePath.split(separator);
|
|
12
|
+
const lastElement = parts[parts.length - 1];
|
|
13
|
+
return lastElement.replace(/\.ts$/, "");
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Build a single file using Rollup
|
|
17
|
+
*/
|
|
18
|
+
async function buildFile(inputPath, outputCjs, outputEsm) {
|
|
19
|
+
const inputOptions = {
|
|
20
|
+
input: inputPath,
|
|
21
|
+
plugins: [
|
|
22
|
+
ts({
|
|
23
|
+
transpileOnly: true,
|
|
24
|
+
transpiler: "swc",
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
const outputOptionsList = [
|
|
29
|
+
{ file: outputCjs, format: "cjs" },
|
|
30
|
+
{ file: outputEsm, format: "es" },
|
|
31
|
+
];
|
|
32
|
+
let bundle;
|
|
33
|
+
try {
|
|
34
|
+
bundle = await rollup(inputOptions);
|
|
35
|
+
for (const outputOptions of outputOptionsList) {
|
|
36
|
+
await bundle.write(outputOptions);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (bundle) {
|
|
41
|
+
await bundle.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Precompile TypeScript schema files to JavaScript
|
|
47
|
+
*
|
|
48
|
+
* This uses Rollup with SWC for fast transpilation, producing
|
|
49
|
+
* both CommonJS (.cjs) and ESM (.js) outputs.
|
|
50
|
+
*
|
|
51
|
+
* @param files - Array of TypeScript file paths to compile
|
|
52
|
+
* @param options - Precompile options
|
|
53
|
+
* @returns Result with compiled files and any errors
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* const result = await precompile([
|
|
58
|
+
* '/path/to/hero.sb.ts',
|
|
59
|
+
* '/path/to/card.sb.ts',
|
|
60
|
+
* ], { cacheDir: '.cache/sb-mig' });
|
|
61
|
+
*
|
|
62
|
+
* // Use compiled CJS files
|
|
63
|
+
* for (const compiled of result.compiled) {
|
|
64
|
+
* const content = require(compiled.outputCjs);
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export async function precompile(files, options = {}) {
|
|
69
|
+
const { cacheDir = ".sb-mig-cache", flushCache = true, projectDir = process.cwd(), } = options;
|
|
70
|
+
const fullCacheDir = path.join(projectDir, cacheDir, "sb-mig");
|
|
71
|
+
// Optionally clear cache
|
|
72
|
+
if (flushCache) {
|
|
73
|
+
try {
|
|
74
|
+
await rm(fullCacheDir, { recursive: true, force: true });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Ignore if doesn't exist
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Ensure cache directory exists
|
|
81
|
+
await mkdir(fullCacheDir, { recursive: true });
|
|
82
|
+
const result = {
|
|
83
|
+
compiled: [],
|
|
84
|
+
errors: [],
|
|
85
|
+
};
|
|
86
|
+
// Filter to only TypeScript files
|
|
87
|
+
const tsFiles = files.filter((f) => f.endsWith(".ts"));
|
|
88
|
+
if (tsFiles.length === 0) {
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
// Compile all files in parallel
|
|
92
|
+
await Promise.all(tsFiles.map(async (inputPath) => {
|
|
93
|
+
const componentName = extractComponentName(inputPath);
|
|
94
|
+
const outputCjs = path.join(fullCacheDir, `${componentName}.cjs`);
|
|
95
|
+
const outputEsm = path.join(fullCacheDir, `${componentName}.js`);
|
|
96
|
+
try {
|
|
97
|
+
await buildFile(inputPath, outputCjs, outputEsm);
|
|
98
|
+
result.compiled.push({
|
|
99
|
+
input: inputPath,
|
|
100
|
+
outputCjs,
|
|
101
|
+
outputEsm,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
result.errors.push({
|
|
106
|
+
input: inputPath,
|
|
107
|
+
error: error instanceof Error ? error.message : String(error),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}));
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the compiled file path for a TypeScript source file
|
|
115
|
+
*
|
|
116
|
+
* @param tsFilePath - Original .ts file path
|
|
117
|
+
* @param options - Options with cacheDir and projectDir
|
|
118
|
+
* @param format - Output format ('cjs' or 'esm')
|
|
119
|
+
* @returns Path to the compiled file
|
|
120
|
+
*/
|
|
121
|
+
export function getCompiledPath(tsFilePath, options = {}, format = "cjs") {
|
|
122
|
+
const { cacheDir = ".sb-mig-cache", projectDir = process.cwd() } = options;
|
|
123
|
+
const fullCacheDir = path.join(projectDir, cacheDir, "sb-mig");
|
|
124
|
+
const componentName = extractComponentName(tsFilePath);
|
|
125
|
+
const ext = format === "cjs" ? ".cjs" : ".js";
|
|
126
|
+
return path.join(fullCacheDir, `${componentName}${ext}`);
|
|
127
|
+
}
|