New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@microsoft/compose-language-service

Package Overview
Dependencies
Maintainers
10
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@microsoft/compose-language-service - npm Package Compare versions

Comparing version 0.0.2-alpha to 0.0.3-alpha

4

CHANGELOG.md

@@ -0,1 +1,5 @@

## 0.0.3-alpha - 8 November 2021
### Fixed
* A handful of minor bugs relating to position logic (especially affecting hover).
## 0.0.2-alpha - 29 October 2021

@@ -2,0 +6,0 @@ ### Added

3

lib/client/TelemetryEvent.d.ts

@@ -33,3 +33,4 @@ /*!--------------------------------------------------------------------------------------------

interface TelemetryProperties {
result?: 'Succeeded' | 'Failed' | 'Canceled';
isActivationEvent: 'true' | 'false';
result: 'Succeeded' | 'Failed' | 'Canceled';
error?: string;

@@ -36,0 +37,0 @@ errorMessage?: string;

@@ -12,2 +12,3 @@ "use strict";

properties: {
isActivationEvent: 'false',
result: 'Succeeded',

@@ -14,0 +15,0 @@ },

@@ -192,2 +192,13 @@ "use strict";

/* eslint-disable @typescript-eslint/no-non-null-assertion */
if ((result = LineWithCommentRegex.exec(currentLine))) {
const commentSepPosition = currentLine.indexOf(result.groups['commentSep']);
// If the cursor is in a comment, then it's not "in" the document per se, but in the comment
// So the path will only be "/<comment>", and the cursorIndentDepth is set to -1 to short-circuit the loop above
if (params.position.character > commentSepPosition) {
return {
pathParts: [Comment],
cursorIndentDepth: -1,
};
}
}
if ((result = ItemKeyValueRegex.exec(currentLine))) {

@@ -243,3 +254,3 @@ // First, see if it's an ItemKeyValue, i.e. ` - foo: bar`

}
else if (params.position.character > indentLength) {
else if (params.position.character >= indentLength) {
// If the position is after the indent, we're in the key

@@ -277,3 +288,3 @@ pathParts.unshift(keyName);

cursorIndentDepth = indentLength / tabSize;
if (params.position.character > indentLength) {
if (params.position.character >= indentLength) {
// If the position is after the indent, we're in the value

@@ -322,2 +333,6 @@ pathParts.unshift(Value);

const WhitespaceRegex = /^(?<indent> *)$/im;
// A regex for matching any line with a comment (or if the whole line is a comment)
// TODO: This will match a 'string with a #', which is *not* a comment, but currently this will not affect any end scenarios
// TODO: The closest I've gotten is /(['"])?.*(?<commentSep>#)(?:(?!\1).)*$/im
const LineWithCommentRegex = /^.*(?<commentSep>#).*$/im;
// Constants for marking non-key parts of a logical path

@@ -327,2 +342,3 @@ const Value = '<value>';

const Sep = '<sep>';
const Comment = '<comment>';
//# sourceMappingURL=ComposeDocument.js.map

@@ -21,3 +21,3 @@ "use strict";

constructor(connection, clientParams) {
var _a;
var _a, _b;
this.connection = connection;

@@ -28,3 +28,3 @@ this.clientParams = clientParams;

// Hook up the document listeners, which create a Disposable which will be added to this.subscriptions
this.createDocumentManagerHandler(this.documentManager.onDidChangeContent, new DiagnosticProvider_1.DiagnosticProvider().on);
this.createDocumentManagerHandler(this.documentManager.onDidChangeContent, new DiagnosticProvider_1.DiagnosticProvider((_a = clientParams.initializationOptions) === null || _a === void 0 ? void 0 : _a.diagnosticDelay));
// Hook up all the LSP listeners, which do not create Disposables for some reason

@@ -40,3 +40,3 @@ this.createLspHandler(this.connection.onCompletion, new MultiCompletionProvider_1.MultiCompletionProvider());

// Start the telemetry aggregator
this.subscriptions.push(this.telemetryAggregator = new TelemetryAggregator_1.TelemetryAggregator(this.connection, (_a = clientParams.initializationOptions) === null || _a === void 0 ? void 0 : _a.telemetryAggregationInterval));
this.subscriptions.push(this.telemetryAggregator = new TelemetryAggregator_1.TelemetryAggregator(this.connection, (_b = clientParams.initializationOptions) === null || _b === void 0 ? void 0 : _b.telemetryAggregationInterval));
}

@@ -97,3 +97,3 @@ dispose() {

event(async (params) => {
return await this.callWithTelemetryAndErrorHandling(handler.name, async () => {
return await this.callWithTelemetryAndErrorHandling(handler.constructor.name, async () => {
const extendedParams = {

@@ -103,3 +103,3 @@ ...params,

};
return await Promise.resolve(handler(extendedParams));
return await Promise.resolve(handler.on(extendedParams, vscode_languageserver_1.CancellationToken.None));
});

@@ -106,0 +106,0 @@ }, this, this.subscriptions);

@@ -10,2 +10,3 @@ "use strict";

const ProviderBase_1 = require("../ProviderBase");
const PortsCompletionCollection_1 = require("./PortsCompletionCollection");
const RootCompletionCollection_1 = require("./RootCompletionCollection");

@@ -26,2 +27,3 @@ const ServiceCompletionCollection_1 = require("./ServiceCompletionCollection");

VolumesCompletionCollection_1.VolumesCompletionCollection,
PortsCompletionCollection_1.PortsCompletionCollection,
];

@@ -28,0 +30,0 @@ }

@@ -8,4 +8,41 @@ "use strict";

exports.PortsCompletionCollection = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const CompletionCollection_1 = require("./CompletionCollection");
exports.PortsCompletionCollection = new CompletionCollection_1.CompletionCollection('ports', { logicalPaths: [/foo/i], indentationDepth: 3 }, ...[]);
// Matches ` - ""` or ` -`, with allowances for other amounts of whitespace/quoting
const PortItemStartRegex = /(\s*-\s*)(?<leadingQuote>"|')?\2\s*$/i;
exports.PortsCompletionCollection = new CompletionCollection_1.CompletionCollection('ports', { logicalPaths: [/^\/services\/[.\w-]+\/ports\/<item>\/.*$/i], indentationDepth: 3 }, ...[
{
matcher: PortItemStartRegex,
label: 'containerPort',
insertText: '"${1:80}"$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
},
{
matcher: PortItemStartRegex,
label: 'hostPort:containerPort',
insertText: '"${1:8080}:${2:80}"$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
},
{
matcher: PortItemStartRegex,
label: 'hostPort:containerPort/protocol',
insertText: '"${1:8080}:${2:80}/${3|tcp,udp|}"$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
},
{
matcher: PortItemStartRegex,
label: 'hostRange:containerRange',
insertText: '"${1:8080}-${2:8081}:${3:80}-${4:81}"$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
},
{
matcher: PortItemStartRegex,
label: '(Long form port specification)',
insertText: 'target: ${1:80}\n published: ${2:8080}\n protocol: ${3|tcp,udp|}\n mode: ${4|host,ingress|}$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
insertTextMode: vscode_languageserver_1.InsertTextMode.adjustIndentation,
documentation: 'target: <containerPort>\n published: <hostPort>\n protocol: <udp, tcp>\n mode: <host, ingress>',
sortText: 'zzz', // Force this to sort to the bottom
},
]);
//# sourceMappingURL=PortsCompletionCollection.js.map

@@ -124,3 +124,3 @@ "use strict";

label: 'ports:',
insertText: 'ports:\n - ${1:port}$0',
insertText: 'ports:\n -$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,

@@ -131,3 +131,3 @@ insertTextMode: vscode_languageserver_1.InsertTextMode.adjustIndentation,

label: 'volumes:',
insertText: 'volumes:\n - ${1:volume}$0',
insertText: 'volumes:\n -$0',
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,

@@ -134,0 +134,0 @@ insertTextMode: vscode_languageserver_1.InsertTextMode.adjustIndentation,

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

export declare class DiagnosticProvider extends ProviderBase<TextDocumentChangeEvent<ComposeDocument> & ExtendedParams, void, never, never> {
private readonly diagnosticDelay;
constructor(diagnosticDelay?: number);
on(params: TextDocumentChangeEvent<ComposeDocument> & ExtendedParams): void;
}

@@ -13,13 +13,18 @@ "use strict";

const ProviderBase_1 = require("./ProviderBase");
// The time between when typing stops and when diagnostics will be sent (milliseconds)
// The default time between when typing stops and when diagnostics will be sent (milliseconds)
const DiagnosticDelay = 1000;
class DiagnosticProvider extends ProviderBase_1.ProviderBase {
constructor(diagnosticDelay = DiagnosticDelay) {
super();
this.diagnosticDelay = diagnosticDelay;
}
on(params) {
var _a;
const ctx = (0, ActionContext_1.getCurrentContext)();
ctx.telemetry.suppressAll = true; // Diagnostics is async and telemetry won't really work
ctx.telemetry.properties.isActivationEvent = 'true'; // In case we do someday enable it, let's make sure it's treated as an activation event since it is done automatically
if (!((_a = ctx.clientCapabilities.textDocument) === null || _a === void 0 ? void 0 : _a.publishDiagnostics)) {
return;
}
ctx.telemetry.suppressAll = true; // Diagnostics is async and telemetry won't really work
(0, debounce_1.debounce)(DiagnosticDelay, { uri: params.document.textDocument.uri, callId: 'diagnostics' }, () => {
(0, debounce_1.debounce)(this.diagnosticDelay, { uri: params.document.textDocument.uri, callId: 'diagnostics' }, () => {
const diagnostics = [];

@@ -26,0 +31,0 @@ for (const error of [...params.document.yamlDocument.value.errors, ...params.document.yamlDocument.value.warnings]) {

@@ -21,3 +21,4 @@ "use strict";

};
const range = vscode_languageserver_1.Range.create(params.document.textDocument.positionAt(0), params.document.textDocument.positionAt(params.document.textDocument.getText().length - 1));
const range = vscode_languageserver_1.Range.create(params.document.textDocument.positionAt(0), params.document.textDocument.positionAt(params.document.textDocument.getText().length) // This technically goes past the end of the doc, but it's OK because the protocol accepts this (positions past the end of the doc are rounded backward)
);
const formatted = params.document.yamlDocument.value.toString(options);

@@ -24,0 +25,0 @@ // It's heavy-handed but the replacement is for the entire document

@@ -19,2 +19,3 @@ "use strict";

const ctx = (0, ActionContext_1.getCurrentContext)();
ctx.telemetry.properties.isActivationEvent = 'true'; // This happens automatically so we'll treat it as isActivationEvent === true
const results = [];

@@ -21,0 +22,0 @@ const imageTypes = new Set();

@@ -20,10 +20,18 @@ "use strict";

const positionInfo = await params.document.getPositionInfo(params);
const keyInfo = ComposeKeyInfo.find((k) => k.pathRegex.test(positionInfo.path));
if (keyInfo) {
for (const keyInfo of ComposeKeyInfo) {
const pathMatch = keyInfo.pathRegex.exec(positionInfo.path);
if (!pathMatch) {
continue;
}
const line = params.document.lineAt(params.position);
const match = ComposeDocument_1.KeyValueRegex.exec(line);
const keyName = (_c = match === null || match === void 0 ? void 0 : match.groups) === null || _c === void 0 ? void 0 : _c['keyName'];
if (keyName) {
const keyIndex = line.indexOf(keyName);
ctx.telemetry.properties.hoverMatch = keyInfo.pathRegex.source;
const lineMatch = ComposeDocument_1.KeyValueRegex.exec(line);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const pathKeyName = pathMatch.groups['keyName']; // Can't be undefined if it matched
const lineKeyName = (_c = lineMatch === null || lineMatch === void 0 ? void 0 : lineMatch.groups) === null || _c === void 0 ? void 0 : _c['keyName'];
// Need to ensure the key on the line is the same as the key in the path
// They can be different is because if you are in the whitespace before a key--the path will be in the parent key, but no hover should be provided here
if (lineKeyName === pathKeyName) {
const keyIndex = line.indexOf(lineKeyName);
// Attach the key name to telemetry
ctx.telemetry.properties.keyName = lineKeyName;
return {

@@ -34,3 +42,3 @@ contents: {

},
range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(params.position.line, keyIndex), vscode_languageserver_1.Position.create(params.position.line, keyIndex + keyName.length)),
range: vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(params.position.line, keyIndex), vscode_languageserver_1.Position.create(params.position.line, keyIndex + lineKeyName.length)),
};

@@ -45,119 +53,119 @@ }

{
pathRegex: /^\/configs$/i,
pathRegex: /^\/(?<keyName>configs)$/i,
plaintextContents: 'Configurations for services in the project',
},
{
pathRegex: /^\/networks$/i,
pathRegex: /^\/(?<keyName>networks)$/i,
plaintextContents: 'Networks that are shared among multiple services',
},
{
pathRegex: /^\/networks\/[.\w-]+\/driver$/i,
pathRegex: /^\/networks\/[.\w-]+\/(?<keyName>driver)$/i,
plaintextContents: 'The driver used for this network',
},
{
pathRegex: /^\/secrets$/i,
pathRegex: /^\/(?<keyName>secrets)$/i,
plaintextContents: 'Secrets that are shared among multiple services',
},
{
pathRegex: /^\/services$/i,
pathRegex: /^\/(?<keyName>services)$/i,
plaintextContents: 'The services in your project',
},
{
pathRegex: /^\/services\/[.\w-]+\/build$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>build)$/i,
plaintextContents: 'The context used for building the image',
},
{
pathRegex: /^\/services\/[.\w-]+\/build\/args$/i,
pathRegex: /^\/services\/[.\w-]+\/build\/(?<keyName>args)$/i,
plaintextContents: 'Arguments used during the image build process',
},
{
pathRegex: /^\/services\/[.\w-]+\/build\/context$/i,
pathRegex: /^\/services\/[.\w-]+\/build\/(?<keyName>context)$/i,
plaintextContents: 'The context used for building the image',
},
{
pathRegex: /^\/services\/[.\w-]+\/build\/dockerfile$/i,
pathRegex: /^\/services\/[.\w-]+\/build\/(?<keyName>dockerfile)$/i,
plaintextContents: 'The Dockerfile used for building the image',
},
{
pathRegex: /^\/services\/[.\w-]+\/command$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>command)$/i,
plaintextContents: 'The command that will be run in the container',
},
{
pathRegex: /^\/services\/[.\w-]+\/container_name$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>container_name)$/i,
plaintextContents: 'The name that will be given to the container',
},
{
pathRegex: /^\/services\/[.\w-]+\/depends_on$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>depends_on)$/i,
plaintextContents: 'Other services that this service depends on, which will be started before this one',
},
{
pathRegex: /^\/services\/[.\w-]+\/entrypoint$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>entrypoint)$/i,
plaintextContents: 'The entrypoint to the application in the container',
},
{
pathRegex: /^\/services\/[.\w-]+\/env_file$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>env_file)$/i,
plaintextContents: 'Files containing environment variables that will be included',
},
{
pathRegex: /^\/services\/[.\w-]+\/environment$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>environment)$/i,
plaintextContents: 'Environment variables that will be included',
},
{
pathRegex: /^\/services\/[.\w-]+\/expose$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>expose)$/i,
plaintextContents: 'Ports exposed to the other services but not to the host machine',
},
{
pathRegex: /^\/services\/[.\w-]+\/healthcheck$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>healthcheck)$/i,
plaintextContents: 'A command for checking if the container is healthy',
},
{
pathRegex: /^\/services\/[.\w-]+\/image$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>image)$/i,
plaintextContents: 'The image that will be pulled for the service. If `build` is specified, the built image will be given this tag.',
},
{
pathRegex: /^\/services\/[.\w-]+\/labels$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>labels)$/i,
plaintextContents: 'Labels that will be given to the container',
},
{
pathRegex: /^\/services\/[.\w-]+\/logging$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>logging)$/i,
plaintextContents: 'Settings for logging for this service',
},
{
pathRegex: /^\/services\/[.\w-]+\/networks$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>networks)$/i,
plaintextContents: 'The service will be included in these networks, allowing it to reach other containers on the same network',
},
{
pathRegex: /^\/services\/[.\w-]+\/ports$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>ports)$/i,
plaintextContents: 'Ports that will be exposed to the host',
},
{
pathRegex: /^\/services\/[.\w-]+\/profiles$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>profiles)$/i,
plaintextContents: 'Profiles that this service is a part of. When the profile is started, this service will be started.',
},
{
pathRegex: /^\/services\/[.\w-]+\/secrets$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>secrets)$/i,
plaintextContents: 'Secrets the service will have access to',
},
{
pathRegex: /^\/services\/[.\w-]+\/user$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>user)$/i,
plaintextContents: 'The username under which the app in the container will be started',
},
{
pathRegex: /^\/services\/[.\w-]+\/volumes$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>volumes)$/i,
plaintextContents: 'Named volumes and paths on the host mapped to paths in the container',
},
{
pathRegex: /^\/services\/[.\w-]+\/working_dir$/i,
pathRegex: /^\/services\/[.\w-]+\/(?<keyName>working_dir)$/i,
plaintextContents: 'The working directory in which the entrypoint or command will be run',
},
{
pathRegex: /^\/version$/i,
pathRegex: /^\/(?<keyName>version)$/i,
plaintextContents: 'The version of the Docker Compose document',
},
{
pathRegex: /^\/volumes$/i,
pathRegex: /^\/(?<keyName>volumes)$/i,
plaintextContents: 'Named volumes that are shared among multiple services',
},
{
pathRegex: /^\/volumes\/[.\w-]+\/driver$/i,
pathRegex: /^\/volumes\/[.\w-]+\/(?<keyName>driver)$/i,
plaintextContents: 'The driver used for this volume',

@@ -164,0 +172,0 @@ },

