@datalayer/core 0.0.20 ā 0.0.23
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/lib/api/iam/datasources.d.ts +86 -0
- package/lib/api/iam/datasources.js +185 -0
- package/lib/api/iam/index.d.ts +2 -0
- package/lib/api/iam/index.js +2 -0
- package/lib/api/iam/secrets.d.ts +85 -0
- package/lib/api/iam/secrets.js +196 -0
- package/lib/client/auth/storage.js +17 -62
- package/lib/client/base.d.ts +3 -0
- package/lib/client/base.js +2 -2
- package/lib/client/index.d.ts +82 -3
- package/lib/client/index.js +5 -1
- package/lib/client/mixins/IAMMixin.d.ts +62 -0
- package/lib/client/mixins/IAMMixin.js +116 -0
- package/lib/collaboration/DatalayerCollaboration.d.ts +1 -2
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +1 -1
- package/lib/collaboration/DatalayerCollaborationProvider.js +1 -1
- package/lib/hooks/useBackdrop.d.ts +2 -3
- package/lib/hooks/useBackdropJupyterLab.d.ts +2 -2
- package/lib/hooks/useCache.d.ts +3 -3
- package/lib/hooks/useScreenshot.d.ts +2 -3
- package/lib/hooks/useWindowSize.d.ts +1 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -1
- package/lib/models/Datasource.d.ts +170 -0
- package/lib/models/Datasource.js +140 -0
- package/lib/models/Runtime.d.ts +1 -1
- package/lib/models/RuntimeSnapshotDTO.d.ts +1 -1
- package/lib/models/RuntimeSnapshotDTO.js +1 -1
- package/lib/models/Secret.d.ts +159 -0
- package/lib/models/Secret.js +135 -0
- package/lib/models/SpaceDTO.d.ts +0 -11
- package/lib/state/substates/IAMState.d.ts +1 -1
- package/lib/state/substates/LayoutState.d.ts +2 -2
- package/lib/state/substates/NbformatState.d.ts +1 -1
- package/lib/utils/File.d.ts +1 -1
- package/lib/utils/File.js +1 -1
- package/lib/utils/Notebook.d.ts +5 -3
- package/lib/utils/Notebook.js +5 -3
- package/package.json +9 -8
- package/patches/.gitkeep +1 -0
- package/scripts/apply-patches.sh +44 -0
- package/scripts/create-patches.sh +40 -0
- package/scripts/fix-esm-imports.cjs +124 -0
- package/scripts/sync-jupyter.sh +121 -0
package/lib/models/Secret.js
CHANGED
|
@@ -11,3 +11,138 @@ export const asSecret = (s) => {
|
|
|
11
11
|
value: s.value_s,
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// New API Types and DTO
|
|
16
|
+
// ============================================================================
|
|
17
|
+
import { validateJSON } from '../api/utils/validation';
|
|
18
|
+
/**
|
|
19
|
+
* Secret domain model for the Datalayer SDK.
|
|
20
|
+
* Provides state management and operations for user secrets.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const secret = await sdk.createSecret({
|
|
25
|
+
* variant: 'password',
|
|
26
|
+
* name: 'db_password',
|
|
27
|
+
* description: 'Production DB password',
|
|
28
|
+
* value: 'my-secure-password'
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* await secret.update({ description: 'Updated description' });
|
|
32
|
+
* await secret.delete();
|
|
33
|
+
* ```
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export class SecretDTO {
|
|
37
|
+
/** @internal */
|
|
38
|
+
_data;
|
|
39
|
+
_sdk;
|
|
40
|
+
_deleted = false;
|
|
41
|
+
/**
|
|
42
|
+
* Create a Secret instance.
|
|
43
|
+
* @param data - Secret data from API
|
|
44
|
+
* @param sdk - SDK instance
|
|
45
|
+
*/
|
|
46
|
+
constructor(data, sdk) {
|
|
47
|
+
this._data = data;
|
|
48
|
+
this._sdk = sdk;
|
|
49
|
+
}
|
|
50
|
+
// ========================================================================
|
|
51
|
+
// Helper Methods
|
|
52
|
+
// ========================================================================
|
|
53
|
+
_checkDeleted() {
|
|
54
|
+
if (this._deleted) {
|
|
55
|
+
throw new Error(`Secret ${this._data.name_s} has been deleted and no longer exists`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
_decodeValue(encodedValue) {
|
|
59
|
+
try {
|
|
60
|
+
if (typeof Buffer !== 'undefined') {
|
|
61
|
+
// Node.js environment
|
|
62
|
+
return Buffer.from(encodedValue, 'base64').toString();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Browser environment
|
|
66
|
+
return atob(encodedValue);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('Failed to decode secret value:', error);
|
|
71
|
+
return encodedValue; // Return as-is if decode fails
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ========================================================================
|
|
75
|
+
// Properties
|
|
76
|
+
// ========================================================================
|
|
77
|
+
get uid() {
|
|
78
|
+
this._checkDeleted();
|
|
79
|
+
return this._data.uid;
|
|
80
|
+
}
|
|
81
|
+
get variant() {
|
|
82
|
+
this._checkDeleted();
|
|
83
|
+
return this._data.variant_s;
|
|
84
|
+
}
|
|
85
|
+
get name() {
|
|
86
|
+
this._checkDeleted();
|
|
87
|
+
return this._data.name_s;
|
|
88
|
+
}
|
|
89
|
+
get description() {
|
|
90
|
+
this._checkDeleted();
|
|
91
|
+
return this._data.description_t;
|
|
92
|
+
}
|
|
93
|
+
/** Returns decoded (plain text) secret value */
|
|
94
|
+
get value() {
|
|
95
|
+
this._checkDeleted();
|
|
96
|
+
return this._decodeValue(this._data.value_s);
|
|
97
|
+
}
|
|
98
|
+
// ========================================================================
|
|
99
|
+
// Action Methods
|
|
100
|
+
// ========================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Update this secret.
|
|
103
|
+
* @param updates - Fields to update
|
|
104
|
+
* @returns Updated Secret instance
|
|
105
|
+
*/
|
|
106
|
+
async update(updates) {
|
|
107
|
+
this._checkDeleted();
|
|
108
|
+
const updated = await this._sdk.updateSecret(this.uid, updates);
|
|
109
|
+
return updated;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Delete this secret permanently.
|
|
113
|
+
*/
|
|
114
|
+
async delete() {
|
|
115
|
+
this._checkDeleted();
|
|
116
|
+
await this._sdk.deleteSecret(this.uid);
|
|
117
|
+
this._deleted = true;
|
|
118
|
+
}
|
|
119
|
+
// ========================================================================
|
|
120
|
+
// Utility Methods
|
|
121
|
+
// ========================================================================
|
|
122
|
+
/**
|
|
123
|
+
* Get secret data in camelCase format.
|
|
124
|
+
*/
|
|
125
|
+
toJSON() {
|
|
126
|
+
this._checkDeleted();
|
|
127
|
+
const obj = {
|
|
128
|
+
uid: this.uid,
|
|
129
|
+
variant: this.variant,
|
|
130
|
+
name: this.name,
|
|
131
|
+
description: this.description,
|
|
132
|
+
value: this.value, // Returns decoded value
|
|
133
|
+
};
|
|
134
|
+
validateJSON(obj, 'Secret');
|
|
135
|
+
return obj;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get raw secret data exactly as received from API.
|
|
139
|
+
*/
|
|
140
|
+
rawData() {
|
|
141
|
+
this._checkDeleted();
|
|
142
|
+
return this._data;
|
|
143
|
+
}
|
|
144
|
+
toString() {
|
|
145
|
+
this._checkDeleted();
|
|
146
|
+
return `Secret(${this.name}, ${this.variant})`;
|
|
147
|
+
}
|
|
148
|
+
}
|
package/lib/models/SpaceDTO.d.ts
CHANGED
|
@@ -202,17 +202,6 @@ export interface GetNotebookResponse {
|
|
|
202
202
|
message: string;
|
|
203
203
|
notebook?: NotebookData;
|
|
204
204
|
}
|
|
205
|
-
/**
|
|
206
|
-
* Request payload for creating a notebook
|
|
207
|
-
* @interface CreateNotebookRequest
|
|
208
|
-
*/
|
|
209
|
-
export interface CreateNotebookRequest {
|
|
210
|
-
spaceId: string;
|
|
211
|
-
notebookType: string;
|
|
212
|
-
name: string;
|
|
213
|
-
description: string;
|
|
214
|
-
file?: File | Blob;
|
|
215
|
-
}
|
|
216
205
|
/**
|
|
217
206
|
* Request payload for updating a notebook
|
|
218
207
|
* @interface UpdateNotebookRequest
|
|
@@ -4,7 +4,7 @@ import type { ICredits, ICreditsReservation } from '../../models';
|
|
|
4
4
|
* Limit to warn about low credits in milliseconds.
|
|
5
5
|
*/
|
|
6
6
|
export declare const RESERVATION_WARNING_TIME_MS: number;
|
|
7
|
-
type IAMProviderAuthorizationURL = string;
|
|
7
|
+
export type IAMProviderAuthorizationURL = string;
|
|
8
8
|
export type IIAMState = {
|
|
9
9
|
/**
|
|
10
10
|
* User credits
|
|
@@ -6,12 +6,12 @@ export type BackdropDisplay = {
|
|
|
6
6
|
open: boolean;
|
|
7
7
|
message?: string | void;
|
|
8
8
|
};
|
|
9
|
-
type BannerDisplay = {
|
|
9
|
+
export type BannerDisplay = {
|
|
10
10
|
message: string;
|
|
11
11
|
variant: BannerDisplayVariant;
|
|
12
12
|
timestamp?: Date;
|
|
13
13
|
};
|
|
14
|
-
type PortalDisplay = {
|
|
14
|
+
export type PortalDisplay = {
|
|
15
15
|
portal: ReactPortal;
|
|
16
16
|
pinned: boolean;
|
|
17
17
|
};
|
package/lib/utils/File.d.ts
CHANGED
package/lib/utils/File.js
CHANGED
package/lib/utils/Notebook.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { JupyterLab } from '@jupyterlab/application';
|
|
|
2
2
|
/**
|
|
3
3
|
* Create a notebook
|
|
4
4
|
*
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
5
|
+
* @param params Configuration object
|
|
6
|
+
* @param params.app JupyterLab application
|
|
7
|
+
* @param params.name Notebook name
|
|
8
|
+
* @param params.url Notebook content URL
|
|
9
|
+
* @param params.options Additional options for notebook creation
|
|
8
10
|
*/
|
|
9
11
|
export declare const createNotebook: ({ app, name, url, options, }: {
|
|
10
12
|
app: JupyterLab;
|
package/lib/utils/Notebook.js
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* Create a notebook
|
|
7
7
|
*
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
10
|
-
* @param
|
|
8
|
+
* @param params Configuration object
|
|
9
|
+
* @param params.app JupyterLab application
|
|
10
|
+
* @param params.name Notebook name
|
|
11
|
+
* @param params.url Notebook content URL
|
|
12
|
+
* @param params.options Additional options for notebook creation
|
|
11
13
|
*/
|
|
12
14
|
export const createNotebook = async ({ app, name, url, options, }) => {
|
|
13
15
|
const notebook = await app.commands.execute('notebook:create-new', options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
"lib/**/*.{css,d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
|
24
24
|
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
|
|
25
|
-
"schema/*.json"
|
|
25
|
+
"schema/*.json",
|
|
26
|
+
"patches/",
|
|
27
|
+
"scripts/"
|
|
26
28
|
],
|
|
27
29
|
"main": "lib/index.js",
|
|
28
30
|
"types": "lib/index.d.ts",
|
|
@@ -50,7 +52,7 @@
|
|
|
50
52
|
"clean:dist": "rimraf dist",
|
|
51
53
|
"clean:cache": "rimraf node_modules/.vite",
|
|
52
54
|
"build": "npm run clean && gulp resources-to-lib && tsc -b && vite build",
|
|
53
|
-
"build:lib": "npm run clean:lib && gulp resources-to-lib && tsc -b",
|
|
55
|
+
"build:lib": "npm run clean:lib && gulp resources-to-lib && tsc -b && node scripts/fix-esm-imports.cjs",
|
|
54
56
|
"build:types": "npm run clean:lib && tsc -b",
|
|
55
57
|
"build:nextjs": "npm run build --workspace=nextjs-notebook-example",
|
|
56
58
|
"build:examples": "npm run build:nextjs",
|
|
@@ -81,6 +83,7 @@
|
|
|
81
83
|
"storybook": "storybook dev -p 6006",
|
|
82
84
|
"build-storybook": "storybook build",
|
|
83
85
|
"typedoc": "typedoc --options typedoc.json --out docs/docs/typescript_api",
|
|
86
|
+
"docs": "make typedoc && make pydoc && cd docs && npm install && npm run build",
|
|
84
87
|
"watch:lib": "run-p 'watch:lib:*'",
|
|
85
88
|
"watch:lib:res": "gulp resources-to-lib-watch",
|
|
86
89
|
"watch:lib:src": "tsc -b -w",
|
|
@@ -89,8 +92,7 @@
|
|
|
89
92
|
"examples:vite": "VITE_DATALAYER_RUN_URL=http://localhost:8888 vite --config vite.examples.config.ts",
|
|
90
93
|
"examples:nextjs": "npm run dev --workspace=nextjs-notebook-example",
|
|
91
94
|
"jupyter:start": "./dev/sh/start-jupyter-server.sh",
|
|
92
|
-
"prepare": "husky",
|
|
93
|
-
"postinstall": "bash scripts/apply-patches.sh",
|
|
95
|
+
"prepare": "husky || true",
|
|
94
96
|
"kill": "./dev/sh/kill.sh || true",
|
|
95
97
|
"sync:jupyter": "bash scripts/sync-jupyter.sh",
|
|
96
98
|
"sync:jupyter:watch": "bash scripts/sync-jupyter.sh --watch",
|
|
@@ -101,8 +103,8 @@
|
|
|
101
103
|
},
|
|
102
104
|
"dependencies": {
|
|
103
105
|
"@datalayer/icons-react": "^1.0.6",
|
|
104
|
-
"@datalayer/jupyter-lexical": "^1.0.
|
|
105
|
-
"@datalayer/jupyter-react": "^2.0.
|
|
106
|
+
"@datalayer/jupyter-lexical": "^1.0.8",
|
|
107
|
+
"@datalayer/jupyter-react": "^2.0.2",
|
|
106
108
|
"@datalayer/primer-addons": "^1.0.4",
|
|
107
109
|
"@datalayer/primer-rjsf": "^1.0.1",
|
|
108
110
|
"@fluentui/react": "^8.125.3",
|
|
@@ -137,7 +139,6 @@
|
|
|
137
139
|
"@tailwindcss/vite": "^4.1.13",
|
|
138
140
|
"@tanstack/react-query": "^5.90.6",
|
|
139
141
|
"@toon-format/toon": "^1.3.0",
|
|
140
|
-
"ai": "^5.0.78",
|
|
141
142
|
"ansi-to-html": "^0.7.2",
|
|
142
143
|
"axios": "^1.7.7",
|
|
143
144
|
"boring-avatars": "^2.0.1",
|
package/patches/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Patches directory for patch-package
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
# Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|
|
5
|
+
# Apply patch-package patches for jupyter packages
|
|
6
|
+
# This is normally run automatically via npm's postinstall hook,
|
|
7
|
+
# but can be run manually if needed.
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
# Colors for output
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
BLUE='\033[0;34m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
NC='\033[0m' # No Color
|
|
16
|
+
|
|
17
|
+
# Get the script directory and project root
|
|
18
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
19
|
+
CORE_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
|
20
|
+
|
|
21
|
+
cd "$CORE_ROOT"
|
|
22
|
+
|
|
23
|
+
# On Netlify or other CI with caching issues, force reinstall packages that need patches
|
|
24
|
+
# This ensures we have clean npm versions before applying patches
|
|
25
|
+
if [ "$NETLIFY" = "true" ] || [ "$CI" = "true" ]; then
|
|
26
|
+
echo -e "${YELLOW}š CI detected - force reinstalling packages that need patches...${NC}"
|
|
27
|
+
|
|
28
|
+
# Remove the specific packages that need patches
|
|
29
|
+
rm -rf node_modules/@datalayer/jupyter-lexical
|
|
30
|
+
rm -rf node_modules/@datalayer/jupyter-react
|
|
31
|
+
|
|
32
|
+
# Reinstall them fresh from npm (with --ignore-scripts to prevent infinite loop)
|
|
33
|
+
npm install @datalayer/jupyter-lexical @datalayer/jupyter-react --no-save --ignore-scripts
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
echo -e "${BLUE}š Applying patches...${NC}"
|
|
37
|
+
|
|
38
|
+
# Check if patches directory exists and has patch files
|
|
39
|
+
if [ -d "patches" ] && [ -n "$(ls -A patches/*.patch 2>/dev/null)" ]; then
|
|
40
|
+
npx patch-package
|
|
41
|
+
echo -e "${GREEN}ā
Patches applied successfully${NC}"
|
|
42
|
+
else
|
|
43
|
+
echo -e "${YELLOW}āļø No patches found - skipping patch application${NC}"
|
|
44
|
+
fi
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
# Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|
|
5
|
+
# Create patch-package patches for locally modified jupyter packages
|
|
6
|
+
# This script generates patches that can be committed to the repo and
|
|
7
|
+
# applied automatically during npm install via the postinstall hook.
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
# Colors for output
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
BLUE='\033[0;34m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
NC='\033[0m' # No Color
|
|
16
|
+
|
|
17
|
+
echo -e "${BLUE}š§ Creating patches for jupyter packages...${NC}"
|
|
18
|
+
|
|
19
|
+
# Get the script directory and project root
|
|
20
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
21
|
+
CORE_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
|
22
|
+
|
|
23
|
+
cd "$CORE_ROOT"
|
|
24
|
+
|
|
25
|
+
# First, sync the latest changes from jupyter-ui to ensure patches include all modifications
|
|
26
|
+
echo -e "${BLUE}š Syncing latest changes from jupyter-ui...${NC}"
|
|
27
|
+
bash "$SCRIPT_DIR/sync-jupyter.sh"
|
|
28
|
+
|
|
29
|
+
# Ensure package-lock.json exists (required by patch-package)
|
|
30
|
+
if [ ! -f "package-lock.json" ]; then
|
|
31
|
+
echo -e "${YELLOW}ā ļø No package-lock.json found. Creating one...${NC}"
|
|
32
|
+
npm i --package-lock-only
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Create patches
|
|
36
|
+
echo -e "${BLUE}š Generating patches with patch-package...${NC}"
|
|
37
|
+
npx patch-package @datalayer/jupyter-lexical @datalayer/jupyter-react
|
|
38
|
+
|
|
39
|
+
echo -e "${GREEN}ā
Patches created successfully in patches/ directory${NC}"
|
|
40
|
+
echo -e "${BLUE}ā¹ļø Patches will be applied automatically on 'npm install' via postinstall hook${NC}"
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Post-compilation script to add .js extensions to relative imports/exports
|
|
8
|
+
* This makes the compiled output compatible with Node.js 22 ES modules
|
|
9
|
+
* while keeping the TypeScript source clean.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const LIB_DIR = path.join(__dirname, '..', 'lib');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Recursively get all .js files in a directory
|
|
19
|
+
*/
|
|
20
|
+
function getAllJsFiles(dir, fileList = []) {
|
|
21
|
+
const files = fs.readdirSync(dir);
|
|
22
|
+
|
|
23
|
+
files.forEach(file => {
|
|
24
|
+
const filePath = path.join(dir, file);
|
|
25
|
+
const stat = fs.statSync(filePath);
|
|
26
|
+
|
|
27
|
+
if (stat.isDirectory()) {
|
|
28
|
+
getAllJsFiles(filePath, fileList);
|
|
29
|
+
} else if (file.endsWith('.js')) {
|
|
30
|
+
fileList.push(filePath);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return fileList;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fix imports/exports in a JavaScript file
|
|
39
|
+
*/
|
|
40
|
+
function fixImportsInFile(filePath) {
|
|
41
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
42
|
+
let modified = false;
|
|
43
|
+
|
|
44
|
+
// Get the directory containing this file for path resolution
|
|
45
|
+
const fileDir = path.dirname(filePath);
|
|
46
|
+
|
|
47
|
+
// Match import/export statements with relative paths that don't have extensions
|
|
48
|
+
// Patterns to match:
|
|
49
|
+
// - export * from './something'
|
|
50
|
+
// - export { foo } from './something'
|
|
51
|
+
// - import { foo } from './something'
|
|
52
|
+
// - import './something'
|
|
53
|
+
// - import type { foo } from './something'
|
|
54
|
+
|
|
55
|
+
const patterns = [
|
|
56
|
+
// export * as foo from './path' or '.' -> export * as foo from './path/index.js' or './index.js'
|
|
57
|
+
/(\bexport\s+\*\s+as\s+\w+\s+from\s+['"])(\..*?)(['"])/g,
|
|
58
|
+
// export * from './path' or '.' -> export * from './path.js' or './index.js'
|
|
59
|
+
/(\bexport\s+\*\s+from\s+['"])(\..*?)(['"])/g,
|
|
60
|
+
// export { ... } from './path' or '.' -> export { ... } from './path.js' or './index.js'
|
|
61
|
+
/(\bexport\s+\{[^}]+\}\s+from\s+['"])(\..*?)(['"])/g,
|
|
62
|
+
// import { ... } from './path' or '.' -> import { ... } from './path.js' or './index.js'
|
|
63
|
+
/(\bimport\s+\{[^}]+\}\s+from\s+['"])(\..*?)(['"])/g,
|
|
64
|
+
// import * as foo from './path' or '.' -> import * as foo from './path.js' or './index.js'
|
|
65
|
+
/(\bimport\s+\*\s+as\s+\w+\s+from\s+['"])(\..*?)(['"])/g,
|
|
66
|
+
// import foo from './path' or '.' -> import foo from './path.js' or './index.js'
|
|
67
|
+
/(\bimport\s+\w+\s+from\s+['"])(\..*?)(['"])/g,
|
|
68
|
+
// import './path' or '.' -> import './path.js' or './index.js'
|
|
69
|
+
/(\bimport\s+['"])(\..*?)(['"])/g,
|
|
70
|
+
// import type { ... } from './path' or '.' -> import type { ... } from './path.js' or './index.js'
|
|
71
|
+
/(\bimport\s+type\s+\{[^}]+\}\s+from\s+['"])(\..*?)(['"])/g,
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
patterns.forEach(pattern => {
|
|
75
|
+
content = content.replace(pattern, (match, prefix, importPath, suffix) => {
|
|
76
|
+
// Skip if already has extension
|
|
77
|
+
if (importPath.match(/\.(js|ts|jsx|tsx|json|css)$/)) {
|
|
78
|
+
return match;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Skip if it's an asset import (images, svg, fonts, etc.)
|
|
82
|
+
if (importPath.match(/\.(jpg|jpeg|png|gif|svg|woff|woff2|ttf|eot|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|pdf|zip|tar|gz)$/)) {
|
|
83
|
+
return match;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Resolve the import path relative to this file
|
|
87
|
+
const resolvedPath = path.join(fileDir, importPath);
|
|
88
|
+
|
|
89
|
+
// Check if it's a directory (needs /index.js instead of .js)
|
|
90
|
+
let extension = '.js';
|
|
91
|
+
if (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory()) {
|
|
92
|
+
extension = '/index.js';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Add appropriate extension
|
|
96
|
+
modified = true;
|
|
97
|
+
return `${prefix}${importPath}${extension}${suffix}`;
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (modified) {
|
|
102
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Main execution
|
|
110
|
+
console.log('š§ Fixing ESM imports in compiled output...\n');
|
|
111
|
+
|
|
112
|
+
const jsFiles = getAllJsFiles(LIB_DIR);
|
|
113
|
+
let fixedCount = 0;
|
|
114
|
+
|
|
115
|
+
jsFiles.forEach(filePath => {
|
|
116
|
+
const relativePath = path.relative(LIB_DIR, filePath);
|
|
117
|
+
if (fixImportsInFile(filePath)) {
|
|
118
|
+
console.log(` ā
Fixed: ${relativePath}`);
|
|
119
|
+
fixedCount++;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
console.log(`\nā
Fixed ${fixedCount} file(s) with missing .js extensions`);
|
|
124
|
+
console.log(' Output is now Node.js 22 ES modules compatible\n');
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
# Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|
|
5
|
+
# Sync local jupyter-ui packages to @datalayer/core node_modules
|
|
6
|
+
# This script builds the local jupyter packages and copies their lib/ outputs
|
|
7
|
+
# into the core package's node_modules for quick testing during development.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# ./sync-jupyter.sh # Run once and exit
|
|
11
|
+
# ./sync-jupyter.sh --watch # Watch for changes and auto-sync
|
|
12
|
+
|
|
13
|
+
set -e
|
|
14
|
+
|
|
15
|
+
# Colors for output
|
|
16
|
+
GREEN='\033[0;32m'
|
|
17
|
+
BLUE='\033[0;34m'
|
|
18
|
+
YELLOW='\033[1;33m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
# Get the script directory and project root
|
|
22
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
23
|
+
CORE_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
|
24
|
+
JUPYTER_UI_ROOT="$( cd "$CORE_ROOT/../jupyter-ui" && pwd )"
|
|
25
|
+
|
|
26
|
+
# Function to perform the sync
|
|
27
|
+
sync_packages() {
|
|
28
|
+
echo -e "${BLUE}š Syncing jupyter-ui packages to @datalayer/core...${NC}"
|
|
29
|
+
|
|
30
|
+
# Build jupyter-react FIRST (lexical depends on it)
|
|
31
|
+
echo -e "${BLUE}š¦ Building @datalayer/jupyter-react...${NC}"
|
|
32
|
+
cd "$JUPYTER_UI_ROOT/packages/react"
|
|
33
|
+
echo -e "${YELLOW}[DEBUG] Current directory: $(pwd)${NC}"
|
|
34
|
+
rm -f tsconfig.tsbuildinfo
|
|
35
|
+
rm -rf lib
|
|
36
|
+
echo -e "${YELLOW}[DEBUG] Running gulp resources-to-lib...${NC}"
|
|
37
|
+
npx gulp resources-to-lib
|
|
38
|
+
echo -e "${YELLOW}[DEBUG] Running TypeScript...${NC}"
|
|
39
|
+
npx tsc --noEmitOnError false
|
|
40
|
+
TSC_EXIT=$?
|
|
41
|
+
echo -e "${YELLOW}[DEBUG] TypeScript exit code: $TSC_EXIT${NC}"
|
|
42
|
+
echo -e "${YELLOW}[DEBUG] Checking if lib exists...${NC}"
|
|
43
|
+
ls -la lib 2>&1 | head -5
|
|
44
|
+
|
|
45
|
+
# Verify lib was created
|
|
46
|
+
if [ ! -d "lib" ]; then
|
|
47
|
+
echo -e "${YELLOW}ā ļø lib directory was not created by TypeScript!${NC}"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
echo -e "${YELLOW}[DEBUG] lib directory verified!${NC}"
|
|
51
|
+
|
|
52
|
+
# Copy react to core's node_modules for patch-package
|
|
53
|
+
echo -e "${BLUE}š Copying react to core/node_modules...${NC}"
|
|
54
|
+
cd "$CORE_ROOT"
|
|
55
|
+
# Only replace lib/ directory, preserving package.json, LICENSE, README.md, etc from npm
|
|
56
|
+
rm -rf node_modules/@datalayer/jupyter-react/lib
|
|
57
|
+
mkdir -p node_modules/@datalayer/jupyter-react/lib
|
|
58
|
+
cp -r "$JUPYTER_UI_ROOT/packages/react/lib/." node_modules/@datalayer/jupyter-react/lib/
|
|
59
|
+
|
|
60
|
+
# Now build jupyter-lexical (finds react via workspace hoisting)
|
|
61
|
+
echo -e "${BLUE}š¦ Building @datalayer/jupyter-lexical...${NC}"
|
|
62
|
+
cd "$JUPYTER_UI_ROOT/packages/lexical"
|
|
63
|
+
rm -f tsconfig.tsbuildinfo
|
|
64
|
+
rm -rf lib
|
|
65
|
+
echo -e "${YELLOW}[DEBUG] Running gulp resources-to-lib...${NC}"
|
|
66
|
+
npx gulp resources-to-lib
|
|
67
|
+
echo -e "${YELLOW}[DEBUG] Running TypeScript...${NC}"
|
|
68
|
+
npx tsc --noEmitOnError false
|
|
69
|
+
|
|
70
|
+
# Copy lexical to node_modules
|
|
71
|
+
echo -e "${BLUE}š Copying lexical to node_modules...${NC}"
|
|
72
|
+
cd "$CORE_ROOT"
|
|
73
|
+
# Only replace lib/ directory, preserving package.json, LICENSE, README.md, etc from npm
|
|
74
|
+
rm -rf node_modules/@datalayer/jupyter-lexical/lib
|
|
75
|
+
mkdir -p node_modules/@datalayer/jupyter-lexical/lib
|
|
76
|
+
cp -r "$JUPYTER_UI_ROOT/packages/lexical/lib/." node_modules/@datalayer/jupyter-lexical/lib/
|
|
77
|
+
|
|
78
|
+
echo -e "${GREEN}ā
Successfully synced at $(date +"%H:%M:%S")${NC}"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Check if watch mode is requested
|
|
82
|
+
if [[ "$1" == "--watch" ]]; then
|
|
83
|
+
# Check if fswatch is installed
|
|
84
|
+
if ! command -v fswatch &> /dev/null; then
|
|
85
|
+
echo -e "${YELLOW}ā ļø fswatch not found. Installing via Homebrew...${NC}"
|
|
86
|
+
if command -v brew &> /dev/null; then
|
|
87
|
+
brew install fswatch
|
|
88
|
+
else
|
|
89
|
+
echo -e "${YELLOW}ā ļø Homebrew not found. Please install fswatch manually:${NC}"
|
|
90
|
+
echo -e "${YELLOW} brew install fswatch${NC}"
|
|
91
|
+
echo -e "${YELLOW} or visit: https://github.com/emcrisostomo/fswatch${NC}"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
echo -e "${BLUE}šļø Watch mode enabled. Monitoring jupyter-ui packages for changes...${NC}"
|
|
97
|
+
echo -e "${YELLOW}š Watching:${NC}"
|
|
98
|
+
echo -e "${YELLOW} - $JUPYTER_UI_ROOT/packages/lexical/src${NC}"
|
|
99
|
+
echo -e "${YELLOW} - $JUPYTER_UI_ROOT/packages/react/src${NC}"
|
|
100
|
+
echo -e "${YELLOW}Press Ctrl+C to stop${NC}"
|
|
101
|
+
echo ""
|
|
102
|
+
|
|
103
|
+
# Initial sync
|
|
104
|
+
sync_packages
|
|
105
|
+
|
|
106
|
+
# Watch for changes in src directories and trigger sync
|
|
107
|
+
# Using fswatch with:
|
|
108
|
+
# -r: recursive
|
|
109
|
+
# -e: exclude patterns (node_modules, lib, etc.)
|
|
110
|
+
# -l 1: latency 1 second (debounce rapid changes)
|
|
111
|
+
fswatch -r -l 1 \
|
|
112
|
+
-e ".*" -i "\\.tsx?$" -i "\\.jsx?$" -i "\\.css$" \
|
|
113
|
+
"$JUPYTER_UI_ROOT/packages/lexical/src" \
|
|
114
|
+
"$JUPYTER_UI_ROOT/packages/react/src" | while read -r file; do
|
|
115
|
+
echo -e "\n${YELLOW}š Change detected in: $(basename "$file")${NC}"
|
|
116
|
+
sync_packages
|
|
117
|
+
done
|
|
118
|
+
else
|
|
119
|
+
# Single run mode
|
|
120
|
+
sync_packages
|
|
121
|
+
fi
|