Skip to content

Commit c861b28

Browse files
authored
Merge pull request #67 from craftship/deprecate
Add npm deprecate Support
2 parents 4c5da08 + 64858ce commit c861b28

File tree

10 files changed

+262
-26
lines changed

10 files changed

+262
-26
lines changed

src/adapters/logger.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import fetch from 'node-fetch';
22

33
export default class Logger {
4-
constructor(namespace, credentials = {}) {
4+
constructor(cmd, namespace, credentials = {}) {
5+
this.command = cmd;
56
this.namespace = namespace;
67
this.credentials = credentials;
78
}
@@ -25,6 +26,7 @@ export default class Logger {
2526
timestamp: new Date(),
2627
level: 'error',
2728
namespace: `error:${this.namespace}`,
29+
command: this.command,
2830
body: {
2931
message,
3032
stack,
@@ -40,6 +42,7 @@ export default class Logger {
4042
timestamp: new Date(),
4143
level: 'info',
4244
namespace: `info:${this.namespace}`,
45+
command: this.command,
4346
body: message,
4447
};
4548

src/contextFactory.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,26 @@ const user = authorizer => ({
77
avatar: authorizer.avatar,
88
});
99

10+
const command = (headers) => {
11+
const refererParts = headers.Referer.split(' ');
12+
const name = refererParts[0];
13+
14+
return {
15+
name,
16+
args: refererParts.slice(1),
17+
};
18+
};
19+
1020
const storage = (region, bucket) =>
1121
new S3({
1222
region,
1323
bucket,
1424
});
1525

16-
const log = (namespace, region, topic) => {
26+
const log = (cmd, namespace, region, topic) => {
1727
if (process.env.clientId && process.env.secret) {
1828
return new Logger(
29+
cmd,
1930
namespace,
2031
{
2132
clientId: process.env.clientId,
@@ -25,25 +36,29 @@ const log = (namespace, region, topic) => {
2536
}
2637

2738
return new Logger(
39+
cmd,
2840
namespace, {
2941
region,
3042
topic,
3143
});
3244
};
3345

34-
export default (namespace, { authorizer }) => {
46+
export default (namespace, { headers, requestContext }) => {
3547
const {
3648
registry,
3749
bucket,
3850
region,
3951
logTopic,
4052
} = process.env;
4153

54+
const cmd = command(headers);
55+
4256
return {
57+
command: cmd,
4358
registry,
44-
user: user(authorizer),
59+
user: user(requestContext.authorizer),
4560
storage: storage(region, bucket),
46-
log: log(namespace, region, logTopic),
61+
log: log(cmd, namespace, region, logTopic),
4762
npm,
4863
};
4964
};

src/get/index.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import lib from './lib';
22
import contextFactory from '../contextFactory';
33

4-
export default async (event, _, callback) => lib(
5-
event,
6-
contextFactory(
7-
'package:get',
8-
event.requestContext,
9-
),
10-
callback,
11-
);
4+
export default async (event, _, callback) => {
5+
lib(
6+
event,
7+
contextFactory(
8+
'package:get',
9+
event,
10+
),
11+
callback,
12+
);
13+
};

src/put/deprecate.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export default async ({
2+
requestContext,
3+
pathParameters,
4+
body,
5+
}, {
6+
registry,
7+
user,
8+
storage,
9+
npm,
10+
log,
11+
}, callback) => {
12+
const name = `${decodeURIComponent(pathParameters.name)}`;
13+
14+
try {
15+
await storage.put(
16+
`${name}/index.json`,
17+
body.toString(),
18+
);
19+
20+
return callback(null, {
21+
statusCode: 200,
22+
body: JSON.stringify({
23+
success: true,
24+
}),
25+
});
26+
} catch (putError) {
27+
await log.error(user, putError);
28+
29+
return callback(null, {
30+
statusCode: 500,
31+
body: JSON.stringify({
32+
success: false,
33+
error: putError.message,
34+
}),
35+
});
36+
}
37+
};

src/put/index.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
1-
import lib from './lib';
1+
import deprecate from './deprecate';
2+
import publish from './publish';
23
import contextFactory from '../contextFactory';
34

4-
export default async (event, _, callback) => lib(
5-
event,
6-
contextFactory(
5+
export default async (event, _, callback) => {
6+
const context = contextFactory(
77
'package:put',
8-
event.requestContext,
9-
),
10-
callback,
11-
);
8+
event,
9+
);
10+
11+
if (context.command.name === 'deprecate') {
12+
return deprecate(
13+
event,
14+
context,
15+
callback,
16+
);
17+
}
18+
19+
return publish(
20+
event,
21+
context,
22+
callback,
23+
);
24+
};
File renamed without changes.

test/adapters/logger.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('Logger', () => {
2121

2222
describe('#info()', () => {
2323
it('should call insights logging endpoint with correct parameters', async () => {
24-
const subject = new Subject('foo:bar', {
24+
const subject = new Subject({ name: 'foo', args: [] }, 'foo:bar', {
2525
clientId: 'foo-client-id',
2626
secret: 'bar-secret',
2727
});
@@ -34,14 +34,14 @@ describe('Logger', () => {
3434
'Content-Type': 'application/json',
3535
Authorization: 'Bearer foo-client-id:bar-secret',
3636
},
37-
body: '{"user":{"name":"foo","avatar":"https://example.com"},"timestamp":"1970-01-01T00:00:00.000Z","level":"info","namespace":"info:foo:bar","body":{"foo":"bar"}}',
37+
body: '{"user":{"name":"foo","avatar":"https://example.com"},"timestamp":"1970-01-01T00:00:00.000Z","level":"info","namespace":"info:foo:bar","command":{"name":"foo","args":[]},"body":{"foo":"bar"}}',
3838
}));
3939
});
4040
});
4141

4242
describe('#error()', () => {
4343
it('should call insights logging endpoint with correct parameters', async () => {
44-
const subject = new Subject('foo:bar', {
44+
const subject = new Subject({ name: 'foo', args: [] }, 'foo:bar', {
4545
clientId: 'foo-client-id',
4646
secret: 'bar-secret',
4747
});
@@ -57,7 +57,7 @@ describe('Logger', () => {
5757
'Content-Type': 'application/json',
5858
Authorization: 'Bearer foo-client-id:bar-secret',
5959
},
60-
body: '{"user":{"name":"foo","avatar":"https://example.com"},"timestamp":"1970-01-01T00:00:00.000Z","level":"error","namespace":"error:foo:bar","body":{"message":"Foo Bar","stack":"foo bar stack"}}',
60+
body: '{"user":{"name":"foo","avatar":"https://example.com"},"timestamp":"1970-01-01T00:00:00.000Z","level":"error","namespace":"error:foo:bar","command":{"name":"foo","args":[]},"body":{"message":"Foo Bar","stack":"foo bar stack"}}',
6161
}));
6262
});
6363
});

test/fixtures/package.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
11
export default {
2+
deprecate: (msg, {
3+
major,
4+
minor,
5+
patch,
6+
}) => new Buffer(
7+
JSON.stringify({
8+
_id: 'foo-bar-package',
9+
name: 'foo-bar-package',
10+
'dist-tags': {
11+
latest: `${major}.${minor}.${patch}`,
12+
},
13+
versions: {
14+
[`${major}.${minor}.${patch}`]: {
15+
name: 'foo-bar-package',
16+
version: `${major}.${minor}.${patch}`,
17+
deprecated: msg,
18+
dist: {
19+
tarball: `https://example.com/registry/foo-bar-package/-/foo-bar-package-${major}.${minor}.${patch}.tgz`,
20+
},
21+
},
22+
},
23+
_attachments: {
24+
[`foo-bar-package-${major}.${minor}.${patch}.tgz`]: {
25+
data: 'foo-package-data',
26+
},
27+
},
28+
}),
29+
),
230
withAttachments: ({
331
major,
432
minor,

test/put/deprecate.test.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/* eslint-disable no-underscore-dangle */
2+
import pkg from '../fixtures/package';
3+
4+
import subject from '../../src/put/deprecate';
5+
6+
describe('PUT /registry/{name}', () => {
7+
let event;
8+
let callback;
9+
let storageStub;
10+
11+
beforeEach(() => {
12+
const env = {
13+
bucket: 'foo-bucket',
14+
region: 'bar-region',
15+
};
16+
17+
process.env = env;
18+
19+
event = (msg, version) => ({
20+
requestContext: {
21+
authorizer: {
22+
username: 'foo',
23+
avatar: 'https://example.com',
24+
},
25+
},
26+
body: pkg.deprecate(msg, version),
27+
pathParameters: {
28+
name: 'foo-bar-package',
29+
},
30+
});
31+
32+
callback = stub();
33+
});
34+
35+
describe('deprecate', () => {
36+
beforeEach(() => {
37+
storageStub = {
38+
put: stub(),
39+
};
40+
});
41+
42+
it('should store package json', async () => {
43+
await subject(
44+
event('This package is deprecated', {
45+
major: 1,
46+
minor: 0,
47+
patch: 0,
48+
}), {
49+
registry: 'https://example.com',
50+
user: stub(),
51+
log: {
52+
info: stub(),
53+
error: stub(),
54+
},
55+
npm: stub(),
56+
storage: storageStub,
57+
command: {
58+
name: 'deprecate',
59+
message: 'This package is deprecated',
60+
},
61+
},
62+
callback,
63+
);
64+
65+
assert(storageStub.put.calledWithExactly(
66+
'foo-bar-package/index.json',
67+
pkg.deprecate('This package is deprecated', {
68+
major: 1,
69+
minor: 0,
70+
patch: 0,
71+
}).toString(),
72+
));
73+
});
74+
75+
it('should return correct response', async () => {
76+
await subject(
77+
event('This package is deprecated', {
78+
major: 1,
79+
minor: 0,
80+
patch: 0,
81+
}), {
82+
registry: 'https://example.com',
83+
user: stub(),
84+
log: {
85+
info: stub(),
86+
error: stub(),
87+
},
88+
npm: stub(),
89+
storage: storageStub,
90+
},
91+
callback,
92+
);
93+
94+
assert(callback.calledWithExactly(null, {
95+
statusCode: 200,
96+
body: '{"success":true}',
97+
}));
98+
});
99+
100+
context('storage put error', () => {
101+
beforeEach(() => {
102+
storageStub = {
103+
get: stub().returns(pkg.deprecate('This package is deprecated', {
104+
major: 1,
105+
minor: 0,
106+
patch: 0,
107+
})),
108+
put: stub().throws(new Error('Failed to put')),
109+
};
110+
});
111+
112+
it('should return 500 response', async () => {
113+
await subject(
114+
event('This package is deprecated', {
115+
major: 2,
116+
minor: 0,
117+
patch: 0,
118+
}), {
119+
registry: 'https://example.com',
120+
user: stub(),
121+
log: {
122+
error: stub(),
123+
info: stub(),
124+
},
125+
npm: stub(),
126+
storage: storageStub,
127+
},
128+
callback,
129+
);
130+
131+
assert(callback.calledWithExactly(null, {
132+
statusCode: 500,
133+
body: '{"success":false,"error":"Failed to put"}',
134+
}));
135+
});
136+
});
137+
});
138+
});
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable no-underscore-dangle */
22
import pkg from '../fixtures/package';
33

4-
import subject from '../../src/put/lib';
4+
import subject from '../../src/put/publish';
55

66
describe('PUT /registry/{name}', () => {
77
let event;

0 commit comments

Comments
 (0)