Skip to content

Commit 9e8bb20

Browse files
authored
feat: multiversion (#750)
1 parent 544d876 commit 9e8bb20

29 files changed

+1324
-227
lines changed

README.md

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,13 @@ All operation use es7 async/await to implement. All api is async function.
103103
- [.putBucketPolicy(name, policy[, options])](#putBucketPolicyname-policy-options)
104104
- [.getBucketPolicy(name, [, options])](#getBucketPolicyname-options)
105105
- [.deleteBucketPolicy(name, [, options])](#deleteBucketPolicyname-options)
106+
- versioning
107+
- [.getBucketVersioning(name, [, options])](#getBucketVersioningname-options)
108+
- [.putBucketVersioning(name, status[, options])](#putBucketVersioningname-status-options)
109+
106110
- [Object Operations](#object-operations)
107111
- [.list(query[, options])](#listquery-options)
112+
- [.getBucketVersions(query[, options])](#getBucketVersionsquery-options)
108113
- [.put(name, file[, options])](#putname-file-options)
109114
- [.putStream(name, stream[, options])](#putstreamname-stream-options)
110115
- [.append(name, file[, options])](#appendname-file-options)
@@ -1155,6 +1160,39 @@ Success will return:
11551160
- status {Number} response status
11561161
- res {Object} response info
11571162

1163+
---
1164+
### .getBucketVersioning(name[, options])
1165+
1166+
Obtains the version status of an object
1167+
1168+
parameters:
1169+
1170+
- name {String} the bucket name
1171+
- [options] {Object} optional args
1172+
1173+
Success will return:
1174+
1175+
- status {Number} response status
1176+
- versionStatus {String | undefined} version status, `Suspended` or `Enabled`. default value: `undefined`
1177+
- res {Object} response info
1178+
1179+
---
1180+
1181+
### .putBucketVersioning(name, status[, options])
1182+
1183+
set the version status of an object
1184+
1185+
parameters:
1186+
1187+
- name {String} the bucket name
1188+
- status {String} version status, allow values: `Enabled` or `Suspended`
1189+
- [options] {Object} optional args
1190+
1191+
Success will return:
1192+
1193+
- status {Number} response status
1194+
- res {Object} response info
1195+
11581196
---
11591197

11601198
## Object Operations
@@ -1778,7 +1816,9 @@ Delete multi objects in one request.
17781816
17791817
parameters:
17801818
1781-
- names {Array<String>} object names, max 1000 objects in once.
1819+
- names {Array<Object>} object names, max 1000 objects in once.
1820+
- key {String} object name
1821+
- [versionId] {String} version id
17821822
- [options] {Object} optional parameters
17831823
- [quiet] {Boolean} quiet mode or verbose mode, default is `false`, verbose mode
17841824
quiet mode: if all objects delete succes, return emtpy response.
@@ -1788,7 +1828,11 @@ parameters:
17881828
17891829
Success will return delete success objects in `deleted` property.
17901830
1791-
- [deleted] {Array<String>} deleted object names list
1831+
- [deleted] {Array<Object>} deleted object or deleteMarker info list
1832+
- [Key] object name
1833+
- [VersionId] object versionId
1834+
- [DeleteMarker] generate or delete marker
1835+
- [DeleteMarkerVersionId] marker versionId
17921836
- res {Object} response info, including
17931837
- status {Number} response status
17941838
- headers {Object} response headers
@@ -1874,6 +1918,79 @@ const result = await store.list({
18741918
console.log(result.objects);
18751919
```
18761920
1921+
### .getBucketVersions(query[, options])
1922+
1923+
List objects in the bucket.
1924+
1925+
parameters:
1926+
1927+
- [query] {Object} query parameters, default is `null`
1928+
- [prefix] {String} search object using `prefix` key
1929+
- [versionIdMarker] {String} set the result to return from the version ID marker of the key marker object and sort by the versions
1930+
- [keyMarker] {String} search start from `keyMarker`, including `keyMarker` key
1931+
- [encodingType] {String} specifies that the returned content is encoded, and specifies the type of encoding
1932+
- [delimiter] {String} delimiter search scope
1933+
e.g. `/` only search current dir, not including subdir
1934+
- [maxKeys] {String|Number} max objects, default is `100`, limit to `1000`
1935+
- [options] {Object} optional parameters
1936+
- [timeout] {Number} the operation timeout
1937+
1938+
Success will return objects list on `objects` properties.
1939+
1940+
- objects {Array<ObjectMeta>} object meta info list
1941+
Each `ObjectMeta` will contains blow properties:
1942+
- name {String} object name on oss
1943+
- lastModified {String} object last modified GMT date, e.g.: `2015-02-19T08:39:44.000Z`
1944+
- etag {String} object etag contains `"`, e.g.: `"5B3C1A2E053D763E1B002CC607C5A0FE"`
1945+
- type {String} object type, e.g.: `Normal`
1946+
- size {Number} object size, e.g.: `344606`
1947+
- isLatest {Boolean}
1948+
- versionId {String} object versionId
1949+
- storageClass {String} storage class type, e.g.: `Standard`
1950+
- owner {Object} object owner, including `id` and `displayName`
1951+
- deleteMarker {Array<ObjectDeleteMarker>} object delete marker info list
1952+
Each `ObjectDeleteMarker`
1953+
- name {String} object name on oss
1954+
- lastModified {String} object last modified GMT date, e.g.: `2015-02-19T08:39:44.000Z`
1955+
- versionId {String} object versionId
1956+
- isTruncated {Boolean} truncate or not
1957+
- nextMarker {String} next marker string
1958+
- NextVersionIdMarker {String} next version ID marker string
1959+
- res {Object} response info, including
1960+
- status {Number} response status
1961+
- headers {Object} response headers
1962+
- size {Number} response size
1963+
- rt {Number} request total use time (ms)
1964+
1965+
example:
1966+
1967+
- View all versions of objects and deleteMarker of bucket
1968+
1969+
```js
1970+
const result = await store.getBucketVersions();
1971+
console.log(result.objects);
1972+
console.log(result.deleteMarker);
1973+
```
1974+
1975+
- List from key-marker
1976+
1977+
```js
1978+
const result = await store.getBucketVersions({
1979+
'keyMarker': 'keyMarker'
1980+
});
1981+
console.log(result.objects);
1982+
```
1983+
1984+
- List from the version-id-marker of key-marker
1985+
1986+
```js
1987+
const result = await store.getBucketVersions({
1988+
'versionIdMarker': 'versionIdMarker',
1989+
'keyMarker': 'keyMarker'
1990+
});
1991+
console.log(result.objects);
1992+
```
1993+
18771994
### .signatureUrl(name[, options])
18781995
18791996
Create a signature url for download or upload object. When you put object with signatureUrl ,you need to pass `Content-Type`.Please look at the example.

lib/browser/client.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ merge(proto, require('../common/bucket/getBucketLifecycle'));
110110
merge(proto, require('../common/bucket/putBucketLifecycle'));
111111
merge(proto, require('../common/bucket/deleteBucketLifecycle'));
112112

113+
// multiversion
114+
merge(proto, require('../common/bucket/putBucketVersioning'));
115+
merge(proto, require('../common/bucket/getBucketVersioning'));
113116

114117
// multipart upload
115118
merge(proto, require('./managed-upload'));

lib/browser/object.js

Lines changed: 4 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -239,48 +239,14 @@ proto.delete = async function _delete(name, options) {
239239
};
240240
};
241241

242-
proto.deleteMulti = async function deleteMulti(names, options) {
243-
options = options || {};
244-
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<Delete>\n';
245-
if (options.quiet) {
246-
xml += ' <Quiet>true</Quiet>\n';
247-
} else {
248-
xml += ' <Quiet>false</Quiet>\n';
249-
}
250-
for (let i = 0; i < names.length; i++) {
251-
xml += ` <Object><Key>${
252-
utility.escape(this._objectName(names[i]))}</Key></Object>\n`;
253-
}
254-
xml += '</Delete>';
255-
this.debug('delete multi objects: %s', xml, 'info');
256-
257-
options.subres = 'delete';
258-
const params = this._objectRequestParams('POST', '', options);
259-
params.mime = 'xml';
260-
params.content = xml;
261-
params.xmlResponse = true;
262-
params.successStatuses = [200];
263-
const result = await this.request(params);
264-
265-
const r = result.data;
266-
let deleted = (r && r.Deleted) || null;
267-
if (deleted) {
268-
if (!Array.isArray(deleted)) {
269-
deleted = [deleted];
270-
}
271-
deleted = deleted.map(item => item.Key);
272-
}
273-
return {
274-
res: result.res,
275-
deleted
276-
};
277-
};
278-
279242
merge(proto, require('../common/object/copyObject'));
280243
merge(proto, require('../common/object/getObjectTagging'));
281244
merge(proto, require('../common/object/putObjectTagging'));
282245
merge(proto, require('../common/object/deleteObjectTagging'));
283246
merge(proto, require('../common/image'));
247+
merge(proto, require('../common/object/getBucketVersions'));
248+
merge(proto, require('../common/object/getACL'));
249+
merge(proto, require('../common/object/putACL'));
284250

285251
proto.putMeta = async function putMeta(name, meta, options) {
286252
const copyResult = await this.copy(name, name, {
@@ -336,56 +302,6 @@ proto.list = async function list(query, options) {
336302
};
337303
};
338304

339-
/*
340-
* Set object's ACL
341-
* @param {String} name the object key
342-
* @param {String} acl the object ACL
343-
* @param {Object} options
344-
*/
345-
proto.putACL = async function putACL(name, acl, options) {
346-
options = options || {};
347-
options.subres = 'acl';
348-
options.headers = options.headers || {};
349-
options.headers['x-oss-object-acl'] = acl;
350-
name = this._objectName(name);
351-
352-
const params = this._objectRequestParams('PUT', name, options);
353-
params.successStatuses = [200];
354-
355-
const result = await this.request(params);
356-
357-
return {
358-
res: result.res
359-
};
360-
};
361-
362-
/*
363-
* Get object's ACL
364-
* @param {String} name the object key
365-
* @param {Object} options
366-
* @return {Object}
367-
*/
368-
proto.getACL = async function getACL(name, options) {
369-
options = options || {};
370-
options.subres = 'acl';
371-
name = this._objectName(name);
372-
373-
const params = this._objectRequestParams('GET', name, options);
374-
params.successStatuses = [200];
375-
params.xmlResponse = true;
376-
377-
const result = await this.request(params);
378-
379-
return {
380-
acl: result.data.AccessControlList.Grant,
381-
owner: {
382-
id: result.data.Owner.ID,
383-
displayName: result.data.Owner.DisplayName
384-
},
385-
res: result.res
386-
};
387-
};
388-
389305
/**
390306
* Restore Object
391307
* @param {String} name the object key
@@ -394,7 +310,7 @@ proto.getACL = async function getACL(name, options) {
394310
*/
395311
proto.restore = async function restore(name, options) {
396312
options = options || {};
397-
options.subres = 'restore';
313+
options.subres = Object.assign({ restore: '' }, options.subres);
398314
const params = this._objectRequestParams('POST', name, options);
399315
params.successStatuses = [202];
400316

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const _checkBucketName = require('../utils/checkBucketName');
2+
3+
const proto = exports;
4+
/**
5+
* getBucketVersioning
6+
* @param {String} bucketName - bucket name
7+
*/
8+
9+
proto.getBucketVersioning = async function getBucketVersioning(bucketName, options) {
10+
_checkBucketName(bucketName);
11+
const params = this._bucketRequestParams('GET', bucketName, 'versioning', options);
12+
params.xmlResponse = true;
13+
params.successStatuses = [200];
14+
const result = await this.request(params);
15+
16+
const versionStatus = result.data.Status;
17+
return {
18+
status: result.status,
19+
versionStatus,
20+
res: result.res
21+
};
22+
};

lib/common/bucket/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ merge(proto, require('./deleteBucketLifecycle'));
2020
merge(proto, require('./getBucketPolicy'));
2121
merge(proto, require('./putBucketPolicy'));
2222
merge(proto, require('./deleteBucketPolicy'));
23+
merge(proto, require('./getBucketVersioning'));
24+
merge(proto, require('./putBucketVersioning'));

lib/common/bucket/putBucketLifecycle.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,19 @@ function checkRule(rule) {
101101
}
102102

103103
if (rule.expiration) {
104-
checkDaysAndDate(rule.expiration, 'Expiration');
104+
if (!rule.expiration.expiredObjectDeleteMarker) {
105+
checkDaysAndDate(rule.expiration, 'Expiration');
106+
} else if (rule.expiration.days || rule.expiration.createdBeforeDate) {
107+
throw new Error('expiredObjectDeleteMarker cannot be used with days or createdBeforeDate');
108+
}
105109
}
106110

107111
if (rule.abortMultipartUpload) {
108112
checkDaysAndDate(rule.abortMultipartUpload, 'AbortMultipartUpload');
109113
}
110114

111-
if (!rule.expiration && !rule.abortMultipartUpload && !rule.transition) {
112-
throw new Error('Rule must includes expiration or abortMultipartUpload or transition');
115+
if (!rule.expiration && !rule.abortMultipartUpload && !rule.transition && !rule.noncurrentVersionTransition) {
116+
throw new Error('Rule must includes expiration or abortMultipartUpload or transition or noncurrentVersionTransition');
113117
}
114118

115119
if (rule.tag) {

lib/common/bucket/putBucketTags.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const checkTag = require('../utils/checkBucketTag');
55
const proto = exports;
66
/**
77
* putBucketTags
8-
* @param {Sting} name - bucket name
8+
* @param {String} name - bucket name
99
* @param {Object} tag - bucket tag, eg: `{a: "1", b: "2"}`
1010
* @param {Object} options
1111
*/
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const _checkBucketName = require('../utils/checkBucketName');
2+
const obj2xml = require('../utils/obj2xml');
3+
4+
const proto = exports;
5+
/**
6+
* putBucketVersioning
7+
* @param {String} name - bucket name
8+
* @param {String} status
9+
* @param {Object} options
10+
*/
11+
12+
proto.putBucketVersioning = async function putBucketVersioning(name, status, options = {}) {
13+
_checkBucketName(name);
14+
if (!['Enabled', 'Suspended'].includes(status)) {
15+
throw new Error('status must be Enabled or Suspended');
16+
}
17+
const params = this._bucketRequestParams('PUT', name, 'versioning', options);
18+
19+
const paramXMLObj = {
20+
VersioningConfiguration: {
21+
Status: status
22+
}
23+
};
24+
25+
params.mime = 'xml';
26+
params.content = obj2xml(paramXMLObj, {
27+
headers: true
28+
});
29+
30+
const result = await this.request(params);
31+
return {
32+
res: result.res,
33+
status: result.status
34+
};
35+
};

0 commit comments

Comments
 (0)