diff --git a/api/.npmignore b/api/.npmignore index aece17d5872..75ae443e214 100644 --- a/api/.npmignore +++ b/api/.npmignore @@ -1,4 +1,5 @@ .gitignore tsconfig.json -build.js +stable.js +proposed.js clean.js diff --git a/api/README.md b/api/README.md index eb06a744a42..4d5f4022f71 100644 --- a/api/README.md +++ b/api/README.md @@ -1,6 +1,6 @@ # Installation -`npm install @vscode/jupyter` +`npm install @vscode/jupyter-extension` # Summary diff --git a/api/build.js b/api/build.js deleted file mode 100644 index decb5e1d3a7..00000000000 --- a/api/build.js +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -const { EOL } = require('os'); -const fs = require('fs'); -const path = require('path'); - -// For stable we only ship the api.d.ts file. -fs.copyFileSync(path.join(__dirname, '../src/api.d.ts'), path.join(__dirname, 'api.d.ts')); - -// For proposed API, we need to merge all proposed API files into a single file. -// Anyone installing the proposed tag will get all of the proposed API -// Today we have at lest 3 extensions that manually pull down *.d.ts files via some automated scripts, shipping proposed API -// in the npm makes it easier for other consumers as well (DW, AzML, Synapse, etc). - -// Ensure all imports are on top -// Ensure we have a module declaration that matches the npm package name. -// Duplicate imports is not a problem. - -if (process.env.npm_config_tag === 'proposed') { - let proposedApi = ''; - let proposedApiImports = []; - const tab = ' '; // 4 spaces used as tab size in source formatting. - const newModuleDeclaration = `declare module '@vscode/jupyter-extension' {`; - fs.readdirSync(path.join(__dirname, '../src')).forEach((file) => { - if (file.startsWith('api.proposed.') && file.endsWith('.d.ts')) { - console.error(file); - let source = fs.readFileSync(path.join(__dirname, '../src', file), 'utf8').toString(); - let foundFirstExport = false; - const newSource = source - .replace(`declare module './api' {`, newModuleDeclaration) - .split(/\r?\n/g) - .filter((line) => { - if (foundFirstExport) { - return true; - } - if (line.startsWith('import ') && line.trim().endsWith(';')) { - proposedApiImports.push(line); - return false; - } - if (line.startsWith(newModuleDeclaration)) { - foundFirstExport = true; - } - return false; - }) - .join(EOL); - - // Remove the trailing `}` - // Do not trim leading spaces, as we need to preserve the indentation. - proposedApi += ('1' + newSource).trim().slice(0, -1).substring(1) + EOL; - } - }); - // Add module namespace to the main api.d.ts file. - // Required for module augmentation to work. - const source = fs.readFileSync(path.join(__dirname, 'api.d.ts'), 'utf8').toString(); - let foundFirstExport = false; - const newSource = source - .split(/\r?\n/g) - .map((line) => { - if (proposedApiImports.length && line.startsWith('import ') && line.trim().endsWith(';')) { - const newLine = [line, ...proposedApiImports].join(EOL); - proposedApiImports = []; - return newLine; - } - if (line.startsWith('export ') && !foundFirstExport) { - foundFirstExport = true; - let imports = ''; - if (proposedApiImports.length) { - imports = proposedApiImports.join(EOL) + EOL + EOL; - } - return imports + [`declare module '@vscode/jupyter-extension' {`, `${tab}${line}`].join(EOL); - } - if (foundFirstExport) { - return `${tab}${line}`; - } - return line; - }) - .join(EOL); - - // Do not trim leading spaces, as we need to preserve the indentation. - fs.writeFileSync( - path.join(__dirname, 'api.d.ts'), - newSource.trim() + EOL + `1${proposedApi}`.trim().substring(1) + EOL + '}' + EOL - ); -} diff --git a/api/package.json b/api/package.json index 8571a4ee761..d6ff233f0a3 100644 --- a/api/package.json +++ b/api/package.json @@ -1,7 +1,7 @@ { "name": "@vscode/jupyter-extension", "description": "Contains the type definitions for the API exposed by the Jupyter Extension for VS Code", - "version": "1.0.0", + "version": "0.0.0", "author": { "name": "Microsoft Corporation" }, @@ -21,8 +21,8 @@ "url": "https://github.com/Microsoft/vscode-jupyter/issues" }, "scripts": { - "prepublishOnly": "npm run clean && npm run build", - "build": "node ./build.js", + "buildStable": "npm run clean && node ./stable.js", + "buildProposed": "npm run clean && node ./proposed.js", "clean": "node ./clean.js" } } diff --git a/api/proposed.js b/api/proposed.js new file mode 100644 index 00000000000..282ffc33dba --- /dev/null +++ b/api/proposed.js @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +const { EOL } = require('os'); +const fs = require('fs'); +const path = require('path'); + +// For stable we only ship the api.d.ts file. +fs.copyFileSync(path.join(__dirname, '../src/api.d.ts'), path.join(__dirname, 'api.d.ts')); + +// For proposed API, we need to merge all proposed API files into a single file. +// Anyone installing the proposed tag will get all of the proposed API +// Today we have at lest 3 extensions that manually pull down *.d.ts files via some automated scripts, shipping proposed API +// in the npm makes it easier for other consumers as well (DW, AzML, Synapse, etc). + +// Ensure all imports are on top +// Ensure we have a module declaration that matches the npm package name. +// Duplicate imports is not a problem. + +let proposedApi = ''; +let proposedApiImports = []; +const tab = ' '; // 4 spaces used as tab size in source formatting. +const newModuleDeclaration = `declare module '@vscode/jupyter-extension' {`; +fs.readdirSync(path.join(__dirname, '../src')).forEach((file) => { + if (file.startsWith('api.proposed.') && file.endsWith('.d.ts')) { + console.error(file); + let source = fs.readFileSync(path.join(__dirname, '../src', file), 'utf8').toString(); + let foundFirstExport = false; + const newSource = source + .replace(`declare module './api' {`, newModuleDeclaration) + .split(/\r?\n/g) + .filter((line) => { + if (foundFirstExport) { + return true; + } + if (line.startsWith('import ') && line.trim().endsWith(';')) { + proposedApiImports.push(line); + return false; + } + if (line.startsWith(newModuleDeclaration)) { + foundFirstExport = true; + } + return false; + }) + .join(EOL); + + // Remove the trailing `}` + // Do not trim leading spaces, as we need to preserve the indentation. + proposedApi += ('1' + newSource).trim().slice(0, -1).substring(1) + EOL; + } +}); +// Add module namespace to the main api.d.ts file. +// Required for module augmentation to work. +const source = fs.readFileSync(path.join(__dirname, 'api.d.ts'), 'utf8').toString(); +let foundFirstExport = false; +const newSource = source + .split(/\r?\n/g) + .map((line) => { + if (proposedApiImports.length && line.startsWith('import ') && line.trim().endsWith(';')) { + const newLine = [line, ...proposedApiImports].join(EOL); + proposedApiImports = []; + return newLine; + } + if (line.startsWith('export ') && !foundFirstExport) { + foundFirstExport = true; + let imports = ''; + if (proposedApiImports.length) { + imports = proposedApiImports.join(EOL) + EOL + EOL; + } + return imports + [`declare module '@vscode/jupyter-extension' {`, `${tab}${line}`].join(EOL); + } + if (foundFirstExport) { + return `${tab}${line}`; + } + return line; + }) + .join(EOL); + +// Do not trim leading spaces, as we need to preserve the indentation. +fs.writeFileSync( + path.join(__dirname, 'api.d.ts'), + newSource.trim() + EOL + `1${proposedApi}`.trim().substring(1) + EOL + '}' + EOL +); diff --git a/api/stable.js b/api/stable.js new file mode 100644 index 00000000000..f426e87fed5 --- /dev/null +++ b/api/stable.js @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +const { EOL } = require('os'); +const fs = require('fs'); +const path = require('path'); + +// For stable we only ship the api.d.ts file. +fs.copyFileSync(path.join(__dirname, '../src/api.d.ts'), path.join(__dirname, 'api.d.ts')); diff --git a/build/azure-pipeline.npm.yml b/build/azure-pipeline.npm.yml index 2ed84ec4044..9dadacc8cea 100644 --- a/build/azure-pipeline.npm.yml +++ b/build/azure-pipeline.npm.yml @@ -11,6 +11,10 @@ resources: endpoint: Monaco parameters: + - name: nextVersion + displayName: '🚀 Release Version (eg: none, major, minor, patch, or X.X.X)' + type: string + default: 'none' - name: quality displayName: Quality type: string @@ -29,6 +33,14 @@ extends: parameters: npmPackages: - name: jupyterExtensionApi + buildSteps: + - script: npm run buildStable + workingDirectory: $(Build.SourcesDirectory)/api + condition: not(eq('${{ parameters.quality }}', 'proposed')) + - script: npm run buildProposed + workingDirectory: $(Build.SourcesDirectory)/api + condition: eq('${{ parameters.quality }}', 'proposed') tag: ${{ parameters.quality }} publishPackage: ${{ parameters.publishJupyterApi }} + nextVersion: ${{ parameters.nextVersion }} workingDirectory: $(Build.SourcesDirectory)/api diff --git a/src/api.d.ts b/src/api.d.ts index a1535db88b8..dfb49edf4fb 100644 --- a/src/api.d.ts +++ b/src/api.d.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { CancellationToken, ProviderResult, CancellationError } from 'vscode'; -import { Event, Uri } from 'vscode'; +import type { CancellationToken, ProviderResult, CancellationError } from 'vscode'; +import type { Event, Uri } from 'vscode'; -export interface JupyterAPI { +export interface Jupyter { /** * Creates a Jupyter Server Collection that can be displayed in the Notebook Kernel Picker. * diff --git a/src/api.internal.d.ts b/src/api.internal.d.ts index af3b638bc32..950a0d737d8 100644 --- a/src/api.internal.d.ts +++ b/src/api.internal.d.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { Event, QuickPickItem, Uri } from 'vscode'; +import type { Event, QuickPickItem, Uri } from 'vscode'; // These types are only used internally within the extension. // Never to be exposed to other extensions. diff --git a/src/api.proposed.mappedRemoteDirectory.d.ts b/src/api.proposed.mappedRemoteDirectory.d.ts index 88b5d5aa33a..a933b800ef6 100644 --- a/src/api.proposed.mappedRemoteDirectory.d.ts +++ b/src/api.proposed.mappedRemoteDirectory.d.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { Uri } from 'vscode'; +import type { Uri } from 'vscode'; declare module './api' { export interface JupyterServer { diff --git a/src/api.proposed.removeJupyterServer.d.ts b/src/api.proposed.removeJupyterServer.d.ts index 77017ba22df..162e7b05d1e 100644 --- a/src/api.proposed.removeJupyterServer.d.ts +++ b/src/api.proposed.removeJupyterServer.d.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { Uri } from 'vscode'; +import type { Uri } from 'vscode'; declare module './api' { export interface JupyterServerProvider { diff --git a/src/api.pythonIntegration.d.ts b/src/api.pythonIntegration.d.ts index 884c20acaa9..b688e16f80a 100644 --- a/src/api.pythonIntegration.d.ts +++ b/src/api.pythonIntegration.d.ts @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { PythonApi } from './platform/api/types'; +import type { PythonApi } from './platform/api/types'; declare module './api' { /** * These types are not required for any other extension, except for the Python extension. * Hence the reason to keep this separate. This way we can keep the API stable for other extensions (which would be the majority case). */ - export interface JupyterAPI { + export interface Jupyter { registerPythonApi(pythonApi: PythonApi): void; } } diff --git a/src/api.unstable.d.ts b/src/api.unstable.d.ts index 503e6225f91..96de9f96e65 100644 --- a/src/api.unstable.d.ts +++ b/src/api.unstable.d.ts @@ -1,13 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { CancellationToken, Disposable, Event, NotebookController, NotebookDocument, QuickPickItem, Uri } from 'vscode'; +import type { + CancellationToken, + Disposable, + Event, + NotebookController, + NotebookDocument, + QuickPickItem, + Uri +} from 'vscode'; import type { Kernel } from '@jupyterlab/services/lib/kernel'; import type { Session } from '@jupyterlab/services'; -import { IDataViewerDataProvider } from './webviews/extension-side/dataviewer/types'; +import type { IDataViewerDataProvider } from './webviews/extension-side/dataviewer/types'; declare module './api' { - export interface JupyterAPI { + export interface Jupyter { /** * Promise indicating whether all parts of the extension have completed loading or not. * @type {Promise} diff --git a/src/standalone/api/api.ts b/src/standalone/api/api.ts index b3b4de771b0..4b7c674fc76 100644 --- a/src/standalone/api/api.ts +++ b/src/standalone/api/api.ts @@ -15,7 +15,7 @@ import { sendTelemetryEvent } from '../../telemetry'; import { noop } from '../../platform/common/utils/misc'; import { isRemoteConnection } from '../../kernels/types'; import { - JupyterAPI, + Jupyter, IExportedKernelService, IJupyterUriProvider, JupyterServerCollection, @@ -33,7 +33,7 @@ export interface IExportedKernelServiceFactory { * This is the public API for other extensions to interact with this extension. */ -export interface IExtensionApi extends JupyterAPI {} +export interface IExtensionApi extends Jupyter {} function waitForNotebookControllersCreationForServer( serverId: { id: string; handle: string },