Skip to content

Commit 9f34c05

Browse files
Merge branch 'main' into NODE-6309
2 parents 0092727 + fb13ebf commit 9f34c05

File tree

7 files changed

+970
-15
lines changed

7 files changed

+970
-15
lines changed

.github/workflows/release-6.8.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
on:
2+
push:
3+
branches: [6.8]
4+
workflow_dispatch: {}
5+
6+
permissions:
7+
contents: write
8+
pull-requests: write
9+
id-token: write
10+
11+
name: release-68
12+
13+
jobs:
14+
release_please:
15+
runs-on: ubuntu-latest
16+
outputs:
17+
release_created: ${{ steps.release.outputs.release_created }}
18+
steps:
19+
- id: release
20+
uses: googleapis/release-please-action@v4
21+
with:
22+
target-branch: 6.8
23+
24+
build:
25+
needs: [release_please]
26+
name: "Perform any build or bundling steps, as necessary."
27+
uses: ./.github/workflows/build.yml
28+
29+
ssdlc:
30+
needs: [release_please, build]
31+
permissions:
32+
# required for all workflows
33+
security-events: write
34+
id-token: write
35+
contents: write
36+
environment: release
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- name: Install Node and dependencies
42+
uses: mongodb-labs/drivers-github-tools/node/setup@v2
43+
with:
44+
ignore_install_scripts: false
45+
46+
- name: Load version and package info
47+
uses: mongodb-labs/drivers-github-tools/node/get_version_info@v2
48+
with:
49+
npm_package_name: mongodb
50+
51+
- name: actions/compress_sign_and_upload
52+
uses: mongodb-labs/drivers-github-tools/node/sign_node_package@v2
53+
with:
54+
aws_role_arn: ${{ secrets.AWS_ROLE_ARN }}
55+
aws_region_name: us-east-1
56+
aws_secret_id: ${{ secrets.AWS_SECRET_ID }}
57+
npm_package_name: mongodb
58+
dry_run: ${{ needs.release_please.outputs.release_created == '' }}
59+
60+
- name: Copy sbom file to release assets
61+
shell: bash
62+
if: ${{ '' == '' }}
63+
run: cp sbom.json ${{ env.S3_ASSETS }}/sbom.json
64+
65+
# only used for mongodb-client-encryption
66+
- name: Augment SBOM and copy to release assets
67+
if: ${{ '' != '' }}
68+
uses: mongodb-labs/drivers-github-tools/sbom@v2
69+
with:
70+
silk_asset_group: ''
71+
sbom_file_name: sbom.json
72+
73+
- name: Generate authorized pub report
74+
uses: mongodb-labs/drivers-github-tools/full-report@v2
75+
with:
76+
release_version: ${{ env.package_version }}
77+
product_name: mongodb
78+
sarif_report_target_ref: 6.8
79+
third_party_dependency_tool: n/a
80+
dist_filenames: artifacts/*
81+
token: ${{ github.token }}
82+
sbom_file_name: sbom.json
83+
evergreen_project: mongo-node-driver-next
84+
evergreen_commit: ${{ env.commit }}
85+
86+
- uses: mongodb-labs/drivers-github-tools/upload-s3-assets@v2
87+
with:
88+
version: ${{ env.package_version }}
89+
product_name: mongodb
90+
dry_run: ${{ needs.release_please.outputs.release_created == '' }}
91+
92+
publish:
93+
needs: [release_please, ssdlc, build]
94+
environment: release
95+
runs-on: ubuntu-latest
96+
steps:
97+
- uses: actions/checkout@v4
98+
99+
- name: Install Node and dependencies
100+
uses: mongodb-labs/drivers-github-tools/node/setup@v2
101+
102+
# Just picking a string to put here so that releases from this branch are not marked "latest",
103+
# we should go and rm-dist-tag after this is published, no reason to keep it tagged.
104+
- run: |
105+
npm publish --provenance --tag=tag-for-publishing-older-releases
106+
npm dist-tag rm mongodb tag-for-publishing-older-releases
107+
if: ${{ needs.release_please.outputs.release_created }}
108+
env:
109+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
import { type Document } from '../../bson';
2+
import { DocumentSequence } from '../../cmap/commands';
3+
import type { Filter, OptionalId, UpdateFilter, WithoutId } from '../../mongo_types';
4+
import { type CollationOptions } from '../command';
5+
import { type Hint } from '../operation';
6+
import type {
7+
AnyClientBulkWriteModel,
8+
ClientBulkWriteOptions,
9+
ClientDeleteManyModel,
10+
ClientDeleteOneModel,
11+
ClientInsertOneModel,
12+
ClientReplaceOneModel,
13+
ClientUpdateManyModel,
14+
ClientUpdateOneModel
15+
} from './common';
16+
17+
/** @internal */
18+
export interface ClientBulkWriteCommand {
19+
bulkWrite: 1;
20+
errorsOnly: boolean;
21+
ordered: boolean;
22+
ops: DocumentSequence;
23+
nsInfo: DocumentSequence;
24+
bypassDocumentValidation?: boolean;
25+
let?: Document;
26+
}
27+
28+
/** @internal */
29+
export class ClientBulkWriteCommandBuilder {
30+
models: AnyClientBulkWriteModel[];
31+
options: ClientBulkWriteOptions;
32+
33+
/**
34+
* Create the command builder.
35+
* @param models - The client write models.
36+
*/
37+
constructor(models: AnyClientBulkWriteModel[], options: ClientBulkWriteOptions) {
38+
this.models = models;
39+
this.options = options;
40+
}
41+
42+
/**
43+
* Gets the errorsOnly value for the command, which is the inverse of the
44+
* user provided verboseResults option. Defaults to true.
45+
*/
46+
get errorsOnly(): boolean {
47+
if ('verboseResults' in this.options) {
48+
return !this.options.verboseResults;
49+
}
50+
return true;
51+
}
52+
53+
/**
54+
* Build the bulk write commands from the models.
55+
*/
56+
buildCommands(): ClientBulkWriteCommand[] {
57+
// Iterate the models to build the ops and nsInfo fields.
58+
const operations = [];
59+
let currentNamespaceIndex = 0;
60+
const namespaces = new Map<string, number>();
61+
for (const model of this.models) {
62+
const ns = model.namespace;
63+
const index = namespaces.get(ns);
64+
if (index != null) {
65+
operations.push(buildOperation(model, index));
66+
} else {
67+
namespaces.set(ns, currentNamespaceIndex);
68+
operations.push(buildOperation(model, currentNamespaceIndex));
69+
currentNamespaceIndex++;
70+
}
71+
}
72+
73+
const nsInfo = Array.from(namespaces.keys(), ns => ({ ns }));
74+
75+
// The base command.
76+
const command: ClientBulkWriteCommand = {
77+
bulkWrite: 1,
78+
errorsOnly: this.errorsOnly,
79+
ordered: this.options.ordered ?? true,
80+
ops: new DocumentSequence(operations),
81+
nsInfo: new DocumentSequence(nsInfo)
82+
};
83+
// Add bypassDocumentValidation if it was present in the options.
84+
if (this.options.bypassDocumentValidation != null) {
85+
command.bypassDocumentValidation = this.options.bypassDocumentValidation;
86+
}
87+
// Add let if it was present in the options.
88+
if (this.options.let) {
89+
command.let = this.options.let;
90+
}
91+
return [command];
92+
}
93+
}
94+
95+
/** @internal */
96+
interface ClientInsertOperation {
97+
insert: number;
98+
document: OptionalId<Document>;
99+
}
100+
101+
/**
102+
* Build the insert one operation.
103+
* @param model - The insert one model.
104+
* @param index - The namespace index.
105+
* @returns the operation.
106+
*/
107+
export const buildInsertOneOperation = (
108+
model: ClientInsertOneModel,
109+
index: number
110+
): ClientInsertOperation => {
111+
const document: ClientInsertOperation = {
112+
insert: index,
113+
document: model.document
114+
};
115+
return document;
116+
};
117+
118+
/** @internal */
119+
export interface ClientDeleteOperation {
120+
delete: number;
121+
multi: boolean;
122+
filter: Filter<Document>;
123+
hint?: Hint;
124+
collation?: CollationOptions;
125+
}
126+
127+
/**
128+
* Build the delete one operation.
129+
* @param model - The insert many model.
130+
* @param index - The namespace index.
131+
* @returns the operation.
132+
*/
133+
export const buildDeleteOneOperation = (model: ClientDeleteOneModel, index: number): Document => {
134+
return createDeleteOperation(model, index, false);
135+
};
136+
137+
/**
138+
* Build the delete many operation.
139+
* @param model - The delete many model.
140+
* @param index - The namespace index.
141+
* @returns the operation.
142+
*/
143+
export const buildDeleteManyOperation = (model: ClientDeleteManyModel, index: number): Document => {
144+
return createDeleteOperation(model, index, true);
145+
};
146+
147+
/**
148+
* Creates a delete operation based on the parameters.
149+
*/
150+
function createDeleteOperation(
151+
model: ClientDeleteOneModel | ClientDeleteManyModel,
152+
index: number,
153+
multi: boolean
154+
): ClientDeleteOperation {
155+
const document: ClientDeleteOperation = {
156+
delete: index,
157+
multi: multi,
158+
filter: model.filter
159+
};
160+
if (model.hint) {
161+
document.hint = model.hint;
162+
}
163+
if (model.collation) {
164+
document.collation = model.collation;
165+
}
166+
return document;
167+
}
168+
169+
/** @internal */
170+
export interface ClientUpdateOperation {
171+
update: number;
172+
multi: boolean;
173+
filter: Filter<Document>;
174+
updateMods: UpdateFilter<Document> | Document[];
175+
hint?: Hint;
176+
upsert?: boolean;
177+
arrayFilters?: Document[];
178+
}
179+
180+
/**
181+
* Build the update one operation.
182+
* @param model - The update one model.
183+
* @param index - The namespace index.
184+
* @returns the operation.
185+
*/
186+
export const buildUpdateOneOperation = (
187+
model: ClientUpdateOneModel,
188+
index: number
189+
): ClientUpdateOperation => {
190+
return createUpdateOperation(model, index, false);
191+
};
192+
193+
/**
194+
* Build the update many operation.
195+
* @param model - The update many model.
196+
* @param index - The namespace index.
197+
* @returns the operation.
198+
*/
199+
export const buildUpdateManyOperation = (
200+
model: ClientUpdateManyModel,
201+
index: number
202+
): ClientUpdateOperation => {
203+
return createUpdateOperation(model, index, true);
204+
};
205+
206+
/**
207+
* Creates a delete operation based on the parameters.
208+
*/
209+
function createUpdateOperation(
210+
model: ClientUpdateOneModel | ClientUpdateManyModel,
211+
index: number,
212+
multi: boolean
213+
): ClientUpdateOperation {
214+
const document: ClientUpdateOperation = {
215+
update: index,
216+
multi: multi,
217+
filter: model.filter,
218+
updateMods: model.update
219+
};
220+
if (model.hint) {
221+
document.hint = model.hint;
222+
}
223+
if (model.upsert) {
224+
document.upsert = model.upsert;
225+
}
226+
if (model.arrayFilters) {
227+
document.arrayFilters = model.arrayFilters;
228+
}
229+
return document;
230+
}
231+
232+
/** @internal */
233+
export interface ClientReplaceOneOperation {
234+
update: number;
235+
multi: boolean;
236+
filter: Filter<Document>;
237+
updateMods: WithoutId<Document>;
238+
hint?: Hint;
239+
upsert?: boolean;
240+
}
241+
242+
/**
243+
* Build the replace one operation.
244+
* @param model - The replace one model.
245+
* @param index - The namespace index.
246+
* @returns the operation.
247+
*/
248+
export const buildReplaceOneOperation = (
249+
model: ClientReplaceOneModel,
250+
index: number
251+
): ClientReplaceOneOperation => {
252+
const document: ClientReplaceOneOperation = {
253+
update: index,
254+
multi: false,
255+
filter: model.filter,
256+
updateMods: model.replacement
257+
};
258+
if (model.hint) {
259+
document.hint = model.hint;
260+
}
261+
if (model.upsert) {
262+
document.upsert = model.upsert;
263+
}
264+
return document;
265+
};
266+
267+
/** @internal */
268+
export function buildOperation(model: AnyClientBulkWriteModel, index: number): Document {
269+
switch (model.name) {
270+
case 'insertOne':
271+
return buildInsertOneOperation(model, index);
272+
case 'deleteOne':
273+
return buildDeleteOneOperation(model, index);
274+
case 'deleteMany':
275+
return buildDeleteManyOperation(model, index);
276+
case 'updateOne':
277+
return buildUpdateOneOperation(model, index);
278+
case 'updateMany':
279+
return buildUpdateManyOperation(model, index);
280+
case 'replaceOne':
281+
return buildReplaceOneOperation(model, index);
282+
}
283+
}

0 commit comments

Comments
 (0)