apizit-cli 0.2.0b2__tar.gz → 0.2.0b3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/PKG-INFO +5 -2
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/README.md +3 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/pyproject.toml +2 -2
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/__init__.py +1 -1
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/authentication.py +68 -9
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/main.py +9 -1
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/PKG-INFO +5 -2
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/setup.cfg +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/commands.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/configuration.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/context.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/credential_store.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/domains.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/errors.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/http.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/operations.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli/sources.py +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/SOURCES.txt +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/dependency_links.txt +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/entry_points.txt +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/requires.txt +0 -0
- {apizit_cli-0.2.0b2 → apizit_cli-0.2.0b3}/src/apizit_cli.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apizit-cli
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: Launch Python
|
|
3
|
+
Version: 0.2.0b3
|
|
4
|
+
Summary: Launch supported Python, JavaScript, TypeScript or Java APIs from your terminal or CI.
|
|
5
5
|
Author: APIZIT
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
7
7
|
Classifier: Environment :: Console
|
|
@@ -20,6 +20,9 @@ Requires-Dist: pathspec<2,>=1
|
|
|
20
20
|
|
|
21
21
|
Launch supported Python, JavaScript, TypeScript or Java projects as managed public APIs, inspect logs and manage releases from your terminal.
|
|
22
22
|
|
|
23
|
+
Managed adapters cover Flask, FastAPI, Django, Express, NestJS and Spring Boot; APIZIT Linking
|
|
24
|
+
provides declarative Python routes. Run a scan to confirm the project's version and structure.
|
|
25
|
+
|
|
23
26
|
APIZIT is an advanced beta. This source version defaults to `https://api.apizit.com/v1`.
|
|
24
27
|
Version `0.2.0b1` uses its original dev default; use `--endpoint` explicitly with that version.
|
|
25
28
|
Check the official CLI documentation for package availability and current workspace capabilities.
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Launch supported Python, JavaScript, TypeScript or Java projects as managed public APIs, inspect logs and manage releases from your terminal.
|
|
4
4
|
|
|
5
|
+
Managed adapters cover Flask, FastAPI, Django, Express, NestJS and Spring Boot; APIZIT Linking
|
|
6
|
+
provides declarative Python routes. Run a scan to confirm the project's version and structure.
|
|
7
|
+
|
|
5
8
|
APIZIT is an advanced beta. This source version defaults to `https://api.apizit.com/v1`.
|
|
6
9
|
Version `0.2.0b1` uses its original dev default; use `--endpoint` explicitly with that version.
|
|
7
10
|
Check the official CLI documentation for package availability and current workspace capabilities.
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apizit-cli"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "Launch Python
|
|
7
|
+
version = "0.2.0b3"
|
|
8
|
+
description = "Launch supported Python, JavaScript, TypeScript or Java APIs from your terminal or CI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
authors = [{name = "APIZIT"}]
|
|
@@ -255,6 +255,8 @@ class NativeSession:
|
|
|
255
255
|
)
|
|
256
256
|
callback = urlsplit(configuration["redirect_uri"])
|
|
257
257
|
outcome = {}
|
|
258
|
+
page_loaded = False
|
|
259
|
+
cleanup_nonce = secrets.token_urlsafe(24)
|
|
258
260
|
deadline = time.monotonic() + timeout
|
|
259
261
|
|
|
260
262
|
class Callback(BaseHTTPRequestHandler):
|
|
@@ -264,12 +266,22 @@ class NativeSession:
|
|
|
264
266
|
|
|
265
267
|
def do_GET(self):
|
|
266
268
|
parsed = urlsplit(self.path)
|
|
269
|
+
if (
|
|
270
|
+
parsed.path == "/complete"
|
|
271
|
+
and not parsed.query
|
|
272
|
+
and not parsed.scheme
|
|
273
|
+
and not parsed.netloc
|
|
274
|
+
and self.headers.get("Host") == callback.netloc
|
|
275
|
+
):
|
|
276
|
+
self._page("Return to the APIZIT terminal.", status=200)
|
|
277
|
+
return
|
|
267
278
|
try:
|
|
268
279
|
query = parse_qs(parsed.query, max_num_fields=8, strict_parsing=True)
|
|
269
280
|
except ValueError:
|
|
270
281
|
query = {}
|
|
271
282
|
valid = (
|
|
272
283
|
parsed.path == callback.path
|
|
284
|
+
and not outcome
|
|
273
285
|
and not parsed.scheme
|
|
274
286
|
and not parsed.netloc
|
|
275
287
|
and self.headers.get("Host") == callback.netloc
|
|
@@ -281,18 +293,59 @@ class NativeSession:
|
|
|
281
293
|
or (len(query.get("error", [])) == 1 and 0 < len(query["error"][0]) <= 256)
|
|
282
294
|
)
|
|
283
295
|
)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
296
|
+
self._page(
|
|
297
|
+
"Return to the APIZIT terminal." if valid else "Invalid login callback.",
|
|
298
|
+
status=200 if valid else 400,
|
|
299
|
+
)
|
|
300
|
+
# Finish sending the cleanup script before allowing the server to shut down.
|
|
301
|
+
if valid:
|
|
302
|
+
outcome["received_at"] = time.monotonic()
|
|
303
|
+
if "code" in query:
|
|
304
|
+
outcome["code"] = query["code"][0]
|
|
305
|
+
else:
|
|
306
|
+
outcome["error"] = True
|
|
307
|
+
|
|
308
|
+
def _page(self, message, *, status):
|
|
309
|
+
body = (
|
|
310
|
+
'<!doctype html><html lang="en"><head><meta charset="utf-8">'
|
|
311
|
+
"<title>APIZIT sign-in</title>"
|
|
312
|
+
f'<script nonce="{cleanup_nonce}">'
|
|
313
|
+
'history.replaceState(null,"","/complete");'
|
|
314
|
+
'fetch("/complete",{method:"POST",credentials:"omit",cache:"no-store",'
|
|
315
|
+
f'headers:{{"X-APIZIT-Page":"{cleanup_nonce}"}}}}).catch(()=>{{}});'
|
|
316
|
+
"</script></head><body><main><h1>APIZIT sign-in</h1>"
|
|
317
|
+
f"<p>{message}</p></main></body></html>"
|
|
318
|
+
).encode("utf-8")
|
|
319
|
+
self.send_response(status)
|
|
320
|
+
self.send_header("Content-Type", "text/html; charset=utf-8")
|
|
321
|
+
self.send_header("Content-Length", str(len(body)))
|
|
290
322
|
self.send_header("Cache-Control", "no-store")
|
|
291
|
-
self.send_header("
|
|
323
|
+
self.send_header("Referrer-Policy", "no-referrer")
|
|
324
|
+
self.send_header("X-Content-Type-Options", "nosniff")
|
|
325
|
+
self.send_header(
|
|
326
|
+
"Content-Security-Policy",
|
|
327
|
+
f"default-src 'none'; script-src 'nonce-{cleanup_nonce}'; "
|
|
328
|
+
"connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'",
|
|
329
|
+
)
|
|
292
330
|
self.end_headers()
|
|
293
|
-
self.wfile.write(
|
|
294
|
-
|
|
331
|
+
self.wfile.write(body)
|
|
332
|
+
self.wfile.flush()
|
|
333
|
+
|
|
334
|
+
def do_POST(self):
|
|
335
|
+
nonlocal page_loaded
|
|
336
|
+
valid = (
|
|
337
|
+
self.path == "/complete"
|
|
338
|
+
and self.headers.get("Host") == callback.netloc
|
|
339
|
+
and hmac.compare_digest(
|
|
340
|
+
self.headers.get("X-APIZIT-Page", "").encode(), cleanup_nonce.encode()
|
|
341
|
+
)
|
|
295
342
|
)
|
|
343
|
+
if valid and outcome:
|
|
344
|
+
page_loaded = True
|
|
345
|
+
self.send_response(204 if valid else 400)
|
|
346
|
+
self.send_header("Cache-Control", "no-store")
|
|
347
|
+
self.send_header("Content-Length", "0")
|
|
348
|
+
self.end_headers()
|
|
296
349
|
|
|
297
350
|
def log_message(self, *_args):
|
|
298
351
|
pass
|
|
@@ -327,6 +380,12 @@ class NativeSession:
|
|
|
327
380
|
server.timeout = 1
|
|
328
381
|
while not outcome and time.monotonic() < deadline:
|
|
329
382
|
server.handle_request()
|
|
383
|
+
# The browser acknowledges after replacing its current history entry. A bounded
|
|
384
|
+
# grace period also accommodates clients without JavaScript without blocking login.
|
|
385
|
+
cleanup_deadline = min(deadline, outcome.get("received_at", deadline) + 2)
|
|
386
|
+
while outcome and not page_loaded and time.monotonic() < cleanup_deadline:
|
|
387
|
+
server.timeout = min(0.2, max(0, cleanup_deadline - time.monotonic()))
|
|
388
|
+
server.handle_request()
|
|
330
389
|
finally:
|
|
331
390
|
server.server_close()
|
|
332
391
|
if "code" not in outcome:
|
|
@@ -51,7 +51,15 @@ def build_parser():
|
|
|
51
51
|
add_options(common, GLOBAL_OPTIONS, global_options=True)
|
|
52
52
|
parser = Parser(
|
|
53
53
|
prog="apizit",
|
|
54
|
-
description=
|
|
54
|
+
description=(
|
|
55
|
+
"Launch supported Python, JavaScript, TypeScript or Java projects as managed public "
|
|
56
|
+
"APIs. Framework support follows the APIZIT compatibility guide. APIZIT prelaunch beta."
|
|
57
|
+
),
|
|
58
|
+
epilog=(
|
|
59
|
+
"Managed frameworks: Flask, FastAPI, Django, Express, NestJS and Spring Boot. "
|
|
60
|
+
"APIZIT Linking supports declarative Python routes. Run a scan to confirm that your "
|
|
61
|
+
"project's version and structure are compatible."
|
|
62
|
+
),
|
|
55
63
|
parents=[common],
|
|
56
64
|
allow_abbrev=False,
|
|
57
65
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apizit-cli
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: Launch Python
|
|
3
|
+
Version: 0.2.0b3
|
|
4
|
+
Summary: Launch supported Python, JavaScript, TypeScript or Java APIs from your terminal or CI.
|
|
5
5
|
Author: APIZIT
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
7
7
|
Classifier: Environment :: Console
|
|
@@ -20,6 +20,9 @@ Requires-Dist: pathspec<2,>=1
|
|
|
20
20
|
|
|
21
21
|
Launch supported Python, JavaScript, TypeScript or Java projects as managed public APIs, inspect logs and manage releases from your terminal.
|
|
22
22
|
|
|
23
|
+
Managed adapters cover Flask, FastAPI, Django, Express, NestJS and Spring Boot; APIZIT Linking
|
|
24
|
+
provides declarative Python routes. Run a scan to confirm the project's version and structure.
|
|
25
|
+
|
|
23
26
|
APIZIT is an advanced beta. This source version defaults to `https://api.apizit.com/v1`.
|
|
24
27
|
Version `0.2.0b1` uses its original dev default; use `--endpoint` explicitly with that version.
|
|
25
28
|
Check the official CLI documentation for package availability and current workspace capabilities.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|