@@ -7,3 +7,3 @@ /*!--------------------------------------------------------------------------------------------

export declare abstract class ProviderBase<P, R, PR, E> {
abstract on(params: P, token: CancellationToken, workDoneProgress: WorkDoneProgressReporter, resultProgress?: ResultProgressReporter<PR>): HandlerResult<R, E>;
abstract on(params: P, token: CancellationToken, workDoneProgress?: WorkDoneProgressReporter, resultProgress?: ResultProgressReporter<PR>): HandlerResult<R, E>;
}

@@ -10,2 +10,2 @@ /*!--------------------------------------------------------------------------------------------

}
export declare function debounce(delay: number, id: DebounceId, callback: () => Promise<void> | void, thisArg: unknown): void;
export declare function debounce(delay: number, id: DebounceId, callback: () => Promise<void> | void, thisArg?: unknown): void;

@@ -8,2 +8,3 @@ /*!--------------------------------------------------------------------------------------------

* Lognormal is a decent approximation of performance (i.e. durations of things).
* Fun fact! Compose file line counts are very well-fit by a lognormal distribution, mu=3.7970, sigma=1.0152
* @see https://en.wikipedia.org/wiki/Log-normal_distribution

@@ -10,0 +11,0 @@ * @param values The list of values to fit a lognormal distribution to

@@ -11,2 +11,3 @@ "use strict";

* Lognormal is a decent approximation of performance (i.e. durations of things).
* Fun fact! Compose file line counts are very well-fit by a lognormal distribution, mu=3.7970, sigma=1.0152
* @see https://en.wikipedia.org/wiki/Log-normal_distribution

@@ -18,4 +19,13 @@ * @param values The list of values to fit a lognormal distribution to

if (!(values === null || values === void 0 ? void 0 : values.length)) {
return { mu: 0, sigma: 0, median: 0 };
// If there's no elements, return all 0's
return { mu: 0, sigma: 0, median: 0, };
}
else if (values.length === 1) {
// If there's only 1 element sigma must be 0
return {
median: round(values[0], 3),
mu: round(ln(values[0]), 3),
sigma: 0,
};
}
const n = values.length;

@@ -27,11 +37,4 @@ const lnValues = values.map(a => ln(a));

// Sigma is calculated from the natural logs and their squares
// If there's only 1 element sigma must be 0
let sigma;
if (n > 1) {
sigma = Math.sqrt((n * sum(sqLnValues) - sq(sum(lnValues))) /
(n * (n - 1)));
}
else {
sigma = 0;
}
const sigma = Math.sqrt((n * sum(sqLnValues) - sq(sum(lnValues))) /
(n * (n - 1)));
return {

@@ -38,0 +41,0 @@ mu: round(mu, 3),

{
"name": "@microsoft/compose-language-service",
"author": "Microsoft Corporation",
"version": "0.0.2-alpha",
"version": "0.0.3-alpha",
"publisher": "ms-azuretools",

@@ -27,3 +27,4 @@ "description": "Language service for Docker Compose documents",

"pretest": "npm run build",
"prepack": "npm run build"
"prepack": "npm run build",
"postinstall": "cd ./src/test/clientExtension && npm install"
},

@@ -30,0 +31,0 @@ "devDependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